Write a Sume video URL back to a CMS record: what to store
Sume media URLs in a finished run are durable and public. Store them on your CMS record, and proxy or copy them if you need per-customer access control.

To attach a finished Sume video to a CMS record, store the media URL from the run's structured output next to the record and the run id. The URLs are durable and public, so if a video must be visible only to certain customers, proxy or copy the file rather than handing out the URL.
This sounds like a small detail and is the main design decision in any pipeline that publishes generated media into a content system.
Typical targets are a headless CMS entry, a product information record, or a row in a media table. The advice is the same for all of them, because the constraint comes from the Sume side, not from the CMS.
Get a predictable output shape
Ask for a structured output so the URL lands in a named field instead of in prose. Bind an output_schema with a root object, additionalProperties false on every object, and every property in required; optional fields become nullable. The built-in shape, sume/action-run-output/v1, has text, images, videos, audio, and files arrays. See Structured output.
Every URL in a structured output must be media the run produced, an exact match, so you can trust that the field points at something real and not at an invented link.
What to store
A CMS record needs very little from the run: the media URL, the run id for traceability, and the format.version that produced it. Keep the thread_id too, so an editor can open the conversation that produced the clip. Because input does not reach the output projection, the record id has to come from your own run index, not from the response.
If the structured output includes a SumeMediaFile, its duration_ms is checked within 10 percent of the ledger. That makes it safe to copy into a duration field in the CMS.
Keep the text field out of the live page until someone has read it. A generated caption can be good and still be wrong for your brand, and the record is the right place to hold it as a draft.
| CMS field | From | Note |
|---|---|---|
| video_url | Structured output videos entry | Durable and public |
| duration_seconds | duration_ms in the media file | Checked within 10 percent |
| generated_by_run | Receipt id | For support |
| format_version | Receipt format.version | For audits |
| body_text | text field | Review before publishing |
When the URL cannot be public
The Embed a Format cookbook is blunt: media URLs are durable and public, so for per-customer access control, proxy or copy them. Copy the file to your own storage and serve it with your own authorization, or stream it through a route that checks the viewer. Do this in a background job after the webhook has been acknowledged, not inside the webhook handler, whose delivery timeout is 10 seconds.
Copy only what you need. A 30 second clip is small enough to copy in a background job, and once it sits in your own bucket, its address is yours to rotate or revoke.
Webhook payload edge case
A terminal webhook carries the receipt as payload, but payload is null when it would exceed 1 MiB, in which case the error code is payload_too_large and error.result_url is set. Your handler should then fetch the result_url. Without this branch, a large structured output looks like a lost delivery.
Dedupe on request_id, which equals the run id, so a repeated delivery does not create a second CMS version.
Add a retry for the copy job with its own idempotency, keyed on the run id. If the copy fails, the CMS record should show a pending state, not a broken link.
Sources
Related posts
More in Developers
- Actix Web: verify a Sume webhook from the web::Bytes extractor
Take the Sume webhook body as web::Bytes in Actix Web, verify HMAC SHA-256 with the hmac and subtle crates, and return 204 or 401.
- Caddy in front of a Sume webhook receiver: body limit and timeouts
Does Caddy break Sume webhook signatures? reverse_proxy passes headers and body through; set max_size above 1 MiB and an 8 s upstream timeout.
- CircleCI no_output_timeout: poll a Sume video job without a kill
CircleCI kills a run step after 10 silent minutes. Print a status line on every poll, raise no_output_timeout, and keep one Sume Idempotency-Key per workflow.
- Clojure: Ring middleware that verifies a Sume webhook from raw bytes
Verify a Sume webhook in Clojure: slurp Ring's one-shot body as bytes, HMAC-SHA256 with javax.crypto, MessageDigest/isEqual, rotation entries, 300 s window.
Written by Sume