Skip to content

Protocol Overview ​

rtpbridge is controlled via JSON messages over WebSocket.

Connection Model ​

Each WebSocket connection is bound to exactly one media session. After session.create or session.attach, all subsequent commands operate on that session — no session_id is needed on most commands.

When a WebSocket connection drops, the session enters an orphaned state. Media continues flowing. A new connection can reclaim the session via session.attach within the configurable timeout (default 30 seconds).

Message Format ​

Request (client to server) ​

json
{
  "id": "req-1",
  "method": "session.create",
  "params": {}
}
  • id — Client-generated correlation ID (string). Returned in the response.
  • method — Method name (string).
  • params — Method parameters (object). Can be omitted or {} for no params.

Success Response ​

json
{
  "id": "req-1",
  "result": { "session_id": "550e8400-..." }
}

Error Response ​

json
{
  "id": "req-1",
  "error": {
    "code": "SESSION_NOT_FOUND",
    "message": "No session with that ID"
  }
}

Event (server to client, unsolicited) ​

json
{
  "event": "dtmf",
  "data": { "endpoint_id": "...", "digit": "5", "duration_ms": 160 }
}

Events are emitted asynchronously and are not correlated to requests.

Event Delivery Semantics ​

  • Asynchronous: Events are emitted independently of request/response pairs. They are not correlated to any specific command.
  • Ordering: Events within the same priority tier are delivered in order. Priority events (see below) may be delivered ahead of normal events queued at the same time.
  • Delivery guarantee: At-most-once. Under backpressure (slow client), events may be dropped rather than block the media pipeline.
  • Drop notification: When events are dropped, the server sends an events.dropped notification with a count field indicating how many events were lost since the last successful delivery.
  • Priority events: Critical events (endpoint.state_changed, endpoint.ice_state_changed, recording.stopped, endpoint.file.started, endpoint.file.finished, session.idle_timeout, session.empty_timeout) are routed through a separate priority channel and are dropped only when both the priority and normal channels are full.

Error Codes ​

CodeDescription
PARSE_ERRORInvalid JSON
UNKNOWN_METHODMethod not recognized
INVALID_PARAMSMissing or invalid parameters
NO_SESSIONNo session bound to this connection
SESSION_ALREADY_BOUNDConnection already has a session
SESSION_NOT_FOUNDSession ID does not exist
SESSION_NOT_ORPHANEDSession exists but is not orphaned
SESSION_GONESession task ended unexpectedly
SESSION_UNRESPONSIVESession did not respond to command within timeout
SESSION_BUSYSession command channel is full
SHUTTING_DOWNServer is shutting down
MAX_SESSIONS_REACHEDResource limit exceeded
ENDPOINT_ERROREndpoint operation failed
RECORDING_ERRORRecording operation failed
VAD_ERRORVAD operation failed
FAX_DETECT_ERRORFax tone detection operation failed
STATS_ERRORStatistics subscribe/unsubscribe failed
TRANSFER_FAILEDEndpoint transfer failed after extraction; rollback was attempted
INVALID_REQUESTRequest id field is empty or invalid
INTERNAL_ERRORInternal server error (e.g., serialization failure)

Error Codes by Method ​

Most methods that require a session can return NO_SESSION (no session bound), SESSION_GONE (session task ended), and SESSION_UNRESPONSIVE (5-second command timeout). These common codes are listed once here and apply to all session-bound methods below.

Session and Server ​

MethodAdditional Error Codes
session.createSESSION_ALREADY_BOUND, SHUTTING_DOWN, MAX_SESSIONS_REACHED
session.attachSESSION_ALREADY_BOUND, INVALID_PARAMS, SESSION_NOT_FOUND, SESSION_NOT_ORPHANED, SESSION_BUSY
session.destroy(none beyond common)
session.info(none beyond common)
session.timeline.mark(none beyond common)
session.list(always succeeds)
server.info(always succeeds)

WebRTC Endpoint Commands ​

MethodAdditional Error Codes
endpoint.create_from_offerINVALID_PARAMS, ENDPOINT_ERROR
endpoint.create_offerINVALID_PARAMS, ENDPOINT_ERROR
endpoint.accept_answerINVALID_PARAMS, ENDPOINT_ERROR
endpoint.accept_offerINVALID_PARAMS, ENDPOINT_ERROR
endpoint.ice_restartINVALID_PARAMS, ENDPOINT_ERROR
endpoint.webrtc.create_from_offerINVALID_PARAMS, ENDPOINT_ERROR
endpoint.webrtc.create_offerINVALID_PARAMS, ENDPOINT_ERROR
endpoint.webrtc.accept_answerINVALID_PARAMS, ENDPOINT_ERROR
endpoint.webrtc.accept_offerINVALID_PARAMS, ENDPOINT_ERROR
endpoint.webrtc.ice_restartINVALID_PARAMS, ENDPOINT_ERROR

RTP Endpoint Commands ​

MethodAdditional Error Codes
endpoint.rtp.create_from_offerINVALID_PARAMS, ENDPOINT_ERROR
endpoint.rtp.create_offerINVALID_PARAMS, ENDPOINT_ERROR
endpoint.rtp.accept_answerINVALID_PARAMS, ENDPOINT_ERROR
endpoint.rtp.reinviteINVALID_PARAMS, ENDPOINT_ERROR
endpoint.srtp_rekeyINVALID_PARAMS, ENDPOINT_ERROR
endpoint.rtp.srtp_rekeyINVALID_PARAMS, ENDPOINT_ERROR

Generic Endpoint Commands ​

MethodAdditional Error Codes
endpoint.update_directionINVALID_PARAMS, ENDPOINT_ERROR
endpoint.update_remote_sdpINVALID_PARAMS, ENDPOINT_ERROR
endpoint.removeINVALID_PARAMS, ENDPOINT_ERROR
endpoint.transferINVALID_PARAMS, SESSION_NOT_FOUND, ENDPOINT_ERROR, TRANSFER_FAILED
endpoint.dtmf.injectINVALID_PARAMS, ENDPOINT_ERROR
endpoint.dtmf.set_sensitiveINVALID_PARAMS, ENDPOINT_ERROR
endpoint.create_with_fileINVALID_PARAMS, ENDPOINT_ERROR
endpoint.create_toneINVALID_PARAMS, ENDPOINT_ERROR
endpoint.create_websocketINVALID_PARAMS, ENDPOINT_ERROR
endpoint.file.seekINVALID_PARAMS, ENDPOINT_ERROR
endpoint.file.pauseINVALID_PARAMS, ENDPOINT_ERROR
endpoint.file.resumeINVALID_PARAMS, ENDPOINT_ERROR
session.bridgeINVALID_PARAMS, SESSION_NOT_FOUND, ENDPOINT_ERROR

Recording, VAD, and Stats ​

MethodAdditional Error Codes
recording.startINVALID_PARAMS, RECORDING_ERROR
recording.stopINVALID_PARAMS, RECORDING_ERROR
vad.startINVALID_PARAMS, VAD_ERROR
vad.stopINVALID_PARAMS, VAD_ERROR
fax_detect.startINVALID_PARAMS, FAX_DETECT_ERROR
fax_detect.stopINVALID_PARAMS, FAX_DETECT_ERROR
stats.subscribeINVALID_PARAMS, STATS_ERROR
stats.snapshotINVALID_PARAMS
stats.unsubscribeSTATS_ERROR

Unknown methods return UNKNOWN_METHOD. Invalid JSON returns PARSE_ERROR.

Media-clock timeline marks ​

session.timeline.mark is a read-only ordering primitive for control-plane facts that must align with recorded media. It is dispatched through the owning media-session actor, after all commands already admitted to that actor and before commands admitted later, and returns the media host's current epoch in milliseconds:

json
{"id":"mark-1","method":"session.timeline.mark","params":{}}
json
{"id":"mark-1","result":{"marked_at_epoch_ms":1730000000123}}

The command does not change endpoints, routing, recording, or media. A caller may use the returned value to place an application event on the same wall-clock axis as PCAP capture and recording/file acknowledgements.

Graceful Shutdown ​

During graceful shutdown, session.create immediately returns SHUTTING_DOWN. Existing sessions continue operating — media flows and commands work normally until connections close or sessions are explicitly destroyed. If a session task has already exited during shutdown, commands may return SESSION_UNRESPONSIVE.