REST API
The AI video generation API for ads.
An AI video generation API makes video from your code. The RiffAds API takes a script and an AI actor and returns a lip-synced UGC video ad, paid from the same credits as the studio.
What it is
What is the RiffAds AI video generation API?
The RiffAds API is an AI video generation API for developers. Your code sends a script, an AI actor and a voice, and gets back a lip-synced UGC video ad as a download link. Every job is priced before it runs, capped by a number you set, and paid from the same credits as the studio.
The same API also makes images and B-roll video, runs editing tools like captions and resize, and starts ready-made workflows.
- Base URL
https://app.riffads.com/api/v1- Authentication
Authorization: Bearer sk_live_...
Send your key as a Bearer token. The
x-api-keyheader works too. Keys belong to the workspace and are shown once, when you create them in the app.- Scopes
Every key can read. Tick Generate to start jobs and Workflows to run workflows.
readBrowse capabilities, actors and voices, read generations back, and check the credit balance. Spends nothing.generateEverything in Read, plus uploading files and starting generations. This one spends credits.workflowsEverything in Read, plus starting a workflow run: a script written, spoken by an actor, captions burned in, in one call. One run is several generations, so it spends more credits than a single one.
Call it from a server. The API sends no CORS headers, so a key never belongs in a web page. There is no test mode: every key is live and every call is real.
Quickstart
Make your first ad in three calls
Price the job, start it, then collect the file. Every step is plain HTTP, so curl, a backend or an automation tool can make it.
- 01
Price the job
The estimate is free and needs only the read scope. It answers
credits,is_ceilingandmax_credits_needed.A talking actor is priced by the second of audio. Before the voice-over exists, the estimate prices the longest audio the model takes, so
is_ceilingis true and the real price will be lower.POST /api/v1/estimates curl -s -X POST https://app.riffads.com/api/v1/estimates \ -H "Authorization: Bearer $RIFFADS_API_KEY" \ -H "Content-Type: application/json" \ -d '{ "capability_id": "actor_ultra", "config": { "script": "Two weeks of battery, in a case this small." } }' | jq '{credits, is_ceiling, max_credits_needed}' - 02
Start it with a spending cap
This needs a key with the
generatescope. It holds the credits and answers201with ageneration_id.max_creditscaps what the job may hold, and a job holds its price plus 10 percent. A job over the cap is refused, never trimmed. Send the estimate'smax_credits_neededas$MAX: the hold is measured from the finished voice-over, so it comes in at or under that number.approved_voice_generation_idis the finished voice-over: attsjob you run first with the same script, actor and voice. Actor and voice ids come fromGET /api/v1/actorsandGET /api/v1/voices.The workspace limit applies too: 600 credits per job by default, which fits about 19 seconds of OmniHuman 1.5 video. For a longer ad, an owner or admin raises the limit in the app first.
POST /api/v1/generations MAX=... # max_credits_needed from step 1 curl -s -X POST https://app.riffads.com/api/v1/generations \ -H "Authorization: Bearer $RIFFADS_API_KEY" \ -H "Content-Type: application/json" \ -d '{ "capability_id": "actor_ultra", "config": { "script": "Two weeks of battery, in a case this small." }, "actor_id": "act_0193c8f0a1b24e7f9d3c5a6b7e8f0011", "voice_id": "voc_0193c8f0a1b24e7f9d3c5a6b7e8f0022", "approved_voice_generation_id": "gen_0193c8f0a1b24e7f9d3c5a6b7e8f0033", "max_credits": '"$MAX"' }' | jq -r '.generation_id' - 03
Get the file
Each call waits up to 20 seconds. Call it again while
still_runningis true. When the job is done,outputs[0].urlis a signed link that lasts 10 minutes: download the file, do not store the link.Rather not loop? Register a webhook and read the generation when
generation.completedarrives.GET /api/v1/generations/{id}/wait GEN=gen_... # the generation_id from step 2 curl -s https://app.riffads.com/api/v1/generations/$GEN/wait \ -H "Authorization: Bearer $RIFFADS_API_KEY" \ | jq '{still_running, status: .generation.status, url: .generation.outputs[0].url}'
Endpoints
Video generation API endpoints
Every path below is on https://app.riffads.com. The read scope comes with every key. The OpenAPI document is the full contract.
| Method | Path | What it does | Scope |
|---|---|---|---|
| Make and track ads | |||
| POST | /api/v1/estimates | Price an exact job against the published rate card. Free. | read |
| POST | /api/v1/generations | Start a job. It holds the credits and answers 201 with the job's id. | generate |
| GET | /api/v1/generations | Your history, filtered by status, capability or date. | read |
| GET | /api/v1/generations/{id} | One job: its status, its cost and download links that last 10 minutes. | read |
| GET | /api/v1/generations/{id}/wait | Waits up to 20 seconds for a job to finish, then answers. | read |
| GET | /api/v1/batches/{id} | Every take of a request that asked for variants. | read |
| Actors, voices and models | |||
| GET | /api/v1/capabilities | Everything the API can make: talking actors, video, images and tools. | read |
| GET | /api/v1/capabilities/{id} | The JSON Schema one capability's config must match, with a valid example. | read |
| GET | /api/v1/actors | The actors this workspace can cast: the library plus its own. | read |
| GET | /api/v1/voices | The voices this workspace can use: the library plus its own. | read |
| GET | /api/v1/presets | Ready-made ad formats and their templates. | read |
| GET | /api/v1/presets/{id}/templates | One preset's full template gallery. | read |
| Files | |||
| POST | /api/v1/uploads | Reserve an upload and get a link to send the file to. | generate |
| POST | /api/v1/uploads/{assetId}/finalize | Finish an upload. The file is checked before it can be used. | generate |
| POST | /api/v1/uploads/from-url | Import an image, video or audio file from a public link. | generate |
| GET | /api/v1/assets | Search the workspace library: uploads, imports and renders. | read |
| GET | /api/v1/assets/{id} | One file's details. | read |
| GET | /api/v1/assets/{id}/download | A signed download link that lasts 10 minutes. | read |
| Workflows | |||
| GET | /api/v1/workflows/templates | Ready-made workflows and the inputs each one takes. | read |
| POST | /api/v1/workflows/templates/{key}/invoke | Run a template in one call, with one max_credits for every step. | workflows |
| POST | /api/v1/workflows/{id}/invoke | Run a workflow your workspace already has. | workflows |
| GET | /api/v1/workflows/{id}/runs | One workflow's runs, newest first. | read |
| GET | /api/v1/workflow-runs | Every run in the workspace, with its cost so far. | read |
| GET | /api/v1/workflow-runs/{id} | One run: its current step, its outputs and its cost. | read |
| Credits and webhooks | |||
| GET | /api/v1/credits/balance | Your balance, and what this key may still spend under its limits. | read |
| GET | /api/v1/webhooks | Your webhook endpoints. | read |
| POST | /api/v1/webhooks | Add an endpoint. Its signing secret is shown once. | generate |
| DELETE | /api/v1/webhooks/{id} | Remove an endpoint and its pending deliveries. | generate |
| Status and spec | |||
| GET | /api/v1/health | Checks that the API is up. No key needed. | No key |
| GET | /api/v1/health/ready | Checks that the API can reach its database. No key needed. | No key |
| GET | /api/v1/openapi.json | The OpenAPI 3.1 document. No key needed. | No key |
Pricing
What the API costs
There is no separate API plan. API, MCP, Agent Skills and CLI are in every plan, and every call spends credits from the same balance as the studio, at the same prices. Credits never expire.
848
credits for a 30 second talking actor ad, voice included
RiffAds
$49
a month for Launch, the entry plan: 4,500 credits and the full API
RiffAds
$0.01
per credit. Estimates are free and credits never expire.
RiffAds
What credits buy
| What | Model | Credits | Per |
|---|---|---|---|
| Talking actor | OmniHuman 1.5 | 28 | sec |
| Video | Veo 3.1 | from35 | sec |
| Video | Kling 3 | from14.7 | sec |
| Video | MiniMax H3 Max | from8.8 | sec |
| Image | Nano Banana 2 | from14 | image |
| Image | GPT Image 2.5 | from11.2 | image |
| Image | Grok Image | from3.5 | image |
| Captions | Burned in | 5.3 | min |
| Camera angle | Reshoot a photo | 14 | call |
A talking actor ad made from a script is two jobs: the voice-over, then the video. At 30 seconds that is about 8 credits of voice and 840 credits of video. Over the API, a video that long is above the default per-job limit of 600 credits, so an owner or admin raises the limit in the app first.
A job is charged at or below what it held, and a job that fails releases its hold.
Webhooks
Webhooks when the video is ready
Skip the wait loop. Register an https endpoint and RiffAds tells your server when work settles.
Events you can subscribe to
generation.completed- A job finished. Read it for its files.
generation.failed- A job failed. Its hold is released.
batch.settled- Every take of a variants request has finished.
workflow_run.completed- A workflow run finished, even if only part of it delivered.
workflow_run.failed- A workflow run failed or was canceled.
credits.low- Available credits fell below 1,000. Sent once per refill.
How a delivery is signed
Every delivery follows the Standard Webhooks convention, so the standardwebhooks library checks it as it is.
webhook-id- The delivery id. It stays the same on every retry, so dedupe on it.
webhook-timestamp- Unix seconds of this attempt. Reject anything older than 5 minutes.
webhook-signaturev1,then a base64 HMAC SHA-256 of{id}.{timestamp}.{body}, made with yourwhsec_secret.
Retries
5 attempts. The first goes out at once, then after 5 minutes, 30 minutes, 2 hours and 12 hours, so the last lands about 14.5 hours after the event. Each attempt times out after 10 seconds.
No download link in the event
An event carries ids and credits, never a download link: a link would expire long before the last retry. Read the generation with GET /api/v1/generations/{id} for a fresh one.
Up to 10 endpoints per workspace, https only. Manage them with the API or in the app.
curl -s -X POST https://app.riffads.com/api/v1/webhooks \
-H "Authorization: Bearer $RIFFADS_API_KEY" \
-H "Content-Type: application/json" \
-d '{
"url": "https://example.com/riffads-webhook",
"events": ["generation.completed", "generation.failed"]
}' | jq -r '.secret'POST https://example.com/riffads-webhook
User-Agent: RiffAds-Webhooks/1.0
webhook-id: {delivery id}
webhook-timestamp: {unix seconds}
webhook-signature: v1,{base64 signature}
{
"id": "{delivery id}",
"type": "generation.completed",
"created_at": "{when it happened}",
"data": { ... }
}Guardrails
Built to be safe to automate
Code runs with nobody watching. These rules stop a loop, a typo or a retry from spending more than you meant.
Priced before it runs
The estimate is free and uses the same rate card as the charge. It tells you the most a job can cost before anything is held.
A cap on every job
max_creditsis required on every call that spends. If the job's hold, its price plus 10 percent, is over it, the job is refused with402 max_credits_exceeded. It is never trimmed to fit, and a refusal charges nothing.Limits a person sets
On top of
max_credits, the workspace caps API and agent spend: 600 credits per job and 2,000 per rolling 24 hours by default, plus an optional 24 hour budget for each key. An owner or admin changes them in the app. The default per-job limit fits about 19 seconds of OmniHuman 1.5 video.Retries that do not pay twice
There is no idempotency key to manage. Each key runs one job at a time, so a resend while the first job runs is refused with
409 submission_in_flightand the id of the job to wait for, and nothing is charged. The same request after the first one finished is a new take.Rate limits you can read
Per key, per minute: 60 estimates, 20 new jobs and 120 reads. Each key also has an allowance of 120 requests that resets after a quiet minute. A
429carriesRetry-After.Errors you can branch on
Every error is JSON under
error, with acode, amessage,retryableandcredits_charged. A spend refusal addslimit.bound_by:max_credits,org_per_generation,api_key_budgetororg_daily.
Checked before it spends
Scripts, prompts and uploads are moderated before any credits are held, the same way on every path.
Files, never posts
The API returns a download link. It never posts to Meta, TikTok, YouTube or X.
Server side only
No CORS, so a key stays on your server. Every key is live: there is no test mode.
Compared
Video ad APIs compared
How each tool sells API access, as its own pages showed it on September 25, 2026. Prices change, so check the source before you decide.
| API | Separate API plan | How it is priced | Official MCP server | Sources |
|---|---|---|---|---|
| RiffAds API | No. API, MCP, Agent Skills and CLI are in every plan. | Credits from one balance, 1 credit is $0.01, on a public rate card. | Yes, on the same credits and limits. | |
| Arcads API | Not published. arcads.ai shows no price list. | Credits from the Arcads plan. The API has an endpoint for the credit balance. | Yes, at mcp.arcads.ai, with an active subscription. | |
| Creatify API | Yes. API Starter $99 a month for 500 credits, API Pro $299 a month for 2,000 credits. | Credits per feature, for example AI Avatar at 5 credits per 30 seconds. | Yes, as a feature of the Pro app plan. | |
| HeyGen API | Yes. Pay-as-you-go API credits, which expire after 12 months. | US dollars by type and length of output. Per-operation prices are shown in the API dashboard. | Yes, with OAuth, on the plan's credits. HeyGen sizes it for trials and points to an API key for scale. | |
| MakeUGC API | Yes. API Starter $99 a month for 2,000 credits, API Pro $299 a month for 6,000 credits. | Credits. App plans are separate and start at $59 a month for 500 credits. | No official MCP. A community one drives the web app. | |
| Synthesia API | No. API access starts on the Creator plan: $89 a month, or $64 a month billed yearly. | Up to 360 minutes of video a year, taken from the plan's limits. | Yes, in public beta. |
FAQ
AI video API questions
Start building
Create a key. Make the first ad.
A key comes with every plan. Price a job for free, then run it on the credits you already have.

Stop waiting on creators. Ship the ad today.
Book a call for a walkthrough, or log in and make your first ad.
New here? Try Growth for $1