# Generations

> Start one, wait for it, read the result, cancel or delete it.

Source: https://docs.nocamclub.com/api/generations

A generation is one order: a model, its `input`, and what came of it.

## Start one

```http
POST /v1/generations
```

| Field | Needed | What it is |
|---|---|---|
| `model` | Yes | A model id from [`GET /v1/models`](https://docs.nocamclub.com/api/models.md) |
| `input` | Yes | What to make. Its fields depend on the model: read its `input_schema` |
| `input.prompt` | Yes | Up to 10,000 characters |
| `end_user` | No | Your own id for your customer. A pseudonym, never an email |
| `metadata` | No | Your notes, strings up to 500 characters. They come back with the generation |
| `retention_hours` | No | Remove results sooner than the default 7 days: 1 to 168 |

Fields of `input` that a model can take: `aspect_ratio`, `resolution`, `quality`, `output_format`, `duration`, `reference_mode`, `images`, `videos`, `audios`. An unknown field is refused, not ignored.

Headers:

| Header | What it does |
|---|---|
| `Idempotency-Key` | Recommended always. See [Idempotency](https://docs.nocamclub.com/api/idempotency.md) |
| `Prefer: wait=60` | Holds the call until it's done, up to that many seconds, 60 at most |

The price is charged now. The answer is `202` with a generation to poll, or `200` if it finished within your `Prefer: wait`.

Response headers:

| Header | What it says |
|---|---|
| `X-Credits-Charged` | Credits this call took: the price on a new live generation, `0` on a repeat and on a test key |
| `Idempotent-Replayed` | `true` when this is a repeat of an earlier request |
| `X-Request-Id` | Always. Quote it if you contact us |

## Follow it

```http
GET /v1/generations/{id}
```

```text
queued -> running -> succeeded
                  -> failed     (credits back)
                  -> canceled   (credits back)
```

Poll every `poll_after_ms`, which is 3 seconds today. It's only there while the generation is in progress.

## The result

```json
{
  "id": "gen_01a1b37b65dc7dcd8c060f296add5cf8",
  "object": "generation",
  "model": "muse-video",
  "status": "succeeded",
  "mode": "live",
  "price": { "credits": 2, "usd": "0.02", "charged": true },
  "params": {},
  "outputs": [
    {
      "type": "video",
      "url": "https://cdn.nocamclub.com/api/8f3c…/1.mp4",
      "content_type": "video/mp4",
      "bytes": 1932156,
      "width": 768,
      "height": 1152,
      "duration_seconds": 10,
      "has_audio": true,
      "expires_at": "2026-11-14T00:55:00.000Z"
    }
  ],
  "error": null,
  "recovered": false,
  "purged": false,
  "timing": { "total_ms": 72000 },
  "urls": { "self": "https://api.nocamclub.com/v1/generations/gen_01a1b37b65dc7dcd8c060f296add5cf8" },
  "created_at": "2026-11-07T00:54:00.000Z",
  "finished_at": "2026-11-07T00:55:12.000Z"
}
```

- A photo or video output has a `url`. A text output has `text` instead: `{ "type": "text", "text": "…" }`.
- `params` shows the settings it ran with, defaults filled in.
- `price.charged` is `false` once the credits have come back, and always on a test key.

## When it fails

`status` is `failed`, `error.message` says why, `error.hint` what to do, and `error.retryable` whether the same request can work (send it with a new `Idempotency-Key`). The credits are already back. With `Prefer: wait` this still answers `200`, so check `status`. See [Errors](https://docs.nocamclub.com/errors.md).

```json
{
  "status": "failed",
  "error": {
    "code": "provider_unavailable",
    "message": "No route can run this model right now. Your credits came back. Try again in a few minutes.",
    "hint": "Try the same request in a few minutes, or another model.",
    "retryable": true,
    "docs_url": "https://docs.nocamclub.com/errors/provider_unavailable"
  }
}
```

**A late result isn't lost.** If a model finishes after we stopped waiting, we keep checking for a day. If it comes, the generation turns to `succeeded` with `recovered: true`, and you keep the refund.

## List them

```http
GET /v1/generations?status=succeeded&model=gpt-image-2&limit=20&cursor=…
```

Newest first. `has_more` and `next_cursor` page through. You see only your own account's, in the key's mode.

## Cancel one

```http
POST /v1/generations/{id}/cancel
```

Works while no model has it yet, and the credits come back. After that it answers [`not_cancelable`](https://docs.nocamclub.com/errors/not_cancelable.md): the generation finishes and is billed.

## Delete one

```http
DELETE /v1/generations/{id}
```

Removes the files and the prompt now, without waiting for them to expire. Only finished generations: otherwise [`not_finished`](https://docs.nocamclub.com/errors/not_finished.md).
