Webhooks are how asynchronous outcomes reach you. Rendering is fire-and-forget — POST /videos/render/{videoId} returns before validation runs — so a webhook is the only push notification that a video finished or failed.
Events
There are exactly two:
| Event | Triggered when |
|---|---|
video_ready | The video's status changes to ready |
video_error | The video hit a validation or rendering error |
Moderation is not a webhook event
A video sent to moderation does not emit anything. If you need to observe that state, poll
GET /videos/{videoId}and readstatus.
Payload
Each delivery is a POST with these headers:
| Header | Meaning |
|---|---|
Delivery-ID | Unique per delivery attempt. Log it — it is what support will ask for |
Elai-Timestamp | Milliseconds since the epoch, sent only when a signing secret is set |
Elai-Signature | HMAC-SHA256 of the delivery, sent only when a signing secret is set |
{
"event": "video_ready",
"error": null,
"video": {
"_id": "627e1c5ef461482766f35f4a",
"name": "Hello John!",
"status": "ready",
"public": false,
"deleted": false,
"tags": ["api"],
"userId": "61b1529d2055d2805c0",
"accountId": "61b1529d2055d2805c",
"duration": 3.456,
"data": {},
"thumbnail": "https://elai-media.s3.eu-west-2.amazonaws.com/videos/627e1c5ef461482766f35f4a/thumbnail.jpg",
"url": "https://elai-media.s3.eu-west-2.amazonaws.com/videos/627e1c5ef461482766f35f4a/hello-john.mp4",
"createdAt": "2022-08-25T09:25:56.228Z",
"updatedAt": "2022-08-26T09:40:03.337Z"
}
}
| Field | Description |
|---|---|
event | video_ready or video_error |
error | On video_error, a summary of what went wrong. null otherwise |
requestId | Present only for videos created through the Personalization API — the id returned by POST /videos/renderTemplate/{videoId} |
batchRowId | Present only for Personalization API videos — this video's index within the batch |
video | The video document |
Delivery is a single attempt
This is the part worth reading twice.
We send one POST and wait up to 10 seconds for a 2xx. There is no retry, no backoff and
no dead-letter queue. If your endpoint is down, slow, or returns a 500, that event is gone —
it is not redelivered when you recover.
The failure counter is about your subscription, not about one event:
- Each failed delivery increments a counter and emails your
techEmail. - After 10 failed deliveries the webhook is disabled. That is ten separate lost events, not
ten attempts at one. - Re-enable by subscribing again with
POST /webhook, or from your
API settings page.
So if you cannot afford to miss a video_ready, do not rely on the callback alone. Reconcile
periodically with GET /videos, filtering on status, and treat the webhook as
the fast path rather than the source of truth. Returning 2xx immediately and processing the
payload afterwards also helps — a slow consumer is indistinguishable from a broken one after 10
seconds.
Verifying that a delivery came from us
Set a signing secret and check the signature on every request. See
Set secret token for a working verifier — and note the ordering
trap: the secret is only stored if a webhook is already enabled.
