# Capabilities (/capabilities)



Every thing RiffAds can make, by `capability_id`. Send that id to REST, MCP or the CLI. Same id, same fields everywhere.

This page is the map. The live list for your workspace is the truth: read it with [`GET /capabilities`](/api/capabilities), `list_capabilities` ([MCP](/mcp/tools)) or `riffads capabilities` ([CLI](/cli/commands)).

## Read the live list first [#read-the-live-list-first]

```bash title="Terminal"
curl -s https://app.riffads.com/api/v1/capabilities \
  -H "Authorization: Bearer $RIFFADS_API_KEY"

# one capability: its config_schema plus a valid example_config
curl -s https://app.riffads.com/api/v1/capabilities/veo_31 \
  -H "Authorization: Bearer $RIFFADS_API_KEY"
```

| `status`        | Means                                                                    |
| --------------- | ------------------------------------------------------------------------ |
| `available`     | Live. Estimate and submit.                                               |
| `requires_plan` | Your plan does not include it. `required_plan` names the plan that does. |
| `coming_soon`   | Listed, not live. Estimates and submits are refused.                     |

<Callout type="warn" title="Config is strict">
  Unknown keys in `config` are refused with `invalid_config`, never ignored. Read `config_schema` before your first submit. A workspace may see fewer options than listed here.
</Callout>

* `capability_id` is a plain string, not an enum. New ids appear with no deploy. Don't hardcode the list.
* `category` is `avatar`, `video`, `image`, `tool` or `preset`.
* `output_kind` is `image`, `video`, `audio` or `text`. Category is not output: `auto_caption` is a `tool` that outputs `video`.
* Media slots take asset ids (`ast_` plus 32 hex chars) from [uploads](/api/uploads), always as an array, even for one file.
* Every capability ends in a signed file link (or text). Nothing posts anywhere.

## Talking actor [#talking-actor]

`actor_ultra`: an actor speaks your script. Category `avatar`, output `video`.

| Field         | Required            | Notes                                                                    |
| ------------- | ------------------- | ------------------------------------------------------------------------ |
| `script`      | script or recording | Up to 1500 characters.                                                   |
| `voiceId`     | no                  | Falls back to the actor's default voice.                                 |
| `voice_audio` | script or recording | Your own recording instead of a script. Up to 60 s. MP3, WAV, OGG, WEBM. |
| `resolution`  | no                  | `720p` only.                                                             |

* `actor_id` (or `actor_image_asset_id`), `voice_id` and `approved_voice_generation_id` are **top-level submit fields**, not `config` keys.
* Script road: run `tts` first, wait, then `actor_ultra` with `approved_voice_generation_id`. Recording road: fill `voice_audio`, no `tts` needed.
* No `aspect_ratio`: refused. Shape follows the actor image.
* No `variants`: refused. No captions switch: run `auto_caption` after.
* The id is `actor_ultra`. `talking_actor` is not an id.

Full flow: [Talking actor ads](/guides/talking-actor).

## Video models [#video-models]

One prompt, one generation, one video.

| id                 | Name                       | Frames and references                                 | Aspect ratio                                | Duration (s)    | Resolution            | Audio toggle         |
| ------------------ | -------------------------- | ----------------------------------------------------- | ------------------------------------------- | --------------- | --------------------- | -------------------- |
| `veo_31`           | Veo 3.1                    | up to 3 reference images, **or** start plus end frame | `auto`, `16:9`, `9:16`                      | 4 to 8, step 2  | `720p`, `1080p`, `4k` | yes                  |
| `kling_v3`         | Kling V3                   | start, end frame                                      | `9:16`, `16:9`, `1:1`                       | 3 to 15         | `720p`, `1080p`       | yes                  |
| `kling_3_standard` | Kling 3 Standard           | start, end frame, elements                            | `16:9`, `9:16`, `1:1`                       | 3 to 15         | set by tier           | yes                  |
| `kling_3_pro`      | Kling 3 Pro                | same as Standard                                      | same                                        | 3 to 15         | set by tier           | yes                  |
| `kling_3_4k`       | Kling 3 4K                 | same as Standard                                      | same                                        | 3 to 15         | set by tier           | yes                  |
| `omni_flash`       | Omni Flash                 | up to 10 reference images, **or** one source video    | `16:9`, `9:16`                              | 3 to 10         | not published         | no, always has sound |
| `seedance_15_pro`  | Seedance 1.5 Pro           | start, end frame                                      | `9:16`, `16:9`, `1:1`                       | 4 to 12         | `720p`, `1080p`       | yes                  |
| `sora_2`           | Sora 2                     | start frame only                                      | `9:16`, `16:9`                              | 4 to 20, step 4 | `720p`, `1080p`       | no                   |
| `h3_max`           | MiniMax H3 Max             | start, end frame                                      | `21:9`, `16:9`, `4:3`, `1:1`, `3:4`, `9:16` | 5 to 15         | `480p`, `768p`        | no                   |
| `seedance_2`       | Seedance 2 (`coming_soon`) | reference images, videos, audio, plus frames          | six ratios, `21:9` to `9:16`                | 4 to 15         | `720p`, `1080p`       | yes                  |

All take `prompt` (required, 8000 chars, Kling 3: 2500), `count` and `prompt_enhancer` (off by default).

Slot rules, checked before anything runs:

* `end_frame` needs `start_frame`: Kling V3, Kling 3, Seedance 1.5 Pro, H3 Max.
* Veo 3.1: no references mixed with frames. A start frame alone is refused: send both.
* Omni Flash: references **or** a source video, not both.
* Seedance 2: max 12 reference files. Reference audio needs a reference image or video. Reference video 2 to 15 s combined. Reference audio max 15 s combined.
* Kling 3 elements: up to 4, max one with a video, needs a start frame.
* A start frame or reference can narrow valid `aspect_ratio`, `resolution` and `duration`. The schema enums show the union. The estimate endpoint checks the exact config.

## Image models [#image-models]

| id                      | Name                   | Shape control                                                                | Quality                        | Max reference images                                         |
| ----------------------- | ---------------------- | ---------------------------------------------------------------------------- | ------------------------------ | ------------------------------------------------------------ |
| `nb_pro`                | Nano Banana Pro        | `aspect_ratio` (`auto`, `21:9` to `9:16`), `resolution` `1K`, `2K`, `4K`     | none                           | 6                                                            |
| `nb_2`                  | Nano Banana 2          | `aspect_ratio` (`auto`, `8:1` to `1:8`), `resolution` `1K`, `2K`, `4K`       | none                           | 6, plus one context video and one context audio (15 MB each) |
| `gpt_image_15`          | GPT Image 1.5          | `image_size`: `auto`, `1536x1024`, `1024x1024`, `1024x1536`                  | `low`, `medium`, `high`        | 2                                                            |
| `gpt_image_2`           | GPT Image 2            | `image_size`, published list                                                 | fixed                          | 16                                                           |
| `gpt_image_25_sunburst` | GPT Image 2.5 Sunburst | `image_size`: `1024x768`, `1024x1024`, `1024x1536`, `2560x1440`, `3840x2160` | `low`, `medium`, `high`, `max` | 2                                                            |
| `gpt_image_25_flare`    | GPT Image 2.5 Flare    | same as Sunburst                                                             | same as Sunburst               | 2                                                            |
| `seedream_45`           | Seedream 4.5           | `image_size`                                                                 | none                           | 10                                                           |
| `seedream_5_lite`       | Seedream 5 Lite        | `image_size`                                                                 | none                           | 4                                                            |
| `seedream_5_pro`        | Seedream 5 Pro         | `image_size`                                                                 | none                           | 4                                                            |
| `grok_image`            | Grok Image             | `aspect_ratio` (`20:9` to `9:20`)                                            | none                           | 3                                                            |
| `grok_image_quality`    | Grok Image Quality     | same aspects, `resolution` `1k`, `2k`                                        | none                           | 3                                                            |

* `image_size` **or** `aspect_ratio`, never both. The schema says which.
* Up to 4 outputs per request over the API. GPT Image 2 publishes `count` up to 10: anything above 4 is clamped to 4 with a message.
* Seedream 4.5 with references: output count is clamped to the number of references.

## Audio and text [#audio-and-text]

| id                 | Name             | Output | Fields and limits                                                                                                                                                                                                            |
| ------------------ | ---------------- | ------ | ---------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- |
| `tts`              | Text to Speech   | audio  | `script` (up to 1500 chars), optional `voiceId`.                                                                                                                                                                             |
| `create_music`     | Create Music     | audio  | `prompt` (1 to 2000 chars), `duration` 1 to 300 s (default 60), `force_instrumental` (default `true`), `lyrics` (up to 3000 chars, needed unless instrumental).                                                              |
| `speech_to_speech` | Speech to Speech | audio  | `source_audio` up to 120 s, plus `voiceId`.                                                                                                                                                                                  |
| `transcribe`       | Transcribe       | text   | `source_media`: one video or recording. No speech: refused.                                                                                                                                                                  |
| `script_llm`       | AI Writer        | text   | `instructions` (12000 chars), `context` (optional, 6000), `reference_image` (up to 4), `model_class` `fast`, `balanced`, `smart` (default `fast`), `max_output_length` 100 to 1500 (default 600, output cut at that length). |

## Editing and media tools [#editing-and-media-tools]

Start from a file, not a prompt. One generation, one output, except `split_scenes`.

| id                  | Takes                                | Gives back                      | Hard limit                      |
| ------------------- | ------------------------------------ | ------------------------------- | ------------------------------- |
| `auto_caption`      | `source_video`                       | same clip, captions burned in   | 600 s                           |
| `text_overlay`      | `source_media` (photo or video)      | same file with a headline       | video 600 s, text 300 chars     |
| `trim_video`        | `source_video`                       | one section                     | 600 s                           |
| `stitch`            | `videos`: 2 to 10 clips              | one video, in array order       | 120 s combined                  |
| `split_scenes`      | `source_video`                       | up to 10 clips                  | 600 s, scenes at least 0.5 s    |
| `merge_layers`      | `background` plus `layers` (up to 6) | one composited video            | background 120 s                |
| `extract_frame`     | `source_video`                       | one PNG                         | `timestamp` 0 to 600 s          |
| `extract_audio`     | `source_video`                       | one 192 kbps MP3                | 600 s, silent video refused     |
| `change_speed`      | `source_media` (video or audio)      | 0.25x to 4x, pitch kept         | 600 s                           |
| `change_voice`      | `source_video` plus `voiceId`        | same words, new speaker         | 120 s                           |
| `resize`            | `source_media` (photo or video)      | reframed file                   | video 120 s                     |
| `upscale`           | `source_media` (photo or video)      | higher resolution               | video 30 s                      |
| `remove_background` | `source_media` (photo or video)      | subject, no background          | unreadable video length refused |
| `skin_enhance`      | `source_image` (portrait)            | cleaned-up copy                 | one photo                       |
| `camera_angle`      | `source_image`                       | same scene, new camera position | no prompt                       |

In-house tools take input files up to 500 MB. An input over a limit is refused before anything runs.

### Tool settings [#tool-settings]

| id              | Settings (default)                                                                                                                                                                                                                                                                                                                                                                                                              |
| --------------- | ------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- |
| `auto_caption`  | `caption_style`: `punch`, `impact`, `boxed`, `word_pop`, `clean`, `marker`, `handwritten`, `terminal` (`punch`). `caption_position`: `auto`, `top`, `center`, `bottom` (`auto`).                                                                                                                                                                                                                                                |
| `text_overlay`  | `text` (1 to 300 chars, required). `text_align`: `left`, `center`, `right` (`center`). `position`: `top`, `center`, `bottom` (`top`). `start` seconds (`0`). `duration` 0.1 to 600 (`3`). `font`: `insta`, `tiktok` (`insta`). `background`: `none`, `dark`, `white` (`none`). `text_size`: `default`, `custom` (`default`). `text_size_px` 8 to 400 (`64`, only with `custom`). `start` and `duration` are ignored for photos. |
| `trim_video`    | `start` seconds (`0`). `length` 0.1 to 600 (`5`).                                                                                                                                                                                                                                                                                                                                                                               |
| `split_scenes`  | `mode`: `auto` finds cuts, `manual` splits equally (`auto`). `threshold` 1 to 90, lower means more scenes, auto only (`17`). `scene_count` 2 to 10, max in auto, exact in manual (`6`).                                                                                                                                                                                                                                         |
| `extract_frame` | `timestamp` 0 to 600, step 0.1. Past the end returns the last frame.                                                                                                                                                                                                                                                                                                                                                            |
| `change_speed`  | `speed` 0.25 to 4, step 0.05 (`1`).                                                                                                                                                                                                                                                                                                                                                                                             |
| `resize`        | `aspect_ratio`: `9:16` (1080x1920), `4:5` (1080x1350), `1:1` (1080x1080), `16:9` (1920x1080) (`9:16`). `mode`: `fit` (bars), `crop` (fill), `smart` (model extends the picture, images only) (`fit`).                                                                                                                                                                                                                           |
| `camera_angle`  | `horizontal`: `front`, `left_45`, `right_45`, `left_profile`, `right_profile`, `behind` (`front`). `vertical`: `eye_level`, `low`, `high`, `overhead` (`eye_level`). `zoom`: `keep`, `wide`, `medium`, `close_up` (`keep`).                                                                                                                                                                                                     |

`stitch`, `merge_layers`, `extract_audio`, `upscale`, `remove_background` and `skin_enhance` have no settings beyond their files.

Chain tools by feeding one output's asset id into the next input slot.

## Presets [#presets]

Pick a template, add one file. Several steps run behind it.

| id                     | Name           | Takes                            | Notes                                                    |
| ---------------------- | -------------- | -------------------------------- | -------------------------------------------------------- |
| `preset_fashion_tryon` | Fashion Try On | template plus one clothes photo  | 5 or 10 s, audio toggle, up to 4 variants                |
| `preset_show_your_app` | Show Your App  | template plus one app screenshot | always 5 s, no duration or audio field, up to 4 variants |

Presets use the `preset_` prefix and can launch with no deploy. The live list is the only full inventory.

## Variants [#variants]

Send top-level `variants` on submit to get N takes of one config.

* Max **4**. Maps to the capability's `count` field and wins over a `count` inside `config`.
* No `count` field on the capability (talking actor included): `variants` is refused.
* The response has `generation_ids` and a `batch_group_id`. Read all takes with `GET /batches/{batch_group_id}` or `get_batch`. Watch every id, not just the first.

## Refusals for an id [#refusals-for-an-id]

| `capability_status` | `code`                   | HTTP | Meaning                                           |
| ------------------- | ------------------------ | ---- | ------------------------------------------------- |
| `coming_soon`       | `capability_unavailable` | 404  | Listed, not live yet                              |
| `retired`           | `capability_unavailable` | 404  | Withdrawn. Old generations still read fine        |
| `requires_plan`     | `required_plan`          | 403  | Plan does not include it. Carries `required_plan` |
| `unknown`           | `capability_unavailable` | 404  | Never existed or misspelled                       |

None are retryable. Re-read the list and pick an `available` row. All codes: [Errors](/reference/errors).
