Format run media URLs are public: copy on webhook or proxy
Sume Format run media lives at durable public media.sume.com URLs. If customer A must not see customer B's video, copy it at receipt time or proxy it.

Every media URL on a Sume Format run receipt is a durable media.sume.com HTTPS URL that does not expire, and anyone holding it can fetch it. If your product promises that customer A never sees customer B's output, copy the file into your own storage when the run finishes, or proxy it through an authenticated route of yours, and store your own URL.
That advice is from the Embed a Format cookbook, section "Map artifacts into your UI", and the Runs and results page repeats the warning.
What does the receipt hand you?
Three media-bearing fields on a terminal completed receipt, per the cookbook.
| Field | Use it for |
|---|---|
primary_output_url | The one thing to show; null when there is no single primary file |
artifacts[] | Everything generated: id, type, url, content_type, size_bytes, width, height, duration_ms, checksum_sha256 |
output | Your structured result; media inside it points at the same URLs |
What does public actually mean here?
The cookbook is blunt: the URL will end up in your logs, your error reports and your customer's browser history. The structured-output docs add that Sume-hosted media is served as public, max-age=31536000, immutable, with expires_at null on the file object, so there is no refresh cycle to lean on.
Nothing in the docs describes a per-customer access control on the URL itself. Treat the URL as a capability link: whoever has it, can read it.
Which should I choose: copy or link?
The cookbook frames it as a decision to make on purpose. Linking is free and instant. Copying costs storage but survives you ever leaving Sume, and it should happen on the webhook, before you mark the record ready, if you want that guarantee.
For per-customer isolation the copy-or-proxy rule applies either way. A copy puts the bytes behind your own authorization; a proxy keeps the Sume URL server-side and never hands it to the browser.
What does a copy-on-receipt step look like?
This stdlib script reads a saved receipt (GET /v1/format-runs/{run_id} body, saved as receipt.json), downloads each artifact and checks the checksum_sha256 field when present. It copies to a local folder; swap the write for your own storage.
import hashlib, json, pathlib, urllib.request
def main():
data = json.load(open("receipt.json"))["data"]
out = pathlib.Path("copies")
out.mkdir(exist_ok=True)
for a in data["artifacts"]:
body = urllib.request.urlopen(a["url"], timeout=60).read()
want = a.get("checksum_sha256")
if want and hashlib.sha256(body).hexdigest() != want:
raise SystemExit(f"checksum mismatch for {a['id']}")
(out / a["id"]).write_bytes(body)
print("copied", a["id"], len(body))
main()Where does the copy run?
Run it in the webhook handler's background step, after you have recorded the event and answered 2xx. A copy inside the request blows the 10-second attempt budget and gets the delivery retried. If the webhook never arrives, read the receipt from result_url and run the same step.
The Runs and results page covers verifying and answering the delivery first.
The structured-output docs describe Sume-hosted media as served with a one-year immutable cache header and a null expires_at, so the copy you take is the same bytes the URL will serve tomorrow. A signed URL with a populated expires_at is possible in principle, but the docs call null the normal case.
Copying also protects you from your own logs. A URL pasted into an error report is a live link, and with a public URL that is enough for anyone who sees the report to open the file.
Sources
Related posts
More in Formats
- Format run `model` picks the orchestrator, not the video model
A new image or video model launches and you set model on a Sume Format run. That field picks the orchestrating LLM only; media models come from Format tools.
- Format run structured output: output_schema or response_format
Pass one JSON Schema as output_schema or response_format on a Format run. Sending both is a 400, and a schema-valid run can still fail with output_error.
- Format run spend cap: above the Format cap is honored, null is $500
generation_spend_cap_usd on a Sume Format run may exceed the Format's cap and is not clamped; null runs at the $500 maximum; 0 or over 500 is a 400.
- Format run spend: wait for usage.final before you quote a cost
On a Sume Format receipt, debited is the cost, held and refunded are not spend, and final turns true only once no hold is open.
Written by Sume