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

# Content autopilot

> Run the durable trend → voice → video → platform adaptation → distribution workflow, with approvals, checkpoints, caps, and retries.

## Configure one channel

```bash theme={null}
curl -X PUT "https://api.sigmora.org/v1/autopilots/$CHANNEL_ID" \
  -H "Authorization: Bearer $SIGMORA_API_KEY" \
  -H "Content-Type: application/json" \
  -d '{
    "enabled": true,
    "mode": "review_first",
    "runIntervalMinutes": 1440,
    "timezone": "Africa/Nairobi",
    "quietHours": { "start": "22:00", "end": "07:00" },
    "caps": {
      "maxVideosPerDay": 3,
      "maxPostsPerDay": 12,
      "maxSpendUsdPerRun": 25
    },
    "destinations": [
      {
        "platform": "youtube",
        "productId": "ACME",
        "productTargetId": "youtube-main"
      },
      {
        "platform": "tiktok",
        "productId": "ACME",
        "productTargetId": "tiktok-main"
      }
    ]
  }'
```

The destination ids refer to the existing marketing publish targets and
credentials. An empty destination list is valid: the run generates the asset
and stops without pretending it posted anywhere.

Autonomy modes:

* `draft_only` researches and writes, then asks before rendering;
* `review_first` renders and adapts, then asks before distribution;
* `full_auto` runs through scheduling, subject to caps and quiet hours.

Every mode still runs the script fact-check gate and channel rails.
`full_auto` removes the ordinary human approval checkpoint; it does not turn a
non-publishable fact-check result into an approved asset.

The configuration response includes `creditQuote`, so a dashboard or API client
can show the exact maximum reservation before activation. The quote is assembled
from the same canonical operations used by first-party workflows:

| Line                                           |            Credits |
| ---------------------------------------------- | -----------------: |
| Trend/topic research                           |                 10 |
| Voice-matched script                           |                100 |
| Generated video                                |                300 |
| Edit supplied footage instead of generating    |                150 |
| Distribution research, when destinations exist |                 10 |
| Platform-native adaptation                     | 15 per destination |

For example, a generated video with no destinations quotes 410 credits. Sending
it to YouTube and TikTok quotes 450. Supplying source clips changes the video
line from 300 to 150.

## Start the complete workflow

```bash theme={null}
curl -X POST https://api.sigmora.org/v1/autopilot-runs \
  -H "Authorization: Bearer $SIGMORA_API_KEY" \
  -H "Idempotency-Key: launch-2026-07-30-finance-01" \
  -H "Content-Type: application/json" \
  -d '{ "channelId": "'"$CHANNEL_ID"'" }'
```

When no topic or trend id is supplied, Sigmora selects the highest-ranked
observed trend matching the channel's primary theme. You can instead send a
specific `trendId` from `GET /v1/trends`, or a manual `topic`.

The endpoint returns `202` and a durable run id. The run then:

1. selects and stores the trend evidence;
2. performs topic research using the configured research providers;
3. writes in the channel voice and applies eligible product rails;
4. edits supplied clips, or generates a narrated faceless video when no clips
   were supplied;
5. waits for the generated video URL before distribution;
6. writes a distinct platform-native caption and hook for every destination;
7. carries the resolved media URL into each queued post;
8. schedules each destination and records publish/measurement join keys.

`Idempotency-Key` is required. Repeating the same request returns the same run;
reusing the key for different input returns `409 conflict`.

## Metering and settlement

Before `POST /v1/autopilot-runs` returns `202`, Sigmora atomically reserves the
whole `creditQuote.totalCredits` from the workspace wallet. If the balance
cannot fund the quote, no run is created and the API returns:

```json theme={null}
{
  "success": false,
  "code": "insufficient_credits",
  "error": "Autopilot requires 410 credits; this workspace has 120.",
  "details": { "required": 410, "available": 120 }
}
```

The run's `billing` object is the audit record. It contains every quote line,
reservation and refund reference, balance after reservation and settlement,
and aggregate reserved, spent, and refunded credits.

Settlement follows delivered value:

* a completed metered step consumes its quoted line;
* skipped, gated, failed, or never-started lines are refunded;
* a failed/capped run that produced no script, video, or platform adaptation
  receives a full refund;
* when a usable deliverable exists, only its completed lines remain charged;
* an approval keeps the original reservation and does not debit again;
* a retry creates a new, separately idempotent billing attempt;
* replaying the original `Idempotency-Key` never creates another reservation.

Wallet debit and refund references are transactionally idempotent. A scheduled
reconciler retries any terminal settlement whose refund provider failed, while
the run exposes `billing.status: "refund_failed"` until the wallet agrees.

## Observe, approve, and recover

```text theme={null}
GET  /v1/autopilot-runs/{runId}
POST /v1/autopilot-runs/{runId}/approve
POST /v1/autopilot-runs/{runId}/retry
```

The run resource contains its current phase, every observed step, generated
video and publishing ids, selected trend, pending approval, billing quote and
settlement, spend estimate, and failure detail.

Approval resumes the same checkpointed engine run. Retry is accepted only for a
failed or capped run and also resumes from its checkpoint, so completed paid
steps are not repeated.

Approvals have an SLA. The default holds; configurations may auto-approve or
discard after the chosen interval. Any approval older than seven days is
rejected as a hard backstop.

Enabled autopilots are queued by the scheduled discovery tick when their
`runIntervalMinutes` has elapsed.
