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

# Quickstart

> Run SwitchX 2.0 and download your first result.

## Prerequisites

1. Create an [API key](/docs/enterprise/authentication) in the [Developer Portal](https://developer.beeble.ai/api-keys).
2. Confirm [SwitchX 2.0 access](/docs/products#discover-your-models) and **Beeble Cloud credits**. Complete any required consent in Beeble Cloud.
3. Prepare a source image as an [uploaded Beeble URI, authorized CDN URL, public/presigned HTTPS URL, or base64 data URI](/docs/guides/uploads#choose-a-media-input).

Set `BEEBLE_API_KEY` in your environment. If your organization uses internal teams,
set `BEEBLE_TEAM_ID`. If using an upload, use the same organization and team for
the upload and job.

<span id="using-your-own-videos" />

<span id="upload-your-image" />

<span id="try-it--one-command" />

## Submit your first job

[Request parameters, body, and response schema](/docs/api-reference/products/create-a-product-job)

Replace `inputs.source` with your media URI. The examples use an uploaded
`beeble_uri`; you can put a public/presigned HTTPS URL or a complete base64
data URI in the same field without calling `/v1/uploads`. See
[media limits and inline examples](/docs/guides/uploads#choose-a-media-input).

Save your request and keep its body and idempotency key unchanged on retries;
use a new key for each new job.

<CodeGroup>
  ```bash cURL theme={null}
  curl --fail-with-body https://api.beeble.ai/v1/products/switchx/jobs \
    -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",
      "idempotency_key": "first-switchx-001",
      "inputs": {
        "source": "beeble://uploads/your-upload-id/source.png",
        "alpha_mode": "fill",
        "max_resolution": 720,
        "prompt": "Warm studio lighting",
        "mode": "standard"
      }
    }'
  ```

  ```python Python theme={null}
  # Install: pip install requests
  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/jobs",
      headers=headers,
      json={
          "model_id": "switchx-2.0",
          "idempotency_key": "first-switchx-001",
          "inputs": {
              "source": "beeble://uploads/your-upload-id/source.png",
              "alpha_mode": "fill",
              "max_resolution": 720,
              "prompt": "Warm studio lighting",
              "mode": "standard",
          },
      },
      timeout=120,
  )
  response.raise_for_status()
  job_id = response.json()["id"]
  print(job_id)
  ```

  ```javascript JavaScript theme={null}
  // Run as a Node.js .mjs file.
  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/jobs", {
    method: "POST",
    headers,
    body: JSON.stringify({
      model_id: "switchx-2.0",
      idempotency_key: "first-switchx-001",
      inputs: {
        source: "beeble://uploads/your-upload-id/source.png",
        alpha_mode: "fill",
        max_resolution: 720,
        prompt: "Warm studio lighting",
        mode: "standard",
      },
    }),
    signal: AbortSignal.timeout(120_000),
  })
  if (!response.ok) throw new Error(await response.text())
  const { id: jobId } = await response.json()
  console.log(jobId)
  ```
</CodeGroup>

**Response (202, abbreviated):**

```json theme={null}
{
  "id": "dap_example",
  "product": "switchx",
  "model_id": "switchx-2.0",
  "status": "processing",
  "billing_unit": "credits",
  "outputs": {}
}
```

## Check Status & Download

[Request parameters and response schema](/docs/api-reference/products/get-a-product-job)

Use the returned `id` to check progress. Wait a few seconds between checks
until `success`; stop on `failed`, `cancelled`, or `credit_required`.

<CodeGroup>
  ```bash cURL theme={null}
  JOB_ID="dap_example" # Replace with the id returned above.
  curl --fail-with-body "https://api.beeble.ai/v1/product-jobs/$JOB_ID" \
    -H "x-api-key: $BEEBLE_API_KEY" \
    -H "X-Beeble-Team-Id: ${BEEBLE_TEAM_ID:-}"
  ```

  ```python Python theme={null}
  # Reuse headers and job_id from the submission example.
  status_response = requests.get(
      f"https://api.beeble.ai/v1/product-jobs/{job_id}",
      headers=headers,
      timeout=30,
  )
  status_response.raise_for_status()
  job = status_response.json()
  print(job)
  ```

  ```javascript JavaScript theme={null}
  // Reuse headers and jobId from the submission example.
  const statusResponse = await fetch(
    `https://api.beeble.ai/v1/product-jobs/${jobId}`,
    { headers, signal: AbortSignal.timeout(30_000) },
  )
  if (!statusResponse.ok) throw new Error(await statusResponse.text())
  const job = await statusResponse.json()
  console.log(job)
  ```
</CodeGroup>

**Example response (200, success; abbreviated):** URLs are illustrative.

```json theme={null}
{
  "id": "dap_example",
  "product": "switchx",
  "model_id": "switchx-2.0",
  "status": "success",
  "outputs": {
    "render": "https://cdn.beeble.ai/.../render.png",
    "source": "https://cdn.beeble.ai/.../source.png",
    "alpha": null
  }
}
```

Once the job succeeds, download `outputs.render`:

<CodeGroup>
  ```bash cURL theme={null}
  RENDER_URL="https://cdn.beeble.ai/.../render.png" # Use outputs.render from your job.
  curl --fail-with-body --output output.png "$RENDER_URL"
  ```

  ```python Python theme={null}
  if job["status"] != "success":
      raise RuntimeError(f"Job is not successful: {job['status']}")
  with requests.get(job["outputs"]["render"], stream=True, timeout=60) as download:
      download.raise_for_status()
      with open("output.png", "wb") as target:
          for chunk in download.iter_content(chunk_size=1024 * 1024):
              target.write(chunk)
  ```

  ```javascript JavaScript theme={null}
  import { writeFile } from "node:fs/promises"

  if (job.status !== "success")
    throw new Error(`Job is not successful: ${job.status}`)
  const download = await fetch(job.outputs.render, {
    signal: AbortSignal.timeout(60_000),
  })
  if (!download.ok) throw new Error(await download.text())
  await writeFile("output.png", Buffer.from(await download.arrayBuffer()))
  ```
</CodeGroup>

<span id="complete-script" />

<span id="alpha-modes" />

The example relights the whole frame with `fill`, so `outputs.alpha` is `null`.
For foreground masks and video controls, see [SwitchX](/docs/products/switchx).

## Next steps

* [Billing & credits](/docs/guides/billing): estimate costs and set a spending cap.
* [Jobs & retries](/docs/guides/jobs): automate polling and handle timeouts safely.
* [Webhooks](/docs/enterprise/webhooks): receive completion notifications.
