Three tools keep work going without you starting each run:

- **Schedules** start a run at set times.
- **Backlog** holds tasks Syndai finds for you to start.
- **Webhooks** tell your server when a run changes.

Every path below starts with `https://api.syndai.ai/api/v1/external/coding`.

## Schedules

A schedule runs a saved prompt on one project at set times. Each fire is a normal run, so it costs credits. Your key needs `coding:schedules:manage`.

```bash
curl -s -X POST https://api.syndai.ai/api/v1/external/coding/schedules \
  -H "Authorization: Bearer $SYNDAI_API_KEY" \
  -H "Content-Type: application/json" \
  -d '{
    "client_request_id": "weekly-deps-001",
    "coding_repository_id": "<REPO_ID>",
    "prompt": "Update dependencies and fix anything the upgrade breaks.",
    "trigger": {"kind": "cron", "expr": "0 9 * * 1", "timezone": "Europe/London"},
    "occurrence_budget_usd": 10
  }'
```

- `trigger` is a 5-part cron with a time zone, at most every 15 minutes. A run starts within 5 minutes of its slot.
- `client_request_id` makes the create safe to retry. A repeat answers `409` with `Location` set to the first schedule.
- `occurrence_budget_usd` caps what each fire may spend.
- `from_coding_run_id` repeats a run that went well. Leave out `prompt` and `coding_repository_id` with it.
- `skip_if_no_new_commits` is `true` unless you say so. A slot rests while the default branch has not moved.
- Scheduled runs never ask questions and never wait for a spec review.

### Spend needs a person's yes

A fire spends nothing until `schedule_paid_on` is `true`. Only an owner or admin, or a key one of them made, may turn it on. It also needs `occurrence_budget_usd`. A fire without that yes does not run.

When the workspace is out of credits, or over its monthly limit, a fire is skipped. Its summary says why, and the next slot tries again.

### Supervised or on its own

`policy_config.autonomy` on the schedule says how far each fire goes:

| `autonomy` | each fire |
|---|---|
| `auto` | opens a pull request. The next slot rests while it is open. |
| `gated` | waits up to 24 hours for approval before a pull request exists |
| `merge` | lands when every gate is green |
| `push` | moves the default branch with no pull request (API only) |

A schedule may merge only while the key or person who saved its policy still may. Revoke that key, or drop that person to member, and each fire opens a pull request instead.

### Manage it

| call | does |
|---|---|
| `GET /schedules/{id}` | the schedule and its recent fires, each with the run it started |
| `PATCH /schedules/{id}` | changes the prompt, trigger, policy or budget |
| `POST /schedules/{id}/pause` | stops the fires until you resume |
| `POST /schedules/{id}/resume` | starts again from now. Missed slots do not run. |
| `POST /schedules/{id}/run-now` | fires once now, even while paused |
| `DELETE /schedules/{id}` | deletes it |

Each call is on the [Schedules](/docs/api) reference page.

## Backlog

Syndai files tasks it finds as offers. They come from a finished run's next steps, scans for bugs, search moves and more. An offer never runs on its own.

`GET /backlog` lists the top offers. Each one has a `source`, which is an open string. Viewing and dismissing are free.

To start one, send its `id` as `backlog_task_id` when you create a run:

```bash
curl -s -X POST https://api.syndai.ai/api/v1/external/coding/runs \
  -H "Authorization: Bearer $SYNDAI_API_KEY" \
  -H "Content-Type: application/json" \
  -d '{
    "prompt": "Fix the broken link in the footer",
    "coding_repository_id": "<REPO_ID>",
    "backlog_task_id": "<OFFER_ID>",
    "external_request_id": "offer-footer-link-001"
  }'
```

To drop it for good, call `POST /backlog/{id}/dismiss`, with an optional `reason`.

### The roadmap

A person can also put an offer on the project's roadmap. These calls need a signed-in person. An API key gets `403`.

| call | does |
|---|---|
| `POST /backlog/{id}/accept` | adds it to the roadmap with the text you saw |
| `PATCH /backlog/{id}` | adds it with your own title or prompt |
| `POST /backlog/{id}/top` | adds it at the top |

The roadmap is worked from the top only when the workspace has turned on runs on its own. Otherwise it waits for you.

### Groups

One chat message can ask for 2 to 5 separate changes. Syndai files them as one group, and a part may build on an earlier part.

- `GET /backlog/groups` lists them, with each part's `status`.
- `POST /backlog/groups/{id}/start` starts every part that is ready. Later parts start as the ones they build on land. Each part is a paid run. It is a person's tap: the project agent gets `403 HUMAN_APPROVAL_REQUIRED`.
- `POST /backlog/groups/{id}/dismiss` skips the group, or one `part`. Running parts keep going.

Each call is on the [Backlog](/docs/api) reference page.

## Webhooks

A webhook sends a signed POST to your server when a run changes. Use it in place of polling. Add an endpoint with `POST /webhooks`, pick the events you want, and check every signature.

[Webhooks](/docs/api/webhooks) has the full guide: the events, the body, signatures, retries and redelivery.
