Presets
List presets and their templates, then run one through POST /generations with config.template_id.
Read as MarkdownA preset is a ready-made recipe, such as Show Your App or Fashion Try On. It is a capability with a preset_ id, so it is priced with POST /estimates and run with POST /generations like any other. What these two routes add is the template list: a template-driven preset has a required config.template_id, and this is where its legal values come from.
| Endpoint | Scope | Rate limit per key | What it does |
|---|---|---|---|
GET /presets | Read | 120 a minute (agent_read) | Every preset this workspace can see, each with its first 20 templates |
GET /presets/{id}/templates | Read | 120 a minute (agent_read) | One preset's whole template gallery |
- Both are reads. They cost nothing.
- MCP:
list_presets(passcapability_idfor one preset's full gallery). MCP tools.
A preset is not a separate submit path
There is no preset endpoint that starts work. You run a preset with POST /generations, capability_id set to its preset_ id, and config.template_id set to a template_id from these lists.
List presets
GET/api/v1/presetsAPI key
| Parameter | Type | Default | Notes |
|---|---|---|---|
limit | integer | 25 | Clamped to 1 to 50 |
cursor | string | none | The previous next_cursor, sent back exactly |
curl -s https://app.riffads.com/api/v1/presets \
-H "Authorization: Bearer $RIFFADS_API_KEY"{
"ok": true,
"presets": [
{
"capability_id": "preset_show_your_app",
"name": "Show Your App",
"description": "Put your app screenshot on a real person's phone, then bring it to life.",
"output_kind": "video",
"status": "available",
"requires_template": true,
"templates": [
{
"template_id": "captpl_0193c8f0a1b24e7f9d3c5a6b7e8f00a1",
"name": "Couch scroll",
"description": "Relaxed, at home, thumb on the screen",
"category": "Lifestyle",
"preview_url": "https://<public-preview-host>/templates/couch-scroll.mp4",
"preview_kind": "video"
}
],
"templates_total": 1,
"next_action": "Call get_capability_schema with capability_id \"preset_show_your_app\" to see its other fields, then call submit_generation with capability_id \"preset_show_your_app\" and config.template_id set to one of the template_id values listed with it. A preset is not a separate tool: submit_generation runs it like any other capability."
}
],
"total": 2,
"next_cursor": null
}Template names, counts and ids are examples. Read the live list, never hardcode one.
Preset fields
| Field | Type | Notes |
|---|---|---|
capability_id | string | preset_ prefix. Send it as capability_id to estimate and submit |
name | string | Display name. Can change. Never match on it |
description | string | Omitted, not null, when empty |
output_kind | image | video | audio | text | What comes out |
status | available | requires_plan | coming_soon | Only available can run. Retired presets are not listed |
required_plan | string | Only with requires_plan. The plan that includes it |
requires_template | boolean | true: config.template_id is required, so pick one of templates |
templates | array | The first 20 live templates, in gallery order |
templates_total | integer | All live templates. More than templates.length means this row is capped |
next_action | string | How to run it, written for an agent. Advice only |
- Order and cursor: the same as
GET /capabilities.next_cursoris the last row'scapability_id, andnullon the last page. totalcounts the presets this workspace can see.requires_template: truewithtemplates_total: 0means the preset cannot run right now. Itsnext_actionsays so.
Template fields
| Field | Type | Notes |
|---|---|---|
template_id | string | captpl_ prefix. The value for config.template_id |
name | string | Display name |
description | string | null | |
category | string | null | Gallery grouping. Free text: display only |
preview_url | string | A permanent public preview of RiffAds' own template art. Not a signed link, and it does not expire |
preview_kind | video | image | What preview_url holds |
A template id is a database id, not a slug
Read it from these routes every time. An id copied from an old list can be withdrawn by the time you submit, and the answer is then a refusal, not a render.
One preset's templates
GET/api/v1/presets/{id}/templatesAPI key
The path id is a preset capability_id. Returns every live template, with no cap and no paging.
curl -s https://app.riffads.com/api/v1/presets/preset_show_your_app/templates \
-H "Authorization: Bearer $RIFFADS_API_KEY"{
"ok": true,
"capability_id": "preset_show_your_app",
"name": "Show Your App",
"status": "available",
"requires_template": true,
"templates": [
{
"template_id": "captpl_0193c8f0a1b24e7f9d3c5a6b7e8f00a1",
"name": "Couch scroll",
"description": "Relaxed, at home, thumb on the screen",
"category": "Lifestyle",
"preview_url": "https://<public-preview-host>/templates/couch-scroll.mp4",
"preview_kind": "video"
}
],
"next_action": "Call get_capability_schema with capability_id \"preset_show_your_app\" to see its other fields, then call submit_generation with capability_id \"preset_show_your_app\" and config.template_id set to one of the template_id values listed with it. A preset is not a separate tool: submit_generation runs it like any other capability."
}required_plan appears only when status is requires_plan.
{
"error": {
"ok": false,
"code": "not_found",
"message": "No such preset. Call list_presets for the presets this workspace can use, or list_capabilities for everything else.",
"retryable": false,
"credits_charged": 0
}
}not_found covers a non-preset id (like veo_31), a typo, and a retired or internal preset.
REST names for the MCP tools in next_action
next_action is written for an agent and names MCP tools. Over REST:
next_action says | REST call |
|---|---|
get_capability_schema | GET /capabilities/{id} |
submit_generation | POST /generations |
list_presets with capability_id | GET /presets/{id}/templates |
list_capabilities | GET /capabilities |
Run a preset
Show Your App puts your app's screenshot on the phone a creator is holding. One upload plus one template.
Pick a template
GET /presets/preset_show_your_app/templates. Show the person the preview_url of each and keep the template_id they choose.
Read the schema
GET /capabilities/preset_show_your_app. It lists template_id and reference_images as required. Locked preset settings are absent: they come from the template. Capabilities API.
Upload the screenshot
POST /uploads, PUT the bytes, finalize, and keep the ast_ id. Uploads.
Estimate
curl -s https://app.riffads.com/api/v1/estimates \
-H "Authorization: Bearer $RIFFADS_API_KEY" \
-H "Content-Type: application/json" \
-d '{
"capability_id": "preset_show_your_app",
"config": {
"template_id": "captpl_0193c8f0a1b24e7f9d3c5a6b7e8f00a1",
"reference_images": [
{ "assetId": "ast_0193c8f0a1b24e7f9d3c5a6b7e8f0011", "alias": "image1", "role": "reference" }
]
}
}'The estimate checks the config exactly as submit does, so a wrong key or a missing template_id is refused here, before anything is spent.
Submit and wait
Send the same capability_id and config to POST /generations with max_credits set to the estimate's max_credits_needed. Then wait on the generation_id, or read the batch when the answer carries a batch_group_id. Generations.
Preset submit refusals
The usual submit refusals apply. These are the preset-specific ones:
| Cause | Code | HTTP | Retry |
|---|---|---|---|
template_id missing on a preset that requires one | invalid_config | 400 | no |
template_id is not one of this preset's templates | not_found | 404 | no |
| The template was withdrawn since you listed it | capability_unavailable | 404 | no |
| The preset needs a higher plan | required_plan | 403 | no |
On a template refusal, list the templates again and pick another.
Not here
- No preset authoring. Presets and templates are made by RiffAds.
- No preview files over the API other than
preview_url, which is template art, not your media. - No per-template price. Price the full config with
POST /estimates.