Recording
Start and stop call recording via the wavstream WebSocket service. Recording configuration (wavstream URL, storage URL) comes from server environment variables, not the API payload.
All recording endpoints require App authentication via X-App-ID and X-API-Key headers. The session must exist and belong to your application.
Record start
Section titled “Record start”Start recording the call via the wavstream WebSocket service. An infinite silence stream is started to keep the channel alive during recording. The command.result fires immediately. No user-supplied fields are needed; all recording parameters come from server configuration.
Request body
| Field | Type | Required | Description |
|---|---|---|---|
command_uid | string | optional | Caller-supplied idempotency key. Auto-generated UUID if omitted. Max 128 chars, ^[a-zA-Z0-9._-]+$. |
No other request body fields are accepted. Recording destination and format are configured server-side.
Rate limit — heavy group, 2 s cooldown per session. Shared with record/stop and play_and_get_digits.
/api/v1/sessions/{uuid}/commands/record/start curl -X POST https://gateway.example.com/api/v1/sessions/{uuid}/commands/record/start \
-H "X-App-ID: YOUR_APP_ID" \
-H "X-API-Key: YOUR_API_KEY" \
-H "Content-Type: application/json" \
-d '{}' Triggered webhooks
command.result— immediate; published by the HTTP handler.
Record stop
Section titled “Record stop”Stop recording the call. Stops the audio stream and the silence stream. Publishes both command.result and recording.completed immediately. The recording.completed webhook includes the recording URL, duration, and the original record/start command_uid.
Request body
| Field | Type | Required | Description |
|---|---|---|---|
command_uid | string | optional | Caller-supplied idempotency key. Auto-generated UUID if omitted. Max 128 chars, ^[a-zA-Z0-9._-]+$. |
Rate limit — heavy group, 2 s cooldown per session. Shared with record/start and play_and_get_digits.
/api/v1/sessions/{uuid}/commands/record/stop curl -X POST https://gateway.example.com/api/v1/sessions/{uuid}/commands/record/stop \
-H "X-App-ID: YOUR_APP_ID" \
-H "X-API-Key: YOUR_API_KEY" \
-H "Content-Type: application/json" \
-d '{}' Triggered webhooks
command.result— immediate; fires right after command dispatch.recording.completed— immediate; includesrecording_url,duration, and the originalrecord/startcommand_uid.
recording.completed webhook payload
Section titled “recording.completed webhook payload”When record/stop is called, the recording.completed webhook includes:
| Field | Type | Description |
|---|---|---|
event | string | Always "recording.completed". |
session_uuid | string | The session that was recorded. |
recording_url | string | URL to download the recording. |
duration | number | Recording duration. |
command_uid | string | The command_uid from the original record/start command. |
Recording lifecycle / URL validity
Section titled “Recording lifecycle / URL validity”The recording_url emitted by the gateway is not stable indefinitely. Applications that need long-lived audio must download and store the WAV themselves within the retention window.
Validity start. The URL is guaranteed-fetchable from the moment the recording.completed webhook fires. Consumers should not attempt to fetch via the URL before that event; in-progress streaming is exposed via GET /api/v1/sessions/{uuid}/recording/file.wav instead.
Default retention — 24 hours from recording stop. The timer starts when recording stops (the same moment recording.completed is emitted), not from recording start and not from last access. Retention is configurable operator-side via the RECORDING_RETENTION_HOURS environment variable on the wavstream service; the deployed default is 24 hours.
Playback does not extend retention. A GET on the recording URL is read-only. There is no sliding expiry; the 24 hours are counted from stop time regardless of how many times the URL is fetched.
Post-expiry behaviour: 404 Not Found. After the retention window, the URL returns HTTP 404. No Location header, no redirect, no structured error body — the resource is simply gone. Clients must treat a 404 from a previously-valid recording_url as “expired, not available” and not retry.
Operator-managed backends override the default. If the operator points the server-side RECORDING_BASE_URL at an external store (S3, a CDN, or any other backend), retention is governed by that store’s lifecycle policy — not by the 24-hour default. In that configuration the gateway makes no TTL guarantee; consult the operator’s storage policy.
Longer-lived audio is the consumer’s responsibility. To retain audio beyond the gateway’s guarantee, download the WAV inside the retention window and persist it in application-controlled storage. Any URL stored by a consumer and dereferenced later is subject to the rules above; schedulers, retry queues, and archival flows must assume URLs may return 404 after 24 hours.
Error responses
Section titled “Error responses”| Status | Condition |
|---|---|
400 | Invalid command_uid format. |
401 | Missing or invalid X-API-Key. |
403 | Session belongs to a different application. |
404 | Session not found. |
429 | Rate limit exceeded (global or per-command cooldown). |
503 | WAVSTREAM_URL not configured on the server (for record/start only). |