Webhooks¶
HeapStream uses webhooks to inform your application about asynchronous events that happen outside the standard API request cycle — most importantly, a video changing status (from encoding to ready, or to errored). HeapStream issues a POST request to your endpoint, and your application reacts: update your database, kick off the next step, notify a user.
Webhooks compared to polling¶
We advise using webhooks for monitoring video statuses instead of polling the Video API. Webhooks are significantly more efficient for both your system and HeapStream. Additionally, the video-list endpoint is rate-limited, making polling an unscalable way to track video status.
Configuring webhooks¶
Add the webhook URL in the project settings page.
Manage webhooks with the webhook endpoints ⧉:
A project can have one webhook (see Limits); once set up, it receives all of the project's events.
Receiving events¶
HeapStream POSTs to your URL; handle it like any route in your application. Respond with a 2xx quickly — the request allows 5 seconds to connect and 10 seconds for your response. If your processing might take longer, queue the work and respond immediately.
Retries: a delivery that fails (non-2xx, timeout, connection error) is retried up to 5 times, with the delay growing by ~10 seconds per attempt. Transient HTTP errors (429, 5xx) also get short immediate retries within each attempt. After the final failure the event is dropped — treat webhooks as a trigger, not as the source of truth, and confirm state with the video API when it matters.
Idempotency: while HeapStream strives to deliver each event once, the same event can be delivered more than once (even after your service responded 2xx). Make your handler idempotent.
Payload format¶
Each POST body carries one or more events under an events key:
An event looks like this:
{
"event_type": "video.created",
"project_id": 20,
"timestamp": "2024-10-10T10:10:10.000010+0000",
"video": {
"asset": {
"duration": -1.0,
"encoding_tier": "full",
"errors": [],
"id": 22,
"normalize_audio": false
},
"id": 500,
"status": "waiting_for_upload"
}
}
| Field | Meaning |
|---|---|
event_type | One of the event types below. |
project_id | The project the event belongs to. |
timestamp | When the event happened (UTC). |
video | The video's id and status, plus a compact asset (duration, encoding tier, and any processing errors). |
See the webhook payload reference ⧉ for the full schema.
Types of events¶
event_type | Fires when |
|---|---|
video.created | A video is created — by upload, fetch, clip, or duplicate. |
video.status_update | The video's status changes — bytes arrived, encoding finished, or processing failed. This is the one to react to. |
video.updated | The video's metadata was edited. |
video.deleted | The video was deleted. |
Securing your endpoint¶
Webhook payloads are currently not signed. To keep others from posting fake events to your endpoint:
- Put an unguessable secret in the webhook URL itself (e.g.
https://example.com/hooks/heapstream/<random-token>) and reject requests without it. - Treat the payload as a hint, not as authority: on receiving an event, read the video's current state from the API before acting on anything sensitive.