---
title: How the API works
description: Submit a request, get a job, poll its status, fetch the result.
---
Every generation on the Sume Open API follows the same four steps, whatever the model.

```text
POST /v1/<router>/generate  →  202 + job id + status_url
GET  status_url             →  queued → processing → completed
GET  result_url             →  artifacts with download URLs
```

## 1. Pick a model

Each router lists the models it runs: [image](/docs/reference/images/list-models) and [video](/docs/reference/video/list-models). Lip-sync and captions models are on the video router. A model row says what the model accepts (aspect ratios, durations, input images) and what it costs. With an open.sume.com key, [List open models](/docs/reference/catalog/list) gives the dollar price.

## 2. Submit

Send the model id and its inputs to the router. The API checks the request, reserves the price, queues the job and answers `202` in well under a second. It does not wait for the model.

## 3. Wait

Choose how to learn the outcome with `mode`:

| `mode` | What happens |
|---|---|
| `async` (default) | You poll `status_url`. See [Polling](/docs/polling). |
| `webhook` | Sume POSTs the outcome to your `webhook_url`. See [Webhooks](/docs/webhooks). |
| `sync` / `subscribe` | The submit call itself waits up to `wait_timeout_seconds` (30 at most), then answers like `async` if the job is still running. |

## 4. Read the result

A completed job has `result.artifacts[]`. Each artifact has a `type` (`image`, `video`, `audio`), a `content_type` and a `url` on `media.sume.com`.

## The response envelope

Successful responses wrap their body in `data`. Errors use one `error` object. Every response carries an `x-sume-request-id` header; quote it when you contact support.

```json
{ "data": { "...": "..." } }
```

```json
{ "error": { "code": "not_found", "message": "API job was not found.", "request_id": "req_..." } }
```

[Errors and retries](/docs/errors) lists the codes.
