Skip to content
streamneo.
Setup Guides12 min read

How to Use Webhooks for a Live Stream

A provider-aware guide to live-stream webhooks: verify callbacks, acknowledge quickly, process asynchronously and handle duplicates safely.

sn.
StreamNeoPublished 4 October 2026
Worth sharing?

A live-stream webhook lets your application learn about a stream event when it happens, rather than repeatedly asking a provider whether anything has changed. You configure a reachable callback URL, verify each request using that provider’s rules, acknowledge it promptly and handle the work safely in your application.

The details are not interchangeable between providers. Mux documents live-stream lifecycle events and its own delivery behaviour; Twitch EventSub has separate callback, challenge and signature requirements. Use the selected provider’s current documentation as the implementation contract, not a generic recipe.

What a live-stream webhook does

A webhook is an HTTP callback sent by a service when an asynchronous event occurs. In a typical flow, the provider sends an HTTP POST to a URL you have registered. Your application can then record a state change, update a status page, notify staff or enqueue another task. This is different from polling, where your application makes repeated requests to check whether the state has changed.

A webhook is a notification about an event, not a guarantee that every part of your application has finished responding to it. For example, receipt of an event might prompt your system to update a stream record and separately refresh a dashboard. Keep the callback handler small; do not make a provider wait while your application performs slow work.

First identify which system is the provider. A YouTube creator using an encoder may be asking about the stream state visible in YouTube Studio, whereas an application built on a streaming API may receive provider events directly. The research and examples here cover Mux and Twitch EventSub. They do not establish a YouTube Live webhook subscription workflow, so do not copy either provider’s procedure into a YouTube integration.

Mux recommends webhooks for tracking asset status rather than polling the Asset API. That is a specific recommendation about asset status, not a rule that every live-stream state should be interpreted in the same way. For background on a continuous broadcast’s operational side, see this guide to recovering a YouTube stream after an encoder crash; it addresses a different layer from receiving application callbacks.

Choose events and inspect provider requirements

Start with the decision your application needs to make. “Tell viewers the stream is playable” is not the same requirement as “record that an encoder connected”, and neither is the same as “show whether a destination in a multi-destination broadcast is failing”. Subscribe only to event families that support a real action or useful record. Unneeded events add code paths and more cases to test.

Before writing the handler, make a short provider checklist: which event types are available, how each state is defined, how the callback is exposed, how authenticity is verified, what response is expected, and what happens on a timeout or failed delivery. Also check whether the provider scopes webhook configuration to an environment or project. Mux endpoints are environment-scoped, so the endpoint and the live-stream resources need to belong to the same environment.

Mux’s lifecycle makes the value of precise event selection clear. video.live_stream.created means a stream resource was created; it does not mean that an encoder is sending video. video.live_stream.connected reports an encoder connection. video.live_stream.recording means initial frames have been processed and recording has started. video.live_stream.active is the useful signal that the stream is playable; before that state, a playback HLS request may return HTTP 412.

Likewise, do not treat every sign of a disconnect as a final end. For Mux, video.live_stream.disconnected means the encoder disconnected, while the stream remains active during its reconnect window. video.live_stream.idle occurs when that window expires and the stream moves to idle. If your interface announces “broadcast ended” on disconnection, a brief encoder interruption could produce a misleading message. Read the Mux webhook guide and its webhook reference for current event definitions.

Twitch EventSub is a separate path, not another name for Mux webhooks. It includes verification, notification and revocation message types, and its requirements differ at the transport, challenge, authentication and acknowledgement layers. A compact comparison helps surface what you must confirm before implementation:

Implementation concern Mux Twitch EventSub
Event model Includes Mux live-stream lifecycle events; interpret each state by its documented meaning. Uses EventSub subscription message types and the event types associated with the subscription.
Callback setup Configure an endpoint in the Dashboard or Webhooks API and match it to the resource environment. Callback must use SSL and listen on port 443.
Verification Follow Mux’s documented signing scheme for webhook requests. Handle the initial callback-verification message and verify notification signatures using Twitch’s specified inputs.
Delivery concerns Mux documents a five-second timeout for an individual attempt and retries unsuccessful deliveries over the next 24 hours with increasing delay; duplicates may still occur after a 2XX response. Acknowledge notifications within a few seconds; slow responses can lead Twitch to revoke a subscription.
Local testing Mux CLI supports forwarding, replay and synthetic events, but forwarding has no production delivery guarantees. Twitch CLI can test challenge and notification handling.

These behaviours are provider-specific, not a shared webhook protocol. For Mux’s configuration permissions, its management guide says reads require system:read and create, update and delete operations require system:write. The create response includes the signing secret once; later list and retrieve calls do not return it. See Mux’s webhook management guide and store that secret securely when you create the endpoint.

Create and expose the callback endpoint

Create one HTTPS route for the provider’s callbacks, then register that exact URL in the provider’s Dashboard or API. The route must be reachable from outside your development machine. A route that only works on localhost is not a production callback. For Twitch EventSub, the official handler requirements specify SSL and port 443; do not assume another provider has identical transport rules.

Keep the callback route separate from a general-purpose page or user-facing API endpoint. It should accept the provider’s expected method and content type, preserve the raw request body where signature verification requires it, and return only the responses specified by that provider. Confirm that any reverse proxy or application framework does not rewrite the body before verification.

For Mux, confirm that your webhook endpoint and the live-stream resources are in the same environment. If you manage endpoints through the Webhooks API, use the documented permissions for the action. Treat the signing secret as a credential: place it in a secret store or protected configuration, limit who can read it, and avoid putting it in source control, logs or error reports.

A useful route layout makes the source of each callback clear, such as a provider-specific path rather than one endpoint that guesses which provider sent a request. This does not itself authenticate anything; it simply makes it easier to apply the correct verification and parsing rules. If your application also runs a looping broadcast, keep callback logic apart from encoder supervision. The Raspberry Pi and FFmpeg looping guide covers the playback process, not provider callback delivery.

Verify callback authenticity

Treat every callback URL as a public internet route. A request body that resembles a provider event is not proof that the provider sent it. Verify the request using the exact signature scheme documented by the provider, and only then use its contents to change application state or trigger work.

Twitch EventSub’s handler guide specifies HMAC-SHA256 over the concatenation of the message ID, message timestamp and raw request body, in that order, using the secret supplied during subscription. Preserve the raw body until verification is complete and compare the signature using a time-safe comparison. Twitch’s guide says to return a 4XX response when the signature is invalid. These are Twitch-specific instructions: do not transplant that construction into a Mux handler.

Challenge handling is also distinct from ordinary notification processing. When a new Twitch subscription sends a webhook_callback_verification message, return HTTP 200 with the raw challenge string as the response body. Do not wrap the challenge in JSON or run it through the ordinary event workflow. A successful challenge proves that the callback can answer the verification request; it does not prove that your notification handler is correct in every other case.

For Mux, use the signing approach in Mux’s documentation and the secret generated for that endpoint. Do not infer Mux’s signature format from Twitch’s message fields or vice versa. Keep the provider-specific verifier in a small, testable component, and ensure that failed verification cannot enqueue a task or alter a stream record. If a signature check fails, log enough to investigate the failure without recording the secret or exposing sensitive request material.

Acknowledge quickly and process asynchronously

A callback request should do the minimum required to accept or reject the event. Verify authenticity, validate the basic event envelope, record or queue the event durably, then return the response required by the provider. Database operations that could take a long time, notifications, media processing and calls to other APIs belong in asynchronous work rather than in the request path.

A reliable pattern is to place an accepted event in a durable queue or temporary storage before returning success. A worker can then load the event, apply the state change and retry your own internal work if needed. If the event cannot be stored, do not claim that it has been safely accepted; follow the provider’s documented response behaviour for unsuccessful delivery. Your queue should retain enough context to identify the event and diagnose processing failures.

The acknowledgement deadline is not a target to use up. Mux documents that an individual attempt times out after five seconds. Twitch says notification requests should be acknowledged within a few seconds and warns that too many slow responses can lead to subscription revocation. The practical response is the same—keep the handler fast—but the exact rules and consequences are not shared. Check each provider’s current guide when setting timeouts.

Separate “accepted by the endpoint” from “fully processed by the application”. A 2XX response should mean that the request passed the checks you require and has been safely handed off, not that a downstream email or dashboard refresh has completed. This distinction matters during bursts or an outage in a downstream dependency. An operations view should show events waiting to process and events that failed, rather than making a slow callback wait for all follow-on work.

Handle retries, duplicates and event order

Do not build as though a webhook is delivered exactly once. Mux says duplicate deliveries can occur even after a 2XX response, and unsuccessful deliveries are retried over the next 24 hours with increasing delay. Retrying is useful when your endpoint is temporarily unavailable, but it means your application must tolerate the same event arriving again. Do not assume another provider follows those retry timings; consult its own current delivery documentation.

Use the provider’s event or message identifier as an idempotency key where one is available. Record that identifier with the result of processing, and make the database update safe to repeat. For example, if the same “stream active” event arrives twice, the second attempt should not send a duplicate announcement or create a second active-stream record. If a provider does not supply a suitable identifier for the event you need, define an application-level key carefully from documented fields and test for collisions.

Think about event order separately from duplicate delivery. A delayed “connected” message may arrive after a newer state has already been applied, or a retry may be processed later than a different event. Store the event timestamp or version information supplied by the provider where appropriate, and define which transitions your application permits. Avoid simply overwriting the current status with whichever request arrived last. The provider’s event semantics should guide whether an update is newer or whether a transition is valid.

Keep the event record and state change consistent. One practical approach is to persist the event identity and a pending state change together, then let a worker process it with an idempotent transaction. When processing fails, preserve enough information to retry without accepting the same provider event as an unrelated new one. This makes later investigation possible and prevents a temporary database or notification problem from turning into an accidental second action.

For a continuous channel, a mistaken “ended” status can be more confusing than a short delay while reconnecting. Mux’s disconnected-versus-idle distinction is a concrete example: reflect the provider’s reconnect window rather than converting every lost encoder connection into a final status. A guide to home-server reconnects during power fluctuations can help you think through the encoder-side failure; the webhook still needs to represent provider events accurately.

Test lifecycle events safely

Test the endpoint before registering it for a production workflow. Begin with signature verification, a valid callback or challenge where relevant, a normal event, an invalid signature, a duplicate event and a slow or unavailable downstream worker. Check both the HTTP response and the resulting application state. A response code alone does not show that the event was interpreted correctly.

For Mux, the CLI can forward events to a local endpoint, replay events retained from listen sessions and trigger synthetic events without creating real resources. The documentation describes forwarding as a local-development tool with no delivery guarantees; configure a production endpoint in the Dashboard for production delivery. A tunnel such as ngrok can expose a local route for testing, but a successful tunnel test is not production verification.

Twitch’s CLI can help test challenge and notification handling. Test the challenge response as its own path, then exercise ordinary notifications and signature failures. Also check that the handler returns promptly when a worker is slow, and that replaying the same event does not repeat side effects. Keep test credentials and production signing secrets separate.

After local tests, verify the configured production callback from the provider’s own setup and current documentation. Check that it is reachable over the required transport, that the right environment or subscription is selected, and that event processing appears in your logs or operational view. The goal is not just to make one request succeed; it is to know what your application does when an event is retried, arrives twice, or cannot be processed immediately.

Before committing, compare the operating options on the pricing page. When the file and channel are ready, start free — 24-hour trial, no card.

FAQ

Is a webhook the same as a live stream?

No. A webhook is a notification sent to your application about an event; it does not itself create or carry the live broadcast. Your streaming provider and encoder or media workflow handle the stream, while the webhook lets an application react to documented state changes.

Can I use one verification method for Mux and Twitch EventSub?

No. Both use HTTP callbacks, but their callback and authentication requirements differ. Follow the selected provider’s current documentation, preserve raw request data where its verifier requires it, and do not copy Twitch’s signature construction into a Mux integration.

Should I announce that a stream has ended as soon as it disconnects?

Not without checking the provider’s lifecycle meaning. In Mux, a disconnected encoder can still be within the reconnect window; the later idle event marks the transition after that window expires. Map events to viewer-facing messages according to the provider’s definitions.

Does a local webhook test prove production delivery?

No. A local forwarding tool or tunnel can test your route and handler, but it does not necessarily provide production delivery guarantees. Separately check the production endpoint configuration, transport requirements, environment or subscription, and your application’s handling of retries and duplicate events.

YOU’VE REACHED THE END

Keep the ideas coming.

More guides, useful tools and a little help for your next broadcast.

Back to the journal ↗
YOUR NEXT READ

A little more to explore.

More Setup Guides guides ↗ · All topics ↗