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

# Schedules

> Scheduled task execution with cron patterns, timezone support, one-off scheduling, pg_cron integration, and run history tracking.

# Schedules

The scheduling system enables time-based automation on CRAFT. Schedules are managed by the **Utils** service (port 8000) and support both recurring cron-based schedules and one-off timed executions. When a schedule triggers, it publishes a notification to a configured topic, which downstream systems (such as workflow orchestrators) can consume.

<Info>
  Schedules use **pg\_cron** for reliable execution. Cron jobs run inside PostgreSQL, ensuring schedule triggers survive application restarts and are executed exactly by the database scheduler.
</Info>

## Schedule Types

<Tabs>
  <Tab title="Cron Schedule">
    Recurring schedules defined using standard cron expressions with timezone support.

    ```json theme={null}
    {
      "type": "cron",
      "cron": "0 9 * * 1-5",
      "timezone": "America/New_York"
    }
    ```

    The cron expression above triggers at 9:00 AM Eastern Time, Monday through Friday. Internally, the expression is converted to UTC for storage and execution, then converted back to the original timezone for display.

    **Cron expression format:**

    ```
    ┌───────── minute (0-59)
    │ ┌─────── hour (0-23)
    │ │ ┌───── day of month (1-31)
    │ │ │ ┌─── month (1-12)
    │ │ │ │ ┌─ day of week (0-7, 0 and 7 are Sunday)
    │ │ │ │ │
    * * * * *
    ```
  </Tab>

  <Tab title="One-Off Schedule">
    Single-execution schedules that trigger at a specific date and time.

    ```json theme={null}
    {
      "type": "one_off",
      "at": "2026-06-15T14:30:00",
      "timezone": "Europe/London"
    }
    ```

    The datetime must be:

    * **Timezone-naive** (no `Z` or offset suffix) -- the `timezone` field specifies interpretation
    * **Minute-precision** -- seconds and microseconds must be zero (pg\_cron limitation)
  </Tab>
</Tabs>

## Notification Configuration

When a schedule triggers, it publishes a notification. Currently, the `NOTIFICATION` config type is supported:

```json theme={null}
{
  "type": "NOTIFICATION",
  "topic": "data-readiness.workflow.run",
  "extra_data": {
    "workflow_config_id": "wf-abc123",
    "environment": "production"
  }
}
```

| Field        | Description                                                            |
| ------------ | ---------------------------------------------------------------------- |
| `topic`      | Topic string for the notification (consumed by workflow orchestrators) |
| `extra_data` | Optional JSON payload included in the notification                     |

## Schedule Lifecycle

<Steps>
  <Step title="Create Schedule">
    Create a schedule with a name, schedule configuration (cron or one-off), a reference ID linking to the target resource, and a notification config.

    Schedules can be created in an enabled or disabled state.
  </Step>

  <Step title="Enable/Disable">
    Enabling a schedule registers it with pg\_cron. Disabling unschedules it. Both operations are idempotent.
  </Step>

  <Step title="Execution">
    When pg\_cron fires, a schedule run record is created with a snapshot of the schedule configuration at execution time. The notification is published to the configured topic.
  </Step>

  <Step title="Monitor Runs">
    Query the runs API to view execution history, including status (PENDING, SUCCESS, FAILURE) and failure reasons.
  </Step>
</Steps>

## API Reference

All endpoints are scoped to the authenticated user's organization. The `X-Project-ID` header optionally filters schedules by project.

<AccordionGroup>
  <Accordion title="POST /utils/schedules" icon="plus">
    Creates a new schedule.

    **Access:** `can_manage_projects` on the organization.

    ```json Request Body theme={null}
    {
      "schedule_name": "Daily Analytics Refresh",
      "schedule": {
        "type": "cron",
        "cron": "0 6 * * *",
        "timezone": "America/Chicago"
      },
      "reference_id": "wf-config-analytics-daily",
      "config": {
        "type": "NOTIFICATION",
        "topic": "data-readiness.workflow.run",
        "extra_data": {
          "workflow_config_id": "wf-config-analytics-daily"
        }
      },
      "enabled": true
    }
    ```

    ```json Response (201 Created) theme={null}
    {
      "schedule_id": "sch-a1b2c3d4"
    }
    ```
  </Accordion>

  <Accordion title="GET /utils/schedules" icon="list">
    Lists all schedules in the organization. Optionally filter by project via the `X-Project-ID` header.

    Schedule values are returned in their original timezone for user-friendly display.
  </Accordion>

  <Accordion title="GET /utils/schedules/{schedule_id}" icon="eye">
    Retrieves a single schedule by ID. Must belong to the authenticated user's organization.
  </Accordion>

  <Accordion title="PUT /utils/schedules/{schedule_id}" icon="pen">
    Full update of a schedule. All fields are required (this is not a partial update).
  </Accordion>

  <Accordion title="PATCH /utils/schedules/{schedule_id}/enable" icon="play">
    Enables a schedule and registers it with pg\_cron. Idempotent if already enabled.
  </Accordion>

  <Accordion title="PATCH /utils/schedules/{schedule_id}/disable" icon="pause">
    Disables a schedule and unschedules it from pg\_cron. Idempotent if already disabled.
  </Accordion>

  <Accordion title="DELETE /utils/schedules/{schedule_id}" icon="trash">
    Permanently deletes a schedule. This action cannot be undone.
  </Accordion>
</AccordionGroup>

### Schedule Runs

<AccordionGroup>
  <Accordion title="GET /utils/schedules/runs" icon="clock-rotate-left">
    Lists schedule runs with pagination.

    **Query Parameters:**

    * `page`, `limit` -- Pagination (default: page 1, 20 per page)
    * `order` -- Sort by `created_at`: `desc` (most recent first) or `asc`
    * `schedule_id` -- Filter runs for a specific schedule

    ```json Response theme={null}
    {
      "data": [
        {
          "id": "run-x1y2z3",
          "schedule_id": "sch-a1b2c3d4",
          "organization_id": "acme-corp",
          "project_id": "analytics-prod",
          "status": "SUCCESS",
          "failure_reason": null,
          "created_at": "2026-04-03T06:00:00Z"
        }
      ],
      "pagination": {
        "page": 1,
        "limit": 20,
        "total": 42,
        "total_pages": 3
      }
    }
    ```
  </Accordion>

  <Accordion title="GET /utils/schedules/runs/{run_id}" icon="eye">
    Retrieves a single run with its full schedule snapshot -- the exact schedule configuration at the time of execution.
  </Accordion>

  <Accordion title="DELETE /utils/schedules/runs/{run_id}" icon="trash">
    Deletes a single schedule run record.
  </Accordion>
</AccordionGroup>

## Timezone Handling

Timezone support is a first-class feature of the scheduling system:

<AccordionGroup>
  <Accordion title="Storage">
    All cron expressions and one-off datetimes are converted to **UTC** before storage. The original timezone name is preserved alongside the expression.
  </Accordion>

  <Accordion title="Display">
    API responses dynamically convert UTC values back to the original timezone. A cron expression stored as `0 11 * * *` (UTC) for a schedule created with timezone `America/New_York` is returned as `0 6 * * *` (EST) or `0 7 * * *` (EDT) depending on the current DST status.
  </Accordion>

  <Accordion title="Validation">
    Timezone values are validated against the IANA timezone database (e.g., `America/New_York`, `Europe/London`, `Asia/Tokyo`). Invalid timezone names are rejected with a descriptive error.
  </Accordion>
</AccordionGroup>

<Tip>
  Always use IANA timezone names (e.g., `America/New_York`) rather than fixed offsets (e.g., `UTC-5`). IANA names automatically handle daylight saving time transitions.
</Tip>

## Next Steps

<CardGroup cols={2}>
  <Card title="Webhooks" icon="webhook" href="/platform/webhooks">
    Trigger actions via event-driven webhooks.
  </Card>

  <Card title="Data Connections" icon="database" href="/platform/data-connections">
    Connect schedules to data source workflows.
  </Card>

  <Card title="Agent Registry" icon="robot" href="/platform/agents">
    Schedule automated agent tasks.
  </Card>

  <Card title="Projects" icon="folder" href="/platform/projects">
    Understand how schedules are scoped to projects.
  </Card>
</CardGroup>
