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.

waitForRun timeout: why SumeRunTimeoutError can arrive early
The Sume SDK's waitForRun checks its deadline before it sleeps, so SumeRunTimeoutError can fire up to one poll interval early. The run keeps going.

waitForRun 429 and 503: the streak resets only on a clean read
Sume SDK waitForRun counts consecutive failed reads, resets only on a clean one, and retries the final result read so a late 429 cannot lose it.

Four avatar clips a week: Python batch, one idempotency key each
HeyGen's survey ties avatars to consistent posting. Submit four Sume avatar clips a week from one handle with week-stamped keys and queue_full handling.

defaultLanguage vs defaultAudioLanguage on a dubbed AI Short
snippet.defaultLanguage is the language of title and description; defaultAudioLanguage is the spoken language. Set each on a dubbed or voiced Short.

YouTube description limit is 5000 bytes, not characters: check it
The Data API caps snippet.description at 5000 bytes and snippet.title at 100 characters. A Python check for both, and where a Sume transcript fits.

Can an AI-made Short be Creative Commons on YouTube?
YouTube's status.license takes youtube or creativeCommon, but a Content ID claim blocks CC BY. What to check before you set it on an AI-made Short.

YouTube tags limit: 500 characters, commas and quotes count
snippet.tags[] has a 500-character cap, and commas plus quotes around multi-word tags count toward it. A Python tag builder that stays under the cap.

videos.insert embeddable and publicStatsViewable for a Shorts batch
status.embeddable and status.publicStatsViewable are settable on videos.insert. Set both explicitly in a Shorts batch body and check them with a small script.

videos.insert OAuth scope: youtube.upload or force-ssl?
videos.insert accepts four OAuth scopes; videos.getRating gained youtube.readonly on Sept 1, 2026. Which to request for a Shorts pipeline and what Sume holds.

videos.update needs snippet.categoryId: retitle a Short safely
YouTube's videos.update requires snippet.categoryId whenever you send a snippet. How to retitle a Short from a batch without a failed call.

Product hero video and LCP: poster, preload, no loading=lazy
A video can be the largest contentful paint. web.dev says to use a poster, preload it with fetchpriority high, and skip loading=lazy. Make the poster with Sume.

Replace a product-page GIF with a muted MP4: autoplay loop
web.dev says a muted looping video replaces a GIF at a fraction of the size: 3.7 MB vs 551 KB in its example. The tag, the attributes and a silent Sume trim.

MCP 401 challenge: the WWW-Authenticate header Sume returns
What a client sees when it calls Sume's MCP endpoint with no token: the WWW-Authenticate challenge, its resource_metadata URL and scope, and the spec.

Sume SDK 429 retry-after is capped at 60 seconds: what follows
createSumeClient waits at most 60 seconds per retry, with 20 percent jitter and 2 retries by default. What that means for a long retry-after and a fix.

timeline_must_start_at_zero and transition_on_first_segment fixes
Timeline 1.0 needs video[0].start to be 0 and no transition on slot 0. How to open on a fade or a later in-point, with a Python builder that runs.

Omni video_url or reference_video_urls: edit a clip or borrow from it?
On Sume, video_url edits your clip and keeps its framing. reference_video_urls only conditions a new clip. How the two differ in limits, fields and billing.

unsupported_media_type: video_url served as text/html or an image
Sume video trim and filter HEAD the source and refuse a declared non-video content type. What is checked, why octet-stream passes, and a runnable check.

"Avatar does not have a usable TTS voice": the 400 and its fixes
Sume TTS with avatar_id or avatar_handle returns 400 when the avatar has no TTS voice, or when voice.id disagrees with it. What each message means and the fix.

waitForJob throws SumeJobRequestError, not a SumeApiError
A catch for SumeApiError does not see failures from waitForJob. Why SumeJobRequestError has no code or requestId, and how to recover both with toSumeApiError.

duck_requires_audio_spine: no music ducking under silence mode
Timeline refuses soundtrack.duck_db when audio.mode is silence, since there is no voice to duck under. The fix, the other silence rules, and a check.

Format contents PUT 409 format_content_sha_required: send the sha
PUT on a Format file that already exists needs its blob sha. Read the sha with GET, retry, and tell the three 409 codes apart from the package If-Match guard.

verifyWebhook returns false when a header arrives as an array
verifyWebhook refuses an array-valued signature header unless it holds exactly one value. How to normalise headers so a rotation window still verifies.

VideoObject for a product video: thumbnail, date and duration
Google's VideoObject needs name, thumbnailUrl and uploadDate. How to fill them and the duration from a Sume trim result and a video-frames still.

Batch of 30-second Seedance clips: Pro, Startup and Scale queues
How many 30-second Seedance 2.5 jobs can a Sume workspace hold? Plan concurrency and queue limits, what happens at job 25 on Pro, and a safe submit loop.

SumeUploadError at step put: the storage upload failed
uploadFile makes three calls. Read SumeUploadError.step to see which failed, and why extra headers on the put step can break the presigned signature.

Timeline segment_overlap: set start times when clips cross-fade
Sume Timeline returns segment_overlap when a slot starts before the previous one ends minus the fade. The rule, the fix, and a Python check.

Synthetic video for robot and driving tests: Seedance 2.5 API
ByteDance says Seedance 2.5 can make synthetic video for robots and driving edge cases. What a video API returns, and what you must add yourself.

Claude Code mcp_server_errors: fail CI when Sume never loaded
In stream-json runs Claude Code reports a skipped MCP entry in mcp_server_errors. Check it with jq before a CI job spends on Sume, then verify with mcp_health.

Sume SDK error code unknown_error and a null requestId
When the response body is not a Sume error envelope, the SDK falls back to code unknown_error with no request id. What it means and what to log instead.

Sume images 400: read details.supported and retry in Python
A 400 invalid_request from Sume's image API lists the accepted values in details.supported. Parse it in Python, then choose a value on purpose.

MAX_MCP_OUTPUT_TOKENS 25,000: size a Sume jobs_wait wave read
Claude Code caps MCP output at 25,000 tokens and saves larger results to a file. How that meets Sume's jobs_wait include_results and a batch jobs_result read.

Image edit returns 415 on Sume: send JSON, not multipart
A 415 unsupported_media_type from Sume's image API means the body was not application/json. Send reference images as public HTTPS URLs inside a JSON body.

Timeline transition_too_long: 1 s cap and half the shorter clip
transition_too_long means a Timeline fade is over 1 s or over half the shorter neighbour. Sub-frame fades fail too. Limits, snapping, and a check.

video_filter_crop_out_of_bounds: FFmpeg crop pixels to fractions
Sume video-filter crop takes fractions of the frame, not pixels. Convert FFmpeg crop=w:h:x:y with a runnable Python check of the bounds.

jobs_result batch: read a wave when some jobs are still running
Sume's batch jobs_result returns one entry per id in request order. Read ok per entry, treat job_not_completed as running, and re-read only failed_job_ids.

Image retry returns 409 idempotency_conflict: new key per payload
A 409 idempotency_conflict on a Sume image job means the same Idempotency-Key was reused with a different payload. Derive the key from the payload in Python.

instanceof SumeNotFoundError is false on a waitForRun 404
waitForRun and subscribeFormatRun throw SumeRunRequestError, not the 401-to-5xx subclasses. Branch on status or code instead; a working catch block.

One request for four Sume video models: 1080p, 5 to 10 s, 16:9 or 9:16
Kling 3, Wan 3.0, H3 Max and Omni share one request shape: 1080p, 5 to 10 seconds, 16:9 or 9:16. Compute the intersection in Python and price each model.

source_too_large on trim or filter: the 300 MiB source cap
Sume's video trim and filter refuse a hosted source over 300 MiB (314,572,800 bytes) at submit. What is checked, the free check call, and ways around it.

video_trim_output_requires_exact: keyframe cuts can't resize
FFmpeg stream copy cannot filter, and Sume's keyframe trim cannot take an output size or fps. Why it is refused, and the one-line fix.

Replay a saved Sume webhook in tests: verifyWebhook says false
A recorded delivery fails verifyWebhook once it is older than 300 seconds. Pin the clock with now or use toleranceSeconds 0 in tests, never in production.

Image batch in Python: read ratelimit headers and retry-after
Sume can send ratelimit-limit, ratelimit-remaining, ratelimit-reset and retry-after on image calls. Back off on 429 in Python, and treat queue_full separately.

Reverse a video by API: FFmpeg reverse is not on Sume's allowlist
FFmpeg's reverse filter buffers a whole clip. Sume's video-filter allowlist has no reverse and no setpts, and the free check shows it. What to do instead.

YouTube .sbv vs .srt: the timestamp difference and a Python converter
YouTube accepts .sbv and .srt as basic caption files. They differ in time format and numbering. A short Python converter turns timed cues into either file.

Caption a folder of videos in Python: thread pool, one key per file
Submit caption jobs from a Python thread pool without double billing: one Idempotency-Key per file, poll with next_poll_after_seconds, and the two 429s.

tts_language_script_mismatch: Korean TTS needs a Hangul syllable
Sume TTS returns 400 tts_language_script_mismatch when language is ko but the text has no Hangul syllable. Usual cause: UTF-8 decoded as Latin-1. Fix it.

video_inspect 400s: frames at[] vs fps, and transcribe fields
Three video_inspect refusals: frames with both at[] and fps, frames with neither, and language_code without transcribe. Causes, fixes, a Python lint.

AI SDK MCP tools(): explicit Zod schemas for Sume's jobs_wait
Pass explicit Zod schemas to mcpClient.tools() so your app exposes only the Sume tools it needs, with typed job ids and a bounded wait_for.