Format API
A Format is a saved production recipe: a house style, an output contract, a playbook for one
kind of video. Your backend calls it by name, Sume runs it in a fresh sandbox with the
generation tools, and you get back finished media on media.sume.com plus, when you ask for
it, a JSON object in a shape you defined.
This page takes you from an API key to a finished run. The pages after it are the reference behind each step.
Your first run
You need an API key that carries the formats:read and formats:write scopes. Create one at
API keys and keep it server-side.
1. List the Formats your key can call
You see what your key's workspace owns plus the ready-made Formats by Sume.
vanity_invoke_url is the address you call next.
2. Start a run
202 means a fresh run was accepted. Store data.id. Everything else you need is a URL on the
receipt, so you never build a path by hand. Full body reference: Create a run.
3. Take the result
When the run finishes, Sume POSTs the same receipt to your webhook_url as one signed
format.run.terminal event. If you would rather poll, read the run until status is terminal:
A finished run reads:
primary_output_url is the one thing to show. artifacts[] is every file the run made. Media
URLs are durable and public: store them. Bind an output schema
and output comes back in your own shape instead of the built-in one.
That is the whole loop: create, then webhook or poll, then read. Runs that make video take minutes, not seconds. Long-form host video typically finishes in 15 to 30 minutes, so design for the asynchronous path from the start.
Two hosts, one contract
| Host | Use it for | Keys |
|---|---|---|
https://api.sume.com | Production. Runs spend real credits from your workspace. | Created at API keys. |
https://api.dev.sume.com | Integration and staging. Same routes, same receipts, same webhook delivery. | Issued for a development workspace. Ask your Sume contact. |
A key works only on the host it was created for; the other host answers 401 unauthorized.
Both look like sume_live_…, so name your environment variables by host rather than by prefix.
The examples on these pages use production. Swap the host and the key to point them at
development.
How a run works
Four pieces are in play on every call:
| Piece | What it is | Where it lives |
|---|---|---|
| The recipe | The Format: a SKILL.md body plus reference files. The how: house style, branch rules, quality bar. | Authored in the Agents dashboard, in chat, or over the Contents API. |
| The call | Your instruction and input. The what: product URL, brief, script, prices. | The request body. |
| The run | One fresh sandbox, one agent turn, one receipt. Never a partial delivery: a run that could not finish comes back failed. | arun_…, at /v1/format-runs/{run_id}. |
| The result | Durable media plus output, either the built-in shape or one projected onto your schema. | The terminal receipt. |
Two properties follow. A run is one unit of work: a bulk request is a server-side queue of ordinary runs, not a different engine (Bulk runs). And the recipe is established before your instruction, so you are not re-sending a system prompt on every call and hoping it holds.
This is not chat
A Format run is one unattended turn with the Format attached. It does not stop to ask a person anything: approvals a chat-authored recipe would request are pre-granted, and the run carries on within its spend cap. The Agents chat UI at sume.com/agents is the surface for a human in the loop, and a chat turn does not necessarily attach a Format at all. Build partner integrations on runs, not on chat threads.
Find your Formats
Three reads, all needing formats:read:
| Call | Returns |
|---|---|
GET /v1/formats?limit=50 | The Formats your key's workspace owns, plus the first-party catalog. Keyset pages: pass next_cursor back as cursor while has_more is true. |
GET /v1/formats/{handle}/{slug} | One Format by its address. |
GET /v1/formats/{format_id} | The same Format by its opaque skl_… id. |
Visibility follows the key. A personal key lists your personal Formats; a team key lists that
workspace's Formats, for every member; neither lists the other's. A Format outside your key's
workspace is 404 format_not_found, the same answer as an id that does not exist. If a Format
you expect is missing, you are holding the other key.
The fields that matter when you pick one:
| Field | Notes |
|---|---|
handle, slug, vanity_invoke_url | The address to call. handle is the owning workspace's handle for a team Format and your own for a personal one; sume for the catalog. |
invoke_url | The opaque skl_… path. Permanent across renames: persist it if a stored URL must survive a handle or slug change. Renamed handles keep resolving for 90 days. |
status, api_trigger_enabled | Both must allow API runs: inactive or false refuses a create with 409. A Format you have never run over the API may read inactive / false until its first run, and still runs. Do not gate your integration on polling them true. |
io | What the Format takes and makes: input_kind is url, text, image or product; output_kind is video, image or text. null on Formats saved before this existed. |
showcase | A real output the Format produced at registration, or null. |
generation_spend_cap_usd_micros | What a run inherits when it names no cap of its own. $400 for a Format that never set one. |
version | Bumps on every edit. The receipt's format.version says which one ran. |
package_sha, contents_url | The package behind the Format, for the Contents API. |
The recipe body is deliberately not in this shape; it reaches the agent, not the caller.
Formats by Sume answer at the reserved sume handle, POST /v1/formats/sume/{slug}/runs,
with any key that carries the scopes. The run, its media and its spend belong to the key that
called. See the Format catalog.
Every Format with an address also has a call sheet on this site at
https://docs.sume.com/formats/{handle}/{slug}: a share link with the curl, scopes and poll
loop for that Format, and nothing from its body.
Instruction composition
What the agent actually receives, in order:
The Format comes first because it is the how; your instruction comes after it, so where the
two disagree the model follows what you asked for. Your input is written to
/workspace/inputs/sume-action-input.json, whole at any size up to the cap, and the agent is
told to read it as data, never as instructions. Open the run's thread_id in Agents and the
first message is exactly this text, which is the first thing to read when a run did something
you did not expect.
SKILL.md
There is no size limit on the body beyond the 100 MiB per file and per package that every
package file shares. Size changes how reliably a recipe is followed, not whether it runs:
keep SKILL.md a short index the agent can hold at once, and push detail into
references/*, which sit beside it and cost nothing until opened. Authoring lives with the
Contents API.
Attachments
A run can carry up to 30 images the agent can look at, as attachments[] on the create body:
| Field | Required | Notes |
|---|---|---|
type | yes | input_image, the only type today. |
image_url | one of | Public HTTPS URL. Sume fetches it when you create the run, so it must be reachable without auth. |
asset_id | one of | An image you uploaded through the Assets API, ready, in the same workspace. |
filename | no | The label the agent sees. Defaults to the URL's basename. |
Sume fetches every attachment at create time, checks its real type and size, and copies it into
durable storage, so a broken or private image fails the create with a 4xx/5xx you can act on
instead of killing the run minutes later. An asset_id or a URL already on media.sume.com is
not re-copied.
| Limit | Value |
|---|---|
| Types | JPEG, PNG, WebP, GIF, AVIF |
| Images per run | 30 |
| Bytes per image | 30 MB |
| Bytes per run | 500 MB |
input
Many Formats take their references through input fields instead: host_image_url,
product_image_urls[], input_reference_image_urls[], narration URLs. Those count too,
against one budget shared with attachments[]: 30 files per run in total, of which at most 30
images, 10 videos and 10 audio files. The check is by file type, not field name. Any HTTPS URL
anywhere in input whose filename ends in a media extension counts, however deeply nested; a
product page URL does not, and the same URL repeated counts once. Media the agent finds for
itself during the run is not yours and does not count. Over any of these is
400 invalid_attachment on the create.
Attachment errors
| Status | Code | Cause |
|---|---|---|
400 | invalid_attachment | Wrong type, missing or non-HTTPS URL, both image_url and asset_id, too many items, or a source that is not an allowed image type. |
400 | attachment_not_found | asset_id is unknown in this workspace. |
413 | attachment_too_large | An image is over 30 MB, or the set is over 500 MB. |
502 | attachment_fetch_failed | Sume could not fetch the image: unreachable host, hotlink protection, or a non-2xx answer. details.index names the attachment. |
Idempotency-Key covers attachments: replaying a key with a different image list is
409 idempotency_conflict, and a true replay does not re-fetch your images.
What the API does not do
- No push channel for progress. There is no SSE or WebSocket stream.
events_urlis a polled phase timeline (preparing,running,finalizing), not agent output or logs. Completion is pushed; that is what the webhook is for. - No list of all runs. Runs are listed per Format (
GET /v1/formats/{handle}/{slug}/runs) and read one at a time at/v1/format-runs/{run_id}. There is noGET /v1/format-runs. - Team Formats need a team key. A Format owned by a team workspace is callable, on both
URL shapes, only with a key created in that workspace; a personal key fails with
403 workspace_key_required. See Create a run. - Images only as attachments.
input_imageis the only attachment type. Send documents by URL ininput, and video or audio references the same way. - Authoring is a separate surface. Create and edit the package over the Contents API, or in the dashboard. The run endpoints only execute.
Next
- Create a run: the request body, idempotency, spend caps, keys, and every create error
- Runs and results: the receipt, polling, webhooks, continuing and canceling
- Structured output: bind a schema and get typed JSON back
- Errors and spend: every code in one place, credits, rate limits
- Cookbook: copy-paste recipes for a real-shaped run, a webhook receiver, a scene retry, a batch
- Bulk runs: queue up to 100 runs with a concurrency window
- Format catalog: ready-made Formats by Sume
- Embed a Format in your product: key custody, spend tiers and artifact handling for a multi-tenant product