# Autopilots API

> Create and manage AI newsletter autopilots through the Broadcast API, trigger runs, poll their progress, and drive product update announcements from your release pipeline.

Source: https://sendbroadcast.net/docs/api-autopilots

The Autopilots API manages [autopilots](https://sendbroadcast.net/docs/autopilot) programmatically: create and configure them, activate or pause them, trigger generation runs, and poll run progress. It is particularly useful for **product update announcements**: your release pipeline can trigger an announcement draft the moment a version ships.

All endpoints are scoped to the channel of the API token you authenticate with. See [API Authentication](https://sendbroadcast.net/docs/api-authentication).

## Required Permissions

- **`autopilot_read`:** GET endpoints (list, show, runs)
- **`autopilot_write`:** POST, PATCH, DELETE endpoints (write permission also satisfies read)

## The Autopilot Object

| Field | Type | Description |
|-------|------|-------------|
| `id` | integer | Unique identifier |
| `name` | string | Name, unique per channel (required) |
| `status` | string | `inactive`, `active`, or `paused` |
| `trigger_mode` | string | `scheduled` (newsletters on a cadence) or `on_new_release` (product update announcements) |
| `last_announced_version` | string | Release-mode only: the newest version already announced or dismissed; detection only fires for newer versions |
| `ai_model` | string | Model id for the per-autopilot OpenRouter path |
| `api_key_configured` | boolean | Whether a per-autopilot OpenRouter key is stored (the key itself is never returned) |
| `schedule_frequency` | string | `daily`, `weekly`, `biweekly`, or `monthly`, in release mode this is the check cadence |
| `schedule_day_of_week` | integer | 0-6 (Sunday-Saturday), for weekly/biweekly |
| `schedule_day_of_month` | integer | 1-31, for monthly |
| `schedule_time` | string | Time of day to run/check |
| `schedule_timezone` | string | Timezone for the schedule |
| `copies_to_generate` | integer | Draft variations per run (1-5) |
| `tone_description` | string | Writing tone guidance |
| `content_instructions` | string | Content guidance for the AI |
| `newsletter_structure` | string | Optional Markdown structure template |
| `segment_ids` | array | Segments pre-filled when a copy is promoted to a broadcast; empty targets all subscribers |
| `total_runs` | integer | Lifetime run count |
| `last_run_at` / `next_run_at` | datetime | Last and next scheduled run times |
| `created_at` / `updated_at` | datetime | Timestamps |

## The Run Object

| Field | Type | Description |
|-------|------|-------------|
| `id` | integer | Unique identifier |
| `autopilot_id` | integer | Parent autopilot |
| `status` | string | `pending`, `fetching`, `analyzing`, `generating`, `review`, `completed`, `failed`, `cancelled`, or `skipped` |
| `status_reason` | string | Why a run ended early, e.g. `No new release (latest: 2.26.0)` on a skipped check |
| `trigger_type` | string | `scheduled`, `manual`, or `api` |
| `release_tag` | string | Release-mode: the version this run is announcing |
| `version_override` | string | Release-mode: the exact version a manual run was asked to announce |
| `created_at` / `updated_at` | datetime | Timestamps |

`skipped` is a normal outcome for release-mode checks, not an error: it means the check ran and found nothing new to announce.

## List Autopilots

```bash
curl -H "Authorization: Bearer YOUR_API_TOKEN" \
  "https://your-broadcast-domain.com/api/v1/autopilots?limit=10&offset=0"
```

Returns `{ "data": [...], "total": n }`, ordered by name. `limit` and `offset` are optional.

## Get Autopilot

```bash
curl -H "Authorization: Bearer YOUR_API_TOKEN" \
  "https://your-broadcast-domain.com/api/v1/autopilots/123"
```

## Create Autopilot

```bash
curl -X POST -H "Authorization: Bearer YOUR_API_TOKEN" \
  -H "Content-Type: application/json" \
  -d '{
    "autopilot": {
      "name": "Product Update Announcements",
      "trigger_mode": "on_new_release",
      "schedule_frequency": "daily",
      "copies_to_generate": 3
    }
  }' \
  "https://your-broadcast-domain.com/api/v1/autopilots"
```

Accepts every writable field from the autopilot object above (not `status`; use the lifecycle endpoints). An unknown `trigger_mode` or `schedule_frequency` returns `422`. Sources and tone samples are managed in the app, not through this API.

## Update Autopilot

```bash
curl -X PATCH -H "Authorization: Bearer YOUR_API_TOKEN" \
  -H "Content-Type: application/json" \
  -d '{"autopilot": {"trigger_mode": "on_new_release"}}' \
  "https://your-broadcast-domain.com/api/v1/autopilots/123"
```

A blank or bullet-masked `openrouter_api_key` is ignored (with a response warning) rather than overwriting a stored key, see [API Response Warnings](https://sendbroadcast.net/docs/api-response-warnings).

## Delete Autopilot

```bash
curl -X DELETE -H "Authorization: Bearer YOUR_API_TOKEN" \
  "https://your-broadcast-domain.com/api/v1/autopilots/123"
```

## Activate, Pause, Deactivate

```bash
curl -X POST -H "Authorization: Bearer YOUR_API_TOKEN" \
  "https://your-broadcast-domain.com/api/v1/autopilots/123/activate"
```

Also `.../pause` and `.../deactivate`. Activation validates prerequisites and returns `422` with the specific failures otherwise: an active source, AI access (an OpenRouter key, or in release mode the installation's system-wide AI default), and in release mode at least one release-bearing source (GitHub repository or Releases API).

## Trigger a Run

```bash
curl -X POST -H "Authorization: Bearer YOUR_API_TOKEN" \
  -H "Content-Type: application/json" \
  -d '{"version": "v2.26.0"}' \
  "https://your-broadcast-domain.com/api/v1/autopilots/123/trigger_run"
```

Returns `202 Accepted` with the created run: generation is asynchronous, so poll the runs endpoint for progress. Manual runs bypass release detection: with no body they draft the newest release (or, for scheduled-mode autopilots, generate a newsletter); with a `version` they draft that exact release, and the run fails with a clear `status_reason` if the version isn't found in any source.

This is the endpoint to call from your release pipeline: ship, `POST` the new version, and a review-ready announcement draft appears in Broadcast.

## List Runs

```bash
curl -H "Authorization: Bearer YOUR_API_TOKEN" \
  "https://your-broadcast-domain.com/api/v1/autopilots/123/runs?limit=5"
```

Returns `{ "data": [...], "total": n }`, newest first. Poll after `trigger_run` until the run reaches `review` (copies ready in the app), `skipped`, or `failed`: `status_reason` explains the latter two.

## What's Next?

- [the Autopilot guide](https://sendbroadcast.net/docs/autopilot): configuring sources, tone, and product update announcements in the app
- [API Authentication](https://sendbroadcast.net/docs/api-authentication): creating tokens and granting the autopilot permissions
- [Broadcasts API](https://sendbroadcast.net/docs/api-broadcasts): working with the broadcasts your autopilots draft
