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.

5 min readSume
All posts

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.

Result URL kinds, as of 2026-10-09.
URLWhere it appearsExpiresNeeds your key
https://media.sume.com/...Format run artifacts[].url, primary_output_urlNo; expires_at is nullNo; public
Signed URLOnly when Sume returns one; expires_at has a valueYes, at expires_atNo
/v1/videos/{jobId}/content?index=0unsigned_urls on a completed video jobNot stated in the docsYes

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

All Developers posts

Written by Sume