Recordings and transcripts
Every conversation an agent holds is transcribed, because transcription is how the agent hears the caller at all. Audio is only kept if you ask for it — and asking has legal consequences worth being deliberate about.
Transcripts
Available on any call an agent held, with no configuration. Turn by turn, with who said what and when.
/v1/calls/{id}/transcriptcurl -s https://voice.sphoro.com/v1/calls/$CALL_ID/transcript \
-H "Authorization: Bearer $SPHORO_API_KEY"{
"call_id": "call_8b21f4c9a07e3d15",
"turns": [
{ "role": "agent", "text": "Thanks for calling Acme Clinic. How can I help?", "at": "2026-09-08T09:41:09Z" },
{ "role": "user", "text": "I need to move my appointment.", "at": "2026-09-08T09:41:14Z", "latency_ms": 690 },
{ "role": "agent", "text": "Of course. Which appointment is that?", "at": "2026-09-08T09:41:15Z" }
]
}latency_ms on a user turn is the gap between them finishing and the agent
starting — the number the latency budget is about, per turn rather
than averaged.
webrtc call and a simple one both put two people on
the line with nothing here listening. Both can be transcribed by setting
transcribe_calls — which needs the clients to uplink their microphones, and is
therefore a decision rather than a default.Live, while the call is happening
call.transcript.updated fires per line, carrying role and
text, on webhooks and on the per-call stream:
/v1/calls/{id}/eventscurl -sN https://voice.sphoro.com/v1/calls/$CALL_ID/events \
-H "Authorization: Bearer $SPHORO_API_KEY"For a live feed across every call at once, see the realtime protocol.
Recording audio
/v1/agents/{id}curl -s -X PATCH https://voice.sphoro.com/v1/agents/$AGENT_ID \
-H "Authorization: Bearer $SPHORO_API_KEY" \
-H "Content-Type: application/json" \
-d '{"record_calls": true}'Because of that, recording behaves unlike every other setting in one specific way: an agent group can never switch it on for members it already has. It must be adopted per agent, deliberately, by somebody who knows the consent position for that line.
Fetching the audio
/v1/calls/{id}/recording/v1/calls/{id}/recording_url# Straight to a file.
curl -s https://voice.sphoro.com/v1/calls/$CALL_ID/recording \
-H "Authorization: Bearer $SPHORO_API_KEY" -o call.wav
# Or a short-lived URL, for handing to a browser without proxying the bytes.
curl -s https://voice.sphoro.com/v1/calls/$CALL_ID/recording_url \
-H "Authorization: Bearer $SPHORO_API_KEY"Wait for call.recording.ready rather than polling. It fires when the recording is
actually fetchable and carries its duration — a request before that answers 404,
which looks like a call that was never recorded.
How long things are kept
| What | Kept |
|---|---|
| The call record — times, numbers, end reason, cost | For as long as the account |
| The transcript | With the call record |
| The summary and extractions | With the call record |
| The audio recording | On a retention window agreed with your account |
Retention is set per account rather than per agent, because it is a policy rather than a setting. See security and data, and talk to us if the default does not match your obligations.
Getting them out
There is no bulk export endpoint. What there is instead is a list endpoint that pages, and transcripts fetched per call — which is what an export script does anyway:
curl -s "https://voice.sphoro.com/v1/calls?from=2026-09-01&to=2026-09-30&limit=100" \
-H "Authorization: Bearer $SPHORO_API_KEY" \
| jq -r '.data[].id' \
| while read -r id; do
curl -s "https://voice.sphoro.com/v1/calls/$id/transcript" \
-H "Authorization: Bearer $SPHORO_API_KEY" > "transcripts/$id.json"
donePagination is covered on using your API key.