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

# Runs lifecycle

> Submit a run, receive run_id, poll until succeeded, read output.

## Why `run_id` (not `task_id`)?

apisale's core object is a **Run** — one inference job for a model slug. The public JSON field is **`run_id`** (snake\_case).

| apisale                 | Similar products                 |
| ----------------------- | -------------------------------- |
| `run_id`                | Pollo `taskId`, fal `request_id` |
| `GET /v1/runs/{run_id}` | Poll task status                 |
| `status: queued`        | waiting / pending                |

We use **run** consistently in URLs (`/v1/run/...`, `/v1/runs/...`), Console, and webhooks.

## 1. Submit

```http theme={null}
POST /v1/run/{model_slug}
Authorization: Key YOUR_API_KEY
```

<ResponseField name="run_id" type="string" required>
  Unique run identifier, e.g. `run_0192a1b2-...`. **Save this** to poll or correlate webhooks.
</ResponseField>

<ResponseField name="status" type="string" required>
  Initial status: `queued` (async) or `processing` / `succeeded` (sync).
</ResponseField>

<ResponseField name="output" type="object">
  `null` until `status` is `succeeded`. On sync runs, may contain the final payload immediately.
</ResponseField>

### Example (async submit)

```json theme={null}
{
  "run_id": "run_550e8400-e29b-41d4-a716-446655440000",
  "endpoint": "google/nano-banana/text-to-image",
  "model": "nano-banana",
  "capability": "image",
  "mode": "text-to-image",
  "status": "queued",
  "output": null,
  "error": null,
  "billing": null,
  "created_at": "2026-06-27T12:00:00.000Z",
  "started_at": null,
  "completed_at": null,
  "elapsed_ms": null
}
```

## 2. Poll status

```http theme={null}
GET /v1/runs/{run_id}
Authorization: Key YOUR_API_KEY
```

| `status`     | Meaning                                                 |
| ------------ | ------------------------------------------------------- |
| `queued`     | Waiting for a worker slot                               |
| `processing` | Provider is generating                                  |
| `succeeded`  | Done — read `output`                                    |
| `failed`     | See `error.message`                                     |
| `timeout`    | Exceeded time limit                                     |
| `cancelled`  | System cancelled (e.g. concurrency limit hit at submit) |

Poll every **2–5 seconds** until terminal state, or use [webhooks](/get-started/webhooks).

## 3. Success output

When `status` is `succeeded`, `output` shape depends on the model (see each model page **Output schema**). Common patterns:

```json theme={null}
{
  "run_id": "run_550e8400-e29b-41d4-a716-446655440000",
  "status": "succeeded",
  "output": {
    "images": [
      { "url": "https://cdn.example.com/result.png", "mime": "image/png" }
    ]
  },
  "billing": { "amount": "0.031200", "currency": "usd" },
  "completed_at": "2026-06-27T12:00:42.000Z",
  "elapsed_ms": 42000
}
```

## 4. Optional webhook

Pass `webhook_url` on submit to receive the same Run JSON when the run reaches a terminal state.

## Related

* [Submit a run](/model-apis/submit-run)
* [Poll runs](/model-apis/poll-runs)
* [Account API](/get-started/account-and-monitoring) — balance & concurrency with the same key
