Download a generated video from the Sume API: 401s and 302s
Sume unsigned_urls need your API key and answer with a 302 redirect. Download the MP4 with curl -L or code, and fix each 401, 404, or 409.

To download a generated video from the Sume API, wait until the job's status is completed, then GET an unsigned_urls entry, https://api.sume.com/v1/videos/{id}/content?index=0, with your API key and follow its 302 redirect to the file. Without the key the route answers 401 unauthorized; without following the redirect you save the redirect response instead of the MP4.
The facts come from Sume's Video Generation and Jobs and results docs, the Sume API reference, and the curl man page, read 2026-09-27; behavior marked as current code is read from the API source. Submitting and polling the job is covered in An OpenRouter-compatible video API.
Why does the download URL return 401?
unsigned_urls holds API URLs, not file URLs. Each entry is the content route for one output, and like the submit and the poll it takes your key as Authorization: Bearer or x-api-key, never both. A request with no key, a malformed or revoked key, or both headers gets 401 unauthorized. index defaults to 0 and picks an output when a model returns more than one.
A key also sees only its own workspace. In current code, an unknown job id, another workspace's job, or a job that is not a video generation answers 404.
How do I download the file with curl?
Add -L. Without it curl does not follow the 302, so --output gets the redirect response rather than the MP4. Add --fail as well: by default curl does not treat HTTP error codes as failures, so a 409 error body would otherwise land in your video file. To keep the file's URL instead of the bytes, leave out -L and print %{redirect_url}, which curl fills with the URL the redirect would have gone to.
# Download the first output, following the redirect
curl -L --fail -o video.mp4 \
-H "Authorization: Bearer $SUME_API_KEY" \
"https://api.sume.com/v1/videos/job_123/content?index=0"
# Or print the file's URL without downloading it
curl -s -o /dev/null -w '%{redirect_url}\n' \
-H "Authorization: Bearer $SUME_API_KEY" \
"https://api.sume.com/v1/videos/job_123/content?index=0"Is my API key sent on to the file host?
Not if you send it as Authorization. In current code the 302 points at the video's public file on media.sume.com, a different host from api.sume.com, and that second request needs no Sume key. curl's man page says Authorization: and Cookie: headers are not passed on when a redirect goes to another origin, unless you use --location-trusted, while other headers set with -H are sent on every request, redirects included. So with -L, send Authorization: Bearer; an x-api-key header would go to the file host too.
Python's Requests library likewise removes Authorization headers when a redirect goes off-host, per its Quickstart; the Python walkthrough streams the file that way. A client that does not follow redirects on its own can read the Location header of the 302 and fetch that URL with no Sume key.
What does the content route return?
The reference calls 409 job_not_completed retryable, and in current code a canceled job gets that same code, with details.status: "canceled". Read details.status before you retry, and stop on canceled.
| Response | When | What to do |
|---|---|---|
302 redirect | The job is completed and has an output at index | Follow it to the video file |
400 invalid_request | index is not a whole number of 0 or more | Fix the query string |
401 unauthorized | No key, a malformed or revoked key, or both auth headers | Send one valid key |
404 not_found | The job id is not a video generation job in this key's workspace | Check the id and the key's workspace |
404 video_content_not_found | No output at that index | Use an index below the length of unsigned_urls |
409 job_not_completed | The job has not finished, or was canceled | Retryable while running: poll GET /v1/videos/{id}, then retry |
409 job_failed | Generation failed | Not retryable; error.message carries the public reason |
429 | The read budget is spent | Wait for retry-after |
Which URL should I store or show to users?
Store or show the Sume media URL the redirect points to, not the unsigned_urls entry. A browser or app would need your API key to open the API URL, and keys never belong in frontend JavaScript or a mobile app. The same job is readable at GET /v1/jobs/{id}/result, whose artifacts list the file as a public media.sume.com URL; in current code the redirect goes to that artifact's URL.
Sume-owned artifact URLs are the public contract, and raw provider URLs are not, so keep the Sume URL. Whether and when those URLs expire is covered in Do Sume video URLs expire?
Sources
Related posts
More in Developers
- How to choose an AI video generation API: 12-point checklist
Choose an AI video generation API by how it handles jobs, retries, webhooks, spend caps, failures, and outputs: a checklist with Sume's answers.
- CORS error calling the Sume API from a browser: the fix
Browsers block direct calls from your site to api.sume.com, and API keys must never ship in frontend code. Call Sume from your server and proxy it.
- Sume API endpoints list: routes, scopes, idempotency
An index of the Sume API's public routes by family: which need no key, which scope each needs, where Idempotency-Key applies, and the post on each.
- Sume API error codes by surface: one index with next steps
Sume API error codes indexed by surface: common codes, paid generation, Formats, Scheduled runs, Agent Completions, media tools, and hosted MCP.
Written by Sume