Do Sume result URLs expire? media.sume.com vs /videos content
Sume Format artifact URLs on media.sume.com do not expire and are public. The /v1/videos content route needs your key. What to store, plus a Python download.

The Sume docs say Format run URLs on media.sume.com do not expire. Each artifact has expires_at: null, the files are served with public, max-age=31536000, immutable, and you can store the URL with your own record and render it later with no refresh step. The same pages warn that a durable URL is also a public URL: anyone holding it can open it.
The video route is different in kind. GET /v1/videos/{jobId}/content is an authenticated Sume endpoint, and the docs show it with an Authorization header. The docs do not state a lifetime for it, so treat it as a download route and store the file.
Which URL is which
The rows below are quotes of behavior from the Structured output, Format runs, and Video generation pages, read 2026-10-09.
| URL | Where it appears | Expires | Needs your key |
|---|---|---|---|
https://media.sume.com/... | Format run artifacts[].url, primary_output_url | No; expires_at is null | No; public |
| Signed URL | Only when Sume returns one; expires_at has a value | Yes, at expires_at | No |
/v1/videos/{jobId}/content?index=0 | unsigned_urls on a completed video job | Not stated in the docs | Yes |
Store the right thing
For Format runs, save artifacts[].url with your run record. If the expires_at field has a value, that URL is a signed one and you should copy the file instead. For per-customer access control, the docs say to proxy or copy the media, since a durable URL is public.
For a video job, download the file once the status is completed, and keep your own copy. The snippet follows the redirect the content route sends, so it works whether the route answers directly or by redirect.
import asyncio
import os
import sys
import httpx
async def main(job_id: str):
headers = {"Authorization": f"Bearer {os.environ['SUME_API_KEY']}"}
url = f"https://api.sume.com/v1/videos/{job_id}/content?index=0"
async with httpx.AsyncClient(follow_redirects=True, timeout=120) as c:
r = await c.get(url, headers=headers)
if r.status_code == 409: # job_failed or job_not_completed
print(r.json())
return
r.raise_for_status()
with open("output.mp4", "wb") as f:
f.write(r.content)
print("saved", len(r.content), "bytes")
asyncio.run(main(sys.argv[1]))Two errors on that route
If the job has not finished, the content route answers 409 job_not_completed, which is retryable: keep polling. If the job failed for good, it answers 409 job_failed with the public reason, and retrying will not help. A missing output index answers 404 video_content_not_found. Those codes come from the OpenAPI description of the route.
A practical split follows from this. Keep Format media.sume.com URLs as they are in your database, since they are durable, and avoid putting them in anything a customer should not share, since they are public. For video jobs from /v1/videos, treat the content route as the way to fetch the file once, and write it to storage you control. If your product needs a link that only one customer can open, the docs say to proxy or copy the media and serve it yourself.
One caution about the snippet: it does not send your key to the host that the redirect points at when the host changes, since httpx drops the Authorization header across origins. That is the behavior you want here, and it is why a signed or public target works without extra code.
Sources
Related posts
More in Developers
- Edit an existing clip with Gemini Omni Flash 1.1: video_url on Sume
Sume exposes Omni video edit mode through the Video Router video_url field: the prompt is the instruction, resolution defaults to 720p, no duration.
- Enterprise API key rate limit before a contract: the Scale row
Until Sume provisions a contracted number, an Enterprise key uses the Scale row: 1,200 writes and 48,000 reads per minute. The full plan table and the math.
- Estimate a 60-image Sume batch in Python before sending it: $3.05
A short Python script that prices a 60-image plan from Sume's list prices: 40 Grok drafts, 8 Nano Banana 2.1 4K finals and 12 FLUX.2 Pro images come to $3.05.
- Express route for a Sume webhook: raw body, verifyWebhook, 204
In Express, express.json() breaks the Sume signature check. Mount express.raw on the webhook route only, call verifyWebhook, and return a fast 2xx. TypeScript.
Written by Sume