Recordings
Record calls and conferences and receive the finished file via webhook.
Recordings
TryVox records audio at the media-server tier and delivers each finished recording asynchronously to a webhook URL you supply. There is no synchronous "give me the recording URL now" endpoint — recording is a side effect of an in-progress call or conference, and the URL only becomes valid after the audio has been finalised and uploaded.
How it works
- Start a recording on a live call or conference, registering a
callback_urlfor the finished asset. - Audio is captured on the media server while the resource is active.
- Finalisation happens when:
- The call hangs up (for call recordings)
- The conference ends or you call Stop Conference Recording
- The
time_limityou set on a call recording elapses - You call the explicit Stop endpoint
- Delivery — TryVox uploads the finished file to its recordings store and
POSTs the metadata to yourcallback_url.
START ──────► CAPTURE ──────► FINALISE ──────► UPLOAD ──────► callback_urlThe recording URL in the webhook payload is signed and stable for the retention window (see Storage and retention).
Starting a recording
There are two flavours: per-call and per-conference. Both return 204 No Content and rely on callback_url to deliver the result.
Per call
curl -X POST https://api.tryvox.io/v1/voice/accounts/$TRYVOX_AUTH_ID/calls/$CALL_UUID/record \
-u $TRYVOX_AUTH_ID:$TRYVOX_AUTH_TOKEN \
-H "Content-Type: application/json" \
-d '{
"file_format": "mp3",
"time_limit": 3600,
"callback_url": "https://your-app.com/recording-callback",
"transcription_type": "auto",
"transcription_url": "https://your-app.com/transcription-callback"
}'Full reference: Start Recording.
Per conference
curl -X POST https://api.tryvox.io/v1/voice/accounts/$TRYVOX_AUTH_ID/conferences/$CONF_NAME/record \
-u $TRYVOX_AUTH_ID:$TRYVOX_AUTH_TOKEN \
-H "Content-Type: application/json" \
-d '{
"file_format": "mp3",
"callback_url": "https://your-app.com/conf-recording-callback"
}'Full reference: Conference Recording.
From VoxML
You can also start recording declaratively at the start of an inbound call by including <Record> in the VoxML returned from answer_url. See VoxML / Record.
Recording webhook payload
Sent to callback_url once the recording is uploaded:
{
"event": "recording.completed",
"recording_id": "rec_950e8400e29b41d4a716446655440000",
"account_id": "TJab12cd34",
"source": "call",
"call_uuid": "650e8400-e29b-41d4-a716-446655440000",
"url": "https://recordings.tryvox.io/<account_id>/<recording_id>.mp3",
"duration": 125,
"file_format": "mp3",
"file_size_bytes": 1024000,
"started_at": "2026-04-09T10:30:15Z",
"ended_at": "2026-04-09T10:32:20Z"
}For conference recordings, source is conference and the payload includes conference_name instead of call_uuid.
| Field | Description |
|---|---|
event | Always recording.completed for the finished asset. |
recording_id | Stable identifier you can store and use to address the recording on retrieval. |
source | call or conference. |
call_uuid / conference_name | The originating resource. |
url | Direct, signed URL to the audio file. Valid for the full retention window. |
duration | Length in whole seconds. |
file_format | mp3 or wav, matching what you requested. |
file_size_bytes | Final on-disk size. |
started_at / ended_at | UTC ISO 8601 timestamps. |
If the call hangs up before recording finishes uploading, the webhook may be deferred by up to a minute while finalisation completes.
Transcription
Setting transcription_type: "auto" on a call recording enables automatic speech-to-text. The transcript is delivered to transcription_url separately from the audio webhook:
{
"event": "transcription.completed",
"recording_id": "rec_950e8400e29b41d4a716446655440000",
"call_uuid": "650e8400-e29b-41d4-a716-446655440000",
"language": "en-US",
"transcript": "Hello, thanks for calling support. How can I help you today? ...",
"segments": [
{"start": 0.0, "end": 2.3, "speaker": "agent", "text": "Hello, thanks for calling support."},
{"start": 2.4, "end": 5.1, "speaker": "caller", "text": "Hi, I need help with my account."}
]
}Speaker diarisation is best-effort and depends on adequate channel separation in the source audio.
Stopping a recording early
If you started a recording and want to cut it short:
# Call recording
curl -X DELETE https://api.tryvox.io/v1/voice/accounts/$TRYVOX_AUTH_ID/calls/$CALL_UUID/record \
-u $TRYVOX_AUTH_ID:$TRYVOX_AUTH_TOKEN
# Conference recording
curl -X DELETE https://api.tryvox.io/v1/voice/accounts/$TRYVOX_AUTH_ID/conferences/$CONF_NAME/record \
-u $TRYVOX_AUTH_ID:$TRYVOX_AUTH_TOKENThe webhook still fires once the file is finalised — you just shorten the duration.
Webhook reliability
- Failed POSTs are retried up to 3 times with exponential backoff (1s → 4s → 16s).
- Each attempt times out after 5 seconds.
- After all retries, the recording is still stored and discoverable in the dashboard, but you'll need to fetch it manually.
Make your webhook handler idempotent — duplicate deliveries can occur on retry edges.
Storage and retention
- Default retention: 30 days from
ended_at. - Format: mp3 (default) or wav. mp3 is mono 8 kHz at the codec level; wav is 16 kHz PCM.
- Mixing: both legs of a call (or all members of a conference) are mixed into a single file. There is no per-channel export today.
- Access: the
urlin the webhook is directly fetchable with no additional auth for the retention window. Treat it as a capability — don't post it publicly.
Limitations
- No list-recordings endpoint. Track
recording_ids on your side as they arrive on the webhook. The dashboard exposes a UI listing for support and debugging only. - No retroactive recording. You can't enable recording on a call that's already in progress without reaching that call's media leg via the API. Decide at start time, or pivot the call into a recorded conference.
- No partial fetch. Recordings are delivered as a single finalised file, not as a stream.
Compliance and consent
You are responsible for satisfying the recording-consent requirements of every jurisdiction your call touches. TryVox does not insert consent prompts automatically — use Speak or a VoxML <Say> at the start of the call to play one.