---
title: "Fork a single call to an external SIPREC recording server"
method: POST
path: "/legs/{id}/siprec"
tags: ["Legs"]
---

# Fork a single call to an external SIPREC recording server

`POST /legs/{id}/siprec`

Originates a SIPREC recording session (RFC 7866) carrying one call as two `sendonly` sections: what the far end says, and what this server sends them. No room is involved. `leg_ids` is ignored here — the two sections are fixed. Returns the resulting `siprec_out` leg; delete it to end the session. Requires `SIPREC_SRC_ENABLED=true`.

## Request body

- StartSIPRECRequest
  - `srs_uri` string, required — SIP URI of the session recording server, e.g. "sip:srs@recorder.example.com:5060". A recording session carries the metadata document alongside the SDP and exceeds the UDP message limit, so the target should accept TCP.
  - `leg_ids` string[] — Which participants to record. Each entry is either a leg ID (that leg's own audio) or "<legID>#<streamID>" for one of a leg's secondary audio streams mixed into the room. Empty or absent records every participant. An entry that is not in the room is a 404.
  - `session_id` string — Communication session identifier put in the recording metadata. Defaults to the room ID.
  - `app_id` string — Application identifier tagged onto the resulting leg and its events.
  - `auth_username` string — SIP digest username, when the recording server challenges the INVITE.
  - `auth_password` string — SIP digest password, when the recording server challenges the INVITE.
  - `headers` object — Extra SIP headers to include in the INVITE. Require: siprec is always sent.

## Response `201`

Recording session established

- Leg
  - `instance_id` string — Instance identifier
  - `id` string, required — Unique leg identifier (UUID)
  - `type` 'sip_inbound' | 'sip_outbound' | 'webrtc' | 'whatsapp_in' | 'whatsapp_out' | 'websocket_in' | 'websocket_out' | 'moq_in' | 'livekit_publish' | 'livekit_participant', required — Leg type
  - `state` 'ringing' | 'early_media' | 'connected' | 'held' | 'hung_up', required — Leg state
  - `room_id` string — Room ID if the leg is in a room, empty otherwise
  - `muted` boolean, required — Whether the leg is muted (cannot be heard by others)
  - `deaf` boolean, required — Whether the leg is deaf (cannot hear others)
  - `accept_dtmf` boolean, required — Whether the leg receives DTMF digits broadcast from other legs in the same room. Defaults to true.
  - `held` boolean, required — Whether the call is on hold (SIP legs only)
  - `role` string — Routing role used by the room's audio routing matrix (e.g. "customer", "agent", "supervisor"). Empty string means unroled (full mesh).
  - `app_id` string — Application identifier for event stream filtering.
  - `sip_headers` object — Deprecated: X-* headers from the inbound INVITE. Only present on sip_inbound legs. Use `headers` for new code; it carries the same map plus surfaces handshake headers for websocket legs.
  - `headers` object — Custom protocol headers exposed by the leg's transport — X-/P- headers from a SIP INVITE, the WebSocket upgrade request, or supplied at outbound dial time.

## Other responses

- `400` — Invalid JSON, invalid srs_uri, or not a SIP leg
- `403` — Outbound SIPREC is disabled
- `404` — Leg not found
- `409` — The leg is itself a recording session
- `502` — The recording server rejected the session

---

[API](https://skmtc.net/voiceblender/apis/voiceblender-api.md) · [All operations](https://skmtc.net/voiceblender/apis/voiceblender-api/llms.txt) · [OpenAPI document](https://skmtc-service-staging.skmtc.workers.dev/v1/apis/voiceblender/voiceblender-api/versions/ad30827d3b57/schema)
