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.

axios rejects Sume 409 and 429: read response.data.error.code
axios rejects any status outside 200-299 by default, so a Sume 409 or 429 throws. Read error.response.data.error.code, and use AbortSignal for timeouts.

Mux 20-second keyframe interval vs Sume Video Trim keyframe precision
Mux wants a keyframe at least every 20 seconds on 1080p input. Sume Video Trim has an exact re-encode and a keyframe copy that may start early. Which to use.

Stripe branding icon: JPG or PNG under 512 KB, 128 px up
Stripe wants a JPG or PNG icon under 512kb and at least 128 x 128 px. Make a 1:1 mark on Sume, shrink it in Pillow, and know where the icon shows up.

Batch of 12 H3 Max Recast swaps: queue limits by Sume plan
Twelve Recast swaps fit in one submit on Pro and above (24+ accepted jobs); on Free only 6 are accepted at once. The queue table and the $45 reserve at 768p.

Mux 1080p input ceiling of 8 Mbps and a Sume 1080x1920 Timeline render
Mux treats 1080p input up to 2048x2048 at 8 Mbps or less as standard. Sume Timeline defaults to 1080x1920, inside the size limit; measure bitrate first.

Timeline audio 400 codes: what each refusal means and the fix
Sume timeline audio refuses bad concat and split requests with stable codes such as audio_concat_requires_parts. Each code, its cause and the fix.

Sume remote MCP upload URL is redacted: use a public HTTPS URL
On Sume's hosted MCP the upload.url from assets_upload_url comes back redacted, so a remote agent cannot PUT. Pass a public HTTPS URL, or upload over REST.

mcp_health on Sume: which credential and scopes is this session using?
Sume's mcp_health tool reports the auth source and the credential behind a session: an OAuth token with client and scopes, or an API key prefix. How to read it.

Verify a Sume job webhook in Python: HMAC, timestamp, rotation
A Python verifier for Sume job webhooks: HMAC SHA 256 over timestamp.body, a 300-second window, key rotation and a refusal of an empty secret.

Sume run webhook behind a redirect: a 3xx counts as a failed attempt
Sume does not follow redirects on run webhooks, so a 301 from an http or www hostname is a failed delivery. The URL is also re-checked at delivery time.

Generated client for Sume schedule runs: handle the undeclared 503
The Sume run-a-schedule route declares 200, 202, 400, 401, 403, 404, 409, 413, 429 and 500 in OpenAPI, but can also return 503. Handle it in generated clients.

jobs_wait wait_for any: other Sume jobs keep running and billing
jobs_wait takes up to 20 job_ids and wait_for all or any. With any it returns on the first finish, but the other jobs keep running and billing.

^0.2.0 does not accept 0.3.0: pinning @sume-com/sdk in npm
A caret range on a 0.x version only allows patch updates: ^0.2.0 means >=0.2.0 <0.3.0-0. What that means for @sume-com/sdk upgrades and CI.

Paging Sume schedule runs: limit 1-100, next_cursor, has_more
List a Sume schedule's runs with limit 1-100 (default 50), then pass next_cursor back as cursor until has_more is false. A forged cursor is a 400. Python loop.

Audio detach file size: 16 kHz mono WAV vs 48 kHz stereo
A 900-second Sume audio detach is about 29 MB as 16 kHz mono WAV, 173 MB as 48 kHz stereo WAV and 14 MB as 128 kbps MP3. The arithmetic and choices.

Dotnet resilience handler retries POST: Sume key rule
The .NET standard resilience handler retries every HTTP method by default, POST included. How to keep a paid Sume submit from running twice.

GitLab CI retry reruns the whole script: pin the Sume key
GitLab's retry keyword re-runs the full job script, so a retried job that calls Sume can submit and pay twice. Retry only runner failures and pin the key.

Sume job status: stop on terminal, fetch on result_ready
A Sume status reply has two booleans. terminal says stop polling; result_ready says GET /result will work. Failed and canceled jobs stop but have no result.

Slack custom emoji under 128 KB: shrink a Sume image to fit
Slack says custom emoji should be square, under 128 KB, JPG, PNG or GIF. Generate a 1:1 mark on Sume, scale it small, and loop a PNG palette down to fit.

Claude Code one-off routine: fire one Sume run once, rerun safely
A one-off routine auto-disables after firing. If you rerun it, send the same Sume Idempotency-Key so a repeat doesn't create a second paid run.

Claude Code routines run hourly at most: use a Sume webhook
A routine's minimum schedule interval is one hour, so a polling loop wastes runs. Submit the Sume job once and let the terminal webhook trigger the next step.

Claude Code routine skips approvals: cap Sume calls with script_run
A routine can use every tool without asking. Sume's script_run bounds a batch of calls with max_calls and max_paid_calls, so one run cannot fan out.

Python handler for the Sume agent.run.terminal webhook
Verify the HMAC over timestamp.raw_body, refuse an empty secret, dedupe on request_id and branch on outcome. Runs offline with a self-test.

timingSafeEqual throws on unequal length: Sume webhook check (Node)
Different-length buffers make Node's timingSafeEqual throw, so a bad Sume signature can become a 500. Check length first and a node:http receiver returns 401.

Python webhook receiver: read artifacts[].url and error.next_action
A standard-library Python receiver for Sume job webhooks: verify, then branch on status OK or ERROR to get the artifact URL or error.retryable and next_action.

Verify a Sume webhook in Ruby with OpenSSL, no Rack or Rails
A plain Ruby verifier for Sume's sume-v1 HMAC header: OpenSSL::HMAC, a constant-time compare that works on old Rubies, a 300 second window and a self-test.

Sume webhook timestamp window: reject stale deliveries (Python)
The Sume signature covers a timestamp, and the SDK default rejects anything over 300 seconds old. Verify at the edge, then queue, so a late worker never fails.

Test your Sume webhook receiver locally: openssl and curl
Sign a fake job.completed body with openssl, post it with curl and confirm your receiver answers 200 for valid, and 401 for stale and forged Sume deliveries.

verifyWebhook toleranceSeconds: 0 turns the replay window off
In @sume-com/sdk, toleranceSeconds: 0 skips the timestamp check, so a day-old signed delivery verifies. Keep the 300-second default.

Zod schema for a Sume job webhook: a discriminated union on status
Model Sume's job webhook in Zod as a union on status OK and ERROR so TypeScript narrows to artifacts or error. Verify the signature first, then parse.

Measure word error rate on your own clips with Python and Sume STT
Microsoft charts 2.5% word error rate for MAI-Transcribe-2-Streaming. Measure yours: Sume STT plus a 20-line word-level edit distance in plain Python.

Test a language on Sume STT with a 30-second sample first
Vendors split languages into trained and verified. On Sume STT, language_code is a hint, so cut a 30-second sample and compare auto-detect with your hint.

Alert on Sume API errors by category and stage, not 4xx (Python)
Sume error envelopes carry category, stage and public_reason for dashboards. A Python tally pages on quota and auth, tickets bad input, watches 429s.

A Python SumeError class: code, retryable, next_action, request id
Turn a Sume error envelope into one Python exception that carries code, retryable, retry_after_seconds, next_action and the request id. Standard library only.

SumeInsufficientCreditsError vs SumeRateLimitError: instanceof (TS)
The Sume SDK has typed errors keyed on status and code. Convert a failed result with toSumeApiError, then branch on instanceof. They are on main, not 0.2.0.

Cancel a queued H3 Max Recast job: when you get a 409
You can cancel a Sume job only before generation starts. A queued Recast cancels cleanly; one already running returns 409 job_generation_already_started.

H3 Max Recast in TypeScript: submit, poll, read the result
A runnable Node script for Recast on Sume: submit with an Idempotency-Key, poll status honoring next_poll_after_seconds, then fetch the result.

Poll Recast like a queue client: IN_QUEUE to COMPLETED
Sume's status route returns IN_QUEUE, IN_PROGRESS and COMPLETED beside its own statuses, for clients ported from queue APIs. How they map for a Recast job.

Poll a Sume job in Python with a deadline and next_poll_after_seconds
A Python wait loop for a Sume job: stop on terminal, sleep at least next_poll_after_seconds, and give up at a monotonic deadline. A timeout is not a failure.

Match loudness between voiceover takes: test sentence plus volume
Two takes recorded on different days sound different in level. Measure one fixed test sentence, then set Sume TTS generation_config.volume (0.5 to 2.0).

Same narrator every week: pin the voice, language and speed
Keep one narrator across a weekly series on Sume TTS: pin avatar_handle with voice.id, language, speed and format in one config, with one key per episode.

Unit test a Sume 429 retry loop in Python with a fake opener
Test a Sume rate_limited retry loop with unittest and a fake opener: retry-after is honored, the last try raises, no network, no spend. Stdlib only.

Size a Recast batch from generation_limits, not wave_size_hint
Each Sume submit returns generation_limits and idempotency_hit. A Python loop computes headroom as concurrency minus active minus queued.

Where to keep a Sume API key in a Claude Code routine
Environment variables are readable by anyone using the environment. On Pro and Max an API credential hides the key from Claude. What changes on Team plans.

Foreign names in an English voiceover: respell or split the job
Sume TTS takes one language per job. For a few foreign names in an English script, respell them phonetically, or split into jobs and join the audio.

Sume hosted MCP wait_busy 429: retry only the rejected call
wait_busy means the host was full and nothing ran. Retry only that call with the same idempotency_key after retry_after_seconds. Accepted calls keep going.

How long does a Sume TTS audio_url last? Archive voiceovers anyway
Sume TTS returns a media.sume.com artifact URL. What the docs and code state about expiry, what they do not, and a Python snippet that saves each voiceover.

Listen to This Article: Audio Player With Read-Along Highlighting
Build a read-along article player: ask Sume TTS for word timestamps and sentence segments, save the timings as JSON, and highlight text from currentTime.