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

> ## Agent Instructions
> This site documents two API families. Choose the family before generating integration code and keep its request fields, billing, statuses, responses, and webhooks together.
> SwitchX API: POST /v1/switchx/generations; use /quickstart and /authentication. Completed generation files are under output.
> Enterprise API: POST /v1/products/{product}/jobs and GET /v1/product-jobs/{job_id}; use /enterprise/quickstart and /products. Check /enterprise for current access requirements. Completed product files are under outputs.
> For product jobs, fetch model-specific input_schema from GET /v1/products/{product}/models. OpenAPI defines the common job response; product guides show illustrative completed outputs. Do not treat output examples as exhaustive schemas.
> SwitchX 2.0 Finish uses the separate switchx_finish product and model_id switchx-2.0. Follow /products/switchx-finish: pass inputs.parent_job_id (a completed Standard switchx product generation's public dap_ ID owned by the same key owner, organization, and team) and inputs.target_resolution (1080 or 2160), without uploading media. Fast results, Finish results, and legacy SwitchX API generations cannot be parents. Estimate the transition, then submit and poll the new child ID; result files are under outputs.
> For product APIs, authenticate with an Organization API Key in x-api-key and keep the same organization and X-Beeble-Team-Id context for uploads, estimates, submissions, and reads. Use Beeble Cloud credits; product routes do not support USD.
> Follow /enterprise/llms-txt for the product API workflow: discover products and models, upload media, estimate credits, submit with an idempotency_key, and poll or receive webhooks. On an uncertain submission, retry the same body and key; do not create a replacement job.
> Product-job success is status=success; stop polling on failed, cancelled, or credit_required. Use the chosen product guide for completed response examples and download fields. Refer to /enterprise/errors, /enterprise/rate-limits, /guides/billing, and /guides/jobs for failures, limits, and refunds.

# Billing & credits

> Estimate costs, set spending caps, and track Beeble Cloud credit charges.

<span id="choose-a-payment-unit" />

## Beeble Cloud credits

Product jobs use your organization's **Beeble Cloud credits**—the same
balance used in Beeble Cloud. Where applicable, charges also count toward the
selected internal team's budget. Personal credits are never a fallback.

Product estimates and jobs default to `billing_unit: "credits"`. You can omit
this field or set it explicitly. USD is not supported on these endpoints;
sending `"usd"` returns `UNSUPPORTED_BILLING_UNIT`.

## Estimate before submitting

[Request parameters, body, and response schema](/docs/api-reference/products/estimate-a-product-job-without-creating-or-charging-it)

Call `POST /v1/products/{product}/estimate` with the same model and inputs you
plan to submit. It validates the inputs and quotes the cost without creating
a job or charging credits. No idempotency key is required.

Estimates may download HTTPS media or decode data URIs and store files for
validation. A separate submission may fetch the media again: keep presigned
URLs valid and their contents unchanged through both calls. For a stable input
that you control, [upload the file first](/docs/guides/uploads).

Use a [supported media URI](/docs/guides/uploads#choose-a-media-input) for `inputs.source`
and set `BEEBLE_API_KEY`. The examples use a Beeble upload URI; HTTPS and data
URIs go in the same field. For internal teams,
also set `BEEBLE_TEAM_ID`.

<CodeGroup>
  ```bash cURL theme={null}
  curl --fail-with-body https://api.beeble.ai/v1/products/switchx/estimate \
    -H "x-api-key: $BEEBLE_API_KEY" \
    -H "X-Beeble-Team-Id: ${BEEBLE_TEAM_ID:-}" \
    -H "Content-Type: application/json" \
    --data '{
      "model_id": "switchx-2.0",
      "inputs": {
        "source": "beeble://uploads/your-upload-id/source.mp4",
        "prompt": "Warm studio lighting",
        "alpha_mode": "fill"
      }
    }'
  ```

  ```python Python theme={null}
  import os
  import requests

  headers = {"x-api-key": os.environ["BEEBLE_API_KEY"]}
  if team_id := os.environ.get("BEEBLE_TEAM_ID"):
      headers["X-Beeble-Team-Id"] = team_id

  response = requests.post(
      "https://api.beeble.ai/v1/products/switchx/estimate",
      headers=headers,
      json={
          "model_id": "switchx-2.0",
          "inputs": {
              "source": "beeble://uploads/your-upload-id/source.mp4",
              "prompt": "Warm studio lighting",
              "alpha_mode": "fill",
          },
      },
      timeout=120,
  )
  response.raise_for_status()
  print(response.json())
  ```

  ```javascript JavaScript theme={null}
  const headers = {
    "x-api-key": process.env.BEEBLE_API_KEY,
    "Content-Type": "application/json",
  }
  if (process.env.BEEBLE_TEAM_ID)
    headers["X-Beeble-Team-Id"] = process.env.BEEBLE_TEAM_ID
  const response = await fetch(
    "https://api.beeble.ai/v1/products/switchx/estimate",
    {
      method: "POST",
      headers,
      body: JSON.stringify({
        model_id: "switchx-2.0",
        inputs: {
          source: "beeble://uploads/your-upload-id/source.mp4",
          prompt: "Warm studio lighting",
          alpha_mode: "fill",
        },
      }),
      signal: AbortSignal.timeout(120_000),
    },
  )
  if (!response.ok) throw new Error(await response.text())
  console.log(await response.json())
  ```
</CodeGroup>

**Example response (200, abbreviated; amount is illustrative):**

```json theme={null}
{
  "product": "switchx",
  "model_id": "switchx-2.0",
  "billing_unit": "credits",
  "estimated_credits": 100
}
```

Use the same organization, team, model, and inputs for the estimate and submission.
The response includes `estimated_credits` and, where available,
[source metadata](/docs/guides/uploads#source-metadata).

<span id="organization-credits" />

### Set a per-job ceiling

Set `max_credits` to cap the charge, including zero to allow no charge.
To use your estimate as the ceiling, copy `estimated_credits` into this field.
If omitted, the server uses a current quote.

An estimate reserves neither price nor credits. Submission quotes again and
checks the measured cost against the ceiling before charging.

## Charges and refunds

`credits_charged` reports the actual charge supplied by the product. A `null`
value means no actual charge has been reported; it is not zero or an estimate.

`refunded` reports the product's refund state. A `null` value means the state
is unreported. **A failed job does not prove a refund has completed.**
SwitchX product jobs currently leave `refunded` as `null`, while their normal
refund process still runs.

## Track usage

API jobs appear alongside web usage in your organization's Beeble Cloud usage
totals.

For a timed-out submission, follow [safe retries](/docs/guides/jobs#safe-retries)
before considering a new job.

<Accordion title="Existing SwitchX generations with organization keys">
  `/v1/switchx/generations` retains its USD default, including for organization
  keys. Explicit `billing_unit: "credits"` charges the bound organization's
  Beeble Cloud credits, without falling back to personal credits. USD uses the
  key owner's Developer API billing account.

  If USD billing is unavailable or its balance is insufficient, a `402`
  response may advise submitting a new request with `billing_unit: "credits"`
  and a new idempotency key. The server never switches payment units itself.
  Changing the billing unit under an existing key returns `409`.

  Legacy generation responses use `organization_id`, `billing_unit`,
  `credits_charged`, and `credit_billing_state`. Failed or cancelled credit jobs
  refund their original organization pool and team budget. `allocation_pending`
  means team budget restoration is retrying; `manual` requires support to
  reconcile an uncertain ledger operation. Poll the legacy job for the current
  state: a failure webhook does not confirm that its refund has finished.
  Product jobs use the separate `refunded` contract described above.
</Accordion>
