Service Disruption Callbacks
The Vonage Video platform continuously monitors all running services. When an internal failure affects a service — such as a media server crash, an archiver failure, a broadcast node going down, a SIP gateway issue, or a captions engine fault — the platform's monitoring system detects the failure, updates the service state, and immediately sends a callback notification to your registered endpoint.
This guide explains which callbacks each service emits on disruption, what the payloads look like, and how to recover each service programmatically.
Overview
Service disruptions can affect any of the following Vonage Video services:
| Service | What is disrupted | Primary callback mechanism |
|---|---|---|
| Sessions | Media Router crashes; participant connections and streams are terminated | Server-side session monitoring webhook + client SDK events |
| Archives (Recordings) | Archiver process crashes; the recording is terminated abnormally | Archive status webhook ("status": "failed") |
| Broadcasts | Broadcast node fails; the HLS/RTMP stream is terminated | Broadcast status webhook ("status": "failed") |
| SIP Calls | SIP gateway fails; the call leg is dropped | Session monitoring webhook callDestroyed |
| Captions | Captions engine fails; live transcription stops | Captions status webhook ("status": "failed") |
In all cases the reason field in the callback payload is normally set to "forceDisconnected". Other reason values may appear depending on the nature of the failure, so your recovery code should treat any unexpected termination (not caused by your own API calls) as a potential disruption.
Note: The platform also sends pre-disruption warnings for server rotations (reason: "serverRotation") via the sessionNotification event. See Server Rotation and Session Migration for details on that specific scenario.
Prerequisites
To receive server-side disruption callbacks you must register a Session Monitoring callback URL for your project. See Session Monitoring for setup instructions.
For archive, broadcast, and captions status callbacks, configure the corresponding status callback URL in your Vonage Video API project dashboard.
Session Disruption
When the Media Router hosting a session crashes, the session is destroyed and the platform sends a sessionDestroyed event to your session monitoring endpoint.
Callback Payloads
{
"sessionId": "2_MX4xMzExMjU3MX5-MTQ3MDI1NzY3OTkxOH45QXRr",
"projectId": "123456",
"event": "sessionDestroyed",
"reason": "forceDisconnected",
"timestamp": 1718000050000
}
Client SDK events
In parallel with server-side webhooks, clients receive lifecycle events via the SDK:
session.on('sessionReconnecting', () => {
// Platform is attempting automatic reconnection via session migration
showReconnectingBanner();
});
session.on('sessionReconnected', () => {
// Automatic recovery succeeded — no further action needed
hideReconnectingBanner();
});
session.on('sessionDisconnected', (event) => {
// Automatic recovery failed or is not enabled
if (event.reason === 'networkDisconnected' || event.reason === 'networkTimedout') {
promptUserToRejoin();
}
});
publisher.on('streamDestroyed', (event) => {
if (event.reason === 'networkDisconnected') {
event.preventDefault(); // Keep the publisher element in the DOM
retryPublish();
}
});
For native SDKs use the equivalent delegate methods:
- iOS:
OTSessionDelegate.sessionDidBeginReconnecting(_:)/sessionDidReconnect(_:)/sessionDidDisconnect(_:) - Android:
Session.SessionListener.onReconnecting()/onReconnected()/onDisconnected()
Recovery
When sessionDisconnected fires with reason: "forceDisconnected" (or after sessionReconnecting times out):
- Create a new session via the REST API or a Server SDK.
- Issue fresh tokens for all participants.
- Notify clients to reconnect — via your own signalling channel, push notification, or in-app message.
// Server-side — handle sessionDestroyed with reason "forceDisconnected"
app.post('/callbacks/vonage/session', (req, res) => {
const { event, reason, sessionId } = req.body;
if (event === 'sessionDestroyed' && reason === 'forceDisconnected') {
createNewSessionAndNotifyClients(sessionId);
}
res.sendStatus(200);
});
Tip: If Session Migration is enabled, the platform may recover the session automatically. In that case sessionReconnected fires on the client and no manual rejoin is needed.
Archive (Recording) Disruption
When an archiver process crashes mid-recording, the platform's monitoring system detects the failure, marks the archive as "failed", and sends a status callback to your registered archive status URL.
Callback Payload
{
"id": "b40ef09b-3811-4726-b508-e41a0f96c68f",
"event": "archive",
"status": "failed",
"reason": "Internal server failure",
"sessionId": "2_MX4xMzExMjU3MX5-MTQ3MDI1NzY3OTkxOH45QXRr",
"projectId": "123456",
"name": "My Recording",
"createdAt": 1718000000000,
"duration": 0,
"outputMode": "composed",
"hasVideo": true,
"hasAudio": true
}
Key fields:
| Field | Value on disruption |
|---|---|
status |
"failed" |
reason |
"Internal server failure" |
duration |
May be 0 if the failure occurred before the first segment was written |
Recovery
app.post('/callbacks/vonage/archive', (req, res) => {
const { status, reason, sessionId } = req.body;
if (status === 'failed' && reason === 'Internal server failure') {
// Start a new archive for the same session
opentok.startArchive(sessionId, { name: 'Resumed recording' }, (err, archive) => {
if (err) console.error('Failed to restart archive:', err);
else console.log('New archive started:', archive.id);
});
}
res.sendStatus(200);
});
Note: Always verify that the session still has active participants before restarting the archive. Starting an archive on an empty session will result in an error.
Broadcast Disruption
When a broadcast node fails, the HLS or RTMP stream is terminated and the broadcast is marked as "failed". A status callback is sent to your broadcast status URL.
Callback Payload
{
"id": "1748b707-0a81-464c-9759-c46ad10d3734",
"sessionId": "2_MX4xMDBfjE0Mzc2NzY1NDgwMTJ-TjMzfn4",
"applicationId": 100,
"createdAt": 1437676551000,
"updatedAt": 1437676551000,
"event": "broadcast",
"group": "status",
"resolution": "640x480",
"streamMode" : "auto",
"streams" : [],
"broadcastUrls": {
"hls" : "http://server/fakepath/playlist.m3u8",
"hlsStatus": "error",
"rtmp": {
"foo": {
"serverUrl": "rtmps://myfooserver:443/myfooapp",
"streamName": "myfoostream",
"status": "error"
},
"bar": {
"serverUrl": "rtmp://mybarserver:443/mybarapp",
"streamName": "mybarstream",
"status": "error"
}
}
},
"settings": {
"hls": {
"dvr": false,
"lowLatency": false
}
},
"status": "failed",
"reason": "Internal server failure"
}
Recovery
- Receive the
"failed"status callback. - Wait until clients have reconnected to the session (listen for
connectionCreatedevents, or poll session participants). - Start a new broadcast:
app.post('/callbacks/vonage/broadcast', (req, res) => {
const { status, reason, sessionId } = req.body;
if (status === 'failed' && reason === 'Internal server failure') {
waitForParticipants(sessionId).then(() => {
opentok.startBroadcast(sessionId, broadcastOptions, (err, broadcast) => {
if (err) console.error('Failed to restart broadcast:', err);
else notifyViewersOfNewStreamUrl(broadcast.broadcastUrls);
});
});
}
res.sendStatus(200);
});
Important: The HLS URL changes with each new broadcast. Make sure to update any players or downstream systems consuming the stream with the new URL.
SIP Call Disruption
When a SIP gateway failure drops an active call leg, the SIP connection is terminated and the platform sends callDestroyed to your session monitoring endpoint with reason_message: "Unexpected Clearing". The connection data of a SIP connection typically contains a sip identifier so you can distinguish it from regular participant connections.
Callback Payload
{
"sessionId": "2_MX4xMzExMjU3MX5-MTQ3MDI1NzY3OTkxOH45QXRr",
"applicationId": "123456",
"event": "callDestroyed",
"reason_code": "703",
"reason_message": "Unexpected Clearing",
"timestamp": 1718000050000,
"call": {
"id": "<conference-id>",
"connectionId": "<sip-ot-connection-id>",
"createdAt": 1470257688143
}
}
Recovery
Identify SIP connections by inspecting connection.data, then re-dial:
app.post('/callbacks/vonage/session', (req, res) => {
const { event, reason_message, connection, sessionId } = req.body;
if (event === 'callDestroyed' && reason_message === 'Unexpected Clearing') {
let connData = {};
try { connData = JSON.parse(connection.data); } catch (_) {}
if (connData.sip) {
// Re-initiate the SIP call
const sipUri = getSipUriForConnection(connection.id);
opentok.dial(sessionId, token, sipUri, sipOptions, (err, call) => {
if (err) console.error('SIP redial failed:', err);
else console.log('SIP call re-established:', call.id);
});
}
}
res.sendStatus(200);
});
Captions Disruption
When the captions engine fails, live transcription stops and the captions session is marked as "failed". A status callback is sent to your captions status URL.
Callback Payload
{
"captionsId": "<captionsId>",
"projectId": "<applicationId>",
"sessionId": "<sessionId>",
"status": "failed",
"createdAt": 1651253477,
"updatedAt": 1651253837,
"duration": 360,
"languageCode": "en-US",
"reason": "Internal server failure",
"provider": "aws-transcribe",
"event": "sessionStatus"
}
Recovery
app.post('/callbacks/vonage/captions', (req, res) => {
const { status, reason, sessionId } = req.body;
if (status === 'failed' && reason === 'Internal server failure') {
// Restart captions for the session
fetch(`https://video.api.vonage.com/v2/project/${PROJECT_ID}/captions`, {
method: 'POST',
headers: {
'Authorization': `Bearer ${jwt}`,
'Content-Type': 'application/json'
},
body: JSON.stringify({ sessionId, token: generateToken(sessionId) })
})
.then(res => res.json())
.then(data => console.log('Captions restarted:', data.captionsId))
.catch(err => console.error('Failed to restart captions:', err));
}
res.sendStatus(200);
});
Best Practices
- Always check the
reasonfield, but do not rely on it exclusively. While disruptions typically carry"Internal server failure", your recovery logic should treat any unexpected"failed"status or<something>Destroyedevent as a potential platform disruption. - Implement idempotent recovery handlers. Callbacks may be delivered more than once. Use the resource ID (
archive.id,captionsId,session.id) to deduplicate. - Use pre-rotation warnings. The
sessionNotificationevent (withremainingTime: 3600or14400) gives you advance notice of planned rotations. Use it to cleanly stop archives, broadcasts, and captions before the rotation, avoiding a hard"forceDisconnected"termination. - Log all disruption events with their full payload for post-incident analysis. The
timestampfield is your ground truth for calculating impact duration. - For sessions, prefer Session Migration. Enabling session migration dramatically reduces the blast radius of Media Router failures by transparently moving clients to a healthy server. See Server Rotation and Session Migration.
- Set up alerts on
"Internal server failure"callbacks. A spike inInternal server failureevents across multiple sessions is an early signal of a wider platform incident.
Related Resources
- Session Monitoring
- Server Rotation and Session Migration
- Archiving Guide
- Broadcast Guide
- SIP Interconnect Guide
- Live Captions Guide