# Generations

Submit a generation and collect the finished asset. Every feature in the platform runs through this one collection.

Base URL: https://api.neurall.io. Authenticate with `Authorization: nl-YOUR_API_KEY`.

### List Generations

`GET /v3/generations`

The project's generations, newest first, keyset-paginated via `cursor`. Use it to recover ids you lost (a process that crashed between submitting and recording the id can find its work here) and to show recent activity in your own dashboard.

It is NOT an archive: a generation created through the API drops out of this list once its `expiresAt` passes, 24 hours after the request, so treat it as a window on the last day rather than as storage.

```bash
curl -X GET "https://api.neurall.io/v3/generations" \
  -H "Authorization: nl-YOUR_API_KEY"
```

**Query**

- `feature` (string): Only generations for one feature, e.g. `video/logo-reveal`. The legacy flat spelling is accepted too and matches the same rows.
- `limit` (integer): Generations per page. Defaults to 24, and anything above 100 is clamped to 100 rather than rejected.
- `cursor` (string): The `nextCursor` of the previous page

**Responses**

- `200`: One page of generations
  - `generations` (object[]): An async generation. `status` moves from `pending` through `running` to `done`, `error` or `timeout`; once done, `output` holds the asset as a signed URL named by the kind (image, video or audio) plus its `mime`.
  - `nextCursor` (string): Pass it back as `?cursor=` for the next page; null on the last one.

  Example:

  ```json
  {
    "generations": [
      {
        "id": "9f2c1d84-6a3b-4f21-9c77-2f0a1b8e5d43",
        "feature": "image/self-portrait",
        "kind": "image",
        "status": "done",
        "output": {
          "image": "https://cdn.neurall.io/…/image.png",
          "mime": "image/png"
        },
        "balanceUsed": 0.05,
        "requestDate": "2026-08-25T17:04:12.000Z",
        "responseDate": "2026-08-25T17:04:41.000Z",
        "expiresAt": "2026-08-26T17:04:12.000Z"
      }
    ],
    "nextCursor": null
  }
  ```
- `401`: Unauthorized

### Create Generation

`POST /v3/generations`

Submits an async generation and returns immediately with status `pending`. Poll GET /v3/generations/{id} until the status is terminal, then read `output`, or pass `webhookUrl` to be notified instead (polling still works as a fallback).

```bash
curl -X POST "https://api.neurall.io/v3/generations" \
  -H "Authorization: nl-YOUR_API_KEY" \
  -H "Content-Type: application/json" \
  -d '{
    "feature": "<feature>",
    "args": { },
    "webhookUrl": "<webhookUrl>"
  }'
```

**Body**

- `feature` (string, required): The generation feature to run, namespaced by output kind ('<kind>/<name>'). The pre-namespacing flat spellings (e.g. image-generation, logo-reveal) are still accepted. One of: `image/self-portrait`, `image/generation`, `image/product-shot`, `image/youtube-thumbnail`, `image/ad`, `video/logo-reveal`, `video/object-reveal`, `video/avatar`, `audio/voiceover`.
- `args` (object, required): Feature-specific inputs. Reference images and audio are file ids from /v3/files/upload. Every input is validated before the generation is accepted or billed; a file that fails answers a descriptive 400 and nothing is charged. Each feature's own docs page lists its arguments, formats and size caps.
- `webhookUrl` (string): Optional https URL to POST the finished generation to when it reaches a terminal status (done / error / timeout). Deliveries are always signed with your project's webhook secret, revealed on the playground's API Keys page. Delivery is best-effort with a brief retry; polling remains authoritative.

**Responses**

- `200`: The pending generation
  - `generation` (object): An async generation. `status` moves from `pending` through `running` to `done`, `error` or `timeout`; once done, `output` holds the asset as a signed URL named by the kind (image, video or audio) plus its `mime`.

  Example:

  ```json
  {
    "generation": {
      "id": "9f2c1d84-6a3b-4f21-9c77-2f0a1b8e5d43",
      "projectId": "3e8b2f60-91c4-4d7a-8f02-6b1de0a97c55",
      "feature": "image/self-portrait",
      "kind": "image",
      "status": "pending",
      "params": {
        "image": "f_9c21e0b4",
        "prompt": "Cinematic studio portrait, moody side light against a deep grey backdrop.",
        "aspectRatio": "3:4"
      },
      "balanceUsed": 0.05,
      "requestDate": "2026-08-25T17:04:12.000Z",
      "expiresAt": "2026-08-26T17:04:12.000Z"
    }
  }
  ```
- `400`: Bad request (unknown feature, invalid args)
- `401`: Unauthorized
- `402`: Insufficient balance

### Get Generation

`GET /v3/generations/{id}`

The one call you make after submitting: poll it every few seconds (5 to 10 for the minute-scale renders: video, voice cloning) until `status` leaves `pending` and `running`, then read `output`. Statuses are `pending`, `running`, `done`, `error` and `timeout`; loop while the status is one of the first two rather than waiting for `done`, or a failed generation spins forever.

The asset in `output` (`image`, `video` or `audio`, named by the generation's kind) is a signed URL you should download, NOT a permanent address: a generation created through the API is reaped at `expiresAt`, 24 hours after the request, and this call then answers 404 as though the generation never existed.

```bash
curl -X GET "https://api.neurall.io/v3/generations/<id>" \
  -H "Authorization: nl-YOUR_API_KEY"
```

**Path**

- `id` (string, required): The generation id returned by POST /v3/generations.

**Responses**

- `200`: The generation
  - `generation` (object): An async generation. `status` moves from `pending` through `running` to `done`, `error` or `timeout`; once done, `output` holds the asset as a signed URL named by the kind (image, video or audio) plus its `mime`.

  Example:

  ```json
  {
    "generation": {
      "id": "9f2c1d84-6a3b-4f21-9c77-2f0a1b8e5d43",
      "projectId": "3e8b2f60-91c4-4d7a-8f02-6b1de0a97c55",
      "feature": "image/self-portrait",
      "kind": "image",
      "status": "done",
      "params": {
        "image": "f_9c21e0b4",
        "prompt": "Cinematic studio portrait, moody side light against a deep grey backdrop.",
        "aspectRatio": "3:4"
      },
      "output": {
        "image": "https://cdn.neurall.io/…/image.png",
        "mime": "image/png"
      },
      "balanceUsed": 0.05,
      "requestDate": "2026-08-25T17:04:12.000Z",
      "responseDate": "2026-08-25T17:04:41.000Z",
      "expiresAt": "2026-08-26T17:04:12.000Z"
    }
  }
  ```
- `401`: Unauthorized
- `404`: Generation not found

### Delete Generation

`DELETE /v3/generations/{id}`

Removes the generation and its rendered assets now, instead of waiting for the 24 hour expiry to do it. Reach for this when something has to be gone on request rather than on schedule: a user withdrew consent, or a render came back wrong and you do not want it reachable while your retry runs.

It does not refund anything, since the render already happened, and it cannot cancel work that is still in flight.

```bash
curl -X DELETE "https://api.neurall.io/v3/generations/<id>" \
  -H "Authorization: nl-YOUR_API_KEY"
```

**Path**

- `id` (string, required): The generation id returned by POST /v3/generations.

**Responses**

- `200`: Deleted
  - `success` (boolean)

  Example:

  ```json
  {
    "success": true
  }
  ```
- `401`: Unauthorized
- `404`: Generation not found
