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

# Pricing & credits

> How credits work, how to read live prices, how to get a quote before you spend, and how to track usage.

Capabilities are priced in **credits**, drawn from your workspace balance. Reading
and managing records — projects, Brands, campaigns, jobs, themes, usage — is
free; generating something costs credits. Buy credits and choose a plan on the
[pricing page](https://sigmora.org/en#pricing).

## Read live prices

`GET /v1/capabilities` returns every capability with its current price, whether
it can run right now, and your balance. Prices come from the same table charges
are taken from, so the catalogue and your bill always agree. Reading it is free.

<CodeGroup>
  ```bash cURL theme={"theme":{"light":"github-light-default","dark":"github-dark-default"}}
  curl https://api.sigmora.org/v1/capabilities \
    -H "Authorization: Bearer $SIGMORA_API_KEY"
  ```

  ```python Python theme={"theme":{"light":"github-light-default","dark":"github-dark-default"}}
  import os
  import requests

  catalogue = requests.get(
      "https://api.sigmora.org/v1/capabilities",
      headers={"Authorization": f"Bearer {os.environ['SIGMORA_API_KEY']}"},
      timeout=30,
  ).json()
  prices = {c["id"]: c["credits"] for c in catalogue["capabilities"]}
  print(prices["video.render"], "credits per render; balance", catalogue["creditBalance"])
  ```

  ```typescript TypeScript theme={"theme":{"light":"github-light-default","dark":"github-dark-default"}}
  const catalogue = await fetch("https://api.sigmora.org/v1/capabilities", {
    headers: { Authorization: `Bearer ${process.env.SIGMORA_API_KEY}` },
  }).then((r) => r.json());
  const prices = Object.fromEntries(catalogue.capabilities.map((c: any) => [c.id, c.credits]));
  console.log(prices["video.render"], "credits per render; balance", catalogue.creditBalance);
  ```
</CodeGroup>

Each entry carries `id`, `method`, `path`, `credits`, `available`, and — for
capabilities that return a job — `async: true`. Some capabilities are priced per
unit, such as per language-minute for translation or per output for footage
edits; the price is per unit and the response reports the units counted.

## What a call costs

Every paid response reports what happened to your balance:

```json theme={"theme":{"light":"github-light-default","dark":"github-dark-default"}}
{
  "success": true,
  "projectId": "prj_9x2a4c",
  "credits": 150,
  "creditBalance": 4050
}
```

* `credits` is what was **actually charged**, not what was quoted.
* `creditBalance` is your balance afterwards.
* A call that fails before producing a usable result is **free**.
* An async job that ends `failed`, `cancelled` or `qa_failed` after being charged
  is **refunded**.
* Retrying with the same `Idempotency-Key` replays the first response and never
  charges twice. See [Errors](/errors#retrying-safely-with-idempotency-keys).

## When you cannot spend

| Status | `code` | What it means |
| - | - | - |
| `402` | `insufficient_credits` | The balance is below the price. `details` carries `required` and `available`. Top up, then retry. |
| `402` | `budget_capped` | A budget policy set by your workspace caps this user or team. Topping up does not help; an owner must raise the budget. |

The balance check accounts for work already in flight, so parallel calls cannot
all spend the same remaining credits.

## Get a quote before you run

Operations that list the `x-sigmora-quote-only` and `x-sigmora-max-credits`
headers in the API reference — currently the UGC Studio frame, animation and AI
creator operations — support a two-step quote and run:

1. Send the request with `x-sigmora-quote-only: 1`. Nothing runs and nothing is
   charged; the response carries a `quote` with `credits`, `balance`,
   `sufficient` and `budgetCapped`.
2. Show the price, then send the same request with
   `x-sigmora-max-credits` set to the price you accepted. If the live price has
   risen above it, the call is refused with `400 invalid_request` before any work
   starts, nothing is charged, and `details` carries `required` and `maxCredits`.
   Quote again and confirm the new price.

`POST /v1/video/footage` takes the same two steps as body fields instead:
`quoteOnly: true`, then `maxCredits`. A live price above `maxCredits` is refused
with `409 conflict`, the response carries the new quote, and nothing is charged.

<CodeGroup>
  ```bash cURL theme={"theme":{"light":"github-light-default","dark":"github-dark-default"}}
  curl -X POST https://api.sigmora.org/v1/video/ugc/frame \
    -H "Authorization: Bearer $SIGMORA_API_KEY" \
    -H "Content-Type: application/json" \
    -H "Idempotency-Key: ugc-frame-pocketledger-001" \
    -H "x-sigmora-quote-only: 1" \
    -d '{
      "projectId": "prj_9x2a4c",
      "presenter": "catalog:maya-fitness:cafe",
      "productImage": "https://cdn.example.com/products/pocketledger-phone.png",
      "instruction": "Holding the phone toward the camera at a cafe table, smiling.",
      "format": "product-in-hands",
      "productRights": true,
      "likenessConsent": true
    }'
  ```

  ```python Python theme={"theme":{"light":"github-light-default","dark":"github-dark-default"}}
  import os
  import requests

  url = "https://api.sigmora.org/v1/video/ugc/frame"
  headers = {
      "Authorization": f"Bearer {os.environ['SIGMORA_API_KEY']}",
      "Idempotency-Key": "ugc-frame-pocketledger-001",
  }
  body = {
      "projectId": "prj_9x2a4c",
      "presenter": "catalog:maya-fitness:cafe",
      "productImage": "https://cdn.example.com/products/pocketledger-phone.png",
      "instruction": "Holding the phone toward the camera at a cafe table, smiling.",
      "format": "product-in-hands",
      "productRights": True,
      "likenessConsent": True,
  }

  quote = requests.post(url, headers={**headers, "x-sigmora-quote-only": "1"}, json=body, timeout=60).json()["quote"]
  if quote["sufficient"]:  # after the user accepts quote["credits"]
      frame = requests.post(
          url, headers={**headers, "x-sigmora-max-credits": str(quote["credits"])}, json=body, timeout=300
      ).json()
  ```

  ```typescript TypeScript theme={"theme":{"light":"github-light-default","dark":"github-dark-default"}}
  const url = "https://api.sigmora.org/v1/video/ugc/frame";
  const headers = {
    Authorization: `Bearer ${process.env.SIGMORA_API_KEY}`,
    "Content-Type": "application/json",
    "Idempotency-Key": "ugc-frame-pocketledger-001",
  };
  const body = JSON.stringify({
    projectId: "prj_9x2a4c",
    presenter: "catalog:maya-fitness:cafe",
    productImage: "https://cdn.example.com/products/pocketledger-phone.png",
    instruction: "Holding the phone toward the camera at a cafe table, smiling.",
    format: "product-in-hands",
    productRights: true,
    likenessConsent: true,
  });

  const { quote } = await fetch(url, {
    method: "POST",
    headers: { ...headers, "x-sigmora-quote-only": "1" },
    body,
  }).then((r) => r.json());

  if (quote.sufficient) {
    // after the user accepts quote.credits
    const frame = await fetch(url, {
      method: "POST",
      headers: { ...headers, "x-sigmora-max-credits": String(quote.credits) },
      body,
    }).then((r) => r.json());
  }
  ```
</CodeGroup>

A quote does not use your idempotency key, so the run that follows it is the
first real call with that key.

Over MCP and in ChatGPT, priced tools follow the same pattern with a
`maxCredits` argument: a call without it returns a quote and runs nothing. See
[Sigmora in ChatGPT](/chatgpt#price-first-then-run).

## Workflows that reserve credits

Some multi-step workflows quote their maximum cost up front and reserve it before
they start. A [content autopilot](/autopilot#metering-and-settlement) run, for
example, reserves its whole `creditQuote` when it is accepted and refunds every
step it does not complete. [Variation batches](/projects#variations-of-a-proven-format)
and paid work proposed by Sigma return a quote you approve before anything runs.

## Track usage

`GET /v1/usage` reports calls, errors and credits by capability, by key and by
day. It defaults to the last 30 days and accepts `from` and `to` dates
(`YYYY-MM-DD`). Any key can read it, including keys that cannot spend.

<CodeGroup>
  ```bash cURL theme={"theme":{"light":"github-light-default","dark":"github-dark-default"}}
  curl "https://api.sigmora.org/v1/usage?from=2026-09-01&to=2026-09-30" \
    -H "Authorization: Bearer $SIGMORA_API_KEY"
  ```

  ```python Python theme={"theme":{"light":"github-light-default","dark":"github-dark-default"}}
  usage = requests.get(
      "https://api.sigmora.org/v1/usage",
      headers={"Authorization": f"Bearer {os.environ['SIGMORA_API_KEY']}"},
      params={"from": "2026-09-01", "to": "2026-09-30"},
      timeout=30,
  ).json()
  print(usage["totals"])
  ```

  ```typescript TypeScript theme={"theme":{"light":"github-light-default","dark":"github-dark-default"}}
  const usage = await fetch("https://api.sigmora.org/v1/usage?from=2026-09-01&to=2026-09-30", {
    headers: { Authorization: `Bearer ${process.env.SIGMORA_API_KEY}` },
  }).then((r) => r.json());
  console.log(usage.totals);
  ```
</CodeGroup>

```json Response theme={"theme":{"light":"github-light-default","dark":"github-dark-default"}}
{
  "success": true,
  "from": "2026-09-01",
  "to": "2026-09-30",
  "totals": { "calls": 412, "errors": 6, "credits": 18350 },
  "byCapability": [{ "name": "video.render", "calls": 41, "errors": 1, "credits": 12000 }],
  "byKey": [{ "name": "key_3f9a", "calls": 412, "errors": 6, "credits": 18350 }],
  "byDate": [{ "name": "2026-09-01", "calls": 12, "errors": 0, "credits": 600 }],
  "creditBalance": 4050
}
```


This documentation is built and hosted on [Mintlify](https://mintlify.com), a developer documentation platform.