Download a Sume video with curl: send the key to /content
The docs' curl call for GET /v1/videos/{id}/content sends the API key and follows redirects. A short script saves the MP4 and prints the 409 reason on failure.

Call GET /v1/videos/{id}/content?index=0 with your Authorization header, follow redirects with -L, and write the body to a file. The completed poll response lists unsigned_urls, and for a Sume job those point at this same content route. Sume's docs show the content call with the key, so send it.
Why send the key to an unsigned URL
The docs are not uniform here. Their curl example for /content includes the key. Their Python example downloads unsigned_urls[0] with a bare request. I could not confirm from the docs that a keyless download always works, and a header costs nothing, so the script sends it. curl does not forward the header to a different host after a redirect.
| Status | Code | What to do |
|---|---|---|
| 200 | none | The body is the video |
| 409 | job_not_completed | Retryable; keep polling GET /v1/videos/{id} |
| 409 | job_failed | Not retryable; the message carries the public reason |
| 404 | not_found | Wrong id, or a job another member created |
The script
It saves to video.mp4, and on any non-200 prints the saved error body, which is JSON, so check the status before opening the file. index defaults to 0; use a higher value only for a model that returns more than one video.
JOB=job_123
code=$(curl -sS -L -o video.mp4 -w '%{http_code}' \
"https://api.sume.com/v1/videos/$JOB/content?index=0" \
-H "Authorization: Bearer $SUME_API_KEY")
if [ "$code" != 200 ]; then
cat video.mp4; echo # 409 job_not_completed: keep polling. 409 job_failed: stop.
exit 1
fiWhat it does not do
It does not poll. Get the id and wait for completed first, using the polling URL from the submit response. The docs' sample sleeps 30 seconds between polls, and status shows cancelled with two Ls on this route but canceled on /v1/jobs.
A saved MP4 is your copy. Store the job id as well, since a later read of the job is the way to recover if a download fails halfway.
Sources
Related posts
More in Developers
- duration vs duration_seconds on each Sume video route
/v1/videos takes duration; motion control and lip-sync take duration_seconds; recast and edit read the source clip. One table of what each does.
- The duration window all fallback video models share: 5 to 10 s on Sume
Pair Omni, Seedance, Wan and MiniMax H3 as fallbacks and the only duration every one accepts is 5 to 10 seconds. Overlap table for each pair on Sume.
- Edit one region of a large photo: crop, edit, stitch back in Pillow
Crop the part you want changed, edit it with Ideogram 4.5 on Sume, then resize and feather it back into the full-resolution photo with Pillow. Code included.
- Edited script, same Idempotency-Key: 409 conflict on Sume TTS
Reusing an Idempotency-Key with a changed transcript returns 409 idempotency_conflict on Sume. How to key each script version so edits never collide.
Written by Sume