Skip to content

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-key header 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.

  1. 01

    Price the job

    The estimate is free and needs only the read scope. It answers credits, is_ceiling and max_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_ceiling is 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}'
  2. 02

    Start it with a spending cap

    This needs a key with the generate scope. It holds the credits and answers 201 with a generation_id.

    max_credits caps 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's max_credits_needed as $MAX: the hold is measured from the finished voice-over, so it comes in at or under that number.

    approved_voice_generation_id is the finished voice-over: a tts job you run first with the same script, actor and voice. Actor and voice ids come from GET /api/v1/actors and GET /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'
  3. 03

    Get the file

    Each call waits up to 20 seconds. Call it again while still_running is true. When the job is done, outputs[0].url is 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.completed arrives.

    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.

RiffAds REST API endpoints, grouped by job, with the method and the key scope each one needs
MethodPathWhat it doesScope
Make and track ads
POST/api/v1/estimatesPrice an exact job against the published rate card. Free.read
POST/api/v1/generationsStart a job. It holds the credits and answers 201 with the job's id.generate
GET/api/v1/generationsYour 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}/waitWaits 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/capabilitiesEverything 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/actorsThe actors this workspace can cast: the library plus its own.read
GET/api/v1/voicesThe voices this workspace can use: the library plus its own.read
GET/api/v1/presetsReady-made ad formats and their templates.read
GET/api/v1/presets/{id}/templatesOne preset's full template gallery.read
Files
POST/api/v1/uploadsReserve an upload and get a link to send the file to.generate
POST/api/v1/uploads/{assetId}/finalizeFinish an upload. The file is checked before it can be used.generate
POST/api/v1/uploads/from-urlImport an image, video or audio file from a public link.generate
GET/api/v1/assetsSearch the workspace library: uploads, imports and renders.read
GET/api/v1/assets/{id}One file's details.read
GET/api/v1/assets/{id}/downloadA signed download link that lasts 10 minutes.read
Workflows
GET/api/v1/workflows/templatesReady-made workflows and the inputs each one takes.read
POST/api/v1/workflows/templates/{key}/invokeRun a template in one call, with one max_credits for every step.workflows
POST/api/v1/workflows/{id}/invokeRun a workflow your workspace already has.workflows
GET/api/v1/workflows/{id}/runsOne workflow's runs, newest first.read
GET/api/v1/workflow-runsEvery 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/balanceYour balance, and what this key may still spend under its limits.read
GET/api/v1/webhooksYour webhook endpoints.read
POST/api/v1/webhooksAdd 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/healthChecks that the API is up. No key needed.No key
GET/api/v1/health/readyChecks that the API can reach its database. No key needed.No key
GET/api/v1/openapi.jsonThe 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

Credits per unit for each model, the same in the API and the studio
WhatModelCreditsPer
Talking actorOmniHuman 1.528sec
VideoVeo 3.1from35sec
VideoKling 3from14.7sec
VideoMiniMax H3 Maxfrom8.8sec
ImageNano Banana 2from14image
ImageGPT Image 2.5from11.2image
ImageGrok Imagefrom3.5image
CaptionsBurned in5.3min
Camera angleReshoot a photo14call

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-signature
v1, then a base64 HMAC SHA-256 of {id}.{timestamp}.{body}, made with your whsec_ 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.

POST /api/v1/webhooks
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'
What your endpoint receives
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_credits is required on every call that spends. If the job's hold, its price plus 10 percent, is over it, the job is refused with 402 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_flight and 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 429 carries Retry-After.

  • Errors you can branch on

    Every error is JSON under error, with a code, a message, retryable and credits_charged. A spend refusal adds limit.bound_by: max_credits, org_per_generation, api_key_budget or org_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.

Video ad APIs compared: separate API plan, pricing unit and official MCP server, with sources
APISeparate API planHow it is pricedOfficial MCP serverSources
RiffAds APINo. 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 APINot 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 APIYes. 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 APIYes. 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 APIYes. 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 APINo. 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

Still unsure? Book a call

Yes. Send a talking actor job to POST /api/v1/generations and RiffAds makes a new video of an AI actor whose lips match the audio. The audio can be a voice-over made from your script, in 74 voice languages, or your own recording. It makes a new video. It does not dub an existing one.

On RiffAds there is no API fee. Jobs spend credits at the published rate card, and 1 credit is $0.01. A 30 second talking actor ad is about 848 credits, voice included. Plans start at $49 a month for 4,500 credits. The estimate endpoint prices any job for free before you spend.

No. API, MCP, Agent Skills and CLI are included in every plan. Every API call spends credits from the same balance as the studio, at the same prices, so there is no separate API plan to buy. Credits never expire.

Yes. Register an https endpoint with POST /api/v1/webhooks or in the app, and choose events such as generation.completed and generation.failed. Each delivery is signed with Standard Webhooks headers and tried up to 5 times over about 14.5 hours. It carries ids, not a download link, so read the generation for a fresh link.

No. RiffAds never posts to Meta, TikTok, YouTube, X or any other platform, and it does not connect to an ad account. The API returns a signed link to the finished file. You download it and publish it wherever you want.

Use the REST API when your own code runs the job: a backend, a script, or a tool like n8n, Make or Zapier. Use the MCP server when an AI agent such as Claude, ChatGPT or Cursor should make the ad from a chat. Both spend the same credits under the same limits.

Every job must name max_credits, and a job that would hold more is refused, never trimmed. A person also sets workspace limits: 600 credits per job and 2,000 credits per rolling 24 hours by default, plus an optional daily budget for each API key. The default per-job limit fits about 19 seconds of OmniHuman 1.5 video, so an owner or admin raises it in the app for a longer ad. Each refusal names the limit that stopped it and charges nothing.

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.

Using an AI agent instead? Claude video generation

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