Web Call Server 5.3 REST API (3.0.0)
Download OpenAPI specification:
This document describes REST Hooks. All hooks are called via POST with a JSON body.
Hook URLs can be configured in WCS_HOME/conf/database.yml.
Example hook:
http://localhost:8081/apps/DefaultApp/connect
This is the very first hook called when a user attempts to connect to the server, for example via the WebSDK API:
Flashphoner.createSession()
Example hook:
http://localhost:8081/apps/DefaultApp/publishStream
This hook is called within the client's session and indicates that the client is attempting to publish a stream.
Hook triggers:
Each hook has a behavior badge — a coloured label that summarises how the Backend response affects the operation — and belongs to a scope visible in the left sidebar (Connection / Stream / SIP).
Confirm — WCS calls the hook before continuing the client operation. A 2xx response lets WCS proceed; a 4xx/5xx response rejects the operation when restOnError=FAIL (connect, playHLS, and playRTSP always fail on hook errors). If the 2xx response body contains fields, they override the corresponding operation parameters when restPolicy=OVERWRITE and restOverwrite are configured; connect always uses returned connection data.
Notify — reports a state change or completed action after the fact. Hook errors do not roll back the server action; returned fields are ignored except where explicitly documented (for example, the ESTABLISHED state of ConnectionStatusEvent).
Control — periodically asks the Backend whether an ongoing operation may continue. A 2xx response lets it keep running; a 4xx/5xx response tells WCS to stop it. For example, a 2xx for StreamKeepAliveEvent keeps the stream alive; a 4xx stops the stream.
The default per-hook behavior described above can be customised per Connection via the restClientConfig field returned by the connect hook. The field is a map keyed by hook name; each entry tunes how WCS invokes that hook for the rest of the session:
restPolicy — DISABLE (skip the hook entirely), NOTIFY (fire-and-forget, ignore Backend response), or OVERWRITE (apply restOverwrite fields from the response back to the operation).restExclude — comma-separated list of fields to strip from the request body before sending to the Backend.restOverwrite — comma-separated list of fields whose returned values are applied back to the operation (effective only with restPolicy=OVERWRITE).restOnError — LOG (continue with the original payload) or FAIL (reject the operation).WCS stores the returned restClientConfig on the session and applies it to every subsequent hook of the matching name.
Example fragment of the connect hook response body:
{ "restClientConfig": { "publishStream": { "restExclude": "hasVideo,hasAudio", "restOverwrite": "createDate", "restOnError": "LOG", "restPolicy": "OVERWRITE" } } }
Connection — client transport connections, sessions, in-session data, and diagnostics.
Stream — media streams: publish, play, snapshot, recording, transcoding, and stream events.
SIP — SIP signaling: calls, transfers, registration, DTMF.
/apps/DefaultApp
By default, all hooks use /apps/DefaultApp as part of the path. Examples:
http://localhost:8081/apps/DefaultApp/call
http://localhost:8081/apps/DefaultApp/answer
...
To use a custom path, configure it in WCS_HOME/conf/database.yml, for example https://mycompany.com/mycompanyapi. WCS will then call the hooks at the custom URL:
https://mycompany.com/mycompanyapi/call
https://mycompany.com/mycompanyapi/answer
...
Category only. Groups REST hooks fired on events of a specific client Connection itself — opening the transport session, in-session data exchange, diagnostics.
/apps/DefaultApp/connect
WCS calls this hook when a client or agent opens a transport connection, for example WebSocket, RTMP/Flash, or CDN. The hook is invoked before the connection is fully accepted, so the Backend can validate the request, attach custom session attributes, or reject the connection. The request body contains the client login, session identifiers, app key, custom data, and transport details. The Backend may return the same payload, return a modified payload to override fields visible to WCS, or reply with a 4xx/5xx status to refuse the connection. If the response is non-2xx, WCS closes the connection and the client receives a FAILED connection status.
object Custom key-value parameters | |
| nodeId | string Unique identifier of the WCS server instance. Auto-generated as {randomString}@{serverIP} and stored in {WCS_HOME}/conf/node_id |
| appKey | string REST hook application key. Determines the webhook URL for event notifications, as configured in database.yml |
| sessionId | string Signaling session ID (Connection ID). For WebSocket connections the format is /remoteIP:port/localIP:port. Format varies for other connection types |
| origin | string Origin URL of the client page (browser domain) |
| width | integer <int32> Default video width in pixels set by the client at connection time. Streams typically override this with their own resolution. Primarily used for SIP call media sessions |
| height | integer <int32> Default video height in pixels set by the client at connection time. Streams typically override this with their own resolution. Primarily used for SIP call media sessions |
| supportedResolutions | string Client resolution in WxH format |
| useDTLS | boolean Whether the connection uses DTLS for secure media transport. Always true for WebRTC connections, false for RTMP |
| authToken | string Session token for reconnection. If the WebSocket connection is lost, the client can reconnect with this token to rejoin the same session instead of creating a new one |
| status | string Enum: "NEW" "PENDING" "ESTABLISHED" "DISCONNECTED" "FAILED" "REGISTERED" "UNREGISTERED" Connection status: NEW (created), PENDING (waiting), ESTABLISHED (connected — WebSocket, RTMP, or other), DISCONNECTED (connection lost, session may be preserved with keepAlive), FAILED (error). SIP-specific: REGISTERED (SIP registration on PBX successful), UNREGISTERED (SIP registration removed) |
object Map of REST hook configurations. Explanation of the fields: • restExclude — fields that should be excluded from the REST request • clientExclude — fields that should be excluded from the REST response • restOverwrite — fields whose values must be overwritten • restOnError — behavior on error: LOG or FAIL • restPolicy — application policy: DISABLE, NOTIFY, or OVERWRITE Map structure: { "publishStream": RestMethodConfig } | |
| logLevel | string Per-connection logging level. Controls the log verbosity for this specific client without affecting other connections or global server logs |
| keepAlive | boolean Whether the session is preserved after WebSocket disconnect. When true, the client can reconnect with authToken to rejoin the same session. When false, the session is removed immediately on disconnect |
| mediaProviders | Array of strings unique List of media providers supported by the connected client (e.g. WebRTC, Flash for RTMP clients like OBS, MSE, WSPlayer) |
| clientVersion | string Version string reported by the client at connection time (e.g. 2.0) |
| clientOSVersion | string Client platform string reported at connection time (e.g. navigator.appVersion in browser) |
| clientBrowserVersion | string Client User-Agent string reported at connection time |
| msePacketizationVersion | integer <int32> MSE packetization format version. Version 1 is the default legacy format, Version 2 is an optimized format. Only applicable to MSE media provider |
{- "custom": {
- "example": 0
}, - "nodeId": "7aoC1Q9IkTCn4zEsNAKvl1P1QMnXfnKE@192.168.100.1",
- "appKey": "defaultApp",
- "sessionId": "/192.168.1.102:13252/192.168.1.101:8443",
- "width": 640,
- "height": 480,
- "supportedResolutions": "720x480",
- "useDTLS": true,
- "authToken": "d62440e7-0e38-4831-9fc1-7d3beb2a0d31",
- "status": "ESTABLISHED",
- "restClientConfig": {
- "publishStream": {
- "restExclude": "hasVideo,hasAudio",
- "clientExclude": "sdp",
- "restOverwrite": "createDate",
- "restOnError": "LOG",
- "restPolicy": "DISABLE"
}
}, - "logLevel": "DEBUG",
- "keepAlive": true,
- "mediaProviders": [
- "WebRTC"
], - "clientVersion": "2.0",
- "clientOSVersion": "5.0 (X11; Linux x86_64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/142.0.0.0 Safari/537.36",
- "clientBrowserVersion": "Mozilla/5.0 (X11; Linux x86_64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/142.0.0.0 Safari/537.36",
- "msePacketizationVersion": 2
}{- "custom": {
- "example": 0
}, - "nodeId": "7aoC1Q9IkTCn4zEsNAKvl1P1QMnXfnKE@192.168.100.1",
- "appKey": "defaultApp",
- "sessionId": "/192.168.1.102:13252/192.168.1.101:8443",
- "width": 640,
- "height": 480,
- "supportedResolutions": "720x480",
- "useDTLS": true,
- "authToken": "d62440e7-0e38-4831-9fc1-7d3beb2a0d31",
- "status": "ESTABLISHED",
- "restClientConfig": {
- "publishStream": {
- "restExclude": "hasVideo,hasAudio",
- "clientExclude": "sdp",
- "restOverwrite": "createDate",
- "restOnError": "LOG",
- "restPolicy": "DISABLE"
}
}, - "logLevel": "DEBUG",
- "keepAlive": true,
- "mediaProviders": [
- "WebRTC"
], - "clientVersion": "2.0",
- "clientOSVersion": "5.0 (X11; Linux x86_64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/142.0.0.0 Safari/537.36",
- "clientBrowserVersion": "Mozilla/5.0 (X11; Linux x86_64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/142.0.0.0 Safari/537.36",
- "msePacketizationVersion": 2
}/apps/DefaultApp/OnDataEvent
WCS calls this hook when a client sends an arbitrary data payload to the server via the WebSDK session.sendData(data) call. The request body contains the application-defined payload and the originating session identifiers.sendData(data) (status ACCEPTED). A hook failure rejects the data operation when restOnError=FAIL and the same Promise is rejected (status FAILED); otherwise WCS logs the failure and continues with the original payload.
object Custom key-value parameters | |
| nodeId | string Unique identifier of the WCS server instance. Auto-generated as {randomString}@{serverIP} and stored in {WCS_HOME}/conf/node_id |
| appKey | string REST hook application key. Determines the webhook URL for event notifications, as configured in database.yml |
| sessionId | string Signaling session ID (Connection ID). For WebSocket connections the format is /remoteIP:port/localIP:port. Format varies for other connection types |
| origin | string Origin URL of the client page (browser domain) |
| operationId | string Unique identifier (UUID) of this data operation, generated by the client. The client uses it to correlate the asynchronous response — delivered via DataStatusEvent — back to the originating sendData call. |
| payload | object Application-defined JSON payload that the client sent through the data channel; the contents are opaque to WCS and are forwarded as-is |
| status | string Outcome of the data operation. Populated by WCS after the sendData flow completes and delivered to the client via the WebSDK SEND_DATA_STATUS event and to the Backend via DataStatusEvent. Possible values: ACCEPTED (operation succeeded; the payload was forwarded to the target session(s)) or FAILED (operation failed; the failure reason is in the info field). In the OnDataEvent request body this field is typically empty (the operation has not yet been processed). |
| info | string Additional information |
| sessionIds | Array of strings Explicit list of signaling session IDs (Connection IDs) that should receive this data payload; when empty the payload is broadcast to every session in the originating app |
| allSessionIds | Array of strings Effective list of signaling session IDs (Connection IDs) that will receive this data payload, including the originating session and any explicitly added sessionIds |
{- "custom": {
- "example": 0
}, - "nodeId": "7aoC1Q9IkTCn4zEsNAKvl1P1QMnXfnKE@192.168.100.1",
- "appKey": "defaultApp",
- "sessionId": "/192.168.1.102:13252/192.168.1.101:8443",
- "operationId": "2497358d-dd6e-4601-926c-cb2b6b12391d",
- "payload": {
- "appKey": "defaultApp",
- "body": "Hello alice",
- "contentType": "application/imdn+xml",
- "custom": {
- "property1": { },
- "property2": { }
}, - "from": "<tel:+447912345678;tag=ab12cd34ef56>\n",
- "id": "a3f9c2b1-ff00-4e5d-9c77-112233445566",
- "isImdnRequired": true,
- "nodeId": "7aoC1Q9IkTCn4zEsNAKvl1P1QMnXfnKE@127.0.0.1",
- "sessionId": "/192.168.1.102:13252/192.168.1.101:8443",
- "sipMessageRaw": "INVITE sip:...",
- "status": "IMDN_NOTIFICATION_SENT",
- "to": "<tel:+447912345678;tag=ab12cd34ef56>\n"
}, - "status": "ACCEPTED",
- "info": "msg: null",
- "sessionIds": [
- "/192.168.1.102:13252/192.168.1.101:8443"
], - "allSessionIds": [
- "/192.168.1.102:13252/192.168.1.101:8443"
]
}{- "custom": {
- "example": 0
}, - "nodeId": "7aoC1Q9IkTCn4zEsNAKvl1P1QMnXfnKE@192.168.100.1",
- "appKey": "defaultApp",
- "sessionId": "/192.168.1.102:13252/192.168.1.101:8443",
- "operationId": "2497358d-dd6e-4601-926c-cb2b6b12391d",
- "payload": {
- "appKey": "defaultApp",
- "body": "Hello alice",
- "contentType": "application/imdn+xml",
- "custom": {
- "property1": { },
- "property2": { }
}, - "from": "<tel:+447912345678;tag=ab12cd34ef56>\n",
- "id": "a3f9c2b1-ff00-4e5d-9c77-112233445566",
- "isImdnRequired": true,
- "nodeId": "7aoC1Q9IkTCn4zEsNAKvl1P1QMnXfnKE@127.0.0.1",
- "sessionId": "/192.168.1.102:13252/192.168.1.101:8443",
- "sipMessageRaw": "INVITE sip:...",
- "status": "IMDN_NOTIFICATION_SENT",
- "to": "<tel:+447912345678;tag=ab12cd34ef56>\n"
}, - "status": "ACCEPTED",
- "info": "msg: null",
- "sessionIds": [
- "/192.168.1.102:13252/192.168.1.101:8443"
], - "allSessionIds": [
- "/192.168.1.102:13252/192.168.1.101:8443"
]
}/apps/DefaultApp/sessionDebug
WCS calls this hook when a client starts or stops session debugging, for example by calling Session.startDebug() or Session.stopDebug() in WebSDK. The feature can be disabled by the sessionDebugEnabled system property. The request body contains the session identifiers and the debug command.
object Custom key-value parameters | |
| nodeId | string Unique identifier of the WCS server instance. Auto-generated as {randomString}@{serverIP} and stored in {WCS_HOME}/conf/node_id |
| appKey | string REST hook application key. Determines the webhook URL for event notifications, as configured in database.yml |
| sessionId | string Signaling session ID (Connection ID). For WebSocket connections the format is /remoteIP:port/localIP:port. Format varies for other connection types |
| origin | string Origin URL of the client page (browser domain) |
| status | string Enum: "STARTED" "STOPPED" "FAILED" "PASSED" Session debug status |
| command | string Command. Supported commands: "start", "stop". |
{- "custom": {
- "example": 0
}, - "nodeId": "7aoC1Q9IkTCn4zEsNAKvl1P1QMnXfnKE@192.168.100.1",
- "appKey": "defaultApp",
- "sessionId": "/192.168.1.102:13252/192.168.1.101:8443",
- "status": "STARTED",
- "command": "start"
}{- "custom": {
- "example": 0
}, - "nodeId": "7aoC1Q9IkTCn4zEsNAKvl1P1QMnXfnKE@192.168.100.1",
- "appKey": "defaultApp",
- "sessionId": "/192.168.1.102:13252/192.168.1.101:8443",
- "status": "STARTED",
- "command": "start"
}/apps/DefaultApp/submitBugReport
WCS calls this hook when a client submits a bug report through the session, for example by calling Session.submitBugReport() with a JSON report object. The request body contains report text, report type, and session identifiers.
object Custom key-value parameters | |
| nodeId | string Unique identifier of the WCS server instance. Auto-generated as {randomString}@{serverIP} and stored in {WCS_HOME}/conf/node_id |
| appKey | string REST hook application key. Determines the webhook URL for event notifications, as configured in database.yml |
| sessionId | string Signaling session ID (Connection ID). For WebSocket connections the format is /remoteIP:port/localIP:port. Format varies for other connection types |
| origin | string Origin URL of the client page (browser domain) |
| text | string Free-form description of the issue, supplied by the client when calling the WebSDK Session.submitBugReport({text, type}). On the server it is appended to the report file together with system info (login, OS, browser, log folder). Present in the submitBugReport hook payload; not used by BugReportStatusEvent. |
| type | string Optional bug report category supplied by the client when calling Session.submitBugReport({text, type}). When set to no_media (and client_dump_level < 2), WCS additionally starts a tcpdump capture of the current SIP call's media ports for no_media_dump_interval milliseconds (default 15000). Other values are accepted but trigger no special server-side behavior. Present in the submitBugReport hook payload; not used by BugReportStatusEvent. |
| file | string Filename of the report saved by WCS under WCS_HOME/logs/bugreports/{yyyy-MM-dd}/. Format: client-{sipLogin}-{yyyy.MM.dd.HH.mm.ss}-{epochMillis}.report. Populated by the server when delivering BugReportStatusEvent; not supplied by the client. |
{- "custom": {
- "example": 0
}, - "nodeId": "7aoC1Q9IkTCn4zEsNAKvl1P1QMnXfnKE@192.168.100.1",
- "appKey": "defaultApp",
- "sessionId": "/192.168.1.102:13252/192.168.1.101:8443",
- "text": "Connection issue",
- "type": "no_media",
- "file": "client-sipLogin-2025.11.21.18.28.35-1763735315290.report"
}{- "custom": {
- "example": 0
}, - "nodeId": "7aoC1Q9IkTCn4zEsNAKvl1P1QMnXfnKE@192.168.100.1",
- "appKey": "defaultApp",
- "sessionId": "/192.168.1.102:13252/192.168.1.101:8443",
- "text": "Connection issue",
- "type": "no_media",
- "file": "client-sipLogin-2025.11.21.18.28.35-1763735315290.report"
}/apps/DefaultApp/pushLogs
WCS calls this hook when session-scoped client log records are uploaded during a debug session and before the logs are stored. The request body contains the originating session identifiers and the log entries.
object Custom key-value parameters | |
| nodeId | string Unique identifier of the WCS server instance. Auto-generated as {randomString}@{serverIP} and stored in {WCS_HOME}/conf/node_id |
| appKey | string REST hook application key. Determines the webhook URL for event notifications, as configured in database.yml |
| sessionId | string Signaling session ID (Connection ID). For WebSocket connections the format is /remoteIP:port/localIP:port. Format varies for other connection types |
| origin | string Origin URL of the client page (browser domain) |
| logs | string Log data |
{- "custom": {
- "example": 0
}, - "nodeId": "7aoC1Q9IkTCn4zEsNAKvl1P1QMnXfnKE@192.168.100.1",
- "appKey": "defaultApp",
- "sessionId": "/192.168.1.102:13252/192.168.1.101:8443",
- "logs": "Log line"
}{- "custom": {
- "example": 0
}, - "nodeId": "7aoC1Q9IkTCn4zEsNAKvl1P1QMnXfnKE@192.168.100.1",
- "appKey": "defaultApp",
- "sessionId": "/192.168.1.102:13252/192.168.1.101:8443",
- "logs": "Log line"
}/apps/DefaultApp/BugReportStatusEvent
WCS sends this notification hook after the submitBugReport flow has successfully saved the bug report file to WCS_HOME/logs/bugreports/{yyyy-MM-dd}/. The hook is not invoked if the file save fails. The request body contains the saved file name and the originating session identifiers. After the hook returns, WCS sends the result as a notifyBugReport WebSocket message to the client; the standard WebSDK does not expose this message to user-level handlers.
object Custom key-value parameters | |
| nodeId | string Unique identifier of the WCS server instance. Auto-generated as {randomString}@{serverIP} and stored in {WCS_HOME}/conf/node_id |
| appKey | string REST hook application key. Determines the webhook URL for event notifications, as configured in database.yml |
| sessionId | string Signaling session ID (Connection ID). For WebSocket connections the format is /remoteIP:port/localIP:port. Format varies for other connection types |
| origin | string Origin URL of the client page (browser domain) |
| text | string Free-form description of the issue, supplied by the client when calling the WebSDK Session.submitBugReport({text, type}). On the server it is appended to the report file together with system info (login, OS, browser, log folder). Present in the submitBugReport hook payload; not used by BugReportStatusEvent. |
| type | string Optional bug report category supplied by the client when calling Session.submitBugReport({text, type}). When set to no_media (and client_dump_level < 2), WCS additionally starts a tcpdump capture of the current SIP call's media ports for no_media_dump_interval milliseconds (default 15000). Other values are accepted but trigger no special server-side behavior. Present in the submitBugReport hook payload; not used by BugReportStatusEvent. |
| file | string Filename of the report saved by WCS under WCS_HOME/logs/bugreports/{yyyy-MM-dd}/. Format: client-{sipLogin}-{yyyy.MM.dd.HH.mm.ss}-{epochMillis}.report. Populated by the server when delivering BugReportStatusEvent; not supplied by the client. |
{- "custom": {
- "example": 0
}, - "nodeId": "7aoC1Q9IkTCn4zEsNAKvl1P1QMnXfnKE@192.168.100.1",
- "appKey": "defaultApp",
- "sessionId": "/192.168.1.102:13252/192.168.1.101:8443",
- "text": "Connection issue",
- "type": "no_media",
- "file": "client-sipLogin-2025.11.21.18.28.35-1763735315290.report"
}{- "custom": {
- "example": 0
}, - "nodeId": "7aoC1Q9IkTCn4zEsNAKvl1P1QMnXfnKE@192.168.100.1",
- "appKey": "defaultApp",
- "sessionId": "/192.168.1.102:13252/192.168.1.101:8443",
- "text": "Connection issue",
- "type": "no_media",
- "file": "client-sipLogin-2025.11.21.18.28.35-1763735315290.report"
}/apps/DefaultApp/ConnectionStatusEvent
WCS sends this notification hook every time a client connection changes its state — for example when the session is ESTABLISHED, DISCONNECTED, or FAILED. The request body contains the connection identifiers, the new status, and fields specific to the connection type: WebRTC, Flash, or SIP. For the ESTABLISHED notification, fields returned by the Backend may be used in the client getUserData response.
object Custom key-value parameters | |
| nodeId | string Unique identifier of the WCS server instance. Auto-generated as {randomString}@{serverIP} and stored in {WCS_HOME}/conf/node_id |
| appKey | string REST hook application key. Determines the webhook URL for event notifications, as configured in database.yml |
| sessionId | string Signaling session ID (Connection ID). For WebSocket connections the format is /remoteIP:port/localIP:port. Format varies for other connection types |
| origin | string Origin URL of the client page (browser domain) |
| width | integer <int32> Default video width in pixels set by the client at connection time. Streams typically override this with their own resolution. Primarily used for SIP call media sessions |
| height | integer <int32> Default video height in pixels set by the client at connection time. Streams typically override this with their own resolution. Primarily used for SIP call media sessions |
| supportedResolutions | string Client resolution in WxH format |
| useDTLS | boolean Whether the connection uses DTLS for secure media transport. Always true for WebRTC connections, false for RTMP |
| authToken | string Session token for reconnection. If the WebSocket connection is lost, the client can reconnect with this token to rejoin the same session instead of creating a new one |
| status | string Enum: "NEW" "PENDING" "ESTABLISHED" "DISCONNECTED" "FAILED" "REGISTERED" "UNREGISTERED" Connection status: NEW (created), PENDING (waiting), ESTABLISHED (connected — WebSocket, RTMP, or other), DISCONNECTED (connection lost, session may be preserved with keepAlive), FAILED (error). SIP-specific: REGISTERED (SIP registration on PBX successful), UNREGISTERED (SIP registration removed) |
object Map of REST hook configurations. Explanation of the fields: • restExclude — fields that should be excluded from the REST request • clientExclude — fields that should be excluded from the REST response • restOverwrite — fields whose values must be overwritten • restOnError — behavior on error: LOG or FAIL • restPolicy — application policy: DISABLE, NOTIFY, or OVERWRITE Map structure: { "publishStream": RestMethodConfig } | |
| logLevel | string Per-connection logging level. Controls the log verbosity for this specific client without affecting other connections or global server logs |
| keepAlive | boolean Whether the session is preserved after WebSocket disconnect. When true, the client can reconnect with authToken to rejoin the same session. When false, the session is removed immediately on disconnect |
| mediaProviders | Array of strings unique List of media providers supported by the connected client (e.g. WebRTC, Flash for RTMP clients like OBS, MSE, WSPlayer) |
| clientVersion | string Version string reported by the client at connection time (e.g. 2.0) |
| clientOSVersion | string Client platform string reported at connection time (e.g. navigator.appVersion in browser) |
| clientBrowserVersion | string Client User-Agent string reported at connection time |
object (RTCMetricsServerDescription) Client-side instructions for collecting and shipping WebRTC RTC metrics: ingest endpoint, authorization header, per-stat metric whitelist, batching window, and optional compressor | |
| msePacketizationVersion | integer <int32> MSE packetization format version. Version 1 is the default legacy format, Version 2 is an optimized format. Only applicable to MSE media provider |
{- "custom": {
- "example": 0
}, - "nodeId": "7aoC1Q9IkTCn4zEsNAKvl1P1QMnXfnKE@192.168.100.1",
- "appKey": "defaultApp",
- "sessionId": "/192.168.1.102:13252/192.168.1.101:8443",
- "width": 640,
- "height": 480,
- "supportedResolutions": "720x480",
- "useDTLS": true,
- "authToken": "d62440e7-0e38-4831-9fc1-7d3beb2a0d31",
- "status": "ESTABLISHED",
- "restClientConfig": {
- "publishStream": {
- "restExclude": "hasVideo,hasAudio",
- "clientExclude": "sdp",
- "restOverwrite": "createDate",
- "restOnError": "LOG",
- "restPolicy": "DISABLE"
}
}, - "logLevel": "DEBUG",
- "keepAlive": true,
- "mediaProviders": [
- "WebRTC"
], - "clientVersion": "2.0",
- "clientOSVersion": "5.0 (X11; Linux x86_64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/142.0.0.0 Safari/537.36",
- "clientBrowserVersion": "Mozilla/5.0 (X11; Linux x86_64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/142.0.0.0 Safari/537.36",
- "webRTCMetricsServerDescription": {
- "authorization": "Bearer eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXV...",
- "types": {
- "codec": {
- "metrics": "timestamp,payloadType,mimeType,clockRate,channels"
}, - "inbound-rtp": {
- "metrics": "timestamp,ssrc,kind,packetsReceived,packetsReceivedWithEct1,packetsReceivedWithCe,packetsReportedAsLost,packetsReportedAsLostButRecovered,packetsLost,jitter,trackIdentifier,mid,remoteId,framesDecoded,keyFramesDecoded,framesRendered,framesDropped,frameWidth,frameHeight,framesPerSecond,qpSum,totalDecodeTime,totalInterFrameDelay,totalSquaredInterFrameDelay,pauseCount,totalPausesDuration,freezeCount,totalFreezesDuration,lastPacketReceivedTimestamp,headerBytesReceived,packetsDiscarded,fecBytesReceived,fecPacketsReceived,fecPacketsDiscarded,bytesReceived,nackCount,firCount,pliCount,totalProcessingDelay,estimatedPlayoutTimestamp,jitterBufferDelay,jitterBufferTargetDelay,jitterBufferEmittedCount,jitterBufferMinimumDelay,totalSamplesReceived,concealedSamples,silentConcealedSamples,concealmentEvents,insertedSamplesForDeceleration,removedSamplesForAcceleration,audioLevel,totalAudioEnergy,totalSamplesDuration,framesReceived,decoderImplementation,playoutId,powerEfficientDecoder,framesAssembledFromMultiplePackets,totalAssemblyTime,retransmittedPacketsReceived,retransmittedBytesReceived,rtxSsrc,fecSsrc,totalCorruptionProbability,totalSquaredCorruptionProbability,corruptionMeasurements"
}, - "outbound-rtp": {
- "metrics": "timestamp,ssrc,kind,packetsSent,bytesSent,mid,mediaSourceId,remoteId,rid,encodingIndex,headerBytesSent,retransmittedPacketsSent,retransmittedBytesSent,rtxSsrc,targetBitrate,totalEncodedBytesTarget,frameWidth,frameHeight,framesPerSecond,framesSent,hugeFramesSent,framesEncoded,keyFramesEncoded,qpSum,psnrSum,psnrMeasurements,totalEncodeTime,totalPacketSendDelay,qualityLimitationReason,qualityLimitationDurations,qualityLimitationResolutionChanges,nackCount,firCount,pliCount,encoderImplementation,powerEfficientEncoder,active,scalabilityMode,packetsSentWithEct1"
}, - "remote-inbound-rtp": {
- "metrics": "timestamp,ssrc,kind,packetsReceived,packetsReceivedWithEct1,packetsReceivedWithCe,packetsReportedAsLost,packetsReportedAsLostButRecovered,packetsLost,jitter,localId,roundTripTime,totalRoundTripTime,fractionLost,roundTripTimeMeasurements,packetsWithBleachedEct1Marking"
}, - "remote-outbound-rtp": {
- "metrics": "timestamp,ssrc,kind,packetsSent,bytesSent,localId,remoteTimestamp,reportsSent,roundTripTime,totalRoundTripTime,roundTripTimeMeasurements"
}, - "media-source": {
- "metrics": "timestamp,trackIdentifier,kind,audioLevel,totalAudioEnergy,totalSamplesDuration,echoReturnLoss,echoReturnLossEnhancement,width,height,frames,framesPerSecond"
}
}, - "sampling": 500,
- "batchSize": 10,
- "collect": "on",
- "compression": [
- "none"
]
}, - "msePacketizationVersion": 2
}{- "custom": {
- "example": 0
}, - "nodeId": "7aoC1Q9IkTCn4zEsNAKvl1P1QMnXfnKE@192.168.100.1",
- "appKey": "defaultApp",
- "sessionId": "/192.168.1.102:13252/192.168.1.101:8443",
- "width": 640,
- "height": 480,
- "supportedResolutions": "720x480",
- "useDTLS": true,
- "authToken": "d62440e7-0e38-4831-9fc1-7d3beb2a0d31",
- "status": "ESTABLISHED",
- "restClientConfig": {
- "publishStream": {
- "restExclude": "hasVideo,hasAudio",
- "clientExclude": "sdp",
- "restOverwrite": "createDate",
- "restOnError": "LOG",
- "restPolicy": "DISABLE"
}
}, - "logLevel": "DEBUG",
- "keepAlive": true,
- "mediaProviders": [
- "WebRTC"
], - "clientVersion": "2.0",
- "clientOSVersion": "5.0 (X11; Linux x86_64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/142.0.0.0 Safari/537.36",
- "clientBrowserVersion": "Mozilla/5.0 (X11; Linux x86_64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/142.0.0.0 Safari/537.36",
- "webRTCMetricsServerDescription": {
- "authorization": "Bearer eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXV...",
- "types": {
- "codec": {
- "metrics": "timestamp,payloadType,mimeType,clockRate,channels"
}, - "inbound-rtp": {
- "metrics": "timestamp,ssrc,kind,packetsReceived,packetsReceivedWithEct1,packetsReceivedWithCe,packetsReportedAsLost,packetsReportedAsLostButRecovered,packetsLost,jitter,trackIdentifier,mid,remoteId,framesDecoded,keyFramesDecoded,framesRendered,framesDropped,frameWidth,frameHeight,framesPerSecond,qpSum,totalDecodeTime,totalInterFrameDelay,totalSquaredInterFrameDelay,pauseCount,totalPausesDuration,freezeCount,totalFreezesDuration,lastPacketReceivedTimestamp,headerBytesReceived,packetsDiscarded,fecBytesReceived,fecPacketsReceived,fecPacketsDiscarded,bytesReceived,nackCount,firCount,pliCount,totalProcessingDelay,estimatedPlayoutTimestamp,jitterBufferDelay,jitterBufferTargetDelay,jitterBufferEmittedCount,jitterBufferMinimumDelay,totalSamplesReceived,concealedSamples,silentConcealedSamples,concealmentEvents,insertedSamplesForDeceleration,removedSamplesForAcceleration,audioLevel,totalAudioEnergy,totalSamplesDuration,framesReceived,decoderImplementation,playoutId,powerEfficientDecoder,framesAssembledFromMultiplePackets,totalAssemblyTime,retransmittedPacketsReceived,retransmittedBytesReceived,rtxSsrc,fecSsrc,totalCorruptionProbability,totalSquaredCorruptionProbability,corruptionMeasurements"
}, - "outbound-rtp": {
- "metrics": "timestamp,ssrc,kind,packetsSent,bytesSent,mid,mediaSourceId,remoteId,rid,encodingIndex,headerBytesSent,retransmittedPacketsSent,retransmittedBytesSent,rtxSsrc,targetBitrate,totalEncodedBytesTarget,frameWidth,frameHeight,framesPerSecond,framesSent,hugeFramesSent,framesEncoded,keyFramesEncoded,qpSum,psnrSum,psnrMeasurements,totalEncodeTime,totalPacketSendDelay,qualityLimitationReason,qualityLimitationDurations,qualityLimitationResolutionChanges,nackCount,firCount,pliCount,encoderImplementation,powerEfficientEncoder,active,scalabilityMode,packetsSentWithEct1"
}, - "remote-inbound-rtp": {
- "metrics": "timestamp,ssrc,kind,packetsReceived,packetsReceivedWithEct1,packetsReceivedWithCe,packetsReportedAsLost,packetsReportedAsLostButRecovered,packetsLost,jitter,localId,roundTripTime,totalRoundTripTime,fractionLost,roundTripTimeMeasurements,packetsWithBleachedEct1Marking"
}, - "remote-outbound-rtp": {
- "metrics": "timestamp,ssrc,kind,packetsSent,bytesSent,localId,remoteTimestamp,reportsSent,roundTripTime,totalRoundTripTime,roundTripTimeMeasurements"
}, - "media-source": {
- "metrics": "timestamp,trackIdentifier,kind,audioLevel,totalAudioEnergy,totalSamplesDuration,echoReturnLoss,echoReturnLossEnhancement,width,height,frames,framesPerSecond"
}
}, - "sampling": 500,
- "batchSize": 10,
- "collect": "on",
- "compression": [
- "none"
]
}, - "msePacketizationVersion": 2
}/apps/DefaultApp/DataStatusEvent
WCS calls this hook when a client sends a DataStatusEvent WebSocket message to acknowledge a data payload it received from WCS. Typical scenario: the Backend pushes a payload via REST POST /rest-api/v3/data/send, the receiving client gets the data as OnDataEvent and responds with DataStatusEvent to confirm processing — the standard WebSDK does not send this message, so the hook is meant for custom client integrations. The request body contains the originating session identifiers, the operationId that correlates with the original payload, and the delivery status.
object Custom key-value parameters | |
| nodeId | string Unique identifier of the WCS server instance. Auto-generated as {randomString}@{serverIP} and stored in {WCS_HOME}/conf/node_id |
| appKey | string REST hook application key. Determines the webhook URL for event notifications, as configured in database.yml |
| sessionId | string Signaling session ID (Connection ID). For WebSocket connections the format is /remoteIP:port/localIP:port. Format varies for other connection types |
| origin | string Origin URL of the client page (browser domain) |
| operationId | string Unique identifier (UUID) of this data operation, generated by the client. The client uses it to correlate the asynchronous response — delivered via DataStatusEvent — back to the originating sendData call. |
| payload | object Application-defined JSON payload that the client sent through the data channel; the contents are opaque to WCS and are forwarded as-is |
| status | string Outcome of the data operation. Populated by WCS after the sendData flow completes and delivered to the client via the WebSDK SEND_DATA_STATUS event and to the Backend via DataStatusEvent. Possible values: ACCEPTED (operation succeeded; the payload was forwarded to the target session(s)) or FAILED (operation failed; the failure reason is in the info field). In the OnDataEvent request body this field is typically empty (the operation has not yet been processed). |
| info | string Additional information |
| sessionIds | Array of strings Explicit list of signaling session IDs (Connection IDs) that should receive this data payload; when empty the payload is broadcast to every session in the originating app |
| allSessionIds | Array of strings Effective list of signaling session IDs (Connection IDs) that will receive this data payload, including the originating session and any explicitly added sessionIds |
{- "custom": {
- "example": 0
}, - "nodeId": "7aoC1Q9IkTCn4zEsNAKvl1P1QMnXfnKE@192.168.100.1",
- "appKey": "defaultApp",
- "sessionId": "/192.168.1.102:13252/192.168.1.101:8443",
- "operationId": "2497358d-dd6e-4601-926c-cb2b6b12391d",
- "payload": {
- "appKey": "defaultApp",
- "body": "Hello alice",
- "contentType": "application/imdn+xml",
- "custom": {
- "property1": { },
- "property2": { }
}, - "from": "<tel:+447912345678;tag=ab12cd34ef56>\n",
- "id": "a3f9c2b1-ff00-4e5d-9c77-112233445566",
- "isImdnRequired": true,
- "nodeId": "7aoC1Q9IkTCn4zEsNAKvl1P1QMnXfnKE@127.0.0.1",
- "sessionId": "/192.168.1.102:13252/192.168.1.101:8443",
- "sipMessageRaw": "INVITE sip:...",
- "status": "IMDN_NOTIFICATION_SENT",
- "to": "<tel:+447912345678;tag=ab12cd34ef56>\n"
}, - "status": "ACCEPTED",
- "info": "msg: null",
- "sessionIds": [
- "/192.168.1.102:13252/192.168.1.101:8443"
], - "allSessionIds": [
- "/192.168.1.102:13252/192.168.1.101:8443"
]
}{- "custom": {
- "example": 0
}, - "nodeId": "7aoC1Q9IkTCn4zEsNAKvl1P1QMnXfnKE@192.168.100.1",
- "appKey": "defaultApp",
- "sessionId": "/192.168.1.102:13252/192.168.1.101:8443",
- "operationId": "2497358d-dd6e-4601-926c-cb2b6b12391d",
- "payload": {
- "appKey": "defaultApp",
- "body": "Hello alice",
- "contentType": "application/imdn+xml",
- "custom": {
- "property1": { },
- "property2": { }
}, - "from": "<tel:+447912345678;tag=ab12cd34ef56>\n",
- "id": "a3f9c2b1-ff00-4e5d-9c77-112233445566",
- "isImdnRequired": true,
- "nodeId": "7aoC1Q9IkTCn4zEsNAKvl1P1QMnXfnKE@127.0.0.1",
- "sessionId": "/192.168.1.102:13252/192.168.1.101:8443",
- "sipMessageRaw": "INVITE sip:...",
- "status": "IMDN_NOTIFICATION_SENT",
- "to": "<tel:+447912345678;tag=ab12cd34ef56>\n"
}, - "status": "ACCEPTED",
- "info": "msg: null",
- "sessionIds": [
- "/192.168.1.102:13252/192.168.1.101:8443"
], - "allSessionIds": [
- "/192.168.1.102:13252/192.168.1.101:8443"
]
}/apps/DefaultApp/ErrorStatusEvent
WCS sends this notification hook whenever an unexpected error related to the current session is raised while processing a SIP or WebRTC operation. The error is always tied to a specific client Connection. The request body contains the error identifiers, code, and message.
object Custom key-value parameters | |
| nodeId | string Unique identifier of the WCS server instance. Auto-generated as {randomString}@{serverIP} and stored in {WCS_HOME}/conf/node_id |
| appKey | string REST hook application key. Determines the webhook URL for event notifications, as configured in database.yml |
| sessionId | string Signaling session ID (Connection ID). For WebSocket connections the format is /remoteIP:port/localIP:port. Format varies for other connection types |
| origin | string Origin URL of the client page (browser domain) |
| status | string Status. Can be NEW, PENDING, ESTABLISHED, DISCONNECTED, FAILED, REGISTERED, UNREGISTERED, TRYING, RINGING, RING, RING_MEDIA, HOLD, BUSY, FINISH, SESSION_PROGRESS, WRONG_SIPPROVIDER_ADDRESS, TOO_MANY_REGISTER_ATTEMPTS, SIP_PORTS_BUSY, MEDIA_PORTS_BUSY, LICENSE_RESTRICTION, LICENSE_NOT_FOUND, AUTHENTICATION_FAIL, USER_NOT_AVAILABLE, INTERNAL_SIP_ERROR, CALLEE_NAME_IS_NULL, PAYMENT_REQUIRED and etc. |
| info | string Extra information |
| sipMessageRaw | string Raw SIP signaling message(s) |
| apiMethod | string Method, this field should indicate API method so client can fire right event |
| id | string Operation identifier. For instance: mediaSessionId |
object (Context) Target context |
{- "custom": {
- "example": 0
}, - "nodeId": "7aoC1Q9IkTCn4zEsNAKvl1P1QMnXfnKE@192.168.100.1",
- "appKey": "defaultApp",
- "sessionId": "/192.168.1.102:13252/192.168.1.101:8443",
- "status": "NEW",
- "info": "App not found",
- "sipMessageRaw": "INVITE sip:...",
- "apiMethod": "MessageStatusEvent",
- "id": "62a497c7-07ee-4580-a477-0e3c8927b4fc",
- "target": {
- "custom": {
- "example": 0
}, - "nodeId": "7aoC1Q9IkTCn4zEsNAKvl1P1QMnXfnKE@192.168.100.1",
- "appKey": "defaultApp",
- "sessionId": "/192.168.1.102:13252/192.168.1.101:8443",
}
}{- "custom": {
- "example": 0
}, - "nodeId": "7aoC1Q9IkTCn4zEsNAKvl1P1QMnXfnKE@192.168.100.1",
- "appKey": "defaultApp",
- "sessionId": "/192.168.1.102:13252/192.168.1.101:8443",
- "status": "NEW",
- "info": "App not found",
- "sipMessageRaw": "INVITE sip:...",
- "apiMethod": "MessageStatusEvent",
- "id": "62a497c7-07ee-4580-a477-0e3c8927b4fc",
- "target": {
- "custom": {
- "example": 0
}, - "nodeId": "7aoC1Q9IkTCn4zEsNAKvl1P1QMnXfnKE@192.168.100.1",
- "appKey": "defaultApp",
- "sessionId": "/192.168.1.102:13252/192.168.1.101:8443",
}
}/apps/DefaultApp/SessionDebugStatusEvent
WCS sends this notification hook when a session debug exchange changes its state — STARTED after the client starts debug, STOPPED after it stops, then PASSED or FAILED depending on whether the captured publish/play streams completed successfully. The request body contains the report identifiers and the resulting status.
object Custom key-value parameters | |
| nodeId | string Unique identifier of the WCS server instance. Auto-generated as {randomString}@{serverIP} and stored in {WCS_HOME}/conf/node_id |
| appKey | string REST hook application key. Determines the webhook URL for event notifications, as configured in database.yml |
| sessionId | string Signaling session ID (Connection ID). For WebSocket connections the format is /remoteIP:port/localIP:port. Format varies for other connection types |
| origin | string Origin URL of the client page (browser domain) |
| status | string Enum: "STARTED" "STOPPED" "FAILED" "PASSED" Session debug status |
| command | string Command. Supported commands: "start", "stop". |
{- "custom": {
- "example": 0
}, - "nodeId": "7aoC1Q9IkTCn4zEsNAKvl1P1QMnXfnKE@192.168.100.1",
- "appKey": "defaultApp",
- "sessionId": "/192.168.1.102:13252/192.168.1.101:8443",
- "status": "STARTED",
- "command": "start"
}{- "custom": {
- "example": 0
}, - "nodeId": "7aoC1Q9IkTCn4zEsNAKvl1P1QMnXfnKE@192.168.100.1",
- "appKey": "defaultApp",
- "sessionId": "/192.168.1.102:13252/192.168.1.101:8443",
- "status": "STARTED",
- "command": "start"
}Category only. Groups REST hooks fired on media streams owned by a specific Connection — publish, play, recording, transcoding, snapshots.
/apps/DefaultApp/publishStream
WCS calls this hook when a client starts publishing a stream — over WebRTC, RTMP, or any other supported protocol. The Backend can authorize publication, override stream parameters, or reject the publish operation. The request body contains the stream identifiers, media information, and publisher session.
object Custom key-value parameters | |
| nodeId | string Unique identifier of the WCS server instance. Auto-generated as {randomString}@{serverIP} and stored in {WCS_HOME}/conf/node_id |
| appKey | string REST hook application key. Determines the webhook URL for event notifications, as configured in database.yml |
| sessionId | string Signaling session ID (Connection ID). For WebSocket connections the format is /remoteIP:port/localIP:port. Format varies for other connection types |
| origin | string Origin URL of the client page (browser domain) |
| mediaSessionId | string Media session identifier within the WCS instance in UUID format |
| remoteMediaElementId | string Remote media session identifier in UUID format |
| name | string Stream name |
| published | boolean Whether this is a publish stream (true) or a play stream (false) |
| hasVideo | boolean Whether the stream has video |
| hasAudio | boolean Whether the stream has audio |
| status | string Enum: "NEW" "PENDING" "PUBLISHING" "PLAYING" "PAUSED" "UNPUBLISHED" "STOPPED" "FAILED" "RESIZE" "SNAPSHOT_COMPLETE" "NOT_ENOUGH_BANDWIDTH" Stream status |
| sdp | string SDP (Session Description Protocol) associated with the stream. For WebRTC this is the client's offer SDP, for other types a default SDP is used |
| audioCodec | string Audio codec name (e.g. opus, PCMA, PCMU, G729, AAC) |
| videoCodec | string Video codec name (e.g. H264, VP8, VP9, H265) |
| info | string Diagnostic information about the stream, typically the reason for stopping or an error description (e.g. Failed by RTP activity, Stopped by publisher stop, Failed by ICE error) |
| description | string Stream state description |
| record | boolean Whether the client requested recording on publish. Does not guarantee that recording is active |
| recordName | string Recording file name (MP4 or MKV). The file is located in the record_dir directory ({WCS_HOME}/records by default) |
| width | integer <int32> Video width in pixels |
| height | integer <int32> Video height in pixels |
| bitrate | integer <int64> Video bitrate in bps |
| minBitrate | integer <int64> Minimum bitrate in bps |
| maxBitrate | integer <int64> Maximum bitrate in bps |
| quality | integer <int32> Video quality as CRF (Constant Rate Factor) for the encoder. Range: 0 (lossless) to 60 (lowest quality). Lower values produce higher quality. For example, CRF 23 is a common default for H.264 |
| rtmpUrl | string RTMP URL specified by the client on publish for re-streaming to an RTMP server (e.g. rtmp://server:1935/live/stream) |
| parentMediaSessionId | string Parent media session identifier in UUID format |
| timeShift | integer <int64> Time offset in milliseconds from the first publish in the room to this stream's publish. Used for multi-track recording synchronization — aligns streams that start at different times within the same room |
| gop | integer <int32> Group of Pictures — number of frames between keyframes. For example, with fps=30 and gop=60, a keyframe is produced every 2 seconds |
| fps | integer <int32> Frames per second |
| audioBitrate | integer <int64> Audio bitrate in bps |
| codecImpl | string Codec implementation name |
| transport | string Transport protocol used for media delivery: UDP, TCP, or SRT |
| profile | integer <int32> Video codec profile (e.g. 66 = Baseline, 77 = Main, 100 = High for H.264) |
| level | integer <int32> Video codec level (e.g. 31 = Level 3.1, 52 = Level 5.2) |
| preset | string Encoder preset (e.g. ultrafast, medium, slow) |
| cvoExtension | boolean Has CVO(Coordinated Video Orientation) RTP header extension or not |
Array of objects (VideoStreamProfile) Negotiated stream profiles for adaptive bitrate (ABR); each entry describes one transcoded resolution/bitrate variant | |
Array of objects (AudioStreamProfile) | |
| createDate | string <date-time> Stream creation timestamp in ISO 8601 format |
| endDate | string <date-time> Timestamp when the stream was finalised on WCS, in ISO 8601 format; null while the stream is still active |
| mediaType | string Stream type: publish, play, pull, push, pcap, mixer, transcoder, transcoder2, sfu-relay |
object (MediaState) Per-track media state describing whether audio or video is currently muted on the stream | |
object (MediaState) Per-track media state describing whether audio or video is currently muted on the stream | |
object Open map of locally collected media information for this stream, such as negotiated SDP attributes, codec parameters, and SSRCs | |
| mediaProvider | string Media provider used by the client: WebRTC (Web SDK with WebRTC support), Flash (deprecated, legacy Flash player), MSE (Media Source Extensions playback), WSPlayer (WebSocket-based player), HLS (HLS playback), RTSP (RTSP pull), VOD (Video on Demand from file), MPEGTS (MPEG-TS ingest) |
{- "custom": {
- "example": 0
}, - "nodeId": "7aoC1Q9IkTCn4zEsNAKvl1P1QMnXfnKE@192.168.100.1",
- "appKey": "defaultApp",
- "sessionId": "/192.168.1.102:13252/192.168.1.101:8443",
- "mediaSessionId": "d1ddc1ce-90e7-40dd-93b7-fff0e4438a60",
- "remoteMediaElementId": "f1ddc2ce-90e7-40dd-93b7-fff0e4438a60",
- "name": "stream1",
- "published": true,
- "hasVideo": true,
- "hasAudio": true,
- "status": "NEW",
- "sdp": "v=0\r\no=- 82374628 2 IN IP4 192.168.100.20\r\ns=-\r\nt=0 0\r\na=group:BUNDLE 0 1\r\na=msid-semantic: WMS\r\nm=audio 49170 RTP/AVP 0\r\nc=IN IP4 192.168.100.20\r\na=rtpmap:0 PCMU/8000\r\na=sendrecv\r\nm=video 51372 RTP/AVP 96\r\nc=IN IP4 192.168.100.20\r\na=rtpmap:96 VP8/90000\r\na=sendrecv\r\n",
- "audioCodec": "opus",
- "videoCodec": "H264",
- "info": "Failed by HLS writer error",
- "description": "Video RTP activity",
- "record": true,
- "recordName": "s0.mp4",
- "width": 720,
- "height": 480,
- "bitrate": 1000,
- "minBitrate": 0,
- "maxBitrate": 0,
- "quality": 23,
- "rtmpUrl": "rtmp://example.com:1935/live",
- "parentMediaSessionId": "f1ddc2ce-90e7-40dd-93b7-fff0e4438a60",
- "timeShift": 1000,
- "gop": 60,
- "fps": 30,
- "audioBitrate": 1000,
- "codecImpl": "OPENH264",
- "transport": "UDP",
- "profile": 66,
- "level": 52,
- "preset": "medium",
- "cvoExtension": true,
- "profiles": [
- {
- "width": 1280,
- "height": 720,
- "gop": 60,
- "fps": 30,
- "bitrate": 2500000,
- "codec": "H264",
- "codecImpl": "OPENH264",
- "quality": 23,
- "profile": 66,
- "level": 31,
- "preset": "veryfast",
- "audioGroupId": "audio0"
}
], - "audioProfiles": [
- {
- "bitrate": 64000,
- "codec": "opus",
- "rate": 48000,
- "channels": 2,
- "groupId": "default",
- "wrappedCodec": "opus"
}
], - "createDate": "2026-04-12 10:30:15.123000+00:00",
- "endDate": "2026-04-12 10:35:42.456000+00:00",
- "mediaType": "play",
- "audioState": {
- "muted": true
}, - "videoState": {
- "muted": true
}, - "localMediaInfo": {
- "property1": { },
- "property2": { }
}, - "mediaProvider": "WebRTC"
}{- "custom": {
- "example": 0
}, - "nodeId": "7aoC1Q9IkTCn4zEsNAKvl1P1QMnXfnKE@192.168.100.1",
- "appKey": "defaultApp",
- "sessionId": "/192.168.1.102:13252/192.168.1.101:8443",
- "mediaSessionId": "d1ddc1ce-90e7-40dd-93b7-fff0e4438a60",
- "remoteMediaElementId": "f1ddc2ce-90e7-40dd-93b7-fff0e4438a60",
- "name": "stream1",
- "published": true,
- "hasVideo": true,
- "hasAudio": true,
- "status": "NEW",
- "sdp": "v=0\r\no=- 82374628 2 IN IP4 192.168.100.20\r\ns=-\r\nt=0 0\r\na=group:BUNDLE 0 1\r\na=msid-semantic: WMS\r\nm=audio 49170 RTP/AVP 0\r\nc=IN IP4 192.168.100.20\r\na=rtpmap:0 PCMU/8000\r\na=sendrecv\r\nm=video 51372 RTP/AVP 96\r\nc=IN IP4 192.168.100.20\r\na=rtpmap:96 VP8/90000\r\na=sendrecv\r\n",
- "audioCodec": "opus",
- "videoCodec": "H264",
- "info": "Failed by HLS writer error",
- "description": "Video RTP activity",
- "record": true,
- "recordName": "s0.mp4",
- "width": 720,
- "height": 480,
- "bitrate": 1000,
- "minBitrate": 0,
- "maxBitrate": 0,
- "quality": 23,
- "rtmpUrl": "rtmp://example.com:1935/live",
- "parentMediaSessionId": "f1ddc2ce-90e7-40dd-93b7-fff0e4438a60",
- "timeShift": 1000,
- "gop": 60,
- "fps": 30,
- "audioBitrate": 1000,
- "codecImpl": "OPENH264",
- "transport": "UDP",
- "profile": 66,
- "level": 52,
- "preset": "medium",
- "cvoExtension": true,
- "profiles": [
- {
- "width": 1280,
- "height": 720,
- "gop": 60,
- "fps": 30,
- "bitrate": 2500000,
- "codec": "H264",
- "codecImpl": "OPENH264",
- "quality": 23,
- "profile": 66,
- "level": 31,
- "preset": "veryfast",
- "audioGroupId": "audio0"
}
], - "audioProfiles": [
- {
- "bitrate": 64000,
- "codec": "opus",
- "rate": 48000,
- "channels": 2,
- "groupId": "default",
- "wrappedCodec": "opus"
}
], - "createDate": "2026-04-12 10:30:15.123000+00:00",
- "endDate": "2026-04-12 10:35:42.456000+00:00",
- "mediaType": "play",
- "audioState": {
- "muted": true
}, - "videoState": {
- "muted": true
}, - "localMediaInfo": {
- "property1": { },
- "property2": { }
}, - "mediaProvider": "WebRTC"
}/apps/DefaultApp/snapshot
WCS calls this hook when a client requests a server-side snapshot of a published stream via the WebSDK call stream.snapshot(). The request body contains the stream identifiers and snapshot parameters.
object Custom key-value parameters | |
| nodeId | string Unique identifier of the WCS server instance. Auto-generated as {randomString}@{serverIP} and stored in {WCS_HOME}/conf/node_id |
| appKey | string REST hook application key. Determines the webhook URL for event notifications, as configured in database.yml |
| sessionId | string Signaling session ID (Connection ID). For WebSocket connections the format is /remoteIP:port/localIP:port. Format varies for other connection types |
| origin | string Origin URL of the client page (browser domain) |
| mediaSessionId | string Media session identifier within the WCS instance in UUID format |
| remoteMediaElementId | string Remote media session identifier in UUID format |
| name | string Stream name |
| published | boolean Whether this is a publish stream (true) or a play stream (false) |
| hasVideo | boolean Whether the stream has video |
| hasAudio | boolean Whether the stream has audio |
| status | string Enum: "NEW" "PENDING" "PUBLISHING" "PLAYING" "PAUSED" "UNPUBLISHED" "STOPPED" "FAILED" "RESIZE" "SNAPSHOT_COMPLETE" "NOT_ENOUGH_BANDWIDTH" Stream status |
| sdp | string SDP (Session Description Protocol) associated with the stream. For WebRTC this is the client's offer SDP, for other types a default SDP is used |
| audioCodec | string Audio codec name (e.g. opus, PCMA, PCMU, G729, AAC) |
| videoCodec | string Video codec name (e.g. H264, VP8, VP9, H265) |
| info | string Diagnostic information about the stream, typically the reason for stopping or an error description (e.g. Failed by RTP activity, Stopped by publisher stop, Failed by ICE error) |
| description | string Stream state description |
| record | boolean Whether the client requested recording on publish. Does not guarantee that recording is active |
| recordName | string Recording file name (MP4 or MKV). The file is located in the record_dir directory ({WCS_HOME}/records by default) |
| width | integer <int32> Video width in pixels |
| height | integer <int32> Video height in pixels |
| bitrate | integer <int64> Video bitrate in bps |
| minBitrate | integer <int64> Minimum bitrate in bps |
| maxBitrate | integer <int64> Maximum bitrate in bps |
| quality | integer <int32> Video quality as CRF (Constant Rate Factor) for the encoder. Range: 0 (lossless) to 60 (lowest quality). Lower values produce higher quality. For example, CRF 23 is a common default for H.264 |
| rtmpUrl | string RTMP URL specified by the client on publish for re-streaming to an RTMP server (e.g. rtmp://server:1935/live/stream) |
| parentMediaSessionId | string Parent media session identifier in UUID format |
| timeShift | integer <int64> Time offset in milliseconds from the first publish in the room to this stream's publish. Used for multi-track recording synchronization — aligns streams that start at different times within the same room |
| gop | integer <int32> Group of Pictures — number of frames between keyframes. For example, with fps=30 and gop=60, a keyframe is produced every 2 seconds |
| fps | integer <int32> Frames per second |
| audioBitrate | integer <int64> Audio bitrate in bps |
| codecImpl | string Codec implementation name |
| transport | string Transport protocol used for media delivery: UDP, TCP, or SRT |
| profile | integer <int32> Video codec profile (e.g. 66 = Baseline, 77 = Main, 100 = High for H.264) |
| level | integer <int32> Video codec level (e.g. 31 = Level 3.1, 52 = Level 5.2) |
| preset | string Encoder preset (e.g. ultrafast, medium, slow) |
| cvoExtension | boolean Has CVO(Coordinated Video Orientation) RTP header extension or not |
Array of objects (VideoStreamProfile) Negotiated stream profiles for adaptive bitrate (ABR); each entry describes one transcoded resolution/bitrate variant | |
Array of objects (AudioStreamProfile) | |
| createDate | string <date-time> Stream creation timestamp in ISO 8601 format |
| endDate | string <date-time> Timestamp when the stream was finalised on WCS, in ISO 8601 format; null while the stream is still active |
| mediaType | string Stream type: publish, play, pull, push, pcap, mixer, transcoder, transcoder2, sfu-relay |
object (MediaState) Per-track media state describing whether audio or video is currently muted on the stream | |
object (MediaState) Per-track media state describing whether audio or video is currently muted on the stream | |
object Open map of locally collected media information for this stream, such as negotiated SDP attributes, codec parameters, and SSRCs | |
| mediaProvider | string Media provider used by the client: WebRTC (Web SDK with WebRTC support), Flash (deprecated, legacy Flash player), MSE (Media Source Extensions playback), WSPlayer (WebSocket-based player), HLS (HLS playback), RTSP (RTSP pull), VOD (Video on Demand from file), MPEGTS (MPEG-TS ingest) |
{- "custom": {
- "example": 0
}, - "nodeId": "7aoC1Q9IkTCn4zEsNAKvl1P1QMnXfnKE@192.168.100.1",
- "appKey": "defaultApp",
- "sessionId": "/192.168.1.102:13252/192.168.1.101:8443",
- "mediaSessionId": "d1ddc1ce-90e7-40dd-93b7-fff0e4438a60",
- "remoteMediaElementId": "f1ddc2ce-90e7-40dd-93b7-fff0e4438a60",
- "name": "stream1",
- "published": true,
- "hasVideo": true,
- "hasAudio": true,
- "status": "NEW",
- "sdp": "v=0\r\no=- 82374628 2 IN IP4 192.168.100.20\r\ns=-\r\nt=0 0\r\na=group:BUNDLE 0 1\r\na=msid-semantic: WMS\r\nm=audio 49170 RTP/AVP 0\r\nc=IN IP4 192.168.100.20\r\na=rtpmap:0 PCMU/8000\r\na=sendrecv\r\nm=video 51372 RTP/AVP 96\r\nc=IN IP4 192.168.100.20\r\na=rtpmap:96 VP8/90000\r\na=sendrecv\r\n",
- "audioCodec": "opus",
- "videoCodec": "H264",
- "info": "Failed by HLS writer error",
- "description": "Video RTP activity",
- "record": true,
- "recordName": "s0.mp4",
- "width": 720,
- "height": 480,
- "bitrate": 1000,
- "minBitrate": 0,
- "maxBitrate": 0,
- "quality": 23,
- "rtmpUrl": "rtmp://example.com:1935/live",
- "parentMediaSessionId": "f1ddc2ce-90e7-40dd-93b7-fff0e4438a60",
- "timeShift": 1000,
- "gop": 60,
- "fps": 30,
- "audioBitrate": 1000,
- "codecImpl": "OPENH264",
- "transport": "UDP",
- "profile": 66,
- "level": 52,
- "preset": "medium",
- "cvoExtension": true,
- "profiles": [
- {
- "width": 1280,
- "height": 720,
- "gop": 60,
- "fps": 30,
- "bitrate": 2500000,
- "codec": "H264",
- "codecImpl": "OPENH264",
- "quality": 23,
- "profile": 66,
- "level": 31,
- "preset": "veryfast",
- "audioGroupId": "audio0"
}
], - "audioProfiles": [
- {
- "bitrate": 64000,
- "codec": "opus",
- "rate": 48000,
- "channels": 2,
- "groupId": "default",
- "wrappedCodec": "opus"
}
], - "createDate": "2026-04-12 10:30:15.123000+00:00",
- "endDate": "2026-04-12 10:35:42.456000+00:00",
- "mediaType": "play",
- "audioState": {
- "muted": true
}, - "videoState": {
- "muted": true
}, - "localMediaInfo": {
- "property1": { },
- "property2": { }
}, - "mediaProvider": "WebRTC"
}{- "custom": {
- "example": 0
}, - "nodeId": "7aoC1Q9IkTCn4zEsNAKvl1P1QMnXfnKE@192.168.100.1",
- "appKey": "defaultApp",
- "sessionId": "/192.168.1.102:13252/192.168.1.101:8443",
- "mediaSessionId": "d1ddc1ce-90e7-40dd-93b7-fff0e4438a60",
- "remoteMediaElementId": "f1ddc2ce-90e7-40dd-93b7-fff0e4438a60",
- "name": "stream1",
- "published": true,
- "hasVideo": true,
- "hasAudio": true,
- "status": "NEW",
- "sdp": "v=0\r\no=- 82374628 2 IN IP4 192.168.100.20\r\ns=-\r\nt=0 0\r\na=group:BUNDLE 0 1\r\na=msid-semantic: WMS\r\nm=audio 49170 RTP/AVP 0\r\nc=IN IP4 192.168.100.20\r\na=rtpmap:0 PCMU/8000\r\na=sendrecv\r\nm=video 51372 RTP/AVP 96\r\nc=IN IP4 192.168.100.20\r\na=rtpmap:96 VP8/90000\r\na=sendrecv\r\n",
- "audioCodec": "opus",
- "videoCodec": "H264",
- "info": "Failed by HLS writer error",
- "description": "Video RTP activity",
- "record": true,
- "recordName": "s0.mp4",
- "width": 720,
- "height": 480,
- "bitrate": 1000,
- "minBitrate": 0,
- "maxBitrate": 0,
- "quality": 23,
- "rtmpUrl": "rtmp://example.com:1935/live",
- "parentMediaSessionId": "f1ddc2ce-90e7-40dd-93b7-fff0e4438a60",
- "timeShift": 1000,
- "gop": 60,
- "fps": 30,
- "audioBitrate": 1000,
- "codecImpl": "OPENH264",
- "transport": "UDP",
- "profile": 66,
- "level": 52,
- "preset": "medium",
- "cvoExtension": true,
- "profiles": [
- {
- "width": 1280,
- "height": 720,
- "gop": 60,
- "fps": 30,
- "bitrate": 2500000,
- "codec": "H264",
- "codecImpl": "OPENH264",
- "quality": 23,
- "profile": 66,
- "level": 31,
- "preset": "veryfast",
- "audioGroupId": "audio0"
}
], - "audioProfiles": [
- {
- "bitrate": 64000,
- "codec": "opus",
- "rate": 48000,
- "channels": 2,
- "groupId": "default",
- "wrappedCodec": "opus"
}
], - "createDate": "2026-04-12 10:30:15.123000+00:00",
- "endDate": "2026-04-12 10:35:42.456000+00:00",
- "mediaType": "play",
- "audioState": {
- "muted": true
}, - "videoState": {
- "muted": true
}, - "localMediaInfo": {
- "property1": { },
- "property2": { }
}, - "mediaProvider": "WebRTC"
}/apps/DefaultApp/sendStreamEvent
WCS calls this hook when a publisher pushes a custom event to subscribers of its stream. The Backend can authorize the broadcast, modify the payload, or reject the request. The request body contains the stream identifiers, the event type, and the payload.
The event is emitted by the WebSDK — via stream.muteAudio(), stream.unmuteAudio(), stream.muteVideo(), stream.unmuteVideo(), stream.sendData(payload).
object Custom key-value parameters | |
| nodeId | string Unique identifier of the WCS server instance. Auto-generated as {randomString}@{serverIP} and stored in {WCS_HOME}/conf/node_id |
| appKey | string REST hook application key. Determines the webhook URL for event notifications, as configured in database.yml |
| sessionId | string Signaling session ID (Connection ID). For WebSocket connections the format is /remoteIP:port/localIP:port. Format varies for other connection types |
| origin | string Origin URL of the client page (browser domain) |
| mediaSessionId | string Media session identifier within the WCS instance in UUID format |
| type | string Enum: "data" "audioMuted" "audioUnmuted" "videoMuted" "videoUnmuted" "snapshotCompleted" "snapshotFailed" "resize" "notEnoughBandwidth" "addedToMixing" "removedFromMixing" "startedRecording" "stoppedByReInit" "stoppedRecording" "failedRecording" "addedToMultiRecording" "removedFromMultiRecording" "answer" "sdp" "offer" Event type |
object Free-form map carrying optional event metadata; the contents are forwarded to subscribers as-is |
{- "custom": {
- "example": 0
}, - "nodeId": "7aoC1Q9IkTCn4zEsNAKvl1P1QMnXfnKE@192.168.100.1",
- "appKey": "defaultApp",
- "sessionId": "/192.168.1.102:13252/192.168.1.101:8443",
- "mediaSessionId": "d1ddc1ce-90e7-40dd-93b7-fff0e4438a60",
- "type": "audioMuted",
- "payload": {
- "property1": { },
- "property2": { }
}
}{- "custom": {
- "example": 0
}, - "nodeId": "7aoC1Q9IkTCn4zEsNAKvl1P1QMnXfnKE@192.168.100.1",
- "appKey": "defaultApp",
- "sessionId": "/192.168.1.102:13252/192.168.1.101:8443",
- "mediaSessionId": "d1ddc1ce-90e7-40dd-93b7-fff0e4438a60",
- "type": "audioMuted",
- "payload": {
- "property1": { },
- "property2": { }
}
}/apps/DefaultApp/unPublishStream
WCS calls this hook when a publisher stops sending a previously published stream. The Backend can authorize or reject the unpublish operation before WCS terminates the publishing session. The request body contains the stream identifiers and the current publishing state.
object Custom key-value parameters | |
| nodeId | string Unique identifier of the WCS server instance. Auto-generated as {randomString}@{serverIP} and stored in {WCS_HOME}/conf/node_id |
| appKey | string REST hook application key. Determines the webhook URL for event notifications, as configured in database.yml |
| sessionId | string Signaling session ID (Connection ID). For WebSocket connections the format is /remoteIP:port/localIP:port. Format varies for other connection types |
| origin | string Origin URL of the client page (browser domain) |
| mediaSessionId | string Media session identifier within the WCS instance in UUID format |
| remoteMediaElementId | string Remote media session identifier in UUID format |
| name | string Stream name |
| published | boolean Whether this is a publish stream (true) or a play stream (false) |
| hasVideo | boolean Whether the stream has video |
| hasAudio | boolean Whether the stream has audio |
| status | string Enum: "NEW" "PENDING" "PUBLISHING" "PLAYING" "PAUSED" "UNPUBLISHED" "STOPPED" "FAILED" "RESIZE" "SNAPSHOT_COMPLETE" "NOT_ENOUGH_BANDWIDTH" Stream status |
| sdp | string SDP (Session Description Protocol) associated with the stream. For WebRTC this is the client's offer SDP, for other types a default SDP is used |
| audioCodec | string Audio codec name (e.g. opus, PCMA, PCMU, G729, AAC) |
| videoCodec | string Video codec name (e.g. H264, VP8, VP9, H265) |
| info | string Diagnostic information about the stream, typically the reason for stopping or an error description (e.g. Failed by RTP activity, Stopped by publisher stop, Failed by ICE error) |
| description | string Stream state description |
| record | boolean Whether the client requested recording on publish. Does not guarantee that recording is active |
| recordName | string Recording file name (MP4 or MKV). The file is located in the record_dir directory ({WCS_HOME}/records by default) |
| width | integer <int32> Video width in pixels |
| height | integer <int32> Video height in pixels |
| bitrate | integer <int64> Video bitrate in bps |
| minBitrate | integer <int64> Minimum bitrate in bps |
| maxBitrate | integer <int64> Maximum bitrate in bps |
| quality | integer <int32> Video quality as CRF (Constant Rate Factor) for the encoder. Range: 0 (lossless) to 60 (lowest quality). Lower values produce higher quality. For example, CRF 23 is a common default for H.264 |
| rtmpUrl | string RTMP URL specified by the client on publish for re-streaming to an RTMP server (e.g. rtmp://server:1935/live/stream) |
| parentMediaSessionId | string Parent media session identifier in UUID format |
| timeShift | integer <int64> Time offset in milliseconds from the first publish in the room to this stream's publish. Used for multi-track recording synchronization — aligns streams that start at different times within the same room |
| gop | integer <int32> Group of Pictures — number of frames between keyframes. For example, with fps=30 and gop=60, a keyframe is produced every 2 seconds |
| fps | integer <int32> Frames per second |
| audioBitrate | integer <int64> Audio bitrate in bps |
| codecImpl | string Codec implementation name |
| transport | string Transport protocol used for media delivery: UDP, TCP, or SRT |
| profile | integer <int32> Video codec profile (e.g. 66 = Baseline, 77 = Main, 100 = High for H.264) |
| level | integer <int32> Video codec level (e.g. 31 = Level 3.1, 52 = Level 5.2) |
| preset | string Encoder preset (e.g. ultrafast, medium, slow) |
| cvoExtension | boolean Has CVO(Coordinated Video Orientation) RTP header extension or not |
Array of objects (VideoStreamProfile) Negotiated stream profiles for adaptive bitrate (ABR); each entry describes one transcoded resolution/bitrate variant | |
Array of objects (AudioStreamProfile) | |
| createDate | string <date-time> Stream creation timestamp in ISO 8601 format |
| endDate | string <date-time> Timestamp when the stream was finalised on WCS, in ISO 8601 format; null while the stream is still active |
| mediaType | string Stream type: publish, play, pull, push, pcap, mixer, transcoder, transcoder2, sfu-relay |
object (MediaState) Per-track media state describing whether audio or video is currently muted on the stream | |
object (MediaState) Per-track media state describing whether audio or video is currently muted on the stream | |
object Open map of locally collected media information for this stream, such as negotiated SDP attributes, codec parameters, and SSRCs | |
| mediaProvider | string Media provider used by the client: WebRTC (Web SDK with WebRTC support), Flash (deprecated, legacy Flash player), MSE (Media Source Extensions playback), WSPlayer (WebSocket-based player), HLS (HLS playback), RTSP (RTSP pull), VOD (Video on Demand from file), MPEGTS (MPEG-TS ingest) |
{- "custom": {
- "example": 0
}, - "nodeId": "7aoC1Q9IkTCn4zEsNAKvl1P1QMnXfnKE@192.168.100.1",
- "appKey": "defaultApp",
- "sessionId": "/192.168.1.102:13252/192.168.1.101:8443",
- "mediaSessionId": "d1ddc1ce-90e7-40dd-93b7-fff0e4438a60",
- "remoteMediaElementId": "f1ddc2ce-90e7-40dd-93b7-fff0e4438a60",
- "name": "stream1",
- "published": true,
- "hasVideo": true,
- "hasAudio": true,
- "status": "NEW",
- "sdp": "v=0\r\no=- 82374628 2 IN IP4 192.168.100.20\r\ns=-\r\nt=0 0\r\na=group:BUNDLE 0 1\r\na=msid-semantic: WMS\r\nm=audio 49170 RTP/AVP 0\r\nc=IN IP4 192.168.100.20\r\na=rtpmap:0 PCMU/8000\r\na=sendrecv\r\nm=video 51372 RTP/AVP 96\r\nc=IN IP4 192.168.100.20\r\na=rtpmap:96 VP8/90000\r\na=sendrecv\r\n",
- "audioCodec": "opus",
- "videoCodec": "H264",
- "info": "Failed by HLS writer error",
- "description": "Video RTP activity",
- "record": true,
- "recordName": "s0.mp4",
- "width": 720,
- "height": 480,
- "bitrate": 1000,
- "minBitrate": 0,
- "maxBitrate": 0,
- "quality": 23,
- "rtmpUrl": "rtmp://example.com:1935/live",
- "parentMediaSessionId": "f1ddc2ce-90e7-40dd-93b7-fff0e4438a60",
- "timeShift": 1000,
- "gop": 60,
- "fps": 30,
- "audioBitrate": 1000,
- "codecImpl": "OPENH264",
- "transport": "UDP",
- "profile": 66,
- "level": 52,
- "preset": "medium",
- "cvoExtension": true,
- "profiles": [
- {
- "width": 1280,
- "height": 720,
- "gop": 60,
- "fps": 30,
- "bitrate": 2500000,
- "codec": "H264",
- "codecImpl": "OPENH264",
- "quality": 23,
- "profile": 66,
- "level": 31,
- "preset": "veryfast",
- "audioGroupId": "audio0"
}
], - "audioProfiles": [
- {
- "bitrate": 64000,
- "codec": "opus",
- "rate": 48000,
- "channels": 2,
- "groupId": "default",
- "wrappedCodec": "opus"
}
], - "createDate": "2026-04-12 10:30:15.123000+00:00",
- "endDate": "2026-04-12 10:35:42.456000+00:00",
- "mediaType": "play",
- "audioState": {
- "muted": true
}, - "videoState": {
- "muted": true
}, - "localMediaInfo": {
- "property1": { },
- "property2": { }
}, - "mediaProvider": "WebRTC"
}{- "custom": {
- "example": 0
}, - "nodeId": "7aoC1Q9IkTCn4zEsNAKvl1P1QMnXfnKE@192.168.100.1",
- "appKey": "defaultApp",
- "sessionId": "/192.168.1.102:13252/192.168.1.101:8443",
- "mediaSessionId": "d1ddc1ce-90e7-40dd-93b7-fff0e4438a60",
- "remoteMediaElementId": "f1ddc2ce-90e7-40dd-93b7-fff0e4438a60",
- "name": "stream1",
- "published": true,
- "hasVideo": true,
- "hasAudio": true,
- "status": "NEW",
- "sdp": "v=0\r\no=- 82374628 2 IN IP4 192.168.100.20\r\ns=-\r\nt=0 0\r\na=group:BUNDLE 0 1\r\na=msid-semantic: WMS\r\nm=audio 49170 RTP/AVP 0\r\nc=IN IP4 192.168.100.20\r\na=rtpmap:0 PCMU/8000\r\na=sendrecv\r\nm=video 51372 RTP/AVP 96\r\nc=IN IP4 192.168.100.20\r\na=rtpmap:96 VP8/90000\r\na=sendrecv\r\n",
- "audioCodec": "opus",
- "videoCodec": "H264",
- "info": "Failed by HLS writer error",
- "description": "Video RTP activity",
- "record": true,
- "recordName": "s0.mp4",
- "width": 720,
- "height": 480,
- "bitrate": 1000,
- "minBitrate": 0,
- "maxBitrate": 0,
- "quality": 23,
- "rtmpUrl": "rtmp://example.com:1935/live",
- "parentMediaSessionId": "f1ddc2ce-90e7-40dd-93b7-fff0e4438a60",
- "timeShift": 1000,
- "gop": 60,
- "fps": 30,
- "audioBitrate": 1000,
- "codecImpl": "OPENH264",
- "transport": "UDP",
- "profile": 66,
- "level": 52,
- "preset": "medium",
- "cvoExtension": true,
- "profiles": [
- {
- "width": 1280,
- "height": 720,
- "gop": 60,
- "fps": 30,
- "bitrate": 2500000,
- "codec": "H264",
- "codecImpl": "OPENH264",
- "quality": 23,
- "profile": 66,
- "level": 31,
- "preset": "veryfast",
- "audioGroupId": "audio0"
}
], - "audioProfiles": [
- {
- "bitrate": 64000,
- "codec": "opus",
- "rate": 48000,
- "channels": 2,
- "groupId": "default",
- "wrappedCodec": "opus"
}
], - "createDate": "2026-04-12 10:30:15.123000+00:00",
- "endDate": "2026-04-12 10:35:42.456000+00:00",
- "mediaType": "play",
- "audioState": {
- "muted": true
}, - "videoState": {
- "muted": true
}, - "localMediaInfo": {
- "property1": { },
- "property2": { }
}, - "mediaProvider": "WebRTC"
}/apps/DefaultApp/playStream
WCS calls this hook when a client starts playing an existing stream. The Backend can authorize playback, override the played stream name, or reject the play operation. The request body contains the stream identifiers and the player session.
object Custom key-value parameters | |
| nodeId | string Unique identifier of the WCS server instance. Auto-generated as {randomString}@{serverIP} and stored in {WCS_HOME}/conf/node_id |
| appKey | string REST hook application key. Determines the webhook URL for event notifications, as configured in database.yml |
| sessionId | string Signaling session ID (Connection ID). For WebSocket connections the format is /remoteIP:port/localIP:port. Format varies for other connection types |
| origin | string Origin URL of the client page (browser domain) |
| mediaSessionId | string Media session identifier within the WCS instance in UUID format |
| remoteMediaElementId | string Remote media session identifier in UUID format |
| name | string Stream name |
| published | boolean Whether this is a publish stream (true) or a play stream (false) |
| hasVideo | boolean Whether the stream has video |
| hasAudio | boolean Whether the stream has audio |
| status | string Enum: "NEW" "PENDING" "PUBLISHING" "PLAYING" "PAUSED" "UNPUBLISHED" "STOPPED" "FAILED" "RESIZE" "SNAPSHOT_COMPLETE" "NOT_ENOUGH_BANDWIDTH" Stream status |
| sdp | string SDP (Session Description Protocol) associated with the stream. For WebRTC this is the client's offer SDP, for other types a default SDP is used |
| audioCodec | string Audio codec name (e.g. opus, PCMA, PCMU, G729, AAC) |
| videoCodec | string Video codec name (e.g. H264, VP8, VP9, H265) |
| info | string Diagnostic information about the stream, typically the reason for stopping or an error description (e.g. Failed by RTP activity, Stopped by publisher stop, Failed by ICE error) |
| description | string Stream state description |
| record | boolean Whether the client requested recording on publish. Does not guarantee that recording is active |
| recordName | string Recording file name (MP4 or MKV). The file is located in the record_dir directory ({WCS_HOME}/records by default) |
| width | integer <int32> Video width in pixels |
| height | integer <int32> Video height in pixels |
| bitrate | integer <int64> Video bitrate in bps |
| minBitrate | integer <int64> Minimum bitrate in bps |
| maxBitrate | integer <int64> Maximum bitrate in bps |
| quality | integer <int32> Video quality as CRF (Constant Rate Factor) for the encoder. Range: 0 (lossless) to 60 (lowest quality). Lower values produce higher quality. For example, CRF 23 is a common default for H.264 |
| rtmpUrl | string RTMP URL specified by the client on publish for re-streaming to an RTMP server (e.g. rtmp://server:1935/live/stream) |
| parentMediaSessionId | string Parent media session identifier in UUID format |
| timeShift | integer <int64> Time offset in milliseconds from the first publish in the room to this stream's publish. Used for multi-track recording synchronization — aligns streams that start at different times within the same room |
| gop | integer <int32> Group of Pictures — number of frames between keyframes. For example, with fps=30 and gop=60, a keyframe is produced every 2 seconds |
| fps | integer <int32> Frames per second |
| audioBitrate | integer <int64> Audio bitrate in bps |
| codecImpl | string Codec implementation name |
| transport | string Transport protocol used for media delivery: UDP, TCP, or SRT |
| profile | integer <int32> Video codec profile (e.g. 66 = Baseline, 77 = Main, 100 = High for H.264) |
| level | integer <int32> Video codec level (e.g. 31 = Level 3.1, 52 = Level 5.2) |
| preset | string Encoder preset (e.g. ultrafast, medium, slow) |
| cvoExtension | boolean Has CVO(Coordinated Video Orientation) RTP header extension or not |
Array of objects (VideoStreamProfile) Negotiated stream profiles for adaptive bitrate (ABR); each entry describes one transcoded resolution/bitrate variant | |
Array of objects (AudioStreamProfile) | |
| createDate | string <date-time> Stream creation timestamp in ISO 8601 format |
| endDate | string <date-time> Timestamp when the stream was finalised on WCS, in ISO 8601 format; null while the stream is still active |
| mediaType | string Stream type: publish, play, pull, push, pcap, mixer, transcoder, transcoder2, sfu-relay |
object (MediaState) Per-track media state describing whether audio or video is currently muted on the stream | |
object (MediaState) Per-track media state describing whether audio or video is currently muted on the stream | |
object Open map of locally collected media information for this stream, such as negotiated SDP attributes, codec parameters, and SSRCs | |
| mediaProvider | string Media provider used by the client: WebRTC (Web SDK with WebRTC support), Flash (deprecated, legacy Flash player), MSE (Media Source Extensions playback), WSPlayer (WebSocket-based player), HLS (HLS playback), RTSP (RTSP pull), VOD (Video on Demand from file), MPEGTS (MPEG-TS ingest) |
{- "custom": {
- "example": 0
}, - "nodeId": "7aoC1Q9IkTCn4zEsNAKvl1P1QMnXfnKE@192.168.100.1",
- "appKey": "defaultApp",
- "sessionId": "/192.168.1.102:13252/192.168.1.101:8443",
- "mediaSessionId": "d1ddc1ce-90e7-40dd-93b7-fff0e4438a60",
- "remoteMediaElementId": "f1ddc2ce-90e7-40dd-93b7-fff0e4438a60",
- "name": "stream1",
- "published": true,
- "hasVideo": true,
- "hasAudio": true,
- "status": "NEW",
- "sdp": "v=0\r\no=- 82374628 2 IN IP4 192.168.100.20\r\ns=-\r\nt=0 0\r\na=group:BUNDLE 0 1\r\na=msid-semantic: WMS\r\nm=audio 49170 RTP/AVP 0\r\nc=IN IP4 192.168.100.20\r\na=rtpmap:0 PCMU/8000\r\na=sendrecv\r\nm=video 51372 RTP/AVP 96\r\nc=IN IP4 192.168.100.20\r\na=rtpmap:96 VP8/90000\r\na=sendrecv\r\n",
- "audioCodec": "opus",
- "videoCodec": "H264",
- "info": "Failed by HLS writer error",
- "description": "Video RTP activity",
- "record": true,
- "recordName": "s0.mp4",
- "width": 720,
- "height": 480,
- "bitrate": 1000,
- "minBitrate": 0,
- "maxBitrate": 0,
- "quality": 23,
- "rtmpUrl": "rtmp://example.com:1935/live",
- "parentMediaSessionId": "f1ddc2ce-90e7-40dd-93b7-fff0e4438a60",
- "timeShift": 1000,
- "gop": 60,
- "fps": 30,
- "audioBitrate": 1000,
- "codecImpl": "OPENH264",
- "transport": "UDP",
- "profile": 66,
- "level": 52,
- "preset": "medium",
- "cvoExtension": true,
- "profiles": [
- {
- "width": 1280,
- "height": 720,
- "gop": 60,
- "fps": 30,
- "bitrate": 2500000,
- "codec": "H264",
- "codecImpl": "OPENH264",
- "quality": 23,
- "profile": 66,
- "level": 31,
- "preset": "veryfast",
- "audioGroupId": "audio0"
}
], - "audioProfiles": [
- {
- "bitrate": 64000,
- "codec": "opus",
- "rate": 48000,
- "channels": 2,
- "groupId": "default",
- "wrappedCodec": "opus"
}
], - "createDate": "2026-04-12 10:30:15.123000+00:00",
- "endDate": "2026-04-12 10:35:42.456000+00:00",
- "mediaType": "play",
- "audioState": {
- "muted": true
}, - "videoState": {
- "muted": true
}, - "localMediaInfo": {
- "property1": { },
- "property2": { }
}, - "mediaProvider": "WebRTC"
}{- "custom": {
- "example": 0
}, - "nodeId": "7aoC1Q9IkTCn4zEsNAKvl1P1QMnXfnKE@192.168.100.1",
- "appKey": "defaultApp",
- "sessionId": "/192.168.1.102:13252/192.168.1.101:8443",
- "mediaSessionId": "d1ddc1ce-90e7-40dd-93b7-fff0e4438a60",
- "remoteMediaElementId": "f1ddc2ce-90e7-40dd-93b7-fff0e4438a60",
- "name": "stream1",
- "published": true,
- "hasVideo": true,
- "hasAudio": true,
- "status": "NEW",
- "sdp": "v=0\r\no=- 82374628 2 IN IP4 192.168.100.20\r\ns=-\r\nt=0 0\r\na=group:BUNDLE 0 1\r\na=msid-semantic: WMS\r\nm=audio 49170 RTP/AVP 0\r\nc=IN IP4 192.168.100.20\r\na=rtpmap:0 PCMU/8000\r\na=sendrecv\r\nm=video 51372 RTP/AVP 96\r\nc=IN IP4 192.168.100.20\r\na=rtpmap:96 VP8/90000\r\na=sendrecv\r\n",
- "audioCodec": "opus",
- "videoCodec": "H264",
- "info": "Failed by HLS writer error",
- "description": "Video RTP activity",
- "record": true,
- "recordName": "s0.mp4",
- "width": 720,
- "height": 480,
- "bitrate": 1000,
- "minBitrate": 0,
- "maxBitrate": 0,
- "quality": 23,
- "rtmpUrl": "rtmp://example.com:1935/live",
- "parentMediaSessionId": "f1ddc2ce-90e7-40dd-93b7-fff0e4438a60",
- "timeShift": 1000,
- "gop": 60,
- "fps": 30,
- "audioBitrate": 1000,
- "codecImpl": "OPENH264",
- "transport": "UDP",
- "profile": 66,
- "level": 52,
- "preset": "medium",
- "cvoExtension": true,
- "profiles": [
- {
- "width": 1280,
- "height": 720,
- "gop": 60,
- "fps": 30,
- "bitrate": 2500000,
- "codec": "H264",
- "codecImpl": "OPENH264",
- "quality": 23,
- "profile": 66,
- "level": 31,
- "preset": "veryfast",
- "audioGroupId": "audio0"
}
], - "audioProfiles": [
- {
- "bitrate": 64000,
- "codec": "opus",
- "rate": 48000,
- "channels": 2,
- "groupId": "default",
- "wrappedCodec": "opus"
}
], - "createDate": "2026-04-12 10:30:15.123000+00:00",
- "endDate": "2026-04-12 10:35:42.456000+00:00",
- "mediaType": "play",
- "audioState": {
- "muted": true
}, - "videoState": {
- "muted": true
}, - "localMediaInfo": {
- "property1": { },
- "property2": { }
}, - "mediaProvider": "WebRTC"
}/apps/DefaultApp/stopStream
WCS calls this hook when an active playback session is about to be stopped by a client command. Publishing sessions use unPublishStream. The request body contains the stream identifiers and the current playback state.
object Custom key-value parameters | |
| nodeId | string Unique identifier of the WCS server instance. Auto-generated as {randomString}@{serverIP} and stored in {WCS_HOME}/conf/node_id |
| appKey | string REST hook application key. Determines the webhook URL for event notifications, as configured in database.yml |
| sessionId | string Signaling session ID (Connection ID). For WebSocket connections the format is /remoteIP:port/localIP:port. Format varies for other connection types |
| origin | string Origin URL of the client page (browser domain) |
| mediaSessionId | string Media session identifier within the WCS instance in UUID format |
| remoteMediaElementId | string Remote media session identifier in UUID format |
| name | string Stream name |
| published | boolean Whether this is a publish stream (true) or a play stream (false) |
| hasVideo | boolean Whether the stream has video |
| hasAudio | boolean Whether the stream has audio |
| status | string Enum: "NEW" "PENDING" "PUBLISHING" "PLAYING" "PAUSED" "UNPUBLISHED" "STOPPED" "FAILED" "RESIZE" "SNAPSHOT_COMPLETE" "NOT_ENOUGH_BANDWIDTH" Stream status |
| sdp | string SDP (Session Description Protocol) associated with the stream. For WebRTC this is the client's offer SDP, for other types a default SDP is used |
| audioCodec | string Audio codec name (e.g. opus, PCMA, PCMU, G729, AAC) |
| videoCodec | string Video codec name (e.g. H264, VP8, VP9, H265) |
| info | string Diagnostic information about the stream, typically the reason for stopping or an error description (e.g. Failed by RTP activity, Stopped by publisher stop, Failed by ICE error) |
| description | string Stream state description |
| record | boolean Whether the client requested recording on publish. Does not guarantee that recording is active |
| recordName | string Recording file name (MP4 or MKV). The file is located in the record_dir directory ({WCS_HOME}/records by default) |
| width | integer <int32> Video width in pixels |
| height | integer <int32> Video height in pixels |
| bitrate | integer <int64> Video bitrate in bps |
| minBitrate | integer <int64> Minimum bitrate in bps |
| maxBitrate | integer <int64> Maximum bitrate in bps |
| quality | integer <int32> Video quality as CRF (Constant Rate Factor) for the encoder. Range: 0 (lossless) to 60 (lowest quality). Lower values produce higher quality. For example, CRF 23 is a common default for H.264 |
| rtmpUrl | string RTMP URL specified by the client on publish for re-streaming to an RTMP server (e.g. rtmp://server:1935/live/stream) |
| parentMediaSessionId | string Parent media session identifier in UUID format |
| timeShift | integer <int64> Time offset in milliseconds from the first publish in the room to this stream's publish. Used for multi-track recording synchronization — aligns streams that start at different times within the same room |
| gop | integer <int32> Group of Pictures — number of frames between keyframes. For example, with fps=30 and gop=60, a keyframe is produced every 2 seconds |
| fps | integer <int32> Frames per second |
| audioBitrate | integer <int64> Audio bitrate in bps |
| codecImpl | string Codec implementation name |
| transport | string Transport protocol used for media delivery: UDP, TCP, or SRT |
| profile | integer <int32> Video codec profile (e.g. 66 = Baseline, 77 = Main, 100 = High for H.264) |
| level | integer <int32> Video codec level (e.g. 31 = Level 3.1, 52 = Level 5.2) |
| preset | string Encoder preset (e.g. ultrafast, medium, slow) |
| cvoExtension | boolean Has CVO(Coordinated Video Orientation) RTP header extension or not |
Array of objects (VideoStreamProfile) Negotiated stream profiles for adaptive bitrate (ABR); each entry describes one transcoded resolution/bitrate variant | |
Array of objects (AudioStreamProfile) | |
| createDate | string <date-time> Stream creation timestamp in ISO 8601 format |
| endDate | string <date-time> Timestamp when the stream was finalised on WCS, in ISO 8601 format; null while the stream is still active |
| mediaType | string Stream type: publish, play, pull, push, pcap, mixer, transcoder, transcoder2, sfu-relay |
object (MediaState) Per-track media state describing whether audio or video is currently muted on the stream | |
object (MediaState) Per-track media state describing whether audio or video is currently muted on the stream | |
object Open map of locally collected media information for this stream, such as negotiated SDP attributes, codec parameters, and SSRCs | |
| mediaProvider | string Media provider used by the client: WebRTC (Web SDK with WebRTC support), Flash (deprecated, legacy Flash player), MSE (Media Source Extensions playback), WSPlayer (WebSocket-based player), HLS (HLS playback), RTSP (RTSP pull), VOD (Video on Demand from file), MPEGTS (MPEG-TS ingest) |
{- "custom": {
- "example": 0
}, - "nodeId": "7aoC1Q9IkTCn4zEsNAKvl1P1QMnXfnKE@192.168.100.1",
- "appKey": "defaultApp",
- "sessionId": "/192.168.1.102:13252/192.168.1.101:8443",
- "mediaSessionId": "d1ddc1ce-90e7-40dd-93b7-fff0e4438a60",
- "remoteMediaElementId": "f1ddc2ce-90e7-40dd-93b7-fff0e4438a60",
- "name": "stream1",
- "published": true,
- "hasVideo": true,
- "hasAudio": true,
- "status": "NEW",
- "sdp": "v=0\r\no=- 82374628 2 IN IP4 192.168.100.20\r\ns=-\r\nt=0 0\r\na=group:BUNDLE 0 1\r\na=msid-semantic: WMS\r\nm=audio 49170 RTP/AVP 0\r\nc=IN IP4 192.168.100.20\r\na=rtpmap:0 PCMU/8000\r\na=sendrecv\r\nm=video 51372 RTP/AVP 96\r\nc=IN IP4 192.168.100.20\r\na=rtpmap:96 VP8/90000\r\na=sendrecv\r\n",
- "audioCodec": "opus",
- "videoCodec": "H264",
- "info": "Failed by HLS writer error",
- "description": "Video RTP activity",
- "record": true,
- "recordName": "s0.mp4",
- "width": 720,
- "height": 480,
- "bitrate": 1000,
- "minBitrate": 0,
- "maxBitrate": 0,
- "quality": 23,
- "rtmpUrl": "rtmp://example.com:1935/live",
- "parentMediaSessionId": "f1ddc2ce-90e7-40dd-93b7-fff0e4438a60",
- "timeShift": 1000,
- "gop": 60,
- "fps": 30,
- "audioBitrate": 1000,
- "codecImpl": "OPENH264",
- "transport": "UDP",
- "profile": 66,
- "level": 52,
- "preset": "medium",
- "cvoExtension": true,
- "profiles": [
- {
- "width": 1280,
- "height": 720,
- "gop": 60,
- "fps": 30,
- "bitrate": 2500000,
- "codec": "H264",
- "codecImpl": "OPENH264",
- "quality": 23,
- "profile": 66,
- "level": 31,
- "preset": "veryfast",
- "audioGroupId": "audio0"
}
], - "audioProfiles": [
- {
- "bitrate": 64000,
- "codec": "opus",
- "rate": 48000,
- "channels": 2,
- "groupId": "default",
- "wrappedCodec": "opus"
}
], - "createDate": "2026-04-12 10:30:15.123000+00:00",
- "endDate": "2026-04-12 10:35:42.456000+00:00",
- "mediaType": "play",
- "audioState": {
- "muted": true
}, - "videoState": {
- "muted": true
}, - "localMediaInfo": {
- "property1": { },
- "property2": { }
}, - "mediaProvider": "WebRTC"
}{- "custom": {
- "example": 0
}, - "nodeId": "7aoC1Q9IkTCn4zEsNAKvl1P1QMnXfnKE@192.168.100.1",
- "appKey": "defaultApp",
- "sessionId": "/192.168.1.102:13252/192.168.1.101:8443",
- "mediaSessionId": "d1ddc1ce-90e7-40dd-93b7-fff0e4438a60",
- "remoteMediaElementId": "f1ddc2ce-90e7-40dd-93b7-fff0e4438a60",
- "name": "stream1",
- "published": true,
- "hasVideo": true,
- "hasAudio": true,
- "status": "NEW",
- "sdp": "v=0\r\no=- 82374628 2 IN IP4 192.168.100.20\r\ns=-\r\nt=0 0\r\na=group:BUNDLE 0 1\r\na=msid-semantic: WMS\r\nm=audio 49170 RTP/AVP 0\r\nc=IN IP4 192.168.100.20\r\na=rtpmap:0 PCMU/8000\r\na=sendrecv\r\nm=video 51372 RTP/AVP 96\r\nc=IN IP4 192.168.100.20\r\na=rtpmap:96 VP8/90000\r\na=sendrecv\r\n",
- "audioCodec": "opus",
- "videoCodec": "H264",
- "info": "Failed by HLS writer error",
- "description": "Video RTP activity",
- "record": true,
- "recordName": "s0.mp4",
- "width": 720,
- "height": 480,
- "bitrate": 1000,
- "minBitrate": 0,
- "maxBitrate": 0,
- "quality": 23,
- "rtmpUrl": "rtmp://example.com:1935/live",
- "parentMediaSessionId": "f1ddc2ce-90e7-40dd-93b7-fff0e4438a60",
- "timeShift": 1000,
- "gop": 60,
- "fps": 30,
- "audioBitrate": 1000,
- "codecImpl": "OPENH264",
- "transport": "UDP",
- "profile": 66,
- "level": 52,
- "preset": "medium",
- "cvoExtension": true,
- "profiles": [
- {
- "width": 1280,
- "height": 720,
- "gop": 60,
- "fps": 30,
- "bitrate": 2500000,
- "codec": "H264",
- "codecImpl": "OPENH264",
- "quality": 23,
- "profile": 66,
- "level": 31,
- "preset": "veryfast",
- "audioGroupId": "audio0"
}
], - "audioProfiles": [
- {
- "bitrate": 64000,
- "codec": "opus",
- "rate": 48000,
- "channels": 2,
- "groupId": "default",
- "wrappedCodec": "opus"
}
], - "createDate": "2026-04-12 10:30:15.123000+00:00",
- "endDate": "2026-04-12 10:35:42.456000+00:00",
- "mediaType": "play",
- "audioState": {
- "muted": true
}, - "videoState": {
- "muted": true
}, - "localMediaInfo": {
- "property1": { },
- "property2": { }
}, - "mediaProvider": "WebRTC"
}/apps/DefaultApp/playRTSP
WCS calls this hook when an external RTSP client (for example VLC or ffplay) connects to WCS's built-in RTSP server and presents an auth token in the URL. WCS asks the Backend whether the token is valid before serving the RTSP session. The hook fires only when the rtsp_server_auth_enabled setting is true and a token is present in the URL. The request body contains the RTSP URL, user agent, stream identifiers, and the token as a custom field. The response does not rewrite the RTSP URL, stream name, or playback parameters.
2xx response — RTSP session is served:
4xx/5xx response — RTSP session is rejected:
object Custom key-value parameters | |
| nodeId | string Unique identifier of the WCS server instance. Auto-generated as {randomString}@{serverIP} and stored in {WCS_HOME}/conf/node_id |
| appKey | string REST hook application key. Determines the webhook URL for event notifications, as configured in database.yml |
| sessionId | string Signaling session ID (Connection ID). For WebSocket connections the format is /remoteIP:port/localIP:port. Format varies for other connection types |
| origin | string Origin URL of the client page (browser domain) |
| mediaSessionId | string Media session identifier within the WCS instance in UUID format |
| name | string Full RTSP URL of the remote source WCS pulls and exposes as an internal stream |
{- "custom": {
- "example": 0
}, - "nodeId": "7aoC1Q9IkTCn4zEsNAKvl1P1QMnXfnKE@192.168.100.1",
- "appKey": "defaultApp",
- "sessionId": "/192.168.1.102:13252/192.168.1.101:8443",
- "mediaSessionId": "d1ddc1ce-90e7-40dd-93b7-fff0e4438a60",
- "name": "rtsp://localhost:554/stream_name?aclAuth=auth_token"
}{- "custom": {
- "example": 0
}, - "nodeId": "7aoC1Q9IkTCn4zEsNAKvl1P1QMnXfnKE@192.168.100.1",
- "appKey": "defaultApp",
- "sessionId": "/192.168.1.102:13252/192.168.1.101:8443",
- "mediaSessionId": "d1ddc1ce-90e7-40dd-93b7-fff0e4438a60",
- "name": "rtsp://localhost:554/stream_name?aclAuth=auth_token"
}/apps/DefaultApp/playHLS
WCS calls this hook when an HLS player (browser, VLC, ffplay) requests an HLS playlist or segment for a stream and presents a token in the URL. WCS asks the Backend whether the token is valid before serving the resource. The request body contains the stream name, the subscriber session identifier, and the token as a custom field. The response does not rewrite the stream URL, stream name, or playback parameters. The hook is fired once per unique token — the result is cached on the WCS node, so subsequent requests with the same token reuse the cached decision without firing the hook again.
object Custom key-value parameters | |
| nodeId | string Unique identifier of the WCS server instance. Auto-generated as {randomString}@{serverIP} and stored in {WCS_HOME}/conf/node_id |
| appKey | string REST hook application key. Determines the webhook URL for event notifications, as configured in database.yml |
| sessionId | string Signaling session ID (Connection ID). For WebSocket connections the format is /remoteIP:port/localIP:port. Format varies for other connection types |
| origin | string Origin URL of the client page (browser domain) |
| name required | string Stream name |
{- "custom": {
- "example": 0
}, - "nodeId": "7aoC1Q9IkTCn4zEsNAKvl1P1QMnXfnKE@192.168.100.1",
- "appKey": "defaultApp",
- "sessionId": "/192.168.1.102:13252/192.168.1.101:8443",
- "name": "stream1"
}{- "custom": {
- "example": 0
}, - "nodeId": "7aoC1Q9IkTCn4zEsNAKvl1P1QMnXfnKE@192.168.100.1",
- "appKey": "defaultApp",
- "sessionId": "/192.168.1.102:13252/192.168.1.101:8443",
- "name": "stream1"
}/apps/DefaultApp/availableStream
WCS calls this hook when a client explicitly probes stream availability via the WebSDK call stream.available(). The request body contains the requested stream identifiers and the player session. After a 2xx response WCS performs the actual availability check — it verifies that the stream exists locally, has a valid CDN route, or satisfies composite-stream profiles; if none applies the WebSDK Promise rejects with reason STREAM_NOT_FOUND (or RESTRICTED_ACCESS on a CDN-restricted node). A hook failure rejects the probe when restOnError=FAIL.
object Custom key-value parameters | |
| nodeId | string Unique identifier of the WCS server instance. Auto-generated as {randomString}@{serverIP} and stored in {WCS_HOME}/conf/node_id |
| appKey | string REST hook application key. Determines the webhook URL for event notifications, as configured in database.yml |
| sessionId | string Signaling session ID (Connection ID). For WebSocket connections the format is /remoteIP:port/localIP:port. Format varies for other connection types |
| origin | string Origin URL of the client page (browser domain) |
| mediaSessionId | string Media session identifier within the WCS instance in UUID format |
| remoteMediaElementId | string Remote media session identifier in UUID format |
| name | string Stream name |
| published | boolean Whether this is a publish stream (true) or a play stream (false) |
| hasVideo | boolean Whether the stream has video |
| hasAudio | boolean Whether the stream has audio |
| status | string Enum: "NEW" "PENDING" "PUBLISHING" "PLAYING" "PAUSED" "UNPUBLISHED" "STOPPED" "FAILED" "RESIZE" "SNAPSHOT_COMPLETE" "NOT_ENOUGH_BANDWIDTH" Stream status |
| sdp | string SDP (Session Description Protocol) associated with the stream. For WebRTC this is the client's offer SDP, for other types a default SDP is used |
| audioCodec | string Audio codec name (e.g. opus, PCMA, PCMU, G729, AAC) |
| videoCodec | string Video codec name (e.g. H264, VP8, VP9, H265) |
| info | string Diagnostic information about the stream, typically the reason for stopping or an error description (e.g. Failed by RTP activity, Stopped by publisher stop, Failed by ICE error) |
| description | string Stream state description |
| record | boolean Whether the client requested recording on publish. Does not guarantee that recording is active |
| recordName | string Recording file name (MP4 or MKV). The file is located in the record_dir directory ({WCS_HOME}/records by default) |
| width | integer <int32> Video width in pixels |
| height | integer <int32> Video height in pixels |
| bitrate | integer <int64> Video bitrate in bps |
| minBitrate | integer <int64> Minimum bitrate in bps |
| maxBitrate | integer <int64> Maximum bitrate in bps |
| quality | integer <int32> Video quality as CRF (Constant Rate Factor) for the encoder. Range: 0 (lossless) to 60 (lowest quality). Lower values produce higher quality. For example, CRF 23 is a common default for H.264 |
| rtmpUrl | string RTMP URL specified by the client on publish for re-streaming to an RTMP server (e.g. rtmp://server:1935/live/stream) |
| parentMediaSessionId | string Parent media session identifier in UUID format |
| timeShift | integer <int64> Time offset in milliseconds from the first publish in the room to this stream's publish. Used for multi-track recording synchronization — aligns streams that start at different times within the same room |
| gop | integer <int32> Group of Pictures — number of frames between keyframes. For example, with fps=30 and gop=60, a keyframe is produced every 2 seconds |
| fps | integer <int32> Frames per second |
| audioBitrate | integer <int64> Audio bitrate in bps |
| codecImpl | string Codec implementation name |
| transport | string Transport protocol used for media delivery: UDP, TCP, or SRT |
| profile | integer <int32> Video codec profile (e.g. 66 = Baseline, 77 = Main, 100 = High for H.264) |
| level | integer <int32> Video codec level (e.g. 31 = Level 3.1, 52 = Level 5.2) |
| preset | string Encoder preset (e.g. ultrafast, medium, slow) |
| cvoExtension | boolean Has CVO(Coordinated Video Orientation) RTP header extension or not |
Array of objects (VideoStreamProfile) Negotiated stream profiles for adaptive bitrate (ABR); each entry describes one transcoded resolution/bitrate variant | |
Array of objects (AudioStreamProfile) | |
| createDate | string <date-time> Stream creation timestamp in ISO 8601 format |
| endDate | string <date-time> Timestamp when the stream was finalised on WCS, in ISO 8601 format; null while the stream is still active |
| mediaType | string Stream type: publish, play, pull, push, pcap, mixer, transcoder, transcoder2, sfu-relay |
object (MediaState) Per-track media state describing whether audio or video is currently muted on the stream | |
object (MediaState) Per-track media state describing whether audio or video is currently muted on the stream | |
object Open map of locally collected media information for this stream, such as negotiated SDP attributes, codec parameters, and SSRCs | |
| mediaProvider | string Media provider used by the client: WebRTC (Web SDK with WebRTC support), Flash (deprecated, legacy Flash player), MSE (Media Source Extensions playback), WSPlayer (WebSocket-based player), HLS (HLS playback), RTSP (RTSP pull), VOD (Video on Demand from file), MPEGTS (MPEG-TS ingest) |
{- "custom": {
- "example": 0
}, - "nodeId": "7aoC1Q9IkTCn4zEsNAKvl1P1QMnXfnKE@192.168.100.1",
- "appKey": "defaultApp",
- "sessionId": "/192.168.1.102:13252/192.168.1.101:8443",
- "mediaSessionId": "d1ddc1ce-90e7-40dd-93b7-fff0e4438a60",
- "remoteMediaElementId": "f1ddc2ce-90e7-40dd-93b7-fff0e4438a60",
- "name": "stream1",
- "published": true,
- "hasVideo": true,
- "hasAudio": true,
- "status": "NEW",
- "sdp": "v=0\r\no=- 82374628 2 IN IP4 192.168.100.20\r\ns=-\r\nt=0 0\r\na=group:BUNDLE 0 1\r\na=msid-semantic: WMS\r\nm=audio 49170 RTP/AVP 0\r\nc=IN IP4 192.168.100.20\r\na=rtpmap:0 PCMU/8000\r\na=sendrecv\r\nm=video 51372 RTP/AVP 96\r\nc=IN IP4 192.168.100.20\r\na=rtpmap:96 VP8/90000\r\na=sendrecv\r\n",
- "audioCodec": "opus",
- "videoCodec": "H264",
- "info": "Failed by HLS writer error",
- "description": "Video RTP activity",
- "record": true,
- "recordName": "s0.mp4",
- "width": 720,
- "height": 480,
- "bitrate": 1000,
- "minBitrate": 0,
- "maxBitrate": 0,
- "quality": 23,
- "rtmpUrl": "rtmp://example.com:1935/live",
- "parentMediaSessionId": "f1ddc2ce-90e7-40dd-93b7-fff0e4438a60",
- "timeShift": 1000,
- "gop": 60,
- "fps": 30,
- "audioBitrate": 1000,
- "codecImpl": "OPENH264",
- "transport": "UDP",
- "profile": 66,
- "level": 52,
- "preset": "medium",
- "cvoExtension": true,
- "profiles": [
- {
- "width": 1280,
- "height": 720,
- "gop": 60,
- "fps": 30,
- "bitrate": 2500000,
- "codec": "H264",
- "codecImpl": "OPENH264",
- "quality": 23,
- "profile": 66,
- "level": 31,
- "preset": "veryfast",
- "audioGroupId": "audio0"
}
], - "audioProfiles": [
- {
- "bitrate": 64000,
- "codec": "opus",
- "rate": 48000,
- "channels": 2,
- "groupId": "default",
- "wrappedCodec": "opus"
}
], - "createDate": "2026-04-12 10:30:15.123000+00:00",
- "endDate": "2026-04-12 10:35:42.456000+00:00",
- "mediaType": "play",
- "audioState": {
- "muted": true
}, - "videoState": {
- "muted": true
}, - "localMediaInfo": {
- "property1": { },
- "property2": { }
}, - "mediaProvider": "WebRTC"
}{- "custom": {
- "example": 0
}, - "nodeId": "7aoC1Q9IkTCn4zEsNAKvl1P1QMnXfnKE@192.168.100.1",
- "appKey": "defaultApp",
- "sessionId": "/192.168.1.102:13252/192.168.1.101:8443",
- "mediaSessionId": "d1ddc1ce-90e7-40dd-93b7-fff0e4438a60",
- "remoteMediaElementId": "f1ddc2ce-90e7-40dd-93b7-fff0e4438a60",
- "name": "stream1",
- "published": true,
- "hasVideo": true,
- "hasAudio": true,
- "status": "NEW",
- "sdp": "v=0\r\no=- 82374628 2 IN IP4 192.168.100.20\r\ns=-\r\nt=0 0\r\na=group:BUNDLE 0 1\r\na=msid-semantic: WMS\r\nm=audio 49170 RTP/AVP 0\r\nc=IN IP4 192.168.100.20\r\na=rtpmap:0 PCMU/8000\r\na=sendrecv\r\nm=video 51372 RTP/AVP 96\r\nc=IN IP4 192.168.100.20\r\na=rtpmap:96 VP8/90000\r\na=sendrecv\r\n",
- "audioCodec": "opus",
- "videoCodec": "H264",
- "info": "Failed by HLS writer error",
- "description": "Video RTP activity",
- "record": true,
- "recordName": "s0.mp4",
- "width": 720,
- "height": 480,
- "bitrate": 1000,
- "minBitrate": 0,
- "maxBitrate": 0,
- "quality": 23,
- "rtmpUrl": "rtmp://example.com:1935/live",
- "parentMediaSessionId": "f1ddc2ce-90e7-40dd-93b7-fff0e4438a60",
- "timeShift": 1000,
- "gop": 60,
- "fps": 30,
- "audioBitrate": 1000,
- "codecImpl": "OPENH264",
- "transport": "UDP",
- "profile": 66,
- "level": 52,
- "preset": "medium",
- "cvoExtension": true,
- "profiles": [
- {
- "width": 1280,
- "height": 720,
- "gop": 60,
- "fps": 30,
- "bitrate": 2500000,
- "codec": "H264",
- "codecImpl": "OPENH264",
- "quality": 23,
- "profile": 66,
- "level": 31,
- "preset": "veryfast",
- "audioGroupId": "audio0"
}
], - "audioProfiles": [
- {
- "bitrate": 64000,
- "codec": "opus",
- "rate": 48000,
- "channels": 2,
- "groupId": "default",
- "wrappedCodec": "opus"
}
], - "createDate": "2026-04-12 10:30:15.123000+00:00",
- "endDate": "2026-04-12 10:35:42.456000+00:00",
- "mediaType": "play",
- "audioState": {
- "muted": true
}, - "videoState": {
- "muted": true
}, - "localMediaInfo": {
- "property1": { },
- "property2": { }
}, - "mediaProvider": "WebRTC"
}/apps/DefaultApp/RecordingStatusEvent
WCS sends this notification hook when a stream recording completes — either successfully (recorded file is finalised) or with an error. The hook is not fired on recording start. The request body contains the source stream identifiers and the resulting RecordReport (file name, duration, size, error details). After the hook returns, WCS sends a notifyRecordComplete WebSocket message to the client; the standard WebSDK does not expose this message to user-level handlers — the recording file name is instead available to the client via stream.getRecordInfo().
object Custom key-value parameters | |
| nodeId | string Unique identifier of the WCS server instance. Auto-generated as {randomString}@{serverIP} and stored in {WCS_HOME}/conf/node_id |
| appKey | string REST hook application key. Determines the webhook URL for event notifications, as configured in database.yml |
| sessionId | string Signaling session ID (Connection ID). For WebSocket connections the format is /remoteIP:port/localIP:port. Format varies for other connection types |
| origin | string Origin URL of the client page (browser domain) |
object (RecordReport) Audio recording report for a SIP call: file paths of incoming, outgoing, and mixed tracks, sampling rate, and the originating Call-ID |
{- "custom": {
- "example": 0
}, - "nodeId": "7aoC1Q9IkTCn4zEsNAKvl1P1QMnXfnKE@192.168.100.1",
- "appKey": "defaultApp",
- "sessionId": "/192.168.1.102:13252/192.168.1.101:8443",
- "report": {
- "incomingFileName": "record/10001-10002-2025-12-04-12-34-56-5cbedcae-0c5c-455e-9c56-5d7c78a82b8d-10-in.wav",
- "outgoingFileName": "record/10001-10002-2025-12-04-12-34-56-5cbedcae-0c5c-455e-9c56-5d7c78a82b8d-10-out.wav",
- "mixedFilename": "record/10001-10002-2025-12-04-12-34-56-5cbedcae-0c5c-455e-9c56-5d7c78a82b8d-10.wav",
- "samplingRate": 48000,
- "callId": "6d62f660"
}
}{- "custom": {
- "example": 0
}, - "nodeId": "7aoC1Q9IkTCn4zEsNAKvl1P1QMnXfnKE@192.168.100.1",
- "appKey": "defaultApp",
- "sessionId": "/192.168.1.102:13252/192.168.1.101:8443",
- "report": {
- "incomingFileName": "record/10001-10002-2025-12-04-12-34-56-5cbedcae-0c5c-455e-9c56-5d7c78a82b8d-10-in.wav",
- "outgoingFileName": "record/10001-10002-2025-12-04-12-34-56-5cbedcae-0c5c-455e-9c56-5d7c78a82b8d-10-out.wav",
- "mixedFilename": "record/10001-10002-2025-12-04-12-34-56-5cbedcae-0c5c-455e-9c56-5d7c78a82b8d-10.wav",
- "samplingRate": 48000,
- "callId": "6d62f660"
}
}/apps/DefaultApp/StreamEvent
WCS sends this notification hook every time a stream-level event is dispatched to a subscriber of the stream. The event carries a type and a payload; the same event is also delivered to the subscriber's WebSDK STREAM_EVENT callback. The request body contains the stream identifiers, event type, and payload.
The event is emitted by one of the following sources:
muteAudio, unmuteAudio, muteVideo, unmuteVideo, sendData;POST /rest-api/v3/stream/send_event (server-initiated broadcast);resize (video dimensions changed) or notEnoughBandwidth.The hook is fired per subscriber: a stream with N active subscribers produces N hook calls per event. Plan Backend throughput accordingly, or set restPolicy=DISABLE on StreamEvent in restClientConfig if Backend notification is not needed.
object Custom key-value parameters | |
| nodeId | string Unique identifier of the WCS server instance. Auto-generated as {randomString}@{serverIP} and stored in {WCS_HOME}/conf/node_id |
| appKey | string REST hook application key. Determines the webhook URL for event notifications, as configured in database.yml |
| sessionId | string Signaling session ID (Connection ID). For WebSocket connections the format is /remoteIP:port/localIP:port. Format varies for other connection types |
| origin | string Origin URL of the client page (browser domain) |
| mediaSessionId | string Media session identifier within the WCS instance in UUID format |
| type | string Enum: "data" "audioMuted" "audioUnmuted" "videoMuted" "videoUnmuted" "snapshotCompleted" "snapshotFailed" "resize" "notEnoughBandwidth" "addedToMixing" "removedFromMixing" "startedRecording" "stoppedByReInit" "stoppedRecording" "failedRecording" "addedToMultiRecording" "removedFromMultiRecording" "answer" "sdp" "offer" Event type |
object Free-form map carrying optional event metadata; the contents are forwarded to subscribers as-is |
{- "custom": {
- "example": 0
}, - "nodeId": "7aoC1Q9IkTCn4zEsNAKvl1P1QMnXfnKE@192.168.100.1",
- "appKey": "defaultApp",
- "sessionId": "/192.168.1.102:13252/192.168.1.101:8443",
- "mediaSessionId": "d1ddc1ce-90e7-40dd-93b7-fff0e4438a60",
- "type": "audioMuted",
- "payload": {
- "property1": { },
- "property2": { }
}
}{- "custom": {
- "example": 0
}, - "nodeId": "7aoC1Q9IkTCn4zEsNAKvl1P1QMnXfnKE@192.168.100.1",
- "appKey": "defaultApp",
- "sessionId": "/192.168.1.102:13252/192.168.1.101:8443",
- "mediaSessionId": "d1ddc1ce-90e7-40dd-93b7-fff0e4438a60",
- "type": "audioMuted",
- "payload": {
- "property1": { },
- "property2": { }
}
}/apps/DefaultApp/StreamStatusEvent
WCS sends this notification hook every time a stream changes its state. Possible values: PUBLISHING, PLAYING, PAUSED, UNPUBLISHED, STOPPED, FAILED. The request body contains the new stream status, identifiers, and media metadata.
object Custom key-value parameters | |
| nodeId | string Unique identifier of the WCS server instance. Auto-generated as {randomString}@{serverIP} and stored in {WCS_HOME}/conf/node_id |
| appKey | string REST hook application key. Determines the webhook URL for event notifications, as configured in database.yml |
| sessionId | string Signaling session ID (Connection ID). For WebSocket connections the format is /remoteIP:port/localIP:port. Format varies for other connection types |
| origin | string Origin URL of the client page (browser domain) |
| mediaSessionId | string Media session identifier within the WCS instance in UUID format |
| remoteMediaElementId | string Remote media session identifier in UUID format |
| name | string Stream name |
| published | boolean Whether this is a publish stream (true) or a play stream (false) |
| hasVideo | boolean Whether the stream has video |
| hasAudio | boolean Whether the stream has audio |
| status | string Enum: "NEW" "PENDING" "PUBLISHING" "PLAYING" "PAUSED" "UNPUBLISHED" "STOPPED" "FAILED" "RESIZE" "SNAPSHOT_COMPLETE" "NOT_ENOUGH_BANDWIDTH" Stream status |
| sdp | string SDP (Session Description Protocol) associated with the stream. For WebRTC this is the client's offer SDP, for other types a default SDP is used |
| audioCodec | string Audio codec name (e.g. opus, PCMA, PCMU, G729, AAC) |
| videoCodec | string Video codec name (e.g. H264, VP8, VP9, H265) |
| info | string Diagnostic information about the stream, typically the reason for stopping or an error description (e.g. Failed by RTP activity, Stopped by publisher stop, Failed by ICE error) |
| description | string Stream state description |
| record | boolean Whether the client requested recording on publish. Does not guarantee that recording is active |
| recordName | string Recording file name (MP4 or MKV). The file is located in the record_dir directory ({WCS_HOME}/records by default) |
| width | integer <int32> Video width in pixels |
| height | integer <int32> Video height in pixels |
| bitrate | integer <int64> Video bitrate in bps |
| minBitrate | integer <int64> Minimum bitrate in bps |
| maxBitrate | integer <int64> Maximum bitrate in bps |
| quality | integer <int32> Video quality as CRF (Constant Rate Factor) for the encoder. Range: 0 (lossless) to 60 (lowest quality). Lower values produce higher quality. For example, CRF 23 is a common default for H.264 |
| rtmpUrl | string RTMP URL specified by the client on publish for re-streaming to an RTMP server (e.g. rtmp://server:1935/live/stream) |
| parentMediaSessionId | string Parent media session identifier in UUID format |
| timeShift | integer <int64> Time offset in milliseconds from the first publish in the room to this stream's publish. Used for multi-track recording synchronization — aligns streams that start at different times within the same room |
| gop | integer <int32> Group of Pictures — number of frames between keyframes. For example, with fps=30 and gop=60, a keyframe is produced every 2 seconds |
| fps | integer <int32> Frames per second |
| audioBitrate | integer <int64> Audio bitrate in bps |
| codecImpl | string Codec implementation name |
| transport | string Transport protocol used for media delivery: UDP, TCP, or SRT |
| profile | integer <int32> Video codec profile (e.g. 66 = Baseline, 77 = Main, 100 = High for H.264) |
| level | integer <int32> Video codec level (e.g. 31 = Level 3.1, 52 = Level 5.2) |
| preset | string Encoder preset (e.g. ultrafast, medium, slow) |
| cvoExtension | boolean Has CVO(Coordinated Video Orientation) RTP header extension or not |
Array of objects (VideoStreamProfile) Negotiated stream profiles for adaptive bitrate (ABR); each entry describes one transcoded resolution/bitrate variant | |
Array of objects (AudioStreamProfile) | |
| createDate | string <date-time> Stream creation timestamp in ISO 8601 format |
| endDate | string <date-time> Timestamp when the stream was finalised on WCS, in ISO 8601 format; null while the stream is still active |
| mediaType | string Stream type: publish, play, pull, push, pcap, mixer, transcoder, transcoder2, sfu-relay |
object (MediaState) Per-track media state describing whether audio or video is currently muted on the stream | |
object (MediaState) Per-track media state describing whether audio or video is currently muted on the stream | |
object Open map of locally collected media information for this stream, such as negotiated SDP attributes, codec parameters, and SSRCs | |
| mediaProvider | string Media provider used by the client: WebRTC (Web SDK with WebRTC support), Flash (deprecated, legacy Flash player), MSE (Media Source Extensions playback), WSPlayer (WebSocket-based player), HLS (HLS playback), RTSP (RTSP pull), VOD (Video on Demand from file), MPEGTS (MPEG-TS ingest) |
{- "custom": {
- "example": 0
}, - "nodeId": "7aoC1Q9IkTCn4zEsNAKvl1P1QMnXfnKE@192.168.100.1",
- "appKey": "defaultApp",
- "sessionId": "/192.168.1.102:13252/192.168.1.101:8443",
- "mediaSessionId": "d1ddc1ce-90e7-40dd-93b7-fff0e4438a60",
- "remoteMediaElementId": "f1ddc2ce-90e7-40dd-93b7-fff0e4438a60",
- "name": "stream1",
- "published": true,
- "hasVideo": true,
- "hasAudio": true,
- "status": "NEW",
- "sdp": "v=0\r\no=- 82374628 2 IN IP4 192.168.100.20\r\ns=-\r\nt=0 0\r\na=group:BUNDLE 0 1\r\na=msid-semantic: WMS\r\nm=audio 49170 RTP/AVP 0\r\nc=IN IP4 192.168.100.20\r\na=rtpmap:0 PCMU/8000\r\na=sendrecv\r\nm=video 51372 RTP/AVP 96\r\nc=IN IP4 192.168.100.20\r\na=rtpmap:96 VP8/90000\r\na=sendrecv\r\n",
- "audioCodec": "opus",
- "videoCodec": "H264",
- "info": "Failed by HLS writer error",
- "description": "Video RTP activity",
- "record": true,
- "recordName": "s0.mp4",
- "width": 720,
- "height": 480,
- "bitrate": 1000,
- "minBitrate": 0,
- "maxBitrate": 0,
- "quality": 23,
- "rtmpUrl": "rtmp://example.com:1935/live",
- "parentMediaSessionId": "f1ddc2ce-90e7-40dd-93b7-fff0e4438a60",
- "timeShift": 1000,
- "gop": 60,
- "fps": 30,
- "audioBitrate": 1000,
- "codecImpl": "OPENH264",
- "transport": "UDP",
- "profile": 66,
- "level": 52,
- "preset": "medium",
- "cvoExtension": true,
- "profiles": [
- {
- "width": 1280,
- "height": 720,
- "gop": 60,
- "fps": 30,
- "bitrate": 2500000,
- "codec": "H264",
- "codecImpl": "OPENH264",
- "quality": 23,
- "profile": 66,
- "level": 31,
- "preset": "veryfast",
- "audioGroupId": "audio0"
}
], - "audioProfiles": [
- {
- "bitrate": 64000,
- "codec": "opus",
- "rate": 48000,
- "channels": 2,
- "groupId": "default",
- "wrappedCodec": "opus"
}
], - "createDate": "2026-04-12 10:30:15.123000+00:00",
- "endDate": "2026-04-12 10:35:42.456000+00:00",
- "mediaType": "play",
- "audioState": {
- "muted": true
}, - "videoState": {
- "muted": true
}, - "localMediaInfo": {
- "property1": { },
- "property2": { }
}, - "mediaProvider": "WebRTC"
}{- "custom": {
- "example": 0
}, - "nodeId": "7aoC1Q9IkTCn4zEsNAKvl1P1QMnXfnKE@192.168.100.1",
- "appKey": "defaultApp",
- "sessionId": "/192.168.1.102:13252/192.168.1.101:8443",
- "mediaSessionId": "d1ddc1ce-90e7-40dd-93b7-fff0e4438a60",
- "remoteMediaElementId": "f1ddc2ce-90e7-40dd-93b7-fff0e4438a60",
- "name": "stream1",
- "published": true,
- "hasVideo": true,
- "hasAudio": true,
- "status": "NEW",
- "sdp": "v=0\r\no=- 82374628 2 IN IP4 192.168.100.20\r\ns=-\r\nt=0 0\r\na=group:BUNDLE 0 1\r\na=msid-semantic: WMS\r\nm=audio 49170 RTP/AVP 0\r\nc=IN IP4 192.168.100.20\r\na=rtpmap:0 PCMU/8000\r\na=sendrecv\r\nm=video 51372 RTP/AVP 96\r\nc=IN IP4 192.168.100.20\r\na=rtpmap:96 VP8/90000\r\na=sendrecv\r\n",
- "audioCodec": "opus",
- "videoCodec": "H264",
- "info": "Failed by HLS writer error",
- "description": "Video RTP activity",
- "record": true,
- "recordName": "s0.mp4",
- "width": 720,
- "height": 480,
- "bitrate": 1000,
- "minBitrate": 0,
- "maxBitrate": 0,
- "quality": 23,
- "rtmpUrl": "rtmp://example.com:1935/live",
- "parentMediaSessionId": "f1ddc2ce-90e7-40dd-93b7-fff0e4438a60",
- "timeShift": 1000,
- "gop": 60,
- "fps": 30,
- "audioBitrate": 1000,
- "codecImpl": "OPENH264",
- "transport": "UDP",
- "profile": 66,
- "level": 52,
- "preset": "medium",
- "cvoExtension": true,
- "profiles": [
- {
- "width": 1280,
- "height": 720,
- "gop": 60,
- "fps": 30,
- "bitrate": 2500000,
- "codec": "H264",
- "codecImpl": "OPENH264",
- "quality": 23,
- "profile": 66,
- "level": 31,
- "preset": "veryfast",
- "audioGroupId": "audio0"
}
], - "audioProfiles": [
- {
- "bitrate": 64000,
- "codec": "opus",
- "rate": 48000,
- "channels": 2,
- "groupId": "default",
- "wrappedCodec": "opus"
}
], - "createDate": "2026-04-12 10:30:15.123000+00:00",
- "endDate": "2026-04-12 10:35:42.456000+00:00",
- "mediaType": "play",
- "audioState": {
- "muted": true
}, - "videoState": {
- "muted": true
}, - "localMediaInfo": {
- "property1": { },
- "property2": { }
}, - "mediaProvider": "WebRTC"
}/apps/DefaultApp/StreamTranscodingGroupEvent
WCS sends this notification hook when the set of audio or video transcoding groups for a stream changes — typically when a subscriber that requires a new codec or resolution variant joins or leaves the stream. The request body contains the source mediaSessionId, the current audioGroups and videoGroups sets (each describing one target codec/resolution variant and the subscribers consuming it), and optional proxyAudioGroup/proxyVideoGroup for unmodified pass-through.
object Custom key-value parameters | |
| nodeId | string Unique identifier of the WCS server instance. Auto-generated as {randomString}@{serverIP} and stored in {WCS_HOME}/conf/node_id |
| appKey | string REST hook application key. Determines the webhook URL for event notifications, as configured in database.yml |
| sessionId | string Signaling session ID (Connection ID). For WebSocket connections the format is /remoteIP:port/localIP:port. Format varies for other connection types |
| origin | string Origin URL of the client page (browser domain) |
| mediaSessionId | string Media session identifier in UUID format |
object (TranscodingGroupParams) Per-track configuration of a transcoding group; binds the source track type (audio or video), target codec and resolution, and the set of subscribers that consume the produced track | |
object (TranscodingGroupParams) Per-track configuration of a transcoding group; binds the source track type (audio or video), target codec and resolution, and the set of subscribers that consume the produced track | |
Array of objects (TranscodingGroupParams) unique Audio transcoding groups produced for the source stream; each group describes one target codec/sample-rate variant and the subscribers consuming it | |
Array of objects (TranscodingGroupParams) unique Video transcoding groups produced for the source stream; each group describes one target codec/resolution variant and the subscribers consuming it | |
Array of objects (TranscodingGroupParams) unique Convenience union of audioGroups and videoGroups | |
Array of objects (TranscodingGroupParams) unique Convenience union of proxyAudioGroup and proxyVideoGroup, omitting any null entries |
{- "custom": {
- "example": 0
}, - "nodeId": "7aoC1Q9IkTCn4zEsNAKvl1P1QMnXfnKE@192.168.100.1",
- "appKey": "defaultApp",
- "sessionId": "/192.168.1.102:13252/192.168.1.101:8443",
- "mediaSessionId": "f0598830-d017-11f0-affd-2f622bc7bad6",
- "proxyAudioGroup": {
- "custom": {
- "example": 0
}, - "nodeId": "7aoC1Q9IkTCn4zEsNAKvl1P1QMnXfnKE@192.168.100.1",
- "appKey": "defaultApp",
- "sessionId": "/192.168.1.102:13252/192.168.1.101:8443",
- "codec": "H264",
- "width": 720,
- "height": 480,
- "sampleRate": 48000,
- "subscribersId": [
- "f0598830-d017-11f0-affd-2f622bc7bad6"
], - "audio": true
}, - "proxyVideoGroup": {
- "custom": {
- "example": 0
}, - "nodeId": "7aoC1Q9IkTCn4zEsNAKvl1P1QMnXfnKE@192.168.100.1",
- "appKey": "defaultApp",
- "sessionId": "/192.168.1.102:13252/192.168.1.101:8443",
- "codec": "H264",
- "width": 720,
- "height": 480,
- "sampleRate": 48000,
- "subscribersId": [
- "f0598830-d017-11f0-affd-2f622bc7bad6"
], - "audio": true
}, - "audioGroups": [
- {
- "custom": {
- "example": 0
}, - "nodeId": "7aoC1Q9IkTCn4zEsNAKvl1P1QMnXfnKE@192.168.100.1",
- "appKey": "defaultApp",
- "sessionId": "/192.168.1.102:13252/192.168.1.101:8443",
- "codec": "H264",
- "width": 720,
- "height": 480,
- "sampleRate": 48000,
- "subscribersId": [
- "f0598830-d017-11f0-affd-2f622bc7bad6"
], - "audio": true
}
], - "videoGroups": [
- {
- "custom": {
- "example": 0
}, - "nodeId": "7aoC1Q9IkTCn4zEsNAKvl1P1QMnXfnKE@192.168.100.1",
- "appKey": "defaultApp",
- "sessionId": "/192.168.1.102:13252/192.168.1.101:8443",
- "codec": "H264",
- "width": 720,
- "height": 480,
- "sampleRate": 48000,
- "subscribersId": [
- "f0598830-d017-11f0-affd-2f622bc7bad6"
], - "audio": true
}
], - "groups": [
- {
- "custom": {
- "example": 0
}, - "nodeId": "7aoC1Q9IkTCn4zEsNAKvl1P1QMnXfnKE@192.168.100.1",
- "appKey": "defaultApp",
- "sessionId": "/192.168.1.102:13252/192.168.1.101:8443",
- "codec": "H264",
- "width": 720,
- "height": 480,
- "sampleRate": 48000,
- "subscribersId": [
- "f0598830-d017-11f0-affd-2f622bc7bad6"
], - "audio": true
}
], - "proxyGroups": [
- {
- "custom": {
- "example": 0
}, - "nodeId": "7aoC1Q9IkTCn4zEsNAKvl1P1QMnXfnKE@192.168.100.1",
- "appKey": "defaultApp",
- "sessionId": "/192.168.1.102:13252/192.168.1.101:8443",
- "codec": "H264",
- "width": 720,
- "height": 480,
- "sampleRate": 48000,
- "subscribersId": [
- "f0598830-d017-11f0-affd-2f622bc7bad6"
], - "audio": true
}
]
}{- "custom": {
- "example": 0
}, - "nodeId": "7aoC1Q9IkTCn4zEsNAKvl1P1QMnXfnKE@192.168.100.1",
- "appKey": "defaultApp",
- "sessionId": "/192.168.1.102:13252/192.168.1.101:8443",
- "mediaSessionId": "f0598830-d017-11f0-affd-2f622bc7bad6",
- "proxyAudioGroup": {
- "custom": {
- "example": 0
}, - "nodeId": "7aoC1Q9IkTCn4zEsNAKvl1P1QMnXfnKE@192.168.100.1",
- "appKey": "defaultApp",
- "sessionId": "/192.168.1.102:13252/192.168.1.101:8443",
- "codec": "H264",
- "width": 720,
- "height": 480,
- "sampleRate": 48000,
- "subscribersId": [
- "f0598830-d017-11f0-affd-2f622bc7bad6"
], - "audio": true
}, - "proxyVideoGroup": {
- "custom": {
- "example": 0
}, - "nodeId": "7aoC1Q9IkTCn4zEsNAKvl1P1QMnXfnKE@192.168.100.1",
- "appKey": "defaultApp",
- "sessionId": "/192.168.1.102:13252/192.168.1.101:8443",
- "codec": "H264",
- "width": 720,
- "height": 480,
- "sampleRate": 48000,
- "subscribersId": [
- "f0598830-d017-11f0-affd-2f622bc7bad6"
], - "audio": true
}, - "audioGroups": [
- {
- "custom": {
- "example": 0
}, - "nodeId": "7aoC1Q9IkTCn4zEsNAKvl1P1QMnXfnKE@192.168.100.1",
- "appKey": "defaultApp",
- "sessionId": "/192.168.1.102:13252/192.168.1.101:8443",
- "codec": "H264",
- "width": 720,
- "height": 480,
- "sampleRate": 48000,
- "subscribersId": [
- "f0598830-d017-11f0-affd-2f622bc7bad6"
], - "audio": true
}
], - "videoGroups": [
- {
- "custom": {
- "example": 0
}, - "nodeId": "7aoC1Q9IkTCn4zEsNAKvl1P1QMnXfnKE@192.168.100.1",
- "appKey": "defaultApp",
- "sessionId": "/192.168.1.102:13252/192.168.1.101:8443",
- "codec": "H264",
- "width": 720,
- "height": 480,
- "sampleRate": 48000,
- "subscribersId": [
- "f0598830-d017-11f0-affd-2f622bc7bad6"
], - "audio": true
}
], - "groups": [
- {
- "custom": {
- "example": 0
}, - "nodeId": "7aoC1Q9IkTCn4zEsNAKvl1P1QMnXfnKE@192.168.100.1",
- "appKey": "defaultApp",
- "sessionId": "/192.168.1.102:13252/192.168.1.101:8443",
- "codec": "H264",
- "width": 720,
- "height": 480,
- "sampleRate": 48000,
- "subscribersId": [
- "f0598830-d017-11f0-affd-2f622bc7bad6"
], - "audio": true
}
], - "proxyGroups": [
- {
- "custom": {
- "example": 0
}, - "nodeId": "7aoC1Q9IkTCn4zEsNAKvl1P1QMnXfnKE@192.168.100.1",
- "appKey": "defaultApp",
- "sessionId": "/192.168.1.102:13252/192.168.1.101:8443",
- "codec": "H264",
- "width": 720,
- "height": 480,
- "sampleRate": 48000,
- "subscribersId": [
- "f0598830-d017-11f0-affd-2f622bc7bad6"
], - "audio": true
}
]
}/apps/DefaultApp/StreamKeepAliveEvent
WCS sends this control hook periodically for active published and played streams when streaming session keep-alive is enabled for the application key. It allows the Backend to keep the media session active or force WCS to stop the stream on the server side. The request body contains the current stream identifiers, media information, and the published flag that shows whether the checked media session is publishing or playing the stream. A 2xx Backend response keeps the stream active and WCS does not change the media session. Any non-2xx response, for example 403 Forbidden, or hook request failure makes WCS terminate the media session with the keep-alive termination reason and notify the client with a failed stream status.
2xx response — stream continues:
4xx/5xx response — stream is terminated:
object Custom key-value parameters | |
| nodeId | string Unique identifier of the WCS server instance. Auto-generated as {randomString}@{serverIP} and stored in {WCS_HOME}/conf/node_id |
| appKey | string REST hook application key. Determines the webhook URL for event notifications, as configured in database.yml |
| sessionId | string Signaling session ID (Connection ID). For WebSocket connections the format is /remoteIP:port/localIP:port. Format varies for other connection types |
| origin | string Origin URL of the client page (browser domain) |
| mediaSessionId | string Media session identifier within the WCS instance in UUID format |
| remoteMediaElementId | string Remote media session identifier in UUID format |
| name | string Stream name |
| published | boolean Whether this is a publish stream (true) or a play stream (false) |
| hasVideo | boolean Whether the stream has video |
| hasAudio | boolean Whether the stream has audio |
| status | string Enum: "NEW" "PENDING" "PUBLISHING" "PLAYING" "PAUSED" "UNPUBLISHED" "STOPPED" "FAILED" "RESIZE" "SNAPSHOT_COMPLETE" "NOT_ENOUGH_BANDWIDTH" Stream status |
| sdp | string SDP (Session Description Protocol) associated with the stream. For WebRTC this is the client's offer SDP, for other types a default SDP is used |
| audioCodec | string Audio codec name (e.g. opus, PCMA, PCMU, G729, AAC) |
| videoCodec | string Video codec name (e.g. H264, VP8, VP9, H265) |
| info | string Diagnostic information about the stream, typically the reason for stopping or an error description (e.g. Failed by RTP activity, Stopped by publisher stop, Failed by ICE error) |
| description | string Stream state description |
| record | boolean Whether the client requested recording on publish. Does not guarantee that recording is active |
| recordName | string Recording file name (MP4 or MKV). The file is located in the record_dir directory ({WCS_HOME}/records by default) |
| width | integer <int32> Video width in pixels |
| height | integer <int32> Video height in pixels |
| bitrate | integer <int64> Video bitrate in bps |
| minBitrate | integer <int64> Minimum bitrate in bps |
| maxBitrate | integer <int64> Maximum bitrate in bps |
| quality | integer <int32> Video quality as CRF (Constant Rate Factor) for the encoder. Range: 0 (lossless) to 60 (lowest quality). Lower values produce higher quality. For example, CRF 23 is a common default for H.264 |
| rtmpUrl | string RTMP URL specified by the client on publish for re-streaming to an RTMP server (e.g. rtmp://server:1935/live/stream) |
| parentMediaSessionId | string Parent media session identifier in UUID format |
| timeShift | integer <int64> Time offset in milliseconds from the first publish in the room to this stream's publish. Used for multi-track recording synchronization — aligns streams that start at different times within the same room |
| gop | integer <int32> Group of Pictures — number of frames between keyframes. For example, with fps=30 and gop=60, a keyframe is produced every 2 seconds |
| fps | integer <int32> Frames per second |
| audioBitrate | integer <int64> Audio bitrate in bps |
| codecImpl | string Codec implementation name |
| transport | string Transport protocol used for media delivery: UDP, TCP, or SRT |
| profile | integer <int32> Video codec profile (e.g. 66 = Baseline, 77 = Main, 100 = High for H.264) |
| level | integer <int32> Video codec level (e.g. 31 = Level 3.1, 52 = Level 5.2) |
| preset | string Encoder preset (e.g. ultrafast, medium, slow) |
| cvoExtension | boolean Has CVO(Coordinated Video Orientation) RTP header extension or not |
Array of objects (VideoStreamProfile) Negotiated stream profiles for adaptive bitrate (ABR); each entry describes one transcoded resolution/bitrate variant | |
Array of objects (AudioStreamProfile) | |
| createDate | string <date-time> Stream creation timestamp in ISO 8601 format |
| endDate | string <date-time> Timestamp when the stream was finalised on WCS, in ISO 8601 format; null while the stream is still active |
| mediaType | string Stream type: publish, play, pull, push, pcap, mixer, transcoder, transcoder2, sfu-relay |
object (MediaState) Per-track media state describing whether audio or video is currently muted on the stream | |
object (MediaState) Per-track media state describing whether audio or video is currently muted on the stream | |
object Open map of locally collected media information for this stream, such as negotiated SDP attributes, codec parameters, and SSRCs | |
| mediaProvider | string Media provider used by the client: WebRTC (Web SDK with WebRTC support), Flash (deprecated, legacy Flash player), MSE (Media Source Extensions playback), WSPlayer (WebSocket-based player), HLS (HLS playback), RTSP (RTSP pull), VOD (Video on Demand from file), MPEGTS (MPEG-TS ingest) |
{- "custom": {
- "example": 0
}, - "nodeId": "7aoC1Q9IkTCn4zEsNAKvl1P1QMnXfnKE@192.168.100.1",
- "appKey": "defaultApp",
- "sessionId": "/192.168.1.102:13252/192.168.1.101:8443",
- "mediaSessionId": "d1ddc1ce-90e7-40dd-93b7-fff0e4438a60",
- "remoteMediaElementId": "f1ddc2ce-90e7-40dd-93b7-fff0e4438a60",
- "name": "stream1",
- "published": true,
- "hasVideo": true,
- "hasAudio": true,
- "status": "NEW",
- "sdp": "v=0\r\no=- 82374628 2 IN IP4 192.168.100.20\r\ns=-\r\nt=0 0\r\na=group:BUNDLE 0 1\r\na=msid-semantic: WMS\r\nm=audio 49170 RTP/AVP 0\r\nc=IN IP4 192.168.100.20\r\na=rtpmap:0 PCMU/8000\r\na=sendrecv\r\nm=video 51372 RTP/AVP 96\r\nc=IN IP4 192.168.100.20\r\na=rtpmap:96 VP8/90000\r\na=sendrecv\r\n",
- "audioCodec": "opus",
- "videoCodec": "H264",
- "info": "Failed by HLS writer error",
- "description": "Video RTP activity",
- "record": true,
- "recordName": "s0.mp4",
- "width": 720,
- "height": 480,
- "bitrate": 1000,
- "minBitrate": 0,
- "maxBitrate": 0,
- "quality": 23,
- "rtmpUrl": "rtmp://example.com:1935/live",
- "parentMediaSessionId": "f1ddc2ce-90e7-40dd-93b7-fff0e4438a60",
- "timeShift": 1000,
- "gop": 60,
- "fps": 30,
- "audioBitrate": 1000,
- "codecImpl": "OPENH264",
- "transport": "UDP",
- "profile": 66,
- "level": 52,
- "preset": "medium",
- "cvoExtension": true,
- "profiles": [
- {
- "width": 1280,
- "height": 720,
- "gop": 60,
- "fps": 30,
- "bitrate": 2500000,
- "codec": "H264",
- "codecImpl": "OPENH264",
- "quality": 23,
- "profile": 66,
- "level": 31,
- "preset": "veryfast",
- "audioGroupId": "audio0"
}
], - "audioProfiles": [
- {
- "bitrate": 64000,
- "codec": "opus",
- "rate": 48000,
- "channels": 2,
- "groupId": "default",
- "wrappedCodec": "opus"
}
], - "createDate": "2026-04-12 10:30:15.123000+00:00",
- "endDate": "2026-04-12 10:35:42.456000+00:00",
- "mediaType": "play",
- "audioState": {
- "muted": true
}, - "videoState": {
- "muted": true
}, - "localMediaInfo": {
- "property1": { },
- "property2": { }
}, - "mediaProvider": "WebRTC"
}{- "custom": {
- "example": 0
}, - "nodeId": "7aoC1Q9IkTCn4zEsNAKvl1P1QMnXfnKE@192.168.100.1",
- "appKey": "defaultApp",
- "sessionId": "/192.168.1.102:13252/192.168.1.101:8443",
- "mediaSessionId": "d1ddc1ce-90e7-40dd-93b7-fff0e4438a60",
- "remoteMediaElementId": "f1ddc2ce-90e7-40dd-93b7-fff0e4438a60",
- "name": "stream1",
- "published": true,
- "hasVideo": true,
- "hasAudio": true,
- "status": "NEW",
- "sdp": "v=0\r\no=- 82374628 2 IN IP4 192.168.100.20\r\ns=-\r\nt=0 0\r\na=group:BUNDLE 0 1\r\na=msid-semantic: WMS\r\nm=audio 49170 RTP/AVP 0\r\nc=IN IP4 192.168.100.20\r\na=rtpmap:0 PCMU/8000\r\na=sendrecv\r\nm=video 51372 RTP/AVP 96\r\nc=IN IP4 192.168.100.20\r\na=rtpmap:96 VP8/90000\r\na=sendrecv\r\n",
- "audioCodec": "opus",
- "videoCodec": "H264",
- "info": "Failed by HLS writer error",
- "description": "Video RTP activity",
- "record": true,
- "recordName": "s0.mp4",
- "width": 720,
- "height": 480,
- "bitrate": 1000,
- "minBitrate": 0,
- "maxBitrate": 0,
- "quality": 23,
- "rtmpUrl": "rtmp://example.com:1935/live",
- "parentMediaSessionId": "f1ddc2ce-90e7-40dd-93b7-fff0e4438a60",
- "timeShift": 1000,
- "gop": 60,
- "fps": 30,
- "audioBitrate": 1000,
- "codecImpl": "OPENH264",
- "transport": "UDP",
- "profile": 66,
- "level": 52,
- "preset": "medium",
- "cvoExtension": true,
- "profiles": [
- {
- "width": 1280,
- "height": 720,
- "gop": 60,
- "fps": 30,
- "bitrate": 2500000,
- "codec": "H264",
- "codecImpl": "OPENH264",
- "quality": 23,
- "profile": 66,
- "level": 31,
- "preset": "veryfast",
- "audioGroupId": "audio0"
}
], - "audioProfiles": [
- {
- "bitrate": 64000,
- "codec": "opus",
- "rate": 48000,
- "channels": 2,
- "groupId": "default",
- "wrappedCodec": "opus"
}
], - "createDate": "2026-04-12 10:30:15.123000+00:00",
- "endDate": "2026-04-12 10:35:42.456000+00:00",
- "mediaType": "play",
- "audioState": {
- "muted": true
}, - "videoState": {
- "muted": true
}, - "localMediaInfo": {
- "property1": { },
- "property2": { }
}, - "mediaProvider": "WebRTC"
}Category only. Groups REST hooks fired on SIP signaling within a specific Connection — calls, transfers, registration, DTMF.
/apps/DefaultApp/call
WCS calls this hook when an outgoing SIP/WebRTC call is initiated. The Backend can authorize the call, override caller/callee fields, or reject it before WCS sends SIP INVITE. The request body contains the call identifiers, parties, and SDP information.
object Custom key-value parameters | |
| nodeId | string Unique identifier of the WCS server instance. Auto-generated as {randomString}@{serverIP} and stored in {WCS_HOME}/conf/node_id |
| appKey | string REST hook application key. Determines the webhook URL for event notifications, as configured in database.yml |
| sessionId | string Signaling session ID (Connection ID). For WebSocket connections the format is /remoteIP:port/localIP:port. Format varies for other connection types |
| origin | string Origin URL of the client page (browser domain) |
| callId | string Unique SIP Call-ID of the call. Format: uuid@host. Sent in the Call-ID header of the SIP INVITE request |
| callUuid | string Unique internal call UUID assigned by server. Also used by iOS CallKit for VoIP calls |
| parentCallId | string Parent SIP Call-ID for transferred or chained calls; format uuid@host |
| incoming | boolean Call direction: true = incoming, false = outgoing |
| status | string Call status. SIP 180 → RING, SIP 183 → SESSION_PROGRESS, SIP 200 → ESTABLISHED. Other values: HOLD (call placed on hold), BUSY (e.g. SIP 486 Busy Here), FINISH (call ended) |
| caller | string Caller (From) peer identifier; value used in SIP From header |
| callee | string Callee (To) peer identifier; value used in SIP To header |
| localAudioCodec | string Audio codec negotiated by WCS on the local side of the SIP session |
| localVideoCodec | string Video codec negotiated by WCS on the local side of the SIP session |
| localWidth | integer <int32> Local video width in pixels |
| localHeight | integer <int32> Local video height in pixels |
| remoteAudioCodec | string Audio codec negotiated by WCS on the remote side of the SIP session |
| remoteVideoCodec | string Video codec negotiated by WCS on the remote side of the SIP session |
| remoteWidth | integer <int32> Remote video width in pixels |
| remoteHeight | integer <int32> Remote video height in pixels |
| createDate | string <date-time> Call creation timestamp in ISO 8601 format |
| endDate | string <date-time> Call end timestamp in ISO 8601 format; null while the call is still active |
| hasAudio | boolean Whether audio media is present |
| hasVideo | boolean Whether video media is present |
| sdp | string SIP SDP offer. Contains the local SDP generated by WCS for this call |
| visibleName | string Caller's display name used in the SIP From header |
object Additional SIP INVITE parameters supplied by the caller (e.g. custom header values forwarded into the INVITE) | |
| mediaProvider | string Deprecated. Always set to Flash for REST API calls |
| sipStatus | integer <int32> Last SIP response status code from the remote endpoint (e.g. 180 Ringing, 183 Session Progress, 200 OK, 486 Busy Here, 408 Request Timeout) |
| rtmpUrl | string RTMP URL of the target server for re-streaming the RTP media received from the SIP endpoint (e.g. rtmp://server:1935/live/stream) |
| rtmpStream | string If provided, this value is appended to rtmpUrl to form the final RTMP publish target. Example: rtmpUrl=rtmp://localhost:1935/live + rtmpStream=test → rtmp://localhost:1935/live/test |
| streamName | string If provided, after the SIP session is established the incoming RTP media will be converted into a server-side internal stream with the specified name. The stream then becomes available for playback and further processing including HLS, transcoding, mixing, etc. |
| rtmpStreamStatus | string Enum: "RTMP_STREAM_WAIT" "RTMP_STREAM_ACTIVE" "RTMP_CONNECTION_FAILED" "RTMP_CONNECTION_LOST" Status of the RTMP re-streaming for this call: RTMP_STREAM_WAIT (SIP call established, waiting for RTMP connection), RTMP_STREAM_ACTIVE (RTMP stream active), RTMP_CONNECTION_FAILED, RTMP_CONNECTION_LOST |
| sipMessageRaw | string Last raw SIP message exchanged in this call (request or response from/to the remote SIP endpoint) |
| target | string SIP target |
| holdForTransfer | boolean Whether the call is on hold specifically for a subsequent transfer (SIP REFER). Regular hold without this flag does not allow transfer |
| sipSDP | Array of strings unique Extra SDP attribute lines forwarded together with the SIP offer/answer (a=... lines outside the main SDP) |
{- "custom": {
- "example": 0
}, - "nodeId": "7aoC1Q9IkTCn4zEsNAKvl1P1QMnXfnKE@192.168.100.1",
- "appKey": "defaultApp",
- "sessionId": "/192.168.1.102:13252/192.168.1.101:8443",
- "callId": "7f8a3c731f6f4f83a9b21c0f9e2c1234@flashphoner.com",
- "callUuid": "4a64e860-c5cd-11f0-b763-ab6a382eac0f",
- "parentCallId": "7f8a3c731f6f4f83a9b21c0f9e2c1234@parent.flashphoner.com",
- "incoming": true,
- "status": "RING",
- "caller": "10001",
- "callee": "10002",
- "localAudioCodec": "opus",
- "localVideoCodec": "H264",
- "localWidth": 720,
- "localHeight": 360,
- "remoteAudioCodec": "opus",
- "remoteVideoCodec": "H264",
- "remoteWidth": 720,
- "remoteHeight": 360,
- "createDate": "2026-04-12 10:30:15.123000+00:00",
- "endDate": "2026-04-12 10:35:42.456000+00:00",
- "hasAudio": true,
- "hasVideo": false,
- "sdp": "v=0\\r\\no=Flashphoner 0 1759480746034...",
- "visibleName": "10001",
- "inviteParameters": {
- "property1": "string",
- "property2": "string"
}, - "mediaProvider": "Flash",
- "sipStatus": 200,
- "rtmpUrl": "rtmp://localhost:1935/live",
- "rtmpStream": "test",
- "streamName": "s0",
- "rtmpStreamStatus": "RTMP_STREAM_WAIT",
- "sipMessageRaw": "INVITE sip:...",
- "target": "sip:alice@example.co...",
- "holdForTransfer": true,
- "sipSDP": [
- "string"
]
}{- "custom": {
- "example": 0
}, - "nodeId": "7aoC1Q9IkTCn4zEsNAKvl1P1QMnXfnKE@192.168.100.1",
- "appKey": "defaultApp",
- "sessionId": "/192.168.1.102:13252/192.168.1.101:8443",
- "callId": "7f8a3c731f6f4f83a9b21c0f9e2c1234@flashphoner.com",
- "callUuid": "4a64e860-c5cd-11f0-b763-ab6a382eac0f",
- "parentCallId": "7f8a3c731f6f4f83a9b21c0f9e2c1234@parent.flashphoner.com",
- "incoming": true,
- "status": "RING",
- "caller": "10001",
- "callee": "10002",
- "localAudioCodec": "opus",
- "localVideoCodec": "H264",
- "localWidth": 720,
- "localHeight": 360,
- "remoteAudioCodec": "opus",
- "remoteVideoCodec": "H264",
- "remoteWidth": 720,
- "remoteHeight": 360,
- "createDate": "2026-04-12 10:30:15.123000+00:00",
- "endDate": "2026-04-12 10:35:42.456000+00:00",
- "hasAudio": true,
- "hasVideo": false,
- "sdp": "v=0\\r\\no=Flashphoner 0 1759480746034...",
- "visibleName": "10001",
- "inviteParameters": {
- "property1": "string",
- "property2": "string"
}, - "mediaProvider": "Flash",
- "sipStatus": 200,
- "rtmpUrl": "rtmp://localhost:1935/live",
- "rtmpStream": "test",
- "streamName": "s0",
- "rtmpStreamStatus": "RTMP_STREAM_WAIT",
- "sipMessageRaw": "INVITE sip:...",
- "target": "sip:alice@example.co...",
- "holdForTransfer": true,
- "sipSDP": [
- "string"
]
}/apps/DefaultApp/answer
WCS calls this hook when an incoming call is answered and a 200 OK with the local SDP is about to be sent to the remote party. The Backend can inspect or override the SDP, or reject the answer. The request body contains the call identifiers and the answer SDP.
object Custom key-value parameters | |
| nodeId | string Unique identifier of the WCS server instance. Auto-generated as {randomString}@{serverIP} and stored in {WCS_HOME}/conf/node_id |
| appKey | string REST hook application key. Determines the webhook URL for event notifications, as configured in database.yml |
| sessionId | string Signaling session ID (Connection ID). For WebSocket connections the format is /remoteIP:port/localIP:port. Format varies for other connection types |
| origin | string Origin URL of the client page (browser domain) |
| callId | string Unique SIP Call-ID of the call. Format: uuid@host. Sent in the Call-ID header of the SIP INVITE request |
| callUuid | string Unique internal call UUID assigned by server. Also used by iOS CallKit for VoIP calls |
| parentCallId | string Parent SIP Call-ID for transferred or chained calls; format uuid@host |
| incoming | boolean Call direction: true = incoming, false = outgoing |
| status | string Call status. SIP 180 → RING, SIP 183 → SESSION_PROGRESS, SIP 200 → ESTABLISHED. Other values: HOLD (call placed on hold), BUSY (e.g. SIP 486 Busy Here), FINISH (call ended) |
| caller | string Caller (From) peer identifier; value used in SIP From header |
| callee | string Callee (To) peer identifier; value used in SIP To header |
| localAudioCodec | string Audio codec negotiated by WCS on the local side of the SIP session |
| localVideoCodec | string Video codec negotiated by WCS on the local side of the SIP session |
| localWidth | integer <int32> Local video width in pixels |
| localHeight | integer <int32> Local video height in pixels |
| remoteAudioCodec | string Audio codec negotiated by WCS on the remote side of the SIP session |
| remoteVideoCodec | string Video codec negotiated by WCS on the remote side of the SIP session |
| remoteWidth | integer <int32> Remote video width in pixels |
| remoteHeight | integer <int32> Remote video height in pixels |
| createDate | string <date-time> Call creation timestamp in ISO 8601 format |
| endDate | string <date-time> Call end timestamp in ISO 8601 format; null while the call is still active |
| hasAudio | boolean Whether audio media is present |
| hasVideo | boolean Whether video media is present |
| sdp | string SIP SDP offer. Contains the local SDP generated by WCS for this call |
| visibleName | string Caller's display name used in the SIP From header |
object Additional SIP INVITE parameters supplied by the caller (e.g. custom header values forwarded into the INVITE) | |
| mediaProvider | string Deprecated. Always set to Flash for REST API calls |
| sipStatus | integer <int32> Last SIP response status code from the remote endpoint (e.g. 180 Ringing, 183 Session Progress, 200 OK, 486 Busy Here, 408 Request Timeout) |
| rtmpUrl | string RTMP URL of the target server for re-streaming the RTP media received from the SIP endpoint (e.g. rtmp://server:1935/live/stream) |
| rtmpStream | string If provided, this value is appended to rtmpUrl to form the final RTMP publish target. Example: rtmpUrl=rtmp://localhost:1935/live + rtmpStream=test → rtmp://localhost:1935/live/test |
| streamName | string If provided, after the SIP session is established the incoming RTP media will be converted into a server-side internal stream with the specified name. The stream then becomes available for playback and further processing including HLS, transcoding, mixing, etc. |
| rtmpStreamStatus | string Enum: "RTMP_STREAM_WAIT" "RTMP_STREAM_ACTIVE" "RTMP_CONNECTION_FAILED" "RTMP_CONNECTION_LOST" Status of the RTMP re-streaming for this call: RTMP_STREAM_WAIT (SIP call established, waiting for RTMP connection), RTMP_STREAM_ACTIVE (RTMP stream active), RTMP_CONNECTION_FAILED, RTMP_CONNECTION_LOST |
| sipMessageRaw | string Last raw SIP message exchanged in this call (request or response from/to the remote SIP endpoint) |
| target | string SIP target |
| holdForTransfer | boolean Whether the call is on hold specifically for a subsequent transfer (SIP REFER). Regular hold without this flag does not allow transfer |
| sipSDP | Array of strings unique Extra SDP attribute lines forwarded together with the SIP offer/answer (a=... lines outside the main SDP) |
{- "custom": {
- "example": 0
}, - "nodeId": "7aoC1Q9IkTCn4zEsNAKvl1P1QMnXfnKE@192.168.100.1",
- "appKey": "defaultApp",
- "sessionId": "/192.168.1.102:13252/192.168.1.101:8443",
- "callId": "7f8a3c731f6f4f83a9b21c0f9e2c1234@flashphoner.com",
- "callUuid": "4a64e860-c5cd-11f0-b763-ab6a382eac0f",
- "parentCallId": "7f8a3c731f6f4f83a9b21c0f9e2c1234@parent.flashphoner.com",
- "incoming": true,
- "status": "RING",
- "caller": "10001",
- "callee": "10002",
- "localAudioCodec": "opus",
- "localVideoCodec": "H264",
- "localWidth": 720,
- "localHeight": 360,
- "remoteAudioCodec": "opus",
- "remoteVideoCodec": "H264",
- "remoteWidth": 720,
- "remoteHeight": 360,
- "createDate": "2026-04-12 10:30:15.123000+00:00",
- "endDate": "2026-04-12 10:35:42.456000+00:00",
- "hasAudio": true,
- "hasVideo": false,
- "sdp": "v=0\\r\\no=Flashphoner 0 1759480746034...",
- "visibleName": "10001",
- "inviteParameters": {
- "property1": "string",
- "property2": "string"
}, - "mediaProvider": "Flash",
- "sipStatus": 200,
- "rtmpUrl": "rtmp://localhost:1935/live",
- "rtmpStream": "test",
- "streamName": "s0",
- "rtmpStreamStatus": "RTMP_STREAM_WAIT",
- "sipMessageRaw": "INVITE sip:...",
- "target": "sip:alice@example.co...",
- "holdForTransfer": true,
- "sipSDP": [
- "string"
]
}{- "custom": {
- "example": 0
}, - "nodeId": "7aoC1Q9IkTCn4zEsNAKvl1P1QMnXfnKE@192.168.100.1",
- "appKey": "defaultApp",
- "sessionId": "/192.168.1.102:13252/192.168.1.101:8443",
- "callId": "7f8a3c731f6f4f83a9b21c0f9e2c1234@flashphoner.com",
- "callUuid": "4a64e860-c5cd-11f0-b763-ab6a382eac0f",
- "parentCallId": "7f8a3c731f6f4f83a9b21c0f9e2c1234@parent.flashphoner.com",
- "incoming": true,
- "status": "RING",
- "caller": "10001",
- "callee": "10002",
- "localAudioCodec": "opus",
- "localVideoCodec": "H264",
- "localWidth": 720,
- "localHeight": 360,
- "remoteAudioCodec": "opus",
- "remoteVideoCodec": "H264",
- "remoteWidth": 720,
- "remoteHeight": 360,
- "createDate": "2026-04-12 10:30:15.123000+00:00",
- "endDate": "2026-04-12 10:35:42.456000+00:00",
- "hasAudio": true,
- "hasVideo": false,
- "sdp": "v=0\\r\\no=Flashphoner 0 1759480746034...",
- "visibleName": "10001",
- "inviteParameters": {
- "property1": "string",
- "property2": "string"
}, - "mediaProvider": "Flash",
- "sipStatus": 200,
- "rtmpUrl": "rtmp://localhost:1935/live",
- "rtmpStream": "test",
- "streamName": "s0",
- "rtmpStreamStatus": "RTMP_STREAM_WAIT",
- "sipMessageRaw": "INVITE sip:...",
- "target": "sip:alice@example.co...",
- "holdForTransfer": true,
- "sipSDP": [
- "string"
]
}/apps/DefaultApp/sendDtmf
WCS calls this hook when a client asks to send a DTMF tone on an active call. The Backend can authorize the tone, override the DTMF transport (RFC2833/INFO), or reject the request. The request body contains the call identifiers, the digit, and the transport type.
object Custom key-value parameters | |
| nodeId | string Unique identifier of the WCS server instance. Auto-generated as {randomString}@{serverIP} and stored in {WCS_HOME}/conf/node_id |
| appKey | string REST hook application key. Determines the webhook URL for event notifications, as configured in database.yml |
| sessionId | string Signaling session ID (Connection ID). For WebSocket connections the format is /remoteIP:port/localIP:port. Format varies for other connection types |
| origin | string Origin URL of the client page (browser domain) |
| callId | string Unique SIP Call-ID of the active call |
| dtmf | string DTMF digit to send (e.g. 0-9, *, #) |
| type | string Enum: "INFO" "INFO_RELAY" "RFC2833" DTMF transmission method |
{- "custom": {
- "example": 0
}, - "nodeId": "7aoC1Q9IkTCn4zEsNAKvl1P1QMnXfnKE@192.168.100.1",
- "appKey": "defaultApp",
- "sessionId": "/192.168.1.102:13252/192.168.1.101:8443",
- "callId": "6d62f660",
- "dtmf": "9",
- "type": "INFO"
}{- "custom": {
- "example": 0
}, - "nodeId": "7aoC1Q9IkTCn4zEsNAKvl1P1QMnXfnKE@192.168.100.1",
- "appKey": "defaultApp",
- "sessionId": "/192.168.1.102:13252/192.168.1.101:8443",
- "callId": "6d62f660",
- "dtmf": "9",
- "type": "INFO"
}/apps/DefaultApp/hold
WCS calls this hook when a client asks to place an active call on hold and before WCS sends the SIP re-INVITE. The request body contains the held call identifiers, parties, and media details.
object Custom key-value parameters | |
| nodeId | string Unique identifier of the WCS server instance. Auto-generated as {randomString}@{serverIP} and stored in {WCS_HOME}/conf/node_id |
| appKey | string REST hook application key. Determines the webhook URL for event notifications, as configured in database.yml |
| sessionId | string Signaling session ID (Connection ID). For WebSocket connections the format is /remoteIP:port/localIP:port. Format varies for other connection types |
| origin | string Origin URL of the client page (browser domain) |
| callId | string Unique SIP Call-ID of the call. Format: uuid@host. Sent in the Call-ID header of the SIP INVITE request |
| callUuid | string Unique internal call UUID assigned by server. Also used by iOS CallKit for VoIP calls |
| parentCallId | string Parent SIP Call-ID for transferred or chained calls; format uuid@host |
| incoming | boolean Call direction: true = incoming, false = outgoing |
| status | string Call status. SIP 180 → RING, SIP 183 → SESSION_PROGRESS, SIP 200 → ESTABLISHED. Other values: HOLD (call placed on hold), BUSY (e.g. SIP 486 Busy Here), FINISH (call ended) |
| caller | string Caller (From) peer identifier; value used in SIP From header |
| callee | string Callee (To) peer identifier; value used in SIP To header |
| localAudioCodec | string Audio codec negotiated by WCS on the local side of the SIP session |
| localVideoCodec | string Video codec negotiated by WCS on the local side of the SIP session |
| localWidth | integer <int32> Local video width in pixels |
| localHeight | integer <int32> Local video height in pixels |
| remoteAudioCodec | string Audio codec negotiated by WCS on the remote side of the SIP session |
| remoteVideoCodec | string Video codec negotiated by WCS on the remote side of the SIP session |
| remoteWidth | integer <int32> Remote video width in pixels |
| remoteHeight | integer <int32> Remote video height in pixels |
| createDate | string <date-time> Call creation timestamp in ISO 8601 format |
| endDate | string <date-time> Call end timestamp in ISO 8601 format; null while the call is still active |
| hasAudio | boolean Whether audio media is present |
| hasVideo | boolean Whether video media is present |
| sdp | string SIP SDP offer. Contains the local SDP generated by WCS for this call |
| visibleName | string Caller's display name used in the SIP From header |
object Additional SIP INVITE parameters supplied by the caller (e.g. custom header values forwarded into the INVITE) | |
| mediaProvider | string Deprecated. Always set to Flash for REST API calls |
| sipStatus | integer <int32> Last SIP response status code from the remote endpoint (e.g. 180 Ringing, 183 Session Progress, 200 OK, 486 Busy Here, 408 Request Timeout) |
| rtmpUrl | string RTMP URL of the target server for re-streaming the RTP media received from the SIP endpoint (e.g. rtmp://server:1935/live/stream) |
| rtmpStream | string If provided, this value is appended to rtmpUrl to form the final RTMP publish target. Example: rtmpUrl=rtmp://localhost:1935/live + rtmpStream=test → rtmp://localhost:1935/live/test |
| streamName | string If provided, after the SIP session is established the incoming RTP media will be converted into a server-side internal stream with the specified name. The stream then becomes available for playback and further processing including HLS, transcoding, mixing, etc. |
| rtmpStreamStatus | string Enum: "RTMP_STREAM_WAIT" "RTMP_STREAM_ACTIVE" "RTMP_CONNECTION_FAILED" "RTMP_CONNECTION_LOST" Status of the RTMP re-streaming for this call: RTMP_STREAM_WAIT (SIP call established, waiting for RTMP connection), RTMP_STREAM_ACTIVE (RTMP stream active), RTMP_CONNECTION_FAILED, RTMP_CONNECTION_LOST |
| sipMessageRaw | string Last raw SIP message exchanged in this call (request or response from/to the remote SIP endpoint) |
| target | string SIP target |
| holdForTransfer | boolean Whether the call is on hold specifically for a subsequent transfer (SIP REFER). Regular hold without this flag does not allow transfer |
| sipSDP | Array of strings unique Extra SDP attribute lines forwarded together with the SIP offer/answer (a=... lines outside the main SDP) |
{- "custom": {
- "example": 0
}, - "nodeId": "7aoC1Q9IkTCn4zEsNAKvl1P1QMnXfnKE@192.168.100.1",
- "appKey": "defaultApp",
- "sessionId": "/192.168.1.102:13252/192.168.1.101:8443",
- "callId": "7f8a3c731f6f4f83a9b21c0f9e2c1234@flashphoner.com",
- "callUuid": "4a64e860-c5cd-11f0-b763-ab6a382eac0f",
- "parentCallId": "7f8a3c731f6f4f83a9b21c0f9e2c1234@parent.flashphoner.com",
- "incoming": true,
- "status": "RING",
- "caller": "10001",
- "callee": "10002",
- "localAudioCodec": "opus",
- "localVideoCodec": "H264",
- "localWidth": 720,
- "localHeight": 360,
- "remoteAudioCodec": "opus",
- "remoteVideoCodec": "H264",
- "remoteWidth": 720,
- "remoteHeight": 360,
- "createDate": "2026-04-12 10:30:15.123000+00:00",
- "endDate": "2026-04-12 10:35:42.456000+00:00",
- "hasAudio": true,
- "hasVideo": false,
- "sdp": "v=0\\r\\no=Flashphoner 0 1759480746034...",
- "visibleName": "10001",
- "inviteParameters": {
- "property1": "string",
- "property2": "string"
}, - "mediaProvider": "Flash",
- "sipStatus": 200,
- "rtmpUrl": "rtmp://localhost:1935/live",
- "rtmpStream": "test",
- "streamName": "s0",
- "rtmpStreamStatus": "RTMP_STREAM_WAIT",
- "sipMessageRaw": "INVITE sip:...",
- "target": "sip:alice@example.co...",
- "holdForTransfer": true,
- "sipSDP": [
- "string"
]
}{- "custom": {
- "example": 0
}, - "nodeId": "7aoC1Q9IkTCn4zEsNAKvl1P1QMnXfnKE@192.168.100.1",
- "appKey": "defaultApp",
- "sessionId": "/192.168.1.102:13252/192.168.1.101:8443",
- "callId": "7f8a3c731f6f4f83a9b21c0f9e2c1234@flashphoner.com",
- "callUuid": "4a64e860-c5cd-11f0-b763-ab6a382eac0f",
- "parentCallId": "7f8a3c731f6f4f83a9b21c0f9e2c1234@parent.flashphoner.com",
- "incoming": true,
- "status": "RING",
- "caller": "10001",
- "callee": "10002",
- "localAudioCodec": "opus",
- "localVideoCodec": "H264",
- "localWidth": 720,
- "localHeight": 360,
- "remoteAudioCodec": "opus",
- "remoteVideoCodec": "H264",
- "remoteWidth": 720,
- "remoteHeight": 360,
- "createDate": "2026-04-12 10:30:15.123000+00:00",
- "endDate": "2026-04-12 10:35:42.456000+00:00",
- "hasAudio": true,
- "hasVideo": false,
- "sdp": "v=0\\r\\no=Flashphoner 0 1759480746034...",
- "visibleName": "10001",
- "inviteParameters": {
- "property1": "string",
- "property2": "string"
}, - "mediaProvider": "Flash",
- "sipStatus": 200,
- "rtmpUrl": "rtmp://localhost:1935/live",
- "rtmpStream": "test",
- "streamName": "s0",
- "rtmpStreamStatus": "RTMP_STREAM_WAIT",
- "sipMessageRaw": "INVITE sip:...",
- "target": "sip:alice@example.co...",
- "holdForTransfer": true,
- "sipSDP": [
- "string"
]
}/apps/DefaultApp/unhold
WCS calls this hook when a client asks to resume a held call and before WCS sends the SIP re-INVITE. The request body contains the resumed call identifiers, parties, and media details.
object Custom key-value parameters | |
| nodeId | string Unique identifier of the WCS server instance. Auto-generated as {randomString}@{serverIP} and stored in {WCS_HOME}/conf/node_id |
| appKey | string REST hook application key. Determines the webhook URL for event notifications, as configured in database.yml |
| sessionId | string Signaling session ID (Connection ID). For WebSocket connections the format is /remoteIP:port/localIP:port. Format varies for other connection types |
| origin | string Origin URL of the client page (browser domain) |
| callId | string Unique SIP Call-ID of the call. Format: uuid@host. Sent in the Call-ID header of the SIP INVITE request |
| callUuid | string Unique internal call UUID assigned by server. Also used by iOS CallKit for VoIP calls |
| parentCallId | string Parent SIP Call-ID for transferred or chained calls; format uuid@host |
| incoming | boolean Call direction: true = incoming, false = outgoing |
| status | string Call status. SIP 180 → RING, SIP 183 → SESSION_PROGRESS, SIP 200 → ESTABLISHED. Other values: HOLD (call placed on hold), BUSY (e.g. SIP 486 Busy Here), FINISH (call ended) |
| caller | string Caller (From) peer identifier; value used in SIP From header |
| callee | string Callee (To) peer identifier; value used in SIP To header |
| localAudioCodec | string Audio codec negotiated by WCS on the local side of the SIP session |
| localVideoCodec | string Video codec negotiated by WCS on the local side of the SIP session |
| localWidth | integer <int32> Local video width in pixels |
| localHeight | integer <int32> Local video height in pixels |
| remoteAudioCodec | string Audio codec negotiated by WCS on the remote side of the SIP session |
| remoteVideoCodec | string Video codec negotiated by WCS on the remote side of the SIP session |
| remoteWidth | integer <int32> Remote video width in pixels |
| remoteHeight | integer <int32> Remote video height in pixels |
| createDate | string <date-time> Call creation timestamp in ISO 8601 format |
| endDate | string <date-time> Call end timestamp in ISO 8601 format; null while the call is still active |
| hasAudio | boolean Whether audio media is present |
| hasVideo | boolean Whether video media is present |
| sdp | string SIP SDP offer. Contains the local SDP generated by WCS for this call |
| visibleName | string Caller's display name used in the SIP From header |
object Additional SIP INVITE parameters supplied by the caller (e.g. custom header values forwarded into the INVITE) | |
| mediaProvider | string Deprecated. Always set to Flash for REST API calls |
| sipStatus | integer <int32> Last SIP response status code from the remote endpoint (e.g. 180 Ringing, 183 Session Progress, 200 OK, 486 Busy Here, 408 Request Timeout) |
| rtmpUrl | string RTMP URL of the target server for re-streaming the RTP media received from the SIP endpoint (e.g. rtmp://server:1935/live/stream) |
| rtmpStream | string If provided, this value is appended to rtmpUrl to form the final RTMP publish target. Example: rtmpUrl=rtmp://localhost:1935/live + rtmpStream=test → rtmp://localhost:1935/live/test |
| streamName | string If provided, after the SIP session is established the incoming RTP media will be converted into a server-side internal stream with the specified name. The stream then becomes available for playback and further processing including HLS, transcoding, mixing, etc. |
| rtmpStreamStatus | string Enum: "RTMP_STREAM_WAIT" "RTMP_STREAM_ACTIVE" "RTMP_CONNECTION_FAILED" "RTMP_CONNECTION_LOST" Status of the RTMP re-streaming for this call: RTMP_STREAM_WAIT (SIP call established, waiting for RTMP connection), RTMP_STREAM_ACTIVE (RTMP stream active), RTMP_CONNECTION_FAILED, RTMP_CONNECTION_LOST |
| sipMessageRaw | string Last raw SIP message exchanged in this call (request or response from/to the remote SIP endpoint) |
| target | string SIP target |
| holdForTransfer | boolean Whether the call is on hold specifically for a subsequent transfer (SIP REFER). Regular hold without this flag does not allow transfer |
| sipSDP | Array of strings unique Extra SDP attribute lines forwarded together with the SIP offer/answer (a=... lines outside the main SDP) |
{- "custom": {
- "example": 0
}, - "nodeId": "7aoC1Q9IkTCn4zEsNAKvl1P1QMnXfnKE@192.168.100.1",
- "appKey": "defaultApp",
- "sessionId": "/192.168.1.102:13252/192.168.1.101:8443",
- "callId": "7f8a3c731f6f4f83a9b21c0f9e2c1234@flashphoner.com",
- "callUuid": "4a64e860-c5cd-11f0-b763-ab6a382eac0f",
- "parentCallId": "7f8a3c731f6f4f83a9b21c0f9e2c1234@parent.flashphoner.com",
- "incoming": true,
- "status": "RING",
- "caller": "10001",
- "callee": "10002",
- "localAudioCodec": "opus",
- "localVideoCodec": "H264",
- "localWidth": 720,
- "localHeight": 360,
- "remoteAudioCodec": "opus",
- "remoteVideoCodec": "H264",
- "remoteWidth": 720,
- "remoteHeight": 360,
- "createDate": "2026-04-12 10:30:15.123000+00:00",
- "endDate": "2026-04-12 10:35:42.456000+00:00",
- "hasAudio": true,
- "hasVideo": false,
- "sdp": "v=0\\r\\no=Flashphoner 0 1759480746034...",
- "visibleName": "10001",
- "inviteParameters": {
- "property1": "string",
- "property2": "string"
}, - "mediaProvider": "Flash",
- "sipStatus": 200,
- "rtmpUrl": "rtmp://localhost:1935/live",
- "rtmpStream": "test",
- "streamName": "s0",
- "rtmpStreamStatus": "RTMP_STREAM_WAIT",
- "sipMessageRaw": "INVITE sip:...",
- "target": "sip:alice@example.co...",
- "holdForTransfer": true,
- "sipSDP": [
- "string"
]
}{- "custom": {
- "example": 0
}, - "nodeId": "7aoC1Q9IkTCn4zEsNAKvl1P1QMnXfnKE@192.168.100.1",
- "appKey": "defaultApp",
- "sessionId": "/192.168.1.102:13252/192.168.1.101:8443",
- "callId": "7f8a3c731f6f4f83a9b21c0f9e2c1234@flashphoner.com",
- "callUuid": "4a64e860-c5cd-11f0-b763-ab6a382eac0f",
- "parentCallId": "7f8a3c731f6f4f83a9b21c0f9e2c1234@parent.flashphoner.com",
- "incoming": true,
- "status": "RING",
- "caller": "10001",
- "callee": "10002",
- "localAudioCodec": "opus",
- "localVideoCodec": "H264",
- "localWidth": 720,
- "localHeight": 360,
- "remoteAudioCodec": "opus",
- "remoteVideoCodec": "H264",
- "remoteWidth": 720,
- "remoteHeight": 360,
- "createDate": "2026-04-12 10:30:15.123000+00:00",
- "endDate": "2026-04-12 10:35:42.456000+00:00",
- "hasAudio": true,
- "hasVideo": false,
- "sdp": "v=0\\r\\no=Flashphoner 0 1759480746034...",
- "visibleName": "10001",
- "inviteParameters": {
- "property1": "string",
- "property2": "string"
}, - "mediaProvider": "Flash",
- "sipStatus": 200,
- "rtmpUrl": "rtmp://localhost:1935/live",
- "rtmpStream": "test",
- "streamName": "s0",
- "rtmpStreamStatus": "RTMP_STREAM_WAIT",
- "sipMessageRaw": "INVITE sip:...",
- "target": "sip:alice@example.co...",
- "holdForTransfer": true,
- "sipSDP": [
- "string"
]
}/apps/DefaultApp/transfer
WCS calls this hook when a client initiates a call transfer (blind or attended) and a SIP REFER is about to be sent. The Backend can authorize the transfer, override transfer targets, or reject it. The request body contains the source call identifiers and the target party.
object Custom key-value parameters | |
| nodeId | string Unique identifier of the WCS server instance. Auto-generated as {randomString}@{serverIP} and stored in {WCS_HOME}/conf/node_id |
| appKey | string REST hook application key. Determines the webhook URL for event notifications, as configured in database.yml |
| sessionId | string Signaling session ID (Connection ID). For WebSocket connections the format is /remoteIP:port/localIP:port. Format varies for other connection types |
| origin | string Origin URL of the client page (browser domain) |
| callId | string Call-ID identifier in uuid@host format |
| target | string Target Call-ID identifier in uuid@host format |
{- "custom": {
- "example": 0
}, - "nodeId": "7aoC1Q9IkTCn4zEsNAKvl1P1QMnXfnKE@192.168.100.1",
- "appKey": "defaultApp",
- "sessionId": "/192.168.1.102:13252/192.168.1.101:8443",
- "callId": "7f8a3c731f6f4f83a9b21c0f9e2c1234@flashphoner.com",
- "target": "7f8a3c731f6f4f83a9b21c0f9e2c1234@flashphoner.com"
}{- "custom": {
- "example": 0
}, - "nodeId": "7aoC1Q9IkTCn4zEsNAKvl1P1QMnXfnKE@192.168.100.1",
- "appKey": "defaultApp",
- "sessionId": "/192.168.1.102:13252/192.168.1.101:8443",
- "callId": "7f8a3c731f6f4f83a9b21c0f9e2c1234@flashphoner.com",
- "target": "7f8a3c731f6f4f83a9b21c0f9e2c1234@flashphoner.com"
}/apps/DefaultApp/hangup
WCS calls this hook when a client asks to terminate an active call and before WCS sends the SIP BYE or CANCEL to the remote party. The request body contains the call identifiers and termination context.
object Custom key-value parameters | |
| nodeId | string Unique identifier of the WCS server instance. Auto-generated as {randomString}@{serverIP} and stored in {WCS_HOME}/conf/node_id |
| appKey | string REST hook application key. Determines the webhook URL for event notifications, as configured in database.yml |
| sessionId | string Signaling session ID (Connection ID). For WebSocket connections the format is /remoteIP:port/localIP:port. Format varies for other connection types |
| origin | string Origin URL of the client page (browser domain) |
| callId | string Unique SIP Call-ID of the call. Format: uuid@host. Sent in the Call-ID header of the SIP INVITE request |
| callUuid | string Unique internal call UUID assigned by server. Also used by iOS CallKit for VoIP calls |
| parentCallId | string Parent SIP Call-ID for transferred or chained calls; format uuid@host |
| incoming | boolean Call direction: true = incoming, false = outgoing |
| status | string Call status. SIP 180 → RING, SIP 183 → SESSION_PROGRESS, SIP 200 → ESTABLISHED. Other values: HOLD (call placed on hold), BUSY (e.g. SIP 486 Busy Here), FINISH (call ended) |
| caller | string Caller (From) peer identifier; value used in SIP From header |
| callee | string Callee (To) peer identifier; value used in SIP To header |
| localAudioCodec | string Audio codec negotiated by WCS on the local side of the SIP session |
| localVideoCodec | string Video codec negotiated by WCS on the local side of the SIP session |
| localWidth | integer <int32> Local video width in pixels |
| localHeight | integer <int32> Local video height in pixels |
| remoteAudioCodec | string Audio codec negotiated by WCS on the remote side of the SIP session |
| remoteVideoCodec | string Video codec negotiated by WCS on the remote side of the SIP session |
| remoteWidth | integer <int32> Remote video width in pixels |
| remoteHeight | integer <int32> Remote video height in pixels |
| createDate | string <date-time> Call creation timestamp in ISO 8601 format |
| endDate | string <date-time> Call end timestamp in ISO 8601 format; null while the call is still active |
| hasAudio | boolean Whether audio media is present |
| hasVideo | boolean Whether video media is present |
| sdp | string SIP SDP offer. Contains the local SDP generated by WCS for this call |
| visibleName | string Caller's display name used in the SIP From header |
object Additional SIP INVITE parameters supplied by the caller (e.g. custom header values forwarded into the INVITE) | |
| mediaProvider | string Deprecated. Always set to Flash for REST API calls |
| sipStatus | integer <int32> Last SIP response status code from the remote endpoint (e.g. 180 Ringing, 183 Session Progress, 200 OK, 486 Busy Here, 408 Request Timeout) |
| rtmpUrl | string RTMP URL of the target server for re-streaming the RTP media received from the SIP endpoint (e.g. rtmp://server:1935/live/stream) |
| rtmpStream | string If provided, this value is appended to rtmpUrl to form the final RTMP publish target. Example: rtmpUrl=rtmp://localhost:1935/live + rtmpStream=test → rtmp://localhost:1935/live/test |
| streamName | string If provided, after the SIP session is established the incoming RTP media will be converted into a server-side internal stream with the specified name. The stream then becomes available for playback and further processing including HLS, transcoding, mixing, etc. |
| rtmpStreamStatus | string Enum: "RTMP_STREAM_WAIT" "RTMP_STREAM_ACTIVE" "RTMP_CONNECTION_FAILED" "RTMP_CONNECTION_LOST" Status of the RTMP re-streaming for this call: RTMP_STREAM_WAIT (SIP call established, waiting for RTMP connection), RTMP_STREAM_ACTIVE (RTMP stream active), RTMP_CONNECTION_FAILED, RTMP_CONNECTION_LOST |
| sipMessageRaw | string Last raw SIP message exchanged in this call (request or response from/to the remote SIP endpoint) |
| target | string SIP target |
| holdForTransfer | boolean Whether the call is on hold specifically for a subsequent transfer (SIP REFER). Regular hold without this flag does not allow transfer |
| sipSDP | Array of strings unique Extra SDP attribute lines forwarded together with the SIP offer/answer (a=... lines outside the main SDP) |
{- "custom": {
- "example": 0
}, - "nodeId": "7aoC1Q9IkTCn4zEsNAKvl1P1QMnXfnKE@192.168.100.1",
- "appKey": "defaultApp",
- "sessionId": "/192.168.1.102:13252/192.168.1.101:8443",
- "callId": "7f8a3c731f6f4f83a9b21c0f9e2c1234@flashphoner.com",
- "callUuid": "4a64e860-c5cd-11f0-b763-ab6a382eac0f",
- "parentCallId": "7f8a3c731f6f4f83a9b21c0f9e2c1234@parent.flashphoner.com",
- "incoming": true,
- "status": "RING",
- "caller": "10001",
- "callee": "10002",
- "localAudioCodec": "opus",
- "localVideoCodec": "H264",
- "localWidth": 720,
- "localHeight": 360,
- "remoteAudioCodec": "opus",
- "remoteVideoCodec": "H264",
- "remoteWidth": 720,
- "remoteHeight": 360,
- "createDate": "2026-04-12 10:30:15.123000+00:00",
- "endDate": "2026-04-12 10:35:42.456000+00:00",
- "hasAudio": true,
- "hasVideo": false,
- "sdp": "v=0\\r\\no=Flashphoner 0 1759480746034...",
- "visibleName": "10001",
- "inviteParameters": {
- "property1": "string",
- "property2": "string"
}, - "mediaProvider": "Flash",
- "sipStatus": 200,
- "rtmpUrl": "rtmp://localhost:1935/live",
- "rtmpStream": "test",
- "streamName": "s0",
- "rtmpStreamStatus": "RTMP_STREAM_WAIT",
- "sipMessageRaw": "INVITE sip:...",
- "target": "sip:alice@example.co...",
- "holdForTransfer": true,
- "sipSDP": [
- "string"
]
}{- "custom": {
- "example": 0
}, - "nodeId": "7aoC1Q9IkTCn4zEsNAKvl1P1QMnXfnKE@192.168.100.1",
- "appKey": "defaultApp",
- "sessionId": "/192.168.1.102:13252/192.168.1.101:8443",
- "callId": "7f8a3c731f6f4f83a9b21c0f9e2c1234@flashphoner.com",
- "callUuid": "4a64e860-c5cd-11f0-b763-ab6a382eac0f",
- "parentCallId": "7f8a3c731f6f4f83a9b21c0f9e2c1234@parent.flashphoner.com",
- "incoming": true,
- "status": "RING",
- "caller": "10001",
- "callee": "10002",
- "localAudioCodec": "opus",
- "localVideoCodec": "H264",
- "localWidth": 720,
- "localHeight": 360,
- "remoteAudioCodec": "opus",
- "remoteVideoCodec": "H264",
- "remoteWidth": 720,
- "remoteHeight": 360,
- "createDate": "2026-04-12 10:30:15.123000+00:00",
- "endDate": "2026-04-12 10:35:42.456000+00:00",
- "hasAudio": true,
- "hasVideo": false,
- "sdp": "v=0\\r\\no=Flashphoner 0 1759480746034...",
- "visibleName": "10001",
- "inviteParameters": {
- "property1": "string",
- "property2": "string"
}, - "mediaProvider": "Flash",
- "sipStatus": 200,
- "rtmpUrl": "rtmp://localhost:1935/live",
- "rtmpStream": "test",
- "streamName": "s0",
- "rtmpStreamStatus": "RTMP_STREAM_WAIT",
- "sipMessageRaw": "INVITE sip:...",
- "target": "sip:alice@example.co...",
- "holdForTransfer": true,
- "sipSDP": [
- "string"
]
}/apps/DefaultApp/OnCallEvent
WCS calls this hook when an incoming SIP INVITE is received for a registered client and before the incoming call notification is delivered to the client. The request body contains the incoming call details: caller, callee, and SDP. Returned fields may be used in the client notification.
object Custom key-value parameters | |
| nodeId | string Unique identifier of the WCS server instance. Auto-generated as {randomString}@{serverIP} and stored in {WCS_HOME}/conf/node_id |
| appKey | string REST hook application key. Determines the webhook URL for event notifications, as configured in database.yml |
| sessionId | string Signaling session ID (Connection ID). For WebSocket connections the format is /remoteIP:port/localIP:port. Format varies for other connection types |
| origin | string Origin URL of the client page (browser domain) |
| callId | string Unique SIP Call-ID of the call. Format: uuid@host. Sent in the Call-ID header of the SIP INVITE request |
| callUuid | string Unique internal call UUID assigned by server. Also used by iOS CallKit for VoIP calls |
| parentCallId | string Parent SIP Call-ID for transferred or chained calls; format uuid@host |
| incoming | boolean Call direction: true = incoming, false = outgoing |
| status | string Call status. SIP 180 → RING, SIP 183 → SESSION_PROGRESS, SIP 200 → ESTABLISHED. Other values: HOLD (call placed on hold), BUSY (e.g. SIP 486 Busy Here), FINISH (call ended) |
| caller | string Caller (From) peer identifier; value used in SIP From header |
| callee | string Callee (To) peer identifier; value used in SIP To header |
| localAudioCodec | string Audio codec negotiated by WCS on the local side of the SIP session |
| localVideoCodec | string Video codec negotiated by WCS on the local side of the SIP session |
| localWidth | integer <int32> Local video width in pixels |
| localHeight | integer <int32> Local video height in pixels |
| remoteAudioCodec | string Audio codec negotiated by WCS on the remote side of the SIP session |
| remoteVideoCodec | string Video codec negotiated by WCS on the remote side of the SIP session |
| remoteWidth | integer <int32> Remote video width in pixels |
| remoteHeight | integer <int32> Remote video height in pixels |
| createDate | string <date-time> Call creation timestamp in ISO 8601 format |
| endDate | string <date-time> Call end timestamp in ISO 8601 format; null while the call is still active |
| hasAudio | boolean Whether audio media is present |
| hasVideo | boolean Whether video media is present |
| sdp | string SIP SDP offer. Contains the local SDP generated by WCS for this call |
| visibleName | string Caller's display name used in the SIP From header |
object Additional SIP INVITE parameters supplied by the caller (e.g. custom header values forwarded into the INVITE) | |
| mediaProvider | string Deprecated. Always set to Flash for REST API calls |
| sipStatus | integer <int32> Last SIP response status code from the remote endpoint (e.g. 180 Ringing, 183 Session Progress, 200 OK, 486 Busy Here, 408 Request Timeout) |
| rtmpUrl | string RTMP URL of the target server for re-streaming the RTP media received from the SIP endpoint (e.g. rtmp://server:1935/live/stream) |
| rtmpStream | string If provided, this value is appended to rtmpUrl to form the final RTMP publish target. Example: rtmpUrl=rtmp://localhost:1935/live + rtmpStream=test → rtmp://localhost:1935/live/test |
| streamName | string If provided, after the SIP session is established the incoming RTP media will be converted into a server-side internal stream with the specified name. The stream then becomes available for playback and further processing including HLS, transcoding, mixing, etc. |
| rtmpStreamStatus | string Enum: "RTMP_STREAM_WAIT" "RTMP_STREAM_ACTIVE" "RTMP_CONNECTION_FAILED" "RTMP_CONNECTION_LOST" Status of the RTMP re-streaming for this call: RTMP_STREAM_WAIT (SIP call established, waiting for RTMP connection), RTMP_STREAM_ACTIVE (RTMP stream active), RTMP_CONNECTION_FAILED, RTMP_CONNECTION_LOST |
| sipMessageRaw | string Last raw SIP message exchanged in this call (request or response from/to the remote SIP endpoint) |
| target | string SIP target |
| holdForTransfer | boolean Whether the call is on hold specifically for a subsequent transfer (SIP REFER). Regular hold without this flag does not allow transfer |
| sipSDP | Array of strings unique Extra SDP attribute lines forwarded together with the SIP offer/answer (a=... lines outside the main SDP) |
{- "custom": {
- "example": 0
}, - "nodeId": "7aoC1Q9IkTCn4zEsNAKvl1P1QMnXfnKE@192.168.100.1",
- "appKey": "defaultApp",
- "sessionId": "/192.168.1.102:13252/192.168.1.101:8443",
- "callId": "7f8a3c731f6f4f83a9b21c0f9e2c1234@flashphoner.com",
- "callUuid": "4a64e860-c5cd-11f0-b763-ab6a382eac0f",
- "parentCallId": "7f8a3c731f6f4f83a9b21c0f9e2c1234@parent.flashphoner.com",
- "incoming": true,
- "status": "RING",
- "caller": "10001",
- "callee": "10002",
- "localAudioCodec": "opus",
- "localVideoCodec": "H264",
- "localWidth": 720,
- "localHeight": 360,
- "remoteAudioCodec": "opus",
- "remoteVideoCodec": "H264",
- "remoteWidth": 720,
- "remoteHeight": 360,
- "createDate": "2026-04-12 10:30:15.123000+00:00",
- "endDate": "2026-04-12 10:35:42.456000+00:00",
- "hasAudio": true,
- "hasVideo": false,
- "sdp": "v=0\\r\\no=Flashphoner 0 1759480746034...",
- "visibleName": "10001",
- "inviteParameters": {
- "property1": "string",
- "property2": "string"
}, - "mediaProvider": "Flash",
- "sipStatus": 200,
- "rtmpUrl": "rtmp://localhost:1935/live",
- "rtmpStream": "test",
- "streamName": "s0",
- "rtmpStreamStatus": "RTMP_STREAM_WAIT",
- "sipMessageRaw": "INVITE sip:...",
- "target": "sip:alice@example.co...",
- "holdForTransfer": true,
- "sipSDP": [
- "string"
]
}{- "custom": {
- "example": 0
}, - "nodeId": "7aoC1Q9IkTCn4zEsNAKvl1P1QMnXfnKE@192.168.100.1",
- "appKey": "defaultApp",
- "sessionId": "/192.168.1.102:13252/192.168.1.101:8443",
- "callId": "7f8a3c731f6f4f83a9b21c0f9e2c1234@flashphoner.com",
- "callUuid": "4a64e860-c5cd-11f0-b763-ab6a382eac0f",
- "parentCallId": "7f8a3c731f6f4f83a9b21c0f9e2c1234@parent.flashphoner.com",
- "incoming": true,
- "status": "RING",
- "caller": "10001",
- "callee": "10002",
- "localAudioCodec": "opus",
- "localVideoCodec": "H264",
- "localWidth": 720,
- "localHeight": 360,
- "remoteAudioCodec": "opus",
- "remoteVideoCodec": "H264",
- "remoteWidth": 720,
- "remoteHeight": 360,
- "createDate": "2026-04-12 10:30:15.123000+00:00",
- "endDate": "2026-04-12 10:35:42.456000+00:00",
- "hasAudio": true,
- "hasVideo": false,
- "sdp": "v=0\\r\\no=Flashphoner 0 1759480746034...",
- "visibleName": "10001",
- "inviteParameters": {
- "property1": "string",
- "property2": "string"
}, - "mediaProvider": "Flash",
- "sipStatus": 200,
- "rtmpUrl": "rtmp://localhost:1935/live",
- "rtmpStream": "test",
- "streamName": "s0",
- "rtmpStreamStatus": "RTMP_STREAM_WAIT",
- "sipMessageRaw": "INVITE sip:...",
- "target": "sip:alice@example.co...",
- "holdForTransfer": true,
- "sipSDP": [
- "string"
]
}/apps/DefaultApp/OnTransferEvent
WCS calls this hook when an incoming SIP REFER is received on an active call and before the transfer request is delivered to the client. The request body contains the transfer parameters and the original call identifiers. Returned fields may be used in the client notification.
object Custom key-value parameters | |
| nodeId | string Unique identifier of the WCS server instance. Auto-generated as {randomString}@{serverIP} and stored in {WCS_HOME}/conf/node_id |
| appKey | string REST hook application key. Determines the webhook URL for event notifications, as configured in database.yml |
| sessionId | string Signaling session ID (Connection ID). For WebSocket connections the format is /remoteIP:port/localIP:port. Format varies for other connection types |
| origin | string Origin URL of the client page (browser domain) |
| callId | string Unique SIP Call-ID of the call. Format: uuid@host. Sent in the Call-ID header of the SIP INVITE request |
| callUuid | string Unique internal call UUID assigned by server. Also used by iOS CallKit for VoIP calls |
| parentCallId | string Parent SIP Call-ID for transferred or chained calls; format uuid@host |
| incoming | boolean Call direction: true = incoming, false = outgoing |
| status | string Call status. SIP 180 → RING, SIP 183 → SESSION_PROGRESS, SIP 200 → ESTABLISHED. Other values: HOLD (call placed on hold), BUSY (e.g. SIP 486 Busy Here), FINISH (call ended) |
| caller | string Caller (From) peer identifier; value used in SIP From header |
| callee | string Callee (To) peer identifier; value used in SIP To header |
| localAudioCodec | string Audio codec negotiated by WCS on the local side of the SIP session |
| localVideoCodec | string Video codec negotiated by WCS on the local side of the SIP session |
| localWidth | integer <int32> Local video width in pixels |
| localHeight | integer <int32> Local video height in pixels |
| remoteAudioCodec | string Audio codec negotiated by WCS on the remote side of the SIP session |
| remoteVideoCodec | string Video codec negotiated by WCS on the remote side of the SIP session |
| remoteWidth | integer <int32> Remote video width in pixels |
| remoteHeight | integer <int32> Remote video height in pixels |
| createDate | string <date-time> Call creation timestamp in ISO 8601 format |
| endDate | string <date-time> Call end timestamp in ISO 8601 format; null while the call is still active |
| hasAudio | boolean Whether audio media is present |
| hasVideo | boolean Whether video media is present |
| sdp | string SIP SDP offer. Contains the local SDP generated by WCS for this call |
| visibleName | string Caller's display name used in the SIP From header |
object Additional SIP INVITE parameters supplied by the caller (e.g. custom header values forwarded into the INVITE) | |
| mediaProvider | string Deprecated. Always set to Flash for REST API calls |
| sipStatus | integer <int32> Last SIP response status code from the remote endpoint (e.g. 180 Ringing, 183 Session Progress, 200 OK, 486 Busy Here, 408 Request Timeout) |
| rtmpUrl | string RTMP URL of the target server for re-streaming the RTP media received from the SIP endpoint (e.g. rtmp://server:1935/live/stream) |
| rtmpStream | string If provided, this value is appended to rtmpUrl to form the final RTMP publish target. Example: rtmpUrl=rtmp://localhost:1935/live + rtmpStream=test → rtmp://localhost:1935/live/test |
| streamName | string If provided, after the SIP session is established the incoming RTP media will be converted into a server-side internal stream with the specified name. The stream then becomes available for playback and further processing including HLS, transcoding, mixing, etc. |
| rtmpStreamStatus | string Enum: "RTMP_STREAM_WAIT" "RTMP_STREAM_ACTIVE" "RTMP_CONNECTION_FAILED" "RTMP_CONNECTION_LOST" Status of the RTMP re-streaming for this call: RTMP_STREAM_WAIT (SIP call established, waiting for RTMP connection), RTMP_STREAM_ACTIVE (RTMP stream active), RTMP_CONNECTION_FAILED, RTMP_CONNECTION_LOST |
| sipMessageRaw | string Last raw SIP message exchanged in this call (request or response from/to the remote SIP endpoint) |
| target | string SIP target |
| holdForTransfer | boolean Whether the call is on hold specifically for a subsequent transfer (SIP REFER). Regular hold without this flag does not allow transfer |
| sipSDP | Array of strings unique Extra SDP attribute lines forwarded together with the SIP offer/answer (a=... lines outside the main SDP) |
{- "custom": {
- "example": 0
}, - "nodeId": "7aoC1Q9IkTCn4zEsNAKvl1P1QMnXfnKE@192.168.100.1",
- "appKey": "defaultApp",
- "sessionId": "/192.168.1.102:13252/192.168.1.101:8443",
- "callId": "7f8a3c731f6f4f83a9b21c0f9e2c1234@flashphoner.com",
- "callUuid": "4a64e860-c5cd-11f0-b763-ab6a382eac0f",
- "parentCallId": "7f8a3c731f6f4f83a9b21c0f9e2c1234@parent.flashphoner.com",
- "incoming": true,
- "status": "RING",
- "caller": "10001",
- "callee": "10002",
- "localAudioCodec": "opus",
- "localVideoCodec": "H264",
- "localWidth": 720,
- "localHeight": 360,
- "remoteAudioCodec": "opus",
- "remoteVideoCodec": "H264",
- "remoteWidth": 720,
- "remoteHeight": 360,
- "createDate": "2026-04-12 10:30:15.123000+00:00",
- "endDate": "2026-04-12 10:35:42.456000+00:00",
- "hasAudio": true,
- "hasVideo": false,
- "sdp": "v=0\\r\\no=Flashphoner 0 1759480746034...",
- "visibleName": "10001",
- "inviteParameters": {
- "property1": "string",
- "property2": "string"
}, - "mediaProvider": "Flash",
- "sipStatus": 200,
- "rtmpUrl": "rtmp://localhost:1935/live",
- "rtmpStream": "test",
- "streamName": "s0",
- "rtmpStreamStatus": "RTMP_STREAM_WAIT",
- "sipMessageRaw": "INVITE sip:...",
- "target": "sip:alice@example.co...",
- "holdForTransfer": true,
- "sipSDP": [
- "string"
]
}{- "custom": {
- "example": 0
}, - "nodeId": "7aoC1Q9IkTCn4zEsNAKvl1P1QMnXfnKE@192.168.100.1",
- "appKey": "defaultApp",
- "sessionId": "/192.168.1.102:13252/192.168.1.101:8443",
- "callId": "7f8a3c731f6f4f83a9b21c0f9e2c1234@flashphoner.com",
- "callUuid": "4a64e860-c5cd-11f0-b763-ab6a382eac0f",
- "parentCallId": "7f8a3c731f6f4f83a9b21c0f9e2c1234@parent.flashphoner.com",
- "incoming": true,
- "status": "RING",
- "caller": "10001",
- "callee": "10002",
- "localAudioCodec": "opus",
- "localVideoCodec": "H264",
- "localWidth": 720,
- "localHeight": 360,
- "remoteAudioCodec": "opus",
- "remoteVideoCodec": "H264",
- "remoteWidth": 720,
- "remoteHeight": 360,
- "createDate": "2026-04-12 10:30:15.123000+00:00",
- "endDate": "2026-04-12 10:35:42.456000+00:00",
- "hasAudio": true,
- "hasVideo": false,
- "sdp": "v=0\\r\\no=Flashphoner 0 1759480746034...",
- "visibleName": "10001",
- "inviteParameters": {
- "property1": "string",
- "property2": "string"
}, - "mediaProvider": "Flash",
- "sipStatus": 200,
- "rtmpUrl": "rtmp://localhost:1935/live",
- "rtmpStream": "test",
- "streamName": "s0",
- "rtmpStreamStatus": "RTMP_STREAM_WAIT",
- "sipMessageRaw": "INVITE sip:...",
- "target": "sip:alice@example.co...",
- "holdForTransfer": true,
- "sipSDP": [
- "string"
]
}/apps/DefaultApp/CallStatusEvent
WCS sends this notification hook every time a call changes its state — for example RING, SESSION_PROGRESS, ESTABLISHED, FINISH, or FAILED. The request body contains the current call status, identifiers, parties, and signaling details.
object Custom key-value parameters | |
| nodeId | string Unique identifier of the WCS server instance. Auto-generated as {randomString}@{serverIP} and stored in {WCS_HOME}/conf/node_id |
| appKey | string REST hook application key. Determines the webhook URL for event notifications, as configured in database.yml |
| sessionId | string Signaling session ID (Connection ID). For WebSocket connections the format is /remoteIP:port/localIP:port. Format varies for other connection types |
| origin | string Origin URL of the client page (browser domain) |
| callId | string Unique SIP Call-ID of the call. Format: uuid@host. Sent in the Call-ID header of the SIP INVITE request |
| callUuid | string Unique internal call UUID assigned by server. Also used by iOS CallKit for VoIP calls |
| parentCallId | string Parent SIP Call-ID for transferred or chained calls; format uuid@host |
| incoming | boolean Call direction: true = incoming, false = outgoing |
| status | string Call status. SIP 180 → RING, SIP 183 → SESSION_PROGRESS, SIP 200 → ESTABLISHED. Other values: HOLD (call placed on hold), BUSY (e.g. SIP 486 Busy Here), FINISH (call ended) |
| caller | string Caller (From) peer identifier; value used in SIP From header |
| callee | string Callee (To) peer identifier; value used in SIP To header |
| localAudioCodec | string Audio codec negotiated by WCS on the local side of the SIP session |
| localVideoCodec | string Video codec negotiated by WCS on the local side of the SIP session |
| localWidth | integer <int32> Local video width in pixels |
| localHeight | integer <int32> Local video height in pixels |
| remoteAudioCodec | string Audio codec negotiated by WCS on the remote side of the SIP session |
| remoteVideoCodec | string Video codec negotiated by WCS on the remote side of the SIP session |
| remoteWidth | integer <int32> Remote video width in pixels |
| remoteHeight | integer <int32> Remote video height in pixels |
| createDate | string <date-time> Call creation timestamp in ISO 8601 format |
| endDate | string <date-time> Call end timestamp in ISO 8601 format; null while the call is still active |
| hasAudio | boolean Whether audio media is present |
| hasVideo | boolean Whether video media is present |
| sdp | string SIP SDP offer. Contains the local SDP generated by WCS for this call |
| visibleName | string Caller's display name used in the SIP From header |
object Additional SIP INVITE parameters supplied by the caller (e.g. custom header values forwarded into the INVITE) | |
| mediaProvider | string Deprecated. Always set to Flash for REST API calls |
| sipStatus | integer <int32> Last SIP response status code from the remote endpoint (e.g. 180 Ringing, 183 Session Progress, 200 OK, 486 Busy Here, 408 Request Timeout) |
| rtmpUrl | string RTMP URL of the target server for re-streaming the RTP media received from the SIP endpoint (e.g. rtmp://server:1935/live/stream) |
| rtmpStream | string If provided, this value is appended to rtmpUrl to form the final RTMP publish target. Example: rtmpUrl=rtmp://localhost:1935/live + rtmpStream=test → rtmp://localhost:1935/live/test |
| streamName | string If provided, after the SIP session is established the incoming RTP media will be converted into a server-side internal stream with the specified name. The stream then becomes available for playback and further processing including HLS, transcoding, mixing, etc. |
| rtmpStreamStatus | string Enum: "RTMP_STREAM_WAIT" "RTMP_STREAM_ACTIVE" "RTMP_CONNECTION_FAILED" "RTMP_CONNECTION_LOST" Status of the RTMP re-streaming for this call: RTMP_STREAM_WAIT (SIP call established, waiting for RTMP connection), RTMP_STREAM_ACTIVE (RTMP stream active), RTMP_CONNECTION_FAILED, RTMP_CONNECTION_LOST |
| sipMessageRaw | string Last raw SIP message exchanged in this call (request or response from/to the remote SIP endpoint) |
| target | string SIP target |
| holdForTransfer | boolean Whether the call is on hold specifically for a subsequent transfer (SIP REFER). Regular hold without this flag does not allow transfer |
| sipSDP | Array of strings unique Extra SDP attribute lines forwarded together with the SIP offer/answer (a=... lines outside the main SDP) |
{- "custom": {
- "example": 0
}, - "nodeId": "7aoC1Q9IkTCn4zEsNAKvl1P1QMnXfnKE@192.168.100.1",
- "appKey": "defaultApp",
- "sessionId": "/192.168.1.102:13252/192.168.1.101:8443",
- "callId": "7f8a3c731f6f4f83a9b21c0f9e2c1234@flashphoner.com",
- "callUuid": "4a64e860-c5cd-11f0-b763-ab6a382eac0f",
- "parentCallId": "7f8a3c731f6f4f83a9b21c0f9e2c1234@parent.flashphoner.com",
- "incoming": true,
- "status": "RING",
- "caller": "10001",
- "callee": "10002",
- "localAudioCodec": "opus",
- "localVideoCodec": "H264",
- "localWidth": 720,
- "localHeight": 360,
- "remoteAudioCodec": "opus",
- "remoteVideoCodec": "H264",
- "remoteWidth": 720,
- "remoteHeight": 360,
- "createDate": "2026-04-12 10:30:15.123000+00:00",
- "endDate": "2026-04-12 10:35:42.456000+00:00",
- "hasAudio": true,
- "hasVideo": false,
- "sdp": "v=0\\r\\no=Flashphoner 0 1759480746034...",
- "visibleName": "10001",
- "inviteParameters": {
- "property1": "string",
- "property2": "string"
}, - "mediaProvider": "Flash",
- "sipStatus": 200,
- "rtmpUrl": "rtmp://localhost:1935/live",
- "rtmpStream": "test",
- "streamName": "s0",
- "rtmpStreamStatus": "RTMP_STREAM_WAIT",
- "sipMessageRaw": "INVITE sip:...",
- "target": "sip:alice@example.co...",
- "holdForTransfer": true,
- "sipSDP": [
- "string"
]
}{- "custom": {
- "example": 0
}, - "nodeId": "7aoC1Q9IkTCn4zEsNAKvl1P1QMnXfnKE@192.168.100.1",
- "appKey": "defaultApp",
- "sessionId": "/192.168.1.102:13252/192.168.1.101:8443",
- "callId": "7f8a3c731f6f4f83a9b21c0f9e2c1234@flashphoner.com",
- "callUuid": "4a64e860-c5cd-11f0-b763-ab6a382eac0f",
- "parentCallId": "7f8a3c731f6f4f83a9b21c0f9e2c1234@parent.flashphoner.com",
- "incoming": true,
- "status": "RING",
- "caller": "10001",
- "callee": "10002",
- "localAudioCodec": "opus",
- "localVideoCodec": "H264",
- "localWidth": 720,
- "localHeight": 360,
- "remoteAudioCodec": "opus",
- "remoteVideoCodec": "H264",
- "remoteWidth": 720,
- "remoteHeight": 360,
- "createDate": "2026-04-12 10:30:15.123000+00:00",
- "endDate": "2026-04-12 10:35:42.456000+00:00",
- "hasAudio": true,
- "hasVideo": false,
- "sdp": "v=0\\r\\no=Flashphoner 0 1759480746034...",
- "visibleName": "10001",
- "inviteParameters": {
- "property1": "string",
- "property2": "string"
}, - "mediaProvider": "Flash",
- "sipStatus": 200,
- "rtmpUrl": "rtmp://localhost:1935/live",
- "rtmpStream": "test",
- "streamName": "s0",
- "rtmpStreamStatus": "RTMP_STREAM_WAIT",
- "sipMessageRaw": "INVITE sip:...",
- "target": "sip:alice@example.co...",
- "holdForTransfer": true,
- "sipSDP": [
- "string"
]
}/apps/DefaultApp/RegistrationStatusEvent
WCS sends this notification hook after a client connection triggers SIP registration and the registration state changes, for example to REGISTERED, UNREGISTERED, or AUTHENTICATION_FAIL. The request body contains the WCS node, application, session, and resulting SIP registration status. For the REGISTERED notification, fields returned by the Backend may be used in the client callback.
| nodeId | string ID representing this server |
| appKey | string Application identifier |
| sessionId | string Session identifier |
| status | string Enum: "REGISTERED" "UNREGISTERED" "AUTHENTICATION_FAIL" SIP registration status |
{- "nodeId": "f02vkq9PbK9A8MrBnKatCK9clLbHbPyR@95.191.130.39",
- "appKey": "defaultApp",
- "sessionId": "/5.129.23.83:53866/95.191.130.39:8443-caab56ae-481a-484e-8ca6-ff8a47456080",
- "status": "REGISTERED"
}{- "nodeId": "f02vkq9PbK9A8MrBnKatCK9clLbHbPyR@95.191.130.39",
- "appKey": "defaultApp",
- "sessionId": "/5.129.23.83:53866/95.191.130.39:8443-caab56ae-481a-484e-8ca6-ff8a47456080",
- "status": "REGISTERED"
}/apps/DefaultApp/TransferStatusEvent
WCS sends this notification hook after a previously started transfer completes — successfully, with a NOTIFY from the transferee, or with an error. The request body contains the final transfer status and the related call identifiers.
object Custom key-value parameters | |
| nodeId | string Unique identifier of the WCS server instance. Auto-generated as {randomString}@{serverIP} and stored in {WCS_HOME}/conf/node_id |
| appKey | string REST hook application key. Determines the webhook URL for event notifications, as configured in database.yml |
| sessionId | string Signaling session ID (Connection ID). For WebSocket connections the format is /remoteIP:port/localIP:port. Format varies for other connection types |
| origin | string Origin URL of the client page (browser domain) |
| callId | string Unique SIP Call-ID of the call. Format: uuid@host. Sent in the Call-ID header of the SIP INVITE request |
| callUuid | string Unique internal call UUID assigned by server. Also used by iOS CallKit for VoIP calls |
| parentCallId | string Parent SIP Call-ID for transferred or chained calls; format uuid@host |
| incoming | boolean Call direction: true = incoming, false = outgoing |
| status | string Call status. SIP 180 → RING, SIP 183 → SESSION_PROGRESS, SIP 200 → ESTABLISHED. Other values: HOLD (call placed on hold), BUSY (e.g. SIP 486 Busy Here), FINISH (call ended) |
| caller | string Caller (From) peer identifier; value used in SIP From header |
| callee | string Callee (To) peer identifier; value used in SIP To header |
| localAudioCodec | string Audio codec negotiated by WCS on the local side of the SIP session |
| localVideoCodec | string Video codec negotiated by WCS on the local side of the SIP session |
| localWidth | integer <int32> Local video width in pixels |
| localHeight | integer <int32> Local video height in pixels |
| remoteAudioCodec | string Audio codec negotiated by WCS on the remote side of the SIP session |
| remoteVideoCodec | string Video codec negotiated by WCS on the remote side of the SIP session |
| remoteWidth | integer <int32> Remote video width in pixels |
| remoteHeight | integer <int32> Remote video height in pixels |
| createDate | string <date-time> Call creation timestamp in ISO 8601 format |
| endDate | string <date-time> Call end timestamp in ISO 8601 format; null while the call is still active |
| hasAudio | boolean Whether audio media is present |
| hasVideo | boolean Whether video media is present |
| sdp | string SIP SDP offer. Contains the local SDP generated by WCS for this call |
| visibleName | string Caller's display name used in the SIP From header |
object Additional SIP INVITE parameters supplied by the caller (e.g. custom header values forwarded into the INVITE) | |
| mediaProvider | string Deprecated. Always set to Flash for REST API calls |
| sipStatus | integer <int32> Last SIP response status code from the remote endpoint (e.g. 180 Ringing, 183 Session Progress, 200 OK, 486 Busy Here, 408 Request Timeout) |
| rtmpUrl | string RTMP URL of the target server for re-streaming the RTP media received from the SIP endpoint (e.g. rtmp://server:1935/live/stream) |
| rtmpStream | string If provided, this value is appended to rtmpUrl to form the final RTMP publish target. Example: rtmpUrl=rtmp://localhost:1935/live + rtmpStream=test → rtmp://localhost:1935/live/test |
| streamName | string If provided, after the SIP session is established the incoming RTP media will be converted into a server-side internal stream with the specified name. The stream then becomes available for playback and further processing including HLS, transcoding, mixing, etc. |
| rtmpStreamStatus | string Enum: "RTMP_STREAM_WAIT" "RTMP_STREAM_ACTIVE" "RTMP_CONNECTION_FAILED" "RTMP_CONNECTION_LOST" Status of the RTMP re-streaming for this call: RTMP_STREAM_WAIT (SIP call established, waiting for RTMP connection), RTMP_STREAM_ACTIVE (RTMP stream active), RTMP_CONNECTION_FAILED, RTMP_CONNECTION_LOST |
| sipMessageRaw | string Last raw SIP message exchanged in this call (request or response from/to the remote SIP endpoint) |
| target | string SIP target |
| holdForTransfer | boolean Whether the call is on hold specifically for a subsequent transfer (SIP REFER). Regular hold without this flag does not allow transfer |
| sipSDP | Array of strings unique Extra SDP attribute lines forwarded together with the SIP offer/answer (a=... lines outside the main SDP) |
{- "custom": {
- "example": 0
}, - "nodeId": "7aoC1Q9IkTCn4zEsNAKvl1P1QMnXfnKE@192.168.100.1",
- "appKey": "defaultApp",
- "sessionId": "/192.168.1.102:13252/192.168.1.101:8443",
- "callId": "7f8a3c731f6f4f83a9b21c0f9e2c1234@flashphoner.com",
- "callUuid": "4a64e860-c5cd-11f0-b763-ab6a382eac0f",
- "parentCallId": "7f8a3c731f6f4f83a9b21c0f9e2c1234@parent.flashphoner.com",
- "incoming": true,
- "status": "RING",
- "caller": "10001",
- "callee": "10002",
- "localAudioCodec": "opus",
- "localVideoCodec": "H264",
- "localWidth": 720,
- "localHeight": 360,
- "remoteAudioCodec": "opus",
- "remoteVideoCodec": "H264",
- "remoteWidth": 720,
- "remoteHeight": 360,
- "createDate": "2026-04-12 10:30:15.123000+00:00",
- "endDate": "2026-04-12 10:35:42.456000+00:00",
- "hasAudio": true,
- "hasVideo": false,
- "sdp": "v=0\\r\\no=Flashphoner 0 1759480746034...",
- "visibleName": "10001",
- "inviteParameters": {
- "property1": "string",
- "property2": "string"
}, - "mediaProvider": "Flash",
- "sipStatus": 200,
- "rtmpUrl": "rtmp://localhost:1935/live",
- "rtmpStream": "test",
- "streamName": "s0",
- "rtmpStreamStatus": "RTMP_STREAM_WAIT",
- "sipMessageRaw": "INVITE sip:...",
- "target": "sip:alice@example.co...",
- "holdForTransfer": true,
- "sipSDP": [
- "string"
]
}{- "custom": {
- "example": 0
}, - "nodeId": "7aoC1Q9IkTCn4zEsNAKvl1P1QMnXfnKE@192.168.100.1",
- "appKey": "defaultApp",
- "sessionId": "/192.168.1.102:13252/192.168.1.101:8443",
- "callId": "7f8a3c731f6f4f83a9b21c0f9e2c1234@flashphoner.com",
- "callUuid": "4a64e860-c5cd-11f0-b763-ab6a382eac0f",
- "parentCallId": "7f8a3c731f6f4f83a9b21c0f9e2c1234@parent.flashphoner.com",
- "incoming": true,
- "status": "RING",
- "caller": "10001",
- "callee": "10002",
- "localAudioCodec": "opus",
- "localVideoCodec": "H264",
- "localWidth": 720,
- "localHeight": 360,
- "remoteAudioCodec": "opus",
- "remoteVideoCodec": "H264",
- "remoteWidth": 720,
- "remoteHeight": 360,
- "createDate": "2026-04-12 10:30:15.123000+00:00",
- "endDate": "2026-04-12 10:35:42.456000+00:00",
- "hasAudio": true,
- "hasVideo": false,
- "sdp": "v=0\\r\\no=Flashphoner 0 1759480746034...",
- "visibleName": "10001",
- "inviteParameters": {
- "property1": "string",
- "property2": "string"
}, - "mediaProvider": "Flash",
- "sipStatus": 200,
- "rtmpUrl": "rtmp://localhost:1935/live",
- "rtmpStream": "test",
- "streamName": "s0",
- "rtmpStreamStatus": "RTMP_STREAM_WAIT",
- "sipMessageRaw": "INVITE sip:...",
- "target": "sip:alice@example.co...",
- "holdForTransfer": true,
- "sipSDP": [
- "string"
]
}