# Render a video clip from an image and a prompt

URL: https://www.atmee.ai/docs/v2/api/reference/generation/generateClip

`POST /v1/generation/clips`

Renders a short mp4 (1 to 15 seconds, 25 fps) of the person or
character in `image`, moving as `prompt` describes, optionally
speaking `audio`. No avatar is made or needed: the clip is rendered
directly by Atmee's v2 renderer.

`image` is `upload:<uploadId>` (a `portrait` upload, which stays
usable afterwards) or a public https link to a jpg, png or webp of at
most 10 MB; `audio` the same for a `voice` upload or link (wav, mp3,
webm, ...). The audio plays once from the start of the clip, padded
with silence and cut at its end. `durationSeconds` is required with
`audio` (the audio's own length is not read: set it to the audio's
length, at most 15; without it the request is `400 invalid_input`)
and defaults to 8 for a silent clip; `resolution` defaults to
512 x 512 (see `RenderResolution`; e.g. 384 x 672 for portrait,
672 x 384 for landscape) and `seed` to 0. The prompt and the image
are moderated first. If the image shows a real person other than the
creator, have that person's permission first.

The clip is returned as `upload:<uploadId>` (24 hours) with a
short-lived `url` to download it. It costs the price per 15 seconds
(`GET /v1/account`, `pricing.generation.clipPer15SecondsMicrocredits`)
times `durationSeconds` / 15, rounded up to a whole microcredit (1
credit for a 15-second clip), charged only when the clip comes back; a
flagged, failed or refused call costs nothing. Clips use the v2
renderer, so an account without v2 access gets
`403 v2_access_required`. A render can take
minutes when the renderer starts cold: past about 45 seconds the
request answers `409 request_in_progress`, and a retry with the same
`Idempotency-Key` after `Retry-After` returns the clip once it is
done, charged once. An image or audio the renderer cannot use (no
face, an unreadable file) is `400 invalid_input` naming
`input_failure image` or `input_failure audio`. Where clips are not
offered the route answers `503 generation_unavailable`. A size this
deployment offers but its render pool does not serve is `400
invalid_input` naming `input_failure resolution` ("the render pool
does not serve WxH"), not an image error. Requires
`generation:write` and `avatars:write`.

## Parameters

| Name | In | Required | Description |
| --- | --- | --- | --- |
| `Idempotency-Key` | header | yes | A new UUID minted for this request. Reuse it only to retry the same request: a retry never charges twice and returns the first result. A malformed key, or a key already used with different inputs, gets 400 invalid_input. |

## Request body

- `application/json`: `GenerateClipRequest`

| Field | Type | Required | Description |
| --- | --- | --- | --- |
| `image` | string | yes | Who or what the clip shows, `upload:<uploadId>` (a `portrait` upload) or a public https link (jpg, png or webp, at most 10 MB). |
| `prompt` | string | yes | The shot and the motion, e.g. "she walks along the beach at sunset, the camera following". |
| `audio` | string | no | What the clip says or plays, `upload:<uploadId>` (a `voice` upload) or a public https link to an audio file. Absent, the clip is silent. |
| `durationSeconds` | integer | no | The clip's length. Required with `audio` (set it to the audio's length, at most 15; it is not read from the file); default 8 for a silent clip. |
| `resolution` | `RenderResolution` | no | A frame size in pixels for the v2 renderer: width and height are each a multiple of 32 from 256 to 1024, and width x height is at most 262,144 (512 x 512); a larger frame is `400 invalid_manifest` on an avatar, `400 invalid_input` on a clip. Default 512 x 512 (square). Common shapes: square 512 x 512, portrait 384 x 672, landscape 672 x 384. A deployment offers only some sizes (512 x 512 always; `GET /v1/account` `pricing.generation.clipResolutions` lists them where clips are offered): another is `400 invalid_input` ("resolution WxH is not offered; offered: ..."). On an avatar it is a build input of v2 avatars only (`400 invalid_input` for a v1 avatar): the portrait is preprocessed at that size, so a change on PATCH builds a new version with new candidates, like a new portrait; sending the current size again builds nothing. Absent or null keeps the current size (on create: the default). |
| `seed` | integer | no | The render's seed; another seed gives other motion. Default 0. |

## Responses

| Status | Description | Schema |
| --- | --- | --- |
| `200` | The clip (or the replayed first result). | `GeneratedClipResponse` |
| `400` | invalid_input (an Idempotency-Key that is not a UUID or was used with different inputs; an input the operation cannot take, or for a clip one the renderer could not use, named as input_failure image or audio) \| moderation_flagged (the description, name, sample text, prompt or photo was flagged; change it) | `ApiErrorResponse` |
| `401` | Missing or invalid API key -- or a user token that is invalid, anonymous, or of a user who may act for no account (invalid_login) | none |
| `402` | insufficient_credits (the balance is below the price; top up, don't retry) \| api_key_spend_cap_reached | `ApiErrorResponse` |
| `403` | insufficient_scope (an API key needs both generation:write and avatars:write) \| account_not_allowed (a user token whose X-Account-Id names an account the user may not act for) \| v2_access_required (clips only; the v2 renderer is invite-only and this account has not been let in yet) | `ApiErrorResponse` |
| `409` | request_in_progress (a call with this Idempotency-Key is still running, or its charge could not be confirmed; retry it with the same Idempotency-Key after Retry-After and get its one result, charged once -- a new key could charge twice) \| account_ambiguous (a user token of several accounts without X-Account-Id) | `ApiErrorResponse` |
| `422` | Request body failed schema validation (e.g. a prompt over 2,000 characters or durationSeconds over 15), or the Idempotency-Key header is missing. | none |
| `429` | rate_limited -- the account has too many generation calls running, or made too many in the last minute; retry after Retry-After. | `ApiErrorResponse` |
| `502` | provider_failed -- no provider returned a usable output; nothing was charged. | `ApiErrorResponse` |
| `503` | generation_unavailable -- this instance does not offer generation. | `ApiErrorResponse` |

## `200` response fields

| Field | Type | Required | Description |
| --- | --- | --- | --- |
| `clip` | `GeneratedClip` | yes |  |
| `microcreditsCharged` | integer | yes | What this call charged (100 microcredits = 1 credit), the price per 15 seconds times `durationSeconds` / 15, rounded up; 0 on a replay. |
| `replayed` | boolean | yes | True when an earlier call with the same Idempotency-Key was replayed. |
