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

# Models in the API

> Find a model, read the request schema it accepts, and handle deprecations.

Every run names one model doing one operation. Use the models endpoints
to find the models your organization can run and the exact request each one
accepts. To compare model families and what each is good at, see
[Models](https://docs.zerogen.com/models/overview.md).

## Model IDs

A model ID has three segments, `{vendor}/{model}/{operation}`, such as
`openai/gpt-image-2/generate` or `kling/o3-pro/reference-to-video`:

* **Vendor** is the company that makes the model, not the provider that ZeroGen
  routes it through, so a change of provider doesn't change the ID.
* **Model** names the model.
* **Operation** names what the model does. A model that does several things has
  one ID for each.

The operation is one of the following: `generate`, `edit`, `inpaint`, `remix`,
`outpaint`, `text-to-vector`, `text-to-video`, `image-to-video`,
`first-last-frame-to-video`, `keyframes-to-video`, `reference-to-video`,
`audio-to-video`, `video-to-video`, `reference-video-to-video`, `extend-video`,
`motion-control`, `lip-sync`, `clean-plate`, `render-to-real`, `hdr`, or
`text-to-speech`.

An ID stays the same across a vendor's builds while its request schema stays
the same. Each run reports the build that ran as `modelVersion`, or
`null` when the provider doesn't name one. A price change keeps the ID. An ID
changes only when the request schema changes or the vendor ships a materially
different model, and ZeroGen never reuses an ID for another model.

## List models

`GET /v1/models` lists the models your organization can run. It needs the
`models:read` scope.

```bash theme={null}
curl "https://api.zerogen.com/v1/models?capability=video&operation=image-to-video" \
  -H "Authorization: Bearer $ZEROGEN_API_KEY"
```

```json theme={null}
{
  "data": [
    {
      "id": "minimax/h3-max/image-to-video",
      "name": "MiniMax H3 Max (image-to-video)",
      "capability": "video",
      "operation": "image-to-video",
      "status": "active",
      "sunsetAt": null
    }
  ],
  "nextCursor": null
}
```

The list takes the following optional filters, plus `limit` and `cursor` as
described in [Pagination](https://docs.zerogen.com/developers/pagination.md):

| Parameter | Values | Lists |
| - | - | - |
| `capability` | `image`, `video`, or `speech` | Models of that capability. |
| `operation` | An operation from the list above | Models doing that operation. |
| `q` | Text | Models whose ID or name matches, including the maker and related operations. |
| `frames` | `start` or `start-end` | Video models that accept at least these frames. |
| `audio` | `true` | Video models that can generate audio. |
| `referenceKind` | `image`, `video`, or `audio` | Models that accept references of that kind. |

## Read the request schema

`GET /v1/models/{vendor}/{model}/{operation}` returns one model with
`requestSchema`: the JSON Schema (draft 2020-12) that a `POST /v1/runs` body
for this model must match. It needs the `models:read` scope.

The schema covers the whole request body, including `projectId`, `folderId`,
`labelIds` and `naming`, which work the same for every model.

```bash theme={null}
curl https://api.zerogen.com/v1/models/openai/gpt-image-2/generate \
  -H "Authorization: Bearer $ZEROGEN_API_KEY"
```

The schema reflects your organization: it leaves out optional controls that
your organization's billing doesn't price. It adds the following extensions to
JSON Schema:

| Extension | Description |
| - | - |
| `x-roles` | Under `inputs`. Each input role the model takes, with the media types it accepts, its limits, and `urlAccept`, the media types a URL input can be. |
| `x-prompt-references` | Present when the prompt can refer to inputs by tokens such as `@image1`. |

## The run request

Every model shares one request shape. The model's request schema states which
fields and values it accepts, and ZeroGen rejects unknown fields.

| Field | Description |
| - | - |
| `model` | Required. The model ID. |
| `prompt` | The prompt, up to 32,000 characters, matching the Generate editor. For a speech model, the script to read aloud. |
| `voice` | Speech models only, and required for them. The voice to read the prompt in, from the voices the model's request schema lists. |
| `inputs` | Up to 50 inputs. Each has a `role` and either `asset`, a Library asset ID, or `url`, an `https` URL. A `keyframe` input also has `timeSeconds`. For details, see [Uploads and URL inputs](https://docs.zerogen.com/developers/uploads.md). |
| `output` | Output settings: `count` (1 to 4), `size`, `quality`, `background`, `format` (`png`, `jpeg`, or `webp`), `aspectRatio`, `resolution`, `durationSeconds`, and `includeAudio`. |
| `parameters` | Model-specific parameters that the model's schema lists. |
| `seed` | An integer from 0 that sets the model's randomness. Only models whose schema lists `seed` take it, up to the schema's `maximum`; other models refuse it. The same seed with the same request gives similar results, but not always identical ones. Omit it for a random seed. |
| `maxCostMicroUsd` | Refuse to start when the quote is higher than this amount. For details, see [Billing](https://docs.zerogen.com/developers/billing.md). |
| `projectId` | The project the outputs are saved in. Defaults to your organization's default project, or with `upscaleDraft`, to the draft's project. |
| `folderId` | A folder in that project to add the outputs to. Omit it, or send `null`, to leave them unfiled. |
| `labelIds` | Up to 100 of your organization's labels to add to every output. Needs the `library:organize` scope. For details, see [Label the outputs](#label-the-outputs). |
| `naming` | Name the outputs with one of the project's naming presets: `presetId`, and `values` for the preset's fields by field ID. Fields you leave out take the preset's defaults. |
| `upscaleDraft` | Upscale a 480p draft output to its final. For details, see [Upscale a draft](#upscale-a-draft). |
| `test` | Test keys only. Rehearses outcomes. For details, see [Test keys](https://docs.zerogen.com/developers/test-keys.md). |

A speech model takes `prompt` and `voice`, and no `inputs` or `output`.

Input roles are `source`, `reference`, `face-reference`, `start-frame`,
`end-frame`, `keyframe`, and `mask`. Send `face-reference` for an image or video
that shows a real person, on models whose schema lists that role.

A `keyframe` pins its image to `timeSeconds`: seconds from the start of the
video, on a whole frame at the role's `frameRate`, and at most
`output.durationSeconds`. Each keyframe needs `timeSeconds`, and no other role
takes it. The role's limit in `x-roles` counts start frames, end frames, and
keyframes together.

## Label the outputs

Send `labelIds` with a run to label its outputs as they arrive, instead of
with a request per output afterward. Each output gets the labels in the same
write that saves it to your Library, so no output appears without them, even
if your client stops before the run ends.

* Each label must be an active label of your organization, from
  `GET /v1/labels`. Another organization's label, or an archived or deleted
  one, returns `404 not_found` with `param` `labelIds` and the label in
  `details.labelId`. Nothing starts or is charged.
* A label archived or deleted after the run starts isn't added. The outputs
  still arrive, with the run's other labels.
* Labels only add; a run never removes one.
* A request with labels also needs the `library:organize` scope, because it
  organizes your Library. Without it, the request fails with
  `403 permission_denied` and `details.scope` is `library:organize`.

Quotes check `labelIds` the same way.

## Quote a run

`POST /v1/runs/quote` takes the same body as a create and runs the same
validation and pricing at your organization's rates. It starts nothing and
holds nothing. It needs the `runs:create` scope.

```json theme={null}
{
  "model": "openai/gpt-image-2/generate",
  "billing": {
    "mode": "platform",
    "quotedMicroUsd": 42000
  }
}
```

`quotedMicroUsd` is the amount that a create with the same body would hold. A
quote imports its URL inputs into your Library, as a create does.

## Warnings and drafts

Each output in a run can carry two more fields:

* `warnings` lists what the provider ignored, such as an unused reference. Each
  warning has a `code` and a `message`. Outputs without warnings leave it out.
* `draft` appears on a succeeded 480p draft output. Models that make drafts,
  such as Seedance 2.5, list a parameter titled `480p Draft` in their request
  schema. `draft.upscalable` says whether the draft can be upscaled now, and
  `draft.expiresAt` is when upscaling closes. `draft.upscale` and
  `draft.finalAssetId` report the newest upscale, whether it started in ZeroGen
  or through the API.

## Upscale a draft

A Seedance 2.5 480p draft can be upscaled to a final with the draft's prompt,
references, seed, and settings, for 7 days after it's made. To upscale one
output, send `upscaleDraft` to `POST /v1/runs` with the draft's model ID, and
leave out `prompt`, `inputs`, `output`, `parameters`, and `naming`:

```bash theme={null}
curl https://api.zerogen.com/v1/runs \
  -H "Authorization: Bearer $ZEROGEN_API_KEY" \
  -H "Content-Type: application/json" \
  -H "Idempotency-Key: 9f8e7d6c-5b4a-4f3e-8d2c-1b0a9f8e7d6c" \
  -d '{
    "model": "bytedance/seedance-2.5/text-to-video",
    "upscaleDraft": { "runId": "<draft run ID>", "outputIndex": 0 }
  }'
```

| Field | Description |
| - | - |
| `runId` | Required. The draft's run: the run's `id`, or an asset's `runId`. |
| `outputIndex` | Required. The draft output to upscale: the output's `index`, or an asset's `outputIndex`. |
| `resolution` | The final's resolution. Defaults to `1080p`. The model's request schema lists the resolutions it offers under `upscaleDraft`. |

* The final is a new run of your own, even when a teammate made the draft. It's
  quoted, held, and charged like any other run, and `maxCostMicroUsd`, your
  spend limits, and `Idempotency-Key` apply. `POST /v1/runs/quote` quotes it
  with the same body.
* The final is saved in the draft's project. Its lineage lists the draft as its
  source.
* Send the model ID that made the draft, which the draft run reports as
  `model`. A different ID returns `400 validation_failed` with `param` set to
  `model`, and the message names the right ID.
* Upscale only an output whose `draft.upscalable` is `true`. One final of an
  output runs at a time, and you can upscale an output again after its final
  finishes.
* A test key upscales the drafts it made in the API sandbox, so you can
  rehearse the flow. The final is quoted like a live one, runs on Echo, and
  costs nothing. For details, see [Test keys](https://docs.zerogen.com/developers/test-keys.md).

To upscale a draft in ZeroGen, see [Draft, then upscale](https://docs.zerogen.com/generate/draft-then-upscale.md).

## Deprecated models

ZeroGen marks a model `deprecated` before retiring it. A deprecated model keeps
working until its `sunsetAt` time. After that, requests that name it fail with
`400 model_unavailable`. A model that anyone used in the 90 days before its
retirement is deprecated at least 90 days ahead.

Responses that name a deprecated model carry two headers:

| Header | Description |
| - | - |
| `Deprecation` | When the model was deprecated, as `@` and Unix seconds ([RFC 9745](https://www.rfc-editor.org/rfc/rfc9745)). |
| `Sunset` | When the model stops accepting requests, as an HTTP date ([RFC 8594](https://www.rfc-editor.org/rfc/rfc8594)). |

ZeroGen sends them on the model's detail, and on creating, reading, quoting, or
cancelling a run with that model:

```http theme={null}
Deprecation: @1792540800
Sunset: Mon, 21 Feb 2028 00:00:00 GMT
```

To migrate, list models with the same `operation`, read the replacement's
request schema, and update your requests before the sunset.


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