REST API

Capabilities API

List what you can run and read the exact config schema for one capability.

Read as Markdown

Two 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_id is 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
ParamTypeDefaultNotes
limitpositive integer25Clamped to 1 to 50
cursorstringnoneThe previous next_cursor
  • Lenient: ?limit=abc, 0, -3 or empty act as if omitted.
  • No search, category, page or offset.
Terminal
curl -s https://app.riffads.com/api/v1/capabilities \
  -H "Authorization: Bearer $RIFFADS_API_KEY"
Response: 200 (trimmed)
{
  "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_id ascending.
  • next_cursor: the last row's capability_id. null on 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
Terminal
curl -s https://app.riffads.com/api/v1/capabilities/actor_ultra \
  -H "Authorization: Bearer $RIFFADS_API_KEY"
Response: 200
{
  "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 in config (like maxCredits) is 400 invalid_config.
  • Locked preset fields are absent. They are not yours to set.
  • Keys with a default may be left out. required lists only required keys with no default. actor_ultra has none, so it has no required array. It still needs a script or an uploaded recording: that either/or is checked at submit.
  • example_config is the smallest valid config. It includes required keys that have defaults, so it can differ from required. File slots hold the placeholder ast_00000000000000000000000000000000: swap in real ids from uploads.
  • count max 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:

config_schema.properties.source_video, from auto_caption
{
  "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:

config_schema.properties.start_frame, from sora_2
{
  "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, resolution and duration. Enums show every value any case allows. Check a real config with POST /estimates. Generations API.
  • Price. None here. POST /estimates returns the number to base max_credits on.
  • REST names. Descriptions name MCP tools (list_voices, estimate_generation). Over REST those are GET /voices and POST /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_statuscodeHTTPMeaning
coming_sooncapability_unavailable404Listed, not live yet
retiredcapability_unavailable404Withdrawn. Old generations still read fine
requires_planrequired_plan403Your plan doesn't include it. Carries required_plan
unknowncapability_unavailable404Never existed, misspelled, or not offered to agents
Response: 404
{
  "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.

On this page