Braze Connected Content has 2 seconds: pre-render the Sume clip
Braze drops Connected Content that answers in over 2 s. A Sume avatar job takes longer, so render first, store the URL, and let the campaign read a fast lookup.
Can Braze Connected Content call Sume directly?
No, not for a render. Braze's page says the server response has to arrive in under 2 seconds, or the content is not inserted. A Sume avatar video is a job: the default mode is async and returns a job envelope, and sync mode waits at most 30 seconds. Neither fits a 2 second budget.
The working shape is two steps. Render the clip ahead of the send. Then let Connected Content call a lookup you own, which answers from a stored video_url in a few milliseconds.
What does Braze say about the call?
Only the facts that matter for a video link are listed here, from Braze's own page.
| Topic | What Braze documents |
|---|---|
| Time budget | Server response must come in under 2 seconds, or the content is not inserted |
| Success | Only a 2xx response counts |
| Redirects | 301 and 302 are not followed |
| 404 | Renders an empty string |
| 500 and 502 | Go to Braze retry logic |
| 429 | Treated as an endpoint failure |
How do I pre-render the clip?
Submit the avatar job when the campaign is approved, not when the message sends. Use mode: "webhook" so Sume calls you on job.completed, then save the video_url from the result next to the user or segment key. Each avatar job needs an Idempotency-Key.
Scripts must land in the 4 to 60 second window. At the plus tier with no product image the rate is $0.245 per second, so a 15 second clip is $3.675.
import json, os, urllib.request
def post(path, body, key):
req = urllib.request.Request(
"https://api.sume.com" + path,
data=json.dumps(body).encode(),
headers={
"Authorization": "Bearer " + os.environ["SUME_API_KEY"],
"Content-Type": "application/json",
"Idempotency-Key": key,
},
)
with urllib.request.urlopen(req) as r:
return json.load(r)
job = post("/v1/avatar-1.0/talking-video", {
"avatar_handle": "your_avatar_handle",
"script": "Your cart is saved. Two more days at this price.",
"aspect_ratio": "9:16",
"mode": "webhook",
"webhook_url": "https://example.com/hooks/sume",
}, "bf-reminder-segment-a")
print(job["status_url"])
What should the Connected Content endpoint return?
Return a 200 with the stored URL once the job is done. Do not answer a not-yet-ready clip with a 404, because Braze renders that as an empty string. The companion post on the 404 case covers the fallback.
Keep the webhook handler small as well. Verify the signature, acknowledge fast and do the storing after, as in acking a Sume webhook.
Sources
Related posts
More in Integrations
- Braze 404 renders empty: a fallback while the Sume clip renders
Braze turns a 404 into an empty string. Sume returns 409 job_not_completed until a result exists. Map one to a fallback URL so no message goes out blank.
- Braze retries a 500: keep the Sume job submit idempotent
Braze sends 500 and 502 responses to retry logic, and a :retry option exists. Give every Sume submit a stable Idempotency-Key so a retry is not a second bill.
- Cloudflare Worker: keep the image model id in KV and swap it live
A Worker that proxies POST /v1/images and reads the Sume model id from Workers KV, so replacing gpt-image-1 is a wrangler command, not a deploy.
- GitHub Actions repository variable for the image model id: no commit
Keep the Sume image model id in a GitHub Actions repository variable, so a gpt-image-1 replacement is a settings change or one gh command, not a pull request.
Written by Sume