
AIOZ Stream webhooks send an HTTP POST to your server when a video moves through upload and encoding, so your pipeline reacts to events instead of polling. You can subscribe to five events, and each delivery is a flat JSON body with the media ID, qualities and status.
TL;DR:
file_received, encoding_started, partial_finished (one quality done), encoding_finished and encoding_failed.type uses dots, such as encoding.finished.type, emitted_at, media_id, media_type, qualities, title, status and user_id.Updated Oct 19, 2026: the payload fields, the dot and underscore naming, the retry policy and the test endpoint are now covered from the current docs. We also added an event diagram and shorter sentences.
A polling loop asks "is it done yet?" every few seconds, and most answers are "still processing," and each one costs a request against your rate limit. Your pipeline also notices a finished encode up to one poll interval late.
A webhook reverses the direction: AIOZ Stream's servers call your endpoint when the state changes, so you make no wasted requests and see the change right away. This matters most when you chain steps: encoding finishes, captions get attached, your CMS updates, and a publish job runs.
The docs list five events, and you switch each one on or off with a boolean in the same registration request, so one webhook can carry all five:
file_received: a new video file finished uploading.encoding_started: transcoding began.partial_finished: one quality level finished encoding.encoding_finished: every quality finished.encoding_failed: encoding failed.
Subscriptions and deliveries name events differently. You subscribe with underscores (encoding_finished), but the type field in each delivery uses dots (encoding.finished). If your handler switches on the underscore names, it will match nothing.
The partial_finished event is the one to build around. It fires once per quality as each rendition finishes, so a low rung of your bitrate ladder can go live before the 4K rung is done.
The webhooks guide documents the same flat fields for all five events:
type: the event name, such as partial.finished.emitted_at: when the event was emitted.media_id: the ID of the video.media_type: for example video or live-stream.qualities: the file's qualities, such as 720p,1080p. For partial.finished it holds the one quality that just finished.title, status (for example transcoding, done or fail) and user_id.The docs list the fields but give no full sample body, and the exact format of emitted_at isn't stated. Log the first real delivery from a test video and keep it as a fixture for your handler tests. The docs' own Express example switches on type and reads media_id:
app.post('/webhook', (req, res) => {
// Fields are flat: type, emitted_at, media_id, media_type, qualities, title, status, user_id
const { type, media_id } = req.body
switch (type) {
case 'encoding.finished':
console.log('Video ready:', media_id)
break
case 'encoding.failed':
console.error('Encoding failed:', media_id)
break
case 'file.received':
console.log('File received:', media_id)
break
}
res.sendStatus(200)
})Here is a practical chain: on file.received, set the video to "processing" in your own UI so your user sees progress. Treat encoding.started as a monitoring signal that the job left the queue.
On each partial.finished, read qualities and mark that rendition as playable. On encoding.finished, run the steps that need the full ladder: update your CMS, publish, and notify the uploader. Route encoding.failed to an alert and a retry decision, because a failure that only lands in a log will go unnoticed.
The docs say your endpoint should answer with a 2xx status, and if it doesn't, AIOZ Stream retries the delivery up to three times, with 3 seconds between attempts. The docs also tell you to respond within a few seconds, so do slow work after you send the 200.
Retries mean your handler can see the same event twice, so store a key for each event you process and check it before you act. A good key is media_id plus type, plus qualities for partial.finished, since the payload has no documented event ID. That one check stops a retried encoding.finished from publishing a video twice. Retries also stop after the third attempt, so for anything critical, run a slow reconciliation job that checks videos still marked "processing."
The webhooks FAQ says you can verify requests by checking the request headers for a signature or token provided by AIOZ Stream. The docs don't name that header, describe how the value is computed, or show a secret in the create-webhook response. Until they do, you can't implement a signature check from the docs alone.
Compare Stripe, which signs each webhook with HMAC-SHA256 in a Stripe-Signature header and adds a timestamp against replay attacks. Without a check like that, anyone who finds your URL could send a fake encoding.finished and trigger an early publish.
The safe pattern is to treat each webhook as a prompt to check. Before anything you can't undo, fetch the video with GET /media/{media_id} and confirm its status yourself. Also keep your webhook URL hard to guess, for example with a random path segment.
You register a webhook with one request to POST /api/webhooks, and the body carries your url, an optional name and a boolean per event. This example from the Webhooks API docs subscribes to every event except file_received:
curl --location 'https://api.aiozstream.network/api/webhooks' \
--header 'stream-public-key: your_public_key_here' \
--header 'stream-secret-key: your_secret_key_here' \
--header 'Content-Type: application/json' \
--data '{
"file_received": false,
"encoding_started": true,
"encoding_finished": true,
"encoding_failed": true,
"partial_finished": true,
"url": "string",
"name": "string"
}'The documented 201 response returns the webhook's id, your event flags, timestamps and last_triggered_at. To test your endpoint before real traffic arrives, trigger the webhook by ID:
curl --location --request POST 'https://api.aiozstream.network/api/webhooks/check/{webhook_id}' \
--header 'stream-public-key: your_public_key_here' \
--header 'stream-secret-key: your_secret_key_here'You can list, update and delete webhooks through the same API, and the Node.js SDK wraps each call as client.webhook.create, update, delete and check. What the docs don't cover yet: the signature header and method, a list of sending IP addresses, and a full sample payload. Next step: read the AIOZ Stream webhooks guide for setup and payload details.
What events does AIOZ Stream's webhook system support?
Five: file_received, encoding_started, partial_finished, encoding_finished and encoding_failed.
Why doesn't my handler match the event names I subscribed to?
Because payloads use dots in type, such as encoding.finished, while subscriptions use underscores, a handler written against the subscription names matches nothing.
Do I need a separate webhook for each event type?
No, one registration carries a boolean for each of the five events.
Does AIOZ Stream retry failed deliveries?
Yes. If your server doesn't return a 2xx, the docs say it retries up to three times at 3-second intervals.
Does AIOZ Stream sign its webhook payloads?
The FAQ mentions a signature or token in the headers, but the docs don't name the header or describe how to check it. Confirm status through the API before you act.
How do I test a webhook?
Call POST /api/webhooks/check/{webhook_id} to trigger a delivery to your URL.
file_receivedWebhook servicepartial_finished reports on
Video streaming protocols move video from encoder to viewer. See how RTMP, SRT, HLS, DASH and WebRTC differ in latency, transport and where each one fits.

Decentralized live streaming sends a real-time broadcast through independently run nodes instead of one company's servers. Here's how each stage of it works.

A video streaming glossary of 114 terms, from AAC and ABR to WebRTC and Widevine, each defined in plain English with sources and links to the deep posts.

Read the AIOZ Stream Statistics panel: bitrate in and out, FPS in and out and current viewers, plus the documented rules for each and what the docs leave out.

Embed an AIOZ Stream livestream with the Share button's iframe or send the Public Playback URL as a link. Covers API fields, public access limits and doc gaps.

Learn how a stream key differs from a streaming session on AIOZ Stream, what each one stores, and what to preconfigure before you go live. Docs-based guide.