Avatar video webhook mode: what arrives and what to poll anyway
Use mode webhook for a Sume avatar video and Sume posts one terminal event: completed, failed or canceled. Payload, signature headers and the polling backup.
Send mode: "webhook" with a public HTTPS webhook_url, and Sume posts exactly one event when your avatar video job finishes: job.completed, job.failed, or job.canceled. There are no progress events and no partial deliveries. Sume avatars are async jobs: you submit a request, get a job id back, and read the finished video later. There is no live video session. The webhook is how your server hears that the wait is over without holding a request open.
If you send a webhook_url and no mode, you get webhook mode anyway. If you omit both, you get async, and you poll.
What the delivery looks like
The body is JSON with event, request_id, job_id, status, and a payload. A completed job carries status: "OK" and a payload.artifacts array with Sume media URLs. Failed and canceled deliveries carry status: "ERROR" and an error object. Sume signs the raw body with HMAC SHA-256 over <timestamp>.<raw_body> and sends two headers.
| Item | Value | Note |
|---|---|---|
| x-sume-webhook-timestamp | Unix seconds | Reject deliveries outside your replay window; five minutes is a reasonable default |
| x-sume-webhook-signature | sume-v1=<hex> | During secret rotation there is one entry per live secret, newest first, comma-separated |
| x-sume-webhook-secret-fingerprint | Fingerprint | Compare it with the fingerprint in the dashboard when a signature fails |
| Events | job.completed, job.failed, job.canceled | Terminal only |
Submit and receive
Webhook URLs must be public HTTPS. Sume rejects localhost, private-network, and non-HTTPS URLs when you submit. Read your signing secret on the Webhooks tab of the dashboard, or with GET /v1/webhooks/signing-secret using an API key that has account:read, and store it as SUME_COM_WEBHOOK_SIGNING_SECRET. Your verifier must refuse to run with an empty secret.
curl -X POST https://api.sume.com/v1/avatar-1.0/talking-video \
-H "Authorization: Bearer $SUME_API_KEY" \
-H "Content-Type: application/json" \
-H "Idempotency-Key: webinar-reminder-001" \
-d '{
"avatar_handle": "product_host",
"script": "Tomorrow at ten we walk through the new reports.",
"quality": "plus",
"mode": "webhook",
"webhook_url": "https://hooks.example.com/sume"
}'Why you still poll
The docs call a webhook a delivery optimization, not your only recovery path. Keep status_url polling available for a missed or retried delivery. Store the job id from the first response before you return, so a later poll has something to read. When the webhook says completed, fetch the result and copy the media URL into your own records.
Rules for the receiving endpoint
- Verify the signature on the raw body before you parse it.
- Return a 2xx fast, then do the heavy work in a queue.
- Treat the job id as the idempotency key for your own processing, because a delivery can arrive more than once.
- On
job.failed, read the public error from the job record before you decide whether to retry. - Never resubmit a paid avatar request just because a callback was late.
Webhook or poll: which for an avatar video
Polling is the simplest thing that works and needs no public endpoint. It suits a script, a back-office tool, or a first prototype: submit, store the job id, ask for status with backoff, fetch the result. Webhook mode suits a product where a user submits a request in one moment and your server must react in another, such as sending an email with the link when the clip is ready.
Because an avatar video can take longer than a request can stay open, the docs steer you away from sync and subscribe for this work. Those two modes are aliases that wait up to 30 seconds for a terminal state and then return the same job envelope, with sync.timed_out set when the wait ended first. They are useful for short image jobs, and they are the wrong tool for most video.
A good production shape is both at once: submit with mode: "webhook", and also schedule a poll a few minutes later that checks for jobs whose webhook never arrived. The second path costs almost nothing and removes the worst failure mode, a job that finished while your endpoint was down.
What to store
Keep a small record for each request: your own request id, the Sume job id, the Idempotency-Key, the avatar handle, the quality tier, the planned duration, and the status you last saw. With those six fields you can answer "where is this video?", "did we pay twice?" and "how much did this campaign cost?" without searching logs. The job envelope also carries status_url and result_url, so you never need to build those paths by hand.
Sources
Related posts
More in Developers
- Balance check before an ad variant burst: Sume API 402 guard
Read GET /v1/balance before sending a burst of video variants. Sume reserves 1.25 times list price on submit and returns 402 insufficient_credits below it.
- How do I make a bilingual English and Spanish audio announcement?
Make one bilingual announcement file: two TTS jobs, one per language, joined by a $0.01 Timeline audio concat with no re-synthesis. About 10 cents in total.
- callback_url or webhook_url: which field each Sume video route takes
POST /v1/videos takes callback_url; motion control, lip-sync and image routes take mode plus webhook_url. The field names and what they share.
- Cap Sume spend from an agent loop: dry_run, max_spend_usd and run caps
Four optional guards cap what an automated Sume caller can spend: dry_run, max_spend_usd, generation_spend_cap_usd on Formats, and a balance check.
Written by Sume