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

# Generation lifecycle

> How a generation moves from queued to processing to succeeded or failed, how to learn when it finishes by polling or webhook, and how to read its outputs.

A **generation** is one request to a model: you send a model's slug and its `input`, and the model produces one or more **outputs**. Every generation is asynchronous. `POST /generations` returns at once with `202 Accepted` and the generation, `queued`; the model then works in the background.

## States

```mermaid theme={null}
stateDiagram-v2
  direction LR
  [*] --> queued
  queued --> processing
  queued --> failed
  processing --> succeeded
  processing --> failed
  succeeded --> [*]
  failed --> [*]
```

| `status` | Meaning |
| - | - |
| `queued` | Accepted and waiting to start. |
| `processing` | The model is working on it. `started_at` is set. |
| `succeeded` | Finished with at least one output. `outputs` lists them and `cost.amount` is the final cost. |
| `failed` | Finished without outputs. `error` says why, and it costs nothing. |

`succeeded` and `failed` are **terminal**: once a generation reaches one, its status, outputs and cost never change. `completed_at` is set at the same time.

A generation fails for any reason it cannot finish: the model rejected the content, the model was unavailable or failed, it timed out, or something went wrong on Codzen's side. The `error.code` tells them apart; see [Errors](https://docs.codzen.ai/guides/errors.md).

> [!WARNING]
>
> New `status` values may be added in future. Treat any value other than `succeeded` or `failed` as not finished yet, rather than as an error.

## Learn when it finishes

Pick one of two ways:

* **Poll** `GET /generations/{id}` until `status` is `succeeded` or `failed`. This is the simplest choice and needs no public endpoint. Poll every few seconds: a generation usually takes from seconds to minutes, depending on the model and its input. Each poll counts toward your [rate limit](https://docs.codzen.ai/guides/authentication.md#rate-limits).
* **Webhook**: pass `webhook_url` when you create the generation, and Codzen sends you the finished generation once it reaches a terminal state. See [Webhooks and signatures](https://docs.codzen.ai/guides/webhooks.md).

You can combine them, for example a webhook with an occasional poll as a fallback for generations whose webhook you have not received.

```javascript Node theme={null}
async function waitForGeneration(id) {
  for (;;) {
    const res = await fetch(`https://codzen.ai/api/v1/generations/${id}`, {
      headers: { Authorization: `Bearer ${process.env.CODZEN_API_KEY}` },
    });
    const generation = await res.json();
    if (!res.ok) throw new Error(generation.error.message);
    if (generation.status === 'succeeded' || generation.status === 'failed') {
      return generation;
    }
    await new Promise((resolve) => setTimeout(resolve, 5000));
  }
}
```

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

import requests


def wait_for_generation(generation_id):
    while True:
        res = requests.get(
            f"https://codzen.ai/api/v1/generations/{generation_id}",
            headers={"Authorization": f"Bearer {os.environ['CODZEN_API_KEY']}"},
        )
        generation = res.json()
        if not res.ok:
            raise RuntimeError(generation["error"]["message"])
        if generation["status"] in ("succeeded", "failed"):
            return generation
        time.sleep(5)
```

## Inputs

The fields of `input` depend on the model; each model's page lists them, linked from the [Models](https://docs.codzen.ai/models.md) index. Unknown fields are rejected with `400 invalid_request`, and `error.param` names the field.

Fields that take an **input asset**, such as an image or video to start from, end in `_url`. An image can be an HTTPS URL or a data URI of at most 10 MB; video and audio must be HTTPS URLs. Codzen downloads each input asset when you submit, and rejects the generation with `400 invalid_request` if it cannot be downloaded or is not a supported format or size.

The generation's `input` is returned normalized: input assets point at Codzen's copies, and other fields are as you sent them.

## Outputs

`outputs` is always an array, empty until the generation succeeds. Each item has a `type` (`video`, `image`, `audio` or `3d`) and a `url`.

Anyone who has an output URL can download it, without an API key. The URLs are hard to guess but not secret, so share them with care.

## List your generations

`GET /generations` returns your generations, newest first. It takes:

| Query | Description |
| - | - |
| `limit` | How many to return, from 1 to 100. Default 20. |
| `after` | The last `id` of the previous page, to get the next page. |
| `status` | Only generations with this status. |
| `model` | Only generations of this model slug. |

The response is `{ "data": [...], "has_more": true }`. While `has_more` is `true`, pass the last `id` in `data` as `after` to get the next page:

```bash theme={null}
curl "https://codzen.ai/api/v1/generations?limit=50&status=succeeded&after=gen_01JBXK2Y7P1N3R5T7V9X1Z3B5D" \
  -H "Authorization: Bearer $CODZEN_API_KEY"
```

You can only see your own account's generations; another account's generation ID returns `404 generation_not_found`.


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