Capabilities API
List what you can run and read the exact config schema for one capability.
Read as MarkdownTwo reads before you submit: what you can run, and what its config must look like. For the full catalog in words, see capabilities.
- Scope
read. Every key has it. - Rate bucket
agent_read: 120 calls a minute per key, shared with other reads. capability_idis a free string, never an enum. Presets have their own ids (preset_fashion_tryon). Read the list, don't hardcode it.
List capabilities
GET/api/v1/capabilitiesAPI key
| Param | Type | Default | Notes |
|---|---|---|---|
limit | positive integer | 25 | Clamped to 1 to 50 |
cursor | string | none | The previous next_cursor |
- Lenient:
?limit=abc,0,-3or empty act as if omitted. - No
search,category,pageoroffset.
curl -s https://app.riffads.com/api/v1/capabilities \
-H "Authorization: Bearer $RIFFADS_API_KEY"{
"ok": true,
"capabilities": [
{
"capability_id": "actor_ultra",
"name": "Talking Actor",
"description": "OmniHuman 1.5: an actor speaks your script.",
"category": "avatar",
"output_kind": "video",
"status": "available"
},
{
"capability_id": "veo_31",
"name": "Veo 3.1",
"description": "Google Veo 3.1 video generation with optional audio.",
"category": "video",
"output_kind": "video",
"status": "available"
},
{
"capability_id": "nb_pro",
"name": "Nano Banana Pro",
"description": "Gemini 3 Pro Image: the premium hero shot, up to 4K, best-in-class text rendering.",
"category": "image",
"output_kind": "image",
"status": "available"
}
],
"next_cursor": "nb_pro"
}The full body also has total: the rows this workspace sees, retired ones left out.
Prop
Type
- Order: category (avatar, video, image, preset, tool), then
capability_idascending. next_cursor: the last row'scapability_id.nullon the last page. A stale cursor restarts at page one.- Hidden: retired rows and rows not offered to agents. Ask for one by id and the detail endpoint says why.
- It changes without notice: plan gates, retirements, launches. Read it each session. Sent with
Cache-Control: no-store. - Agent only: AI Writer (
script_llm) and Transcribe (transcribe) are listed here, not in the app. Both return text.
Read one schema
GET/api/v1/capabilities/{capability_id}API key
curl -s https://app.riffads.com/api/v1/capabilities/actor_ultra \
-H "Authorization: Bearer $RIFFADS_API_KEY"{
"ok": true,
"capability": {
"capability_id": "actor_ultra",
"name": "Talking Actor",
"description": "OmniHuman 1.5: an actor speaks your script.",
"category": "avatar",
"output_kind": "video",
"config_schema": {
"type": "object",
"properties": {
"script": {
"description": "Script.",
"type": "string",
"maxLength": 1500
},
"voiceId": {
"description": "Voice. A voice id from list_voices.",
"type": "string",
"minLength": 1
},
"voice_audio": {
"description": "Audio. Upload a voice recording to use instead of a script. Up to 60s, MP3, WAV, OGG or WEBM. Up to 1 audio asset id(s). Accepts an upload or anything this project already produced.",
"maxItems": 1,
"type": "array",
"items": { "type": "string", "pattern": "^ast_[0-9a-f]{32}$" }
},
"resolution": {
"default": "720p",
"description": "Resolution.",
"type": "string",
"enum": ["720p"]
}
},
"additionalProperties": false,
"description": "Configuration for Talking Actor. Only the keys listed here are accepted: any other key is refused rather than ignored. A key with a default may be omitted. Call estimate_generation to price a config before submitting it."
},
"example_config": {
"resolution": "720p"
}
}
}No status on the detail body. A 200 means you can run it.
Schema rules
- Strict.
additionalProperties: false. An unknown key inconfig(likemaxCredits) is400 invalid_config. - Locked preset fields are absent. They are not yours to set.
- Keys with a default may be left out.
requiredlists only required keys with no default.actor_ultrahas none, so it has norequiredarray. It still needs a script or an uploaded recording: that either/or is checked at submit. example_configis the smallest valid config. It includes required keys that have defaults, so it can differ fromrequired. File slots hold the placeholderast_00000000000000000000000000000000: swap in real ids from uploads.countmax is 4 over the API.- Asset ids match
^ast_[0-9a-f]{32}$. - Read the descriptions. File limits, per-file durations, step sizes, slot dependencies and group rules live there.
Two file slot shapes
Plain tools take an array of bare ids:
{
"description": "Video. Up to 1 video asset id(s). Each file may run up to 600 seconds. Accepts an upload or anything this project already produced.",
"minItems": 1,
"maxItems": 1,
"type": "array",
"items": { "type": "string", "pattern": "^ast_[0-9a-f]{32}$" }
}Image and video models take one strict object per file, with the role pinned and an alias you pick:
{
"description": "Start Frame. Up to 1 image file(s), each as an asset id plus its own alias, with role \"start_frame\".",
"maxItems": 1,
"type": "array",
"items": {
"type": "object",
"properties": {
"assetId": { "type": "string", "pattern": "^ast_[0-9a-f]{32}$" },
"alias": { "type": "string", "pattern": "^(image|video|audio)[1-9]\\d*$" },
"role": { "type": "string", "const": "start_frame" }
},
"required": ["assetId", "alias", "role"],
"additionalProperties": false
}
}Aliases count from 1 per kind (image1, image2, video1). Don't reuse an alias across slots in one config. The config level description says this too.
What the schema can't tell you
- Settings that depend on a file. A start frame or reference image can change the valid
aspect_ratio,resolutionandduration. Enums show every value any case allows. Check a real config withPOST /estimates. Generations API. - Price. None here.
POST /estimatesreturns the number to basemax_creditson. - REST names. Descriptions name MCP tools (
list_voices,estimate_generation). Over REST those areGET /voicesandPOST /estimates.
Fields that are not config
actor_id, actor_image_asset_id, voice_id and approved_voice_generation_id go on the submit body, not in config. Inside config they are unknown keys. Generations API, actors and voices.
actor_ultra has no aspect_ratio
Sending aspect_ratio is an unknown key. The shape comes from the actor. Script road: run tts first and pass its generation_id as approved_voice_generation_id. Audio road: fill voice_audio with your recording, no tts needed. Talking actor guide.
Errors
An id you can't use adds capability_status to the error envelope.
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 | Your plan doesn't include it. Carries required_plan |
unknown | capability_unavailable | 404 | Never existed, misspelled, or not offered to agents |
{
"error": {
"ok": false,
"code": "capability_unavailable",
"message": "No such capability. Call list_capabilities for the current list.",
"retryable": false,
"credits_charged": 0,
"capability_status": "unknown"
}
}None are retryable. Read the list again and pick an available row. All codes: error codes.