Quickstart
Make a 5-second video from a prompt: get a key, check the price, start the render, wait for it, and download the MP4. Every request goes to https://api.everyframe.studio/v1.
Make an API key
In the console, choose Create key. Copy the key when it appears, because it is shown only once, and keep it in an environment variable on your server.
export EVERYFRAME_API_KEY=ef_live_...
Then add API credits on the Billing page. Check that the key works; the reply names it and shows your API credit balance:
curl https://api.everyframe.studio/v1/key \
-H "Authorization: Bearer $EVERYFRAME_API_KEY"Check the price
A quote takes the same body as a render and charges nothing. Use it to show your users a price, or to stop before an expensive request.
curl https://api.everyframe.studio/v1/render/quote \ -H "Authorization: Bearer $EVERYFRAME_API_KEY" \ -H "Content-Type: application/json" \ -d '{"modelId":"seedance-2-0-fast","duration":5,"resolution":"720p"}'
200 OK { "modelId": "seedance-2-0-fast", "mode": "video", "duration": 5, "resolution": "720p", "credits": 130 }
Start the render
Send the prompt with the same settings. The credits are taken now and you get the render back straight away, with its id.
curl https://api.everyframe.studio/v1/render \ -H "Authorization: Bearer $EVERYFRAME_API_KEY" \ -H "Content-Type: application/json" \ -d '{ "modelId": "seedance-2-0-fast", "prompt": "A lighthouse keeper climbs the stairs at dusk, handheld", "duration": 5, "resolution": "720p", "aspect": "16:9" }'
202 Accepted { "render": { "id": "rnd_Qm3vX8pL2kNc7RtY", "status": "queued", "credits": 130, ... }, "credits": 4865 }
The top-level credits is your API credit balance after the charge.
Wait for it
Ask for the render every 5 to 10 seconds. Its status moves from queued to running, then ends as succeeded or failed. While it runs, progress (0 to 1) and stage say how far along it is.
curl https://api.everyframe.studio/v1/render/rnd_Qm3vX8pL2kNc7RtY \
-H "Authorization: Bearer $EVERYFRAME_API_KEY"200 OK { "render": { "id": "rnd_Qm3vX8pL2kNc7RtY", "status": "succeeded", "width": 1280, "height": 720, "videoUrl": "/render/rnd_Qm3vX8pL2kNc7RtY/video?t=...", "posterUrl": "/render/rnd_Qm3vX8pL2kNc7RtY/poster?t=...", ... }, "credits": 4865 }
A failed render gives its credits back automatically, and its error says what went wrong.
Download the video
The videoUrl and posterUrl are relative to the API base and carry their own access token, so they work without the key, in a browser or a <video> tag. Add &full=1 to the video URL for the full-quality master rather than the lighter streaming copy.
curl -L "https://api.everyframe.studio/v1/render/rnd_Qm3vX8pL2kNc7RtY/video?t=...&full=1" -o clip.mp4Treat these URLs like the files themselves: anyone with the link can watch the clip.
API keys and scopes
A key acts as you and spends your credits. Send it on every request as Authorization: Bearer ef_live_.... Keep keys on a server: never put one in a web page or a mobile app. When you make a key you choose what it can do:
| Scope | Allows |
|---|---|
render | Quotes and new renders. This is the scope that spends credits. |
read | Reading renders, listing them, and downloading files. |
upload | Uploading reference images, video and audio, and listing uploads. |
Any key can call GET /v1/key and GET /v1/render/models. A key can also have a monthly credit limit, which resets on the 1st of each month (UTC), and an expiry date. Keys can't manage other keys or change your account: do that in the console.
API credits
Renders made with an API key are paid from your API credits. They are a separate balance from your EveryFrame Studio credits: Studio credits never pay for API calls, and API credits never pay for Studio work. Buy them on the Billing page with TAO or other crypto, at 500 API credits to the dollar.
A render is charged when it starts, at the price its quote gave, and a failed render gives its credits back to your API balance.
List models
GET/v1/render/models
Every model with its id, maker, the lengths and resolutions it makes, its prices (credits by "resolution:seconds", or "image"), the reference inputs it takes (inputs, referenceModes, referenceLimits) and its longest prompt (maxPrompt). No key needed. The same list is on the models page.
Quote a render
POST/v1/render/quote
Takes modelId, duration, resolution and referenceMode, and returns them as the render would use them (the length and resolution snapped to what the model makes) with the exact credits. An unknown model is a 404.
Start a render
POST/v1/render
| Field | What it is |
|---|---|
modelId | Required. A model id from the list. |
prompt | Required. What to make. Each model publishes its own maximum length. |
duration | Seconds, for video. Snapped to the nearest length the model makes. Default 5. |
resolution | For video, for example "480p", "720p" or "1080p". Default 480p. |
aspect | "16:9" (default), "9:16", "1:1", "4:5" or "21:9". |
attachmentIds | Reference files you uploaded, in order. See reference files. |
referenceMode | How the references are used: "first-frame", "first-last" (opening and closing frames), or "omni" (characters, motion and sound). Each model lists the modes it takes. |
negative | What to avoid, up to 500 characters, where the model supports it. |
seed | A number, to repeat a result where the model supports it. |
Returns 202 with the render and your new balance. The render's credits is what was charged.
Get a render
GET/v1/render/:id
The render's status, progress, stage, settings, credits, error when it failed, and once it has succeeded its width, height, bytes, videoUrl, videoFullUrl and posterUrl.
List renders
GET/v1/renders
Your account's recent renders, newest first, including ones made in the Studio.
Download files
GET/v1/render/:id/video?t=…
GET/v1/render/:id/poster?t=…
Use the URLs from the render, which carry their token. Video is MP4 and supports range requests; the poster is a JPEG still. Copy files you need to keep long-term to your own storage.
Reference files
POST/v1/render/attachment
Send the file itself as the request body, with its content type: JPEG, PNG, WebP or AVIF images, MP4, MOV or WebM video, or MP3, WAV, M4A, AAC or OGG audio. You get back an attachment with its id, which you pass in attachmentIds.
curl https://api.everyframe.studio/v1/render/attachment \ -H "Authorization: Bearer $EVERYFRAME_API_KEY" \ -H "Content-Type: image/jpeg" \ --data-binary @first-frame.jpg
Then render from it, for example "attachmentIds": ["att_..."], "referenceMode": "first-frame". GET /v1/attachments lists your uploads.
Errors and limits
Errors come back as JSON with a sentence you can show people, a code to branch on, and the field at fault when there is one.
| Status | Code | What to do |
|---|---|---|
| 400 | prompt_too_long, bad_attachment | Fix the field named in the reply. |
| 401 | invalid_api_key, api_key_expired | The key is missing, wrong, revoked or past its end date. |
| 402 | insufficient_credits | Not enough API credits. Add some on the Billing page. |
| 402 | key_limit_reached | The render would pass the key's monthly limit. Raise it in the console, or wait for the 1st. |
| 403 | insufficient_scope | The key isn't allowed to do that. Make a key with the scope you need. |
| 404 | not_found | No such model, or no such render on this account. |
| 422 | blocked | The prompt was refused by the content policy. Nothing was charged. |
| 429 | rate_limited | Up to 40 new renders per 15 minutes per account. Wait and retry. |
| 503 | provider_unavailable | The model is down for now. Nothing was charged; try another model. |
Claude Code and MCP
To let an agent make videos for you, add the EveryFrame MCP server to Claude Code. It signs in through your browser, and each call has a credit cap.
claude mcp add everyframe -- npx -y https://app.everyframe.studio/mcp/everyframe-mcp-0.1.0.tgz
There is also a skill: npx skills add https://app.everyframe.studio. See EveryFrame for agents.