Schedules
Call a path on your project on a cron timer in UTC, pause and resume it, and see when it last ran and how it answered.
A schedule asks for a path on your project at the times a cron expression names. Each run is an ordinary GET request to your project's own address, so it reaches your app the same way a visitor's request does. Times are in UTC, the expression has five fields, and an expression Fortly cannot run is refused when you save it rather than silently never firing.
Add a schedule
Open schedules
Open your project, go to Deployments, and choose the Schedules tab.
Describe the job
Under Add a schedule, give it a Name (what it is for), When it runs as a cron expression such as 0 3 * * *, and the Path to request, such as /cron/digest.
Save it
The schedule appears under On this project, with when it runs next.
curl -X POST https://api.fortly.com/projects/my-app-ada/schedules \
-H "Authorization: Bearer $FORTLY_TOKEN" \
-H "Content-Type: application/json" \
-d '{"name": "Nightly digest", "spec": "0 3 * * *", "path": "/cron/digest"}'namestringRequiredspecstringRequiredpathstringRequired/, and may include a query string.The reply is 201 with the schedule, including its id and "enabled": true. Use the project's full API name, such as my-app-ada. The full reference is in Schedules API.
The cron format
Five fields separated by spaces, always evaluated in UTC:
┌───────── minute 0-59
│ ┌─────── hour 0-23
│ │ ┌───── day of month 1-31
│ │ │ ┌─── month 1-12
│ │ │ │ ┌─ day of week 0-7 (0 and 7 are both Sunday)
│ │ │ │ │
0 3 * * *Each field accepts:
| Syntax | Meaning | Example |
|---|---|---|
* | Every value | * in the hour field: every hour |
| A number | That value | 30 in the minute field |
a,b | A list | 1,15 in the day field: the 1st and the 15th |
a-b | A range, inclusive | 1-5 in the weekday field: Monday to Friday |
*/n | Every nth value | */15 in the minute field: 0, 15, 30, 45 |
a-b/n | Every nth value within a range | 9-17/2 in the hour field: 9, 11, 13, 15, 17 |
When both the day-of-month and the day-of-week fields are restricted, a day that matches either one runs. 0 9 1 * 1 runs at 09:00 on the 1st of every month and on every Monday. This is how cron has always behaved.
What is refused
Fortly accepts numbers only. These are refused when you save, with a message that says which field is wrong:
| You wrote | Refused with |
|---|---|
@daily, @hourly | a schedule has five fields — minute hour day month weekday — and this has 1 |
| Six fields, with seconds | a schedule has five fields — minute hour day month weekday — and this has 6 |
0 9 * * MON | weekday: MON is not a number |
0 9 * JAN * | month: JAN is not a number |
60 * * * * | minute: 60 is outside 0-59 |
*/0 * * * * | minute: a step of zero never comes round |
L, W and # are not supported either.
An expression that can never come round, such as 0 0 31 2 * (31 February), is accepted but never runs. Its next_run_at is null, which is how you spot one.
Examples
| Expression | Runs |
|---|---|
*/5 * * * * | Every 5 minutes |
0 * * * * | At the start of every hour |
0 3 * * * | Every day at 03:00 UTC |
30 8 * * 1-5 | Weekdays at 08:30 UTC |
*/15 9-17 * * 1-5 | Every 15 minutes from 09:00 to 17:45 UTC, Monday to Friday |
0 0 * * 0 | Every Sunday at midnight UTC |
0 0 1 * * | The first of every month at midnight UTC |
0 6 1 1,4,7,10 * | 06:00 UTC on the first day of each quarter |
How a run works
At the top of each minute, Fortly checks every enabled schedule and runs the ones whose expression matches that minute.
- The request is a
GETto the schedule's path on your project's own address. It goes through the same front door as visitor traffic, so it appears in your project's metrics like any other request. - Success is any
2xxor3xxanswer. Anything else is recorded as an error:the project answered 500. - Time limit: a run that has not answered within five minutes is abandoned and recorded as
the job did not finish within five minutes. - The result is kept on the schedule:
last_run_at,last_status(the HTTP status),last_ms(how long it took) andlast_error.
A scheduled run carries no Fortly credential or header that marks it as scheduled. Anyone who knows the path can request it too. Make the job safe to run more than once, and check your own secret in the path's query string or handler if running it must be restricted.
Missed runs are not replayed
If a run's minute passes while Fortly cannot run it — during maintenance on the machine that runs schedules, for example — that run is skipped, not made up later. A five-minute schedule that missed an hour does not fire twelve times when it can run again. The schedule's last_run_at shows when it last actually ran.
Pause, resume and remove
Each schedule under On this project has a Pause button, which becomes Resume while it is paused. A paused schedule shows Paused where its next run would be.
# Pause
curl -X PATCH https://api.fortly.com/projects/my-app-ada/schedules/SCHEDULE_ID \
-H "Authorization: Bearer $FORTLY_TOKEN" \
-H "Content-Type: application/json" \
-d '{"enabled": false}'
# Remove
curl -X DELETE https://api.fortly.com/projects/my-app-ada/schedules/SCHEDULE_ID \
-H "Authorization: Bearer $FORTLY_TOKEN"Send {"enabled": true} to resume. Both answer 204, or 404 with no such schedule.
A paused schedule does not run and its next_run_at is null. Resuming it does not run the times it missed while paused. To change a schedule's expression or path, remove it and add it again.
List schedules
curl https://api.fortly.com/projects/my-app-ada/schedules \
-H "Authorization: Bearer $FORTLY_TOKEN"Each schedule in schedules comes with next_run_at, the next time it will run in seconds since the epoch, worked out when you ask.
/ projects/ {name}/ schedulesA project's schedules, with their next run/ projects/ {name}/ schedulesAdd one — name, spec, path/ projects/ {name}/ schedules/ {id}Pause or resume/ projects/ {name}/ schedules/ {id}Remove it/ schedulesEvery schedule across the projects you can reach