> ## 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.

# Quickstart

> From nothing to a finished, fact-checked script in four calls — and how to find out what else this host will run for you.

<Steps>
  <Step title="Get a key">
    Mint a workspace API key in the dashboard under **Settings → API keys**. A key
    is bound to one workspace and is shown once.

    ```bash theme={null}
    export SIGMORA_API_KEY=sk_live_...
    ```
  </Step>

  <Step title="Ask what this host serves, and what it costs">
    The catalogue is live: prices come from the same table the charge is taken
    from, and `available` says whether **this** deployment runs a capability or
    answers `503 capability_unavailable` and names the service that does. Reading
    it is free.

    ```bash theme={null}
    curl https://api.sigmora.org/v1/capabilities \
      -H "Authorization: Bearer $SIGMORA_API_KEY"
    ```

    ```json theme={null}
    {
      "success": true,
      "capabilities": [
        { "id": "text.script", "path": "/v1/text/script", "credits": 150, "available": true },
        { "id": "video.render", "path": "/v1/video/render", "credits": 300, "available": false,
          "servedBy": "video-curriculum",
          "unavailableReason": "Rendering runs on the video-curriculum service, not on this deployment." }
      ],
      "creditBalance": 4200,
      "billingEnabled": true
    }
    ```
  </Step>

  <Step title="Create a project">
    Every call files its output in a project, so start by making one. A project id
    belonging to another workspace answers `404`, never `403` — an id is never a
    way to test what exists elsewhere.

    ```bash theme={null}
    curl -X POST https://api.sigmora.org/v1/projects \
      -H "Authorization: Bearer $SIGMORA_API_KEY" \
      -H "Content-Type: application/json" \
      -d '{"title":"Compound interest explainer","kind":"video"}'
    ```

    ```json theme={null}
    {
      "success": true,
      "project": { "id": "prj_9x2...", "title": "Compound interest explainer", "kind": "video", "status": "active" }
    }
    ```
  </Step>

  <Step title="Run a capability">
    `text.script` watches a seed video, researches and fact-checks as it writes,
    and answers with the finished script. It is synchronous and slow by nature —
    one call can hold a model for minutes, so set a generous client timeout.

    ```bash theme={null}
    curl -X POST https://api.sigmora.org/v1/text/script \
      -H "Authorization: Bearer $SIGMORA_API_KEY" \
      -H "Content-Type: application/json" \
      -H "Idempotency-Key: quickstart-0001" \
      -d '{
        "projectId": "prj_9x2...",
        "sourceUrl": "https://www.youtube.com/watch?v=...",
        "angle": "for someone who has never invested",
        "targetDurationMinutes": 8
      }'
    ```

    ```json theme={null}
    {
      "success": true,
      "projectId": "prj_9x2...",
      "script": { "title_options": ["..."], "script": "...", "research": { "claims_checked": ["..."] } },
      "credits": 150,
      "creditBalance": 4050
    }
    ```

    `credits` is what was actually taken, not what was quoted. A call that fails —
    including one whose engine answered `200` carrying nothing usable — is free.
  </Step>
</Steps>

## Retrying safely

Send an `Idempotency-Key` on anything that spends. A retry with the same key and
the same body returns the **stored** response instead of running the work again,
so a client-side timeout on a 150-credit call cannot become two charges. The same
key with a different body answers `409 conflict` rather than a wrong result, and a
retry sent while the first call is still running answers `409` too.

## Capabilities that answer with a job

Some capabilities hand back a job id instead of a result. They all converge on one
endpoint — there is no per-capability status route to learn.

```bash theme={null}
curl https://api.sigmora.org/v1/jobs/job_4k1... \
  -H "Authorization: Bearer $SIGMORA_API_KEY"
```

Terminal states are `done` and `failed`; `awaiting_review` waits for a person and
polling will not advance it. When a job is done, `artifacts` carries URLs you fetch
**directly** — they point at the origin holding the bytes, not back through the API.

<Note>
  `api.sigmora.org` runs the text, transcript, thumbnail and music capabilities, and
  the render flows (`video.render`, `video.shorts`, `3d.*`) — the last of these are
  asynchronous and answer with a `jobId` you poll. Footage editing (`video.edit`) is
  served by another deployment and answers `503 capability_unavailable` here, with the
  owning service named in the body. Step 2 is the authority on which is which — ask it
  rather than assuming.
</Note>

## What to read next

<CardGroup cols={2}>
  <Card title="Projects" icon="folder" href="/projects">
    Grouping related work, and why an id you do not own is not an error.
  </Card>

  <Card title="Errors" icon="triangle-exclamation" href="/errors">
    The pairs that share a status code and call for opposite responses.
  </Card>
</CardGroup>
