Developers
Building on the Sume API: keys and hosts, jobs and runs, polling, webhooks, idempotency, errors and rate limits, the SDK, the CLI, and MCP auth.

A Hurl file for a Sume job: submit, poll until terminal, fetch
A plain-text Hurl file chains submit, a retrying status poll on data.terminal, and the result read. Run it in CI with hurl --variable and an Idempotency-Key.

Image brief template: consistent Sume prompts with string.Template
Stop rewriting prompts by hand. Keep subject, style, lighting and constraints as fields, fill them from data and send the same shape to Sume's image endpoint.

Jupyter contact sheet: one prompt across four Sume image models
A notebook cell that sends one prompt to four Sume image models, tiles the results into a labeled contact sheet with Pillow, and prints each billed cost.

Kestra webhook trigger has no HMAC: verify Sume deliveries first
Kestra's Webhook trigger is protected by its key alone. Verify Sume's sume-v1 signature in a thin relay, then start the flow, and submit with a stable key.

Koa receiver for Sume webhooks: verify with koa-bodyparser rawBody
koa-bodyparser keeps the raw string on ctx.request.rawBody. Check the sume-v1 HMAC against it, not against a re-stringified ctx.request.body, then answer 204.

Sume docs for a coding assistant: llms.txt, llms-full.txt, .md
docs.sume.com serves a 73-link llms.txt index, one llms-full.txt file and any page as markdown by adding .md. Which to hand to a coding assistant, and when.

nginx 413 on a Sume run webhook: raise client_max_body_size
nginx rejects bodies over client_max_body_size, default 1m, with 413. A Sume run receipt can reach 1 MiB, so set the limit on the webhook location and test it.

Nuxt server route for Sume webhooks: readRawBody, then verify
A Nuxt 3 or 4 server route at server/api/sume.post.ts that reads the raw body with readRawBody, checks sume-v1 with node:crypto, and answers 204 fast.

Poll Sume audio jobs at the recommended interval, not a fixed sleep
The Sume job status response tells you when to poll next and whether the job is terminal. Read those fields instead of hardcoding sleep(2).

pytest and respx: fake a Sume job that is queued, then completed
Test your Sume poll loop with respx: a queued, a processing and a completed response in order, with sleep injected so the test finishes in milliseconds.

React Router 7 resource route as a Sume webhook receiver
A React Router 7 route module with only an action is a resource route. Read request.text(), call verifyWebhook from @sume-com/sdk, answer 204, branch on event.

Spring Boot endpoint for Sume webhooks: take the body as byte[]
Take @RequestBody byte[] so Spring never re-encodes the JSON, feed timestamp, a dot and the bytes to Mac HmacSHA256, and compare with MessageDigest.isEqual.

Streamlit image generator app with the Sume Images API (30 lines)
A 30-line Streamlit app: pick a Sume image model from the live catalog, type a prompt, show the result and the billed cost. Handles 200 and 202 responses.

Sume STT metadata: tag a transcript job with your own ids
The metadata field on a Sume STT request is stored with the job and is not sent to the speech provider. Use it to tie transcripts to your records.

Sume STT sentence segmentation fails closed when no words are timed
If the speech provider returns no timed words, a Sume STT request with segmentation returns a typed error instead of guessed sentences. Plan for it.

Sume SDK: try/catch misses a 402, generated calls return { error }
Generated @sume-com/sdk operations return { data, error, response } instead of throwing, so a 402 or 429 slips past try/catch. Check error on every call.

Sume STT language_code: set a hint or omit it for auto-detect?
language_code is optional on Sume STT. Omit it to auto-detect, pass a BCP-47 hint like en or ko when you know the language. A quick way to choose.

Sume sync mode waits at most 30 seconds: short TTS vs long scripts
mode sync is a bounded wait, clamped to 0-30 seconds, not a promise the audio is ready. When to use it, and when to go async or webhook.

Sume TTS takes transcript or transcript_source, never both
A Sume TTS request accepts exactly one text input: literal transcript, or a transcript_source that points at a stored script. How to pick.

Sume TTS volume 0.5 to 2.0: set the voiceover level before the mix
generation_config volume is a multiplier from 0.5 to 2.0 on Sume TTS. Use it to match narration loudness across jobs before you join or mix them.

Symfony 7 controller for Sume webhooks: getContent and hash_equals
A Symfony controller that reads getContent(), recomputes hash_hmac over timestamp.raw_body, compares with hash_equals, and returns 204 for a Sume delivery.

Transcribe audio from a private bucket: Sume STT needs a public URL
Sume STT takes a public HTTPS audio_url. If your files sit in a private bucket, here is how to hand them over without opening the whole bucket.

Abort waitForJob on SIGTERM, then resume from the stored job id
On a deploy, abort waitForJob with an AbortController on SIGTERM, keep the Sume job id, and resume the wait after restart. Aborting stops the wait, not the job.

Claude programmatic tool calling skips MCP connector tools: Sume fix
Claude's programmatic tool calling cannot call tools from the MCP connector. Sume's script_run runs the loop on the server instead, with a call journal.

mcp:read hides Sume's write tools from tools/list: insufficient_scope
Under OAuth mcp:read, Sume's tools/list hides write and paid tools and a direct call returns insufficient_scope. How to tell a hidden tool from a broken one.

Programmatic tool calling 270 s timeout vs Sume's 55 s script_run cap
Claude times out a pending programmatic tool call after about 4 minutes. Sume's script_run stops at 55 seconds. How to size slow video jobs around both.

Sume MCP 256 KiB output budget: oversize error is not a failed job
Sume's MCP tool results are capped at 256 KiB serialized. An oversize result returns an explicit error instead of a cut-off value, and the job may be fine.

Sume MCP wait_busy 429: a retryable isError, paid creates queue 20 s
A busy Sume MCP server returns an isError result with http_status 429, retryable. The paid-create limits behind it and how to back off without double billing.

Sume MCP token lasts 3600 s with no refresh grant: plan for it
Sume's hosted MCP OAuth issues one-hour access tokens and only the authorization code grant. What a long agent run should do at minute 61.

One video per request: three hook variants as three Sume jobs
Google lists Veo 3.1 Lite at one video per request. On Sume every model works that way too: three hook tests are three jobs, each with its own Idempotency-Key.

Sume 400: Idempotency-Key must be 255 printable characters or less
The Sume API rejects an Idempotency-Key over 255 characters or with control characters. Why it happens (JSON blobs, newlines) and a TypeScript key builder.

Sume API 503 deploy_draining: retry after 5 seconds in Python
A redeploy answers 503 deploy_draining with retry-after. Why it is safe to retry, why a POST still needs an Idempotency-Key, and a stdlib Python retry loop.

A blank Idempotency-Key on Sume is ignored, not rejected: guard it
An empty or whitespace Idempotency-Key header is treated as no key at all, so a retry can create a second job. Build a key that cannot be blank in Python.

Freeze a TTS preset so every episode sounds the same
Keep one JSON preset for a recurring voiceover: avatar handle, language, speed 0.6-1.5, volume 0.5-2, output format. Sume also records these values on each job.

Transcribe a clip when you do not know the language: STT auto-detect
Omit language_code on Sume speech-to-text and the job auto-detects the language. What the result returns, the 10-minute cap, and the $0.01 a minute rate.

Image job progress bar: Sume has no percentage, so show job stages
ChatGPT Images 2.5 shows a progress percentage. Sume image jobs report queued, processing and completed plus events, and stream:true returns 400.

Measure your voice's characters per second, then budget video slots
Guessing words per minute breaks a 3-second hook. Voice one Sume take, divide characters by duration_seconds, and size each video slot from your own number.

Sume 429 body: parse details.scope and window_seconds in TypeScript
A Sume rate_limited 429 names the read or write bucket and gives limit, window_seconds and retry_after_seconds. Parse them in TypeScript and wait.

Sume 429 retry with a deadline: give up when retry-after is too long
Retrying a Sume 429 forever blocks a request. Cap the total wait, give up when retry-after exceeds what is left, then surface the error. TypeScript wrapper.

Sume ratelimit-limit: read the budget from the header, not a table
Plan numbers are 120 to 1200 writes a minute, but dev and self-hosted deployments can differ. Calibrate a Python client from ratelimit-limit at startup.

Sume write limits as submits per second: a Python pacer by plan
Free 120, Pro 300, Startup 600, Scale 1200 writes per minute is 2, 5, 10 and 20 per second. A fixed-window pacer in Python that never trips the 429.

Sume webhook handler status codes: when to return 401, 2xx or 5xx
Sume retries any non-2xx up to 10 times, 30 seconds apart. Return 2xx only after you store the event. A Python handler that refuses a bad signature.

Sume job webhooks: failed and canceled both say ERROR, branch on event
job.failed and job.canceled webhook payloads both use status ERROR with an error object. Dispatch on the event name, not status, in Python.

AI voiceover preflight checklist: 12 checks before you render
A voiceover is cheap to redo and costly to find wrong after a render. Twelve checks tied to Sume TTS limits and error codes, from the 20,000-character cap down.

Blind A/B test of two image edits: reviewer sheet and key in Python
Pick between GPT Image 2.5 and Nano Banana 2 edits without bias: shuffle left and right, hide model names, save an answer key. Pillow script, 25 lines.

Draw in the browser, send to Sume: a canvas Sketch pad in 20 lines
ChatGPT Sketch lives inside ChatGPT. For your own app, export a canvas as PNG, upload it to a public HTTPS URL and pass it to Sume as a reference.

Image edit reference URL rejected? Public HTTPS checklist for Sume
Sume rejects localhost, private-network and non-HTTPS reference URLs, and a URL it cannot download fails as input_media_unreachable. Check yours in 12 lines.

A JSONL ledger for image edits: model, prompt, cost and URL on Sume
Every paid image edit should leave one line: model, prompt, references, status, usage.cost and result URL. 25 lines of Python make that audit trail.