Schedules
A schedule starts a flow at a recurring cadence or a selected time. Use it for periodic ingestion, daily reporting, or time-based application work. For an external system deciding when to run, use a direct run or an event sensor.
On this page
Create a scheduleSchedule modesCatch-up behaviorPause, resume, and triggerMonitor executionCommon problemsA schedule identifies a registered flow_name and flow_version, with an optional deployment and environment. It stores default parameters and exposes the next run and most recent trigger result. Full fields are in the OpenAPI reference.
Create a schedule
You need a deployed flow and schedules.write. API keys creating schedules also need runs.trigger; a key listing them needs both schedules.read and runs.read. See scope compatibility.
curl --fail-with-body -X POST "$DAGY_API_URL/schedules" \
-H "Authorization: Bearer $DAGY_TOKEN" \
-H "Content-Type: application/json" \
-d '{
"flow_name": "orders_daily",
"flow_version": "1",
"deployment_name": "orders-develop",
"environment": "develop",
"mode": "cron",
"cron_expression": "0 6 * * *",
"timezone": "UTC",
"catchup_policy": "none",
"enabled": true,
"parameters": {"region": "eu"},
"description": "Refresh orders each morning"
}'Save the returned schedule_id. POST /schedules also updates an existing schedule when you supply its ID. Use a deployment and version that correspond to the same flow. Set timezone explicitly: the request default is America/New_York, not UTC.
Schedule modes
| Mode | Required setting | Behavior |
|---|---|---|
cron | cron_expression | Five-field minute/hour/day/month/weekday expression in the schedule timezone. |
interval | Positive interval_seconds | Recurs at the interval; the first occurrence can be immediately due unless start_at is in the future. |
one_time | one_time_at ISO 8601 timestamp | One automatic occurrence; no next automatic occurrence after triggering. |
manual | No cadence field | Stores parameters and identity for explicit triggering only. |
An interval example replaces the cron settings with:
{"mode":"interval","interval_seconds":3600,"timezone":"UTC"}A one-time example uses:
{"mode":"one_time","one_time_at":"2026-12-01T09:00:00Z","timezone":"UTC"}These are mode-specific fragments; also supply flow_name and flow_version in the complete request. Optional start_at and end_at constrain the active window; start_at must not exceed end_at. Use timestamps with Z or an explicit offset to avoid ambiguity.
Cron supports numeric values, *, lists, ranges, and steps, such as */15 * * * *. Sunday can be 0 or 7. Do not use seconds, a year field, or named months/weekdays. The next occurrence must be resolvable within two years. In timezones with daylight saving, nonexistent spring-forward times are skipped and the repeated fall-back occurrence fires once.
Catch-up behavior
catchup_policy: "none" advances from current time after a trigger; missed occurrences are not replayed. "all" advances from the previous due occurrence and can work through missed occurrences. This is not a guarantee that all missed runs launch simultaneously. Use backfill when you want an explicit preview, historical window, and concurrency setting.
The scheduler evaluates due work periodically. An interval measured in seconds is not a precision timer or a guaranteed subsecond launch service.
Pause, resume, and trigger
| Operation | Request/query | Result |
|---|---|---|
GET /schedules | Optional flow_name, mode, enabled, positive limit (default 100) | items; no continuation token. |
GET /schedules/{id} | None | Current definition and runtime status. |
PATCH /schedules/{id} | Only supplied non-null fields | Updated schedule. |
POST /schedules/{id}/trigger | {"parameters":{}} | A newly submitted run. Requires runs.trigger. |
Pause with PATCH {"enabled":false} and resume with PATCH {"enabled":true}. A partial update can change timezone, catch-up policy, cadence settings, window, parameters, description, and environment. mode cannot be changed through PATCH; submit the full definition with its schedule_id to change mode. Null fields are ignored rather than cleared. There is no schedule-delete endpoint; pause a schedule to stop future automatic triggers.
A manual trigger works independently of automatic enabled state. Its supplied parameters override matching saved parameters and preserve other saved parameters. It also updates schedule runtime fields and computes the next occurrence, so it can affect the schedule's next due time.
Monitor execution
Inspect next_run_at / next_run_epoch, last_triggered_at, last_run_id, last_run_slug, and last_error. Follow last_run_id through the runs API; a recorded trigger does not establish successful completion.
Keep schedules aligned when changing deployment versions. If you need a precise historical version or environment, verify both the schedule and the deployment that it references before triggering.
Common problems
| Symptom | Resolution |
|---|---|
422 on creation | Check required mode field, positive interval, five-field cron, valid IANA timezone, and timestamp order. |
403 for a scoped key | Include the additional scheduling compatibility scope. |
| No next run | Check enabled, mode, end time, and whether a one-time schedule already fired. |
| Run occurs at unexpected local time | Read the saved timezone; omitted timezone defaults to America/New_York. |
| Schedule shows a recent trigger but data is stale | Inspect the run status, task errors, and logs. |
| Promoted deployment has no automatic runs | Create or update a schedule for the target; a copied schedule string alone is not enough. |