> ## Documentation Index
> Fetch the complete documentation index at: https://docs.getdialed.ai/llms.txt
> Use this file to discover all available pages before exploring further.

# Schedules

> Fire a flow definition on a recurring UTC cron schedule, backed by a managed schedule

A schedule fires a [definition](/concepts/flow-definitions) on a recurring cron schedule. Each schedule is backed by a managed cron; every fire creates a normal [batch](/concepts/batches-and-executions) — visible under `GET /definitions/{definition_id}/batches` with `trigger_type: "schedule"` and a `schedule_id` linking back to the schedule that produced it. The batch and execution lifecycle is otherwise identical to a manual trigger.

```json theme={null}
{
  "id": "sched_c9beda5f",
  "definition_id": "def_a1b2c3d4",
  "description": "Refresh Five9 lists every 15 minutes",
  "cron_expression": "*/15 * * * *",
  "input_data": { "list": "prod" }
}
```

Create the schedule once; the platform re-fires it on every cron tick with no further calls from you.

## The schedule object

| Field              | Type             | Description                                                                                                                              |
| ------------------ | ---------------- | ---------------------------------------------------------------------------------------------------------------------------------------- |
| `id`               | string           | Schedule identifier (e.g. `sched_c9beda5f`).                                                                                             |
| `definition_id`    | string           | The definition to fire. Must belong to your org. **Immutable after creation** — to point at a different definition, delete and recreate. |
| `org_id`           | string           | Owning organization.                                                                                                                     |
| `description`      | string           | Human-readable description (1–200 chars).                                                                                                |
| `cron_expression`  | string           | 5-field UTC cron (e.g. `*/15 * * * *`).                                                                                                  |
| `enabled`          | boolean          | `true` fires on schedule; `false` creates or leaves the schedule paused without losing fire history.                                     |
| `input_data`       | object           | Input passed to each fired batch — the same role as a trigger's `input_data`.                                                            |
| `metadata`         | object           | Free-form metadata. Defaults to `{}`.                                                                                                    |
| `next_fire_at`     | datetime         | Computed from `cron_expression` **at read time** — never stored.                                                                         |
| `last_fired_at`    | datetime \| null | When the most recent fire occurred.                                                                                                      |
| `last_fire_status` | string \| null   | State of the most recent fire: `running`, `success`, or `failure`. Written by the worker as the fired batch progresses.                  |

<Warning>
  Cron expressions are **UTC-only and 5-field syntax only**. Six-field expressions (with seconds), aliases like `@reboot`/`@hourly`/`@daily`/`@weekly`/`@monthly`/`@yearly`, and any `timezone` / `tz` field are rejected with `422`. There is no per-schedule timezone — convert your local cadence to UTC before you set the expression.
</Warning>

## Fire policy

The fire policy is fixed and not configurable:

* **Overlap = SKIP.** If a previous fire is still running when the next cron tick arrives, that tick is **dropped, not queued** — a slow run never stacks up a backlog of overlapping fires.
* **60-second catch-up window.** Missed fires during downtime are replayed only within a 60-second window; anything older is skipped, so recovering from an outage never triggers a thundering herd of stale fires.

## Managing schedules

All management endpoints require authentication and operate only on your organization's schedules. Mutating endpoints require an admin-role caller (an `X-API-Key` is admin-equivalent).

| Method   | Endpoint                   | Purpose                                                                                                              |
| -------- | -------------------------- | -------------------------------------------------------------------------------------------------------------------- |
| `POST`   | `/schedules`               | Create a schedule and its backing cron. Returns `201`.                                                               |
| `GET`    | `/schedules`               | List your org's schedules with cursor pagination (`cursor`, `limit`), newest first.                                  |
| `GET`    | `/schedules/{schedule_id}` | Fetch one schedule; `next_fire_at` is computed at read time.                                                         |
| `PATCH`  | `/schedules/{schedule_id}` | Partial update — change the cadence, pause/resume with `enabled`, or update `input_data`. Fire history is preserved. |
| `DELETE` | `/schedules/{schedule_id}` | Remove the backing cron then the record. Returns `204`. Batches already fired are unaffected.                        |

Creating one:

```bash theme={null}
curl -X POST "$BASE_URL/schedules" \
  -H "X-API-Key: $GETDIALED_API_KEY" \
  -H "Content-Type: application/json" \
  -d '{
    "definition_id": "def_a1b2c3d4",
    "description": "Refresh Five9 lists every 15 minutes",
    "cron_expression": "*/15 * * * *",
    "input_data": { "list": "prod" }
  }'
```

<Warning>
  The target definition must be **active**. `POST /schedules` rejects a definition whose status is not `active` with `400 "Definition is not active"` — matching the manual trigger contract, so you never schedule a definition that could not be fired on demand. A missing or cross-tenant `definition_id` still returns `404` (never `403`); the active-status check runs after that ownership gate.
</Warning>

<Note>
  `PATCH` updates the backing schedule in place — a new `cron_expression` re-times future fires, and toggling `enabled` pauses or unpauses the schedule, but neither resets the fire history. `DELETE` is idempotent: if the backing cron is already gone, the record is still removed and the call returns `204`.
</Note>

<Tip>
  `next_fire_at` is derived from the cron expression every time you read the object, so it always reflects the current cadence even immediately after a `PATCH`. Poll `last_fired_at` / `last_fire_status` to confirm a schedule is firing as expected.
</Tip>

## Next steps

<CardGroup cols={2}>
  <Card title="Schedule a flow" icon="clock" href="/guides/schedule-a-flow">
    A step-by-step walkthrough: create, pause, and re-time a recurring schedule.
  </Card>

  <Card title="Batches and executions" icon="list-check" href="/concepts/batches-and-executions">
    Follow the batches each fire produces through their execution lifecycle.
  </Card>
</CardGroup>
