curl -X POST https://api.60db.ai/dialer/click2call/7d004ba2-565f-4ee2-9aa2-19523d8db7ae/recording \
-H "Authorization: Bearer your-api-key"
// 1. Has the audio landed yet?
const call = await fetch(
`https://api.60db.ai/dialer/click2call/${callId}?refresh=1`,
{ headers: { Authorization: `Bearer ${key}` } },
).then((r) => r.json());
// 2. Mint the URL
if (call.data.call.recording_available) {
const res = await fetch(
`https://api.60db.ai/dialer/click2call/${callId}/recording`,
{ method: 'POST', headers: { Authorization: `Bearer ${key}` } },
);
const { data } = await res.json();
console.log('Play at:', data.recording.playback_url);
}
res = requests.post(
f"https://api.60db.ai/dialer/click2call/{call_id}/recording",
headers={"Authorization": f"Bearer {os.environ['SIXTYDB_API_KEY']}"},
)
rec = res.json()["data"]["recording"]
print(rec["playback_url"], rec["expires_at"])
{
"success": true,
"data": {
"recording": {
"call_id": "7d004ba2-565f-4ee2-9aa2-19523d8db7ae",
"recording_id": "rec_01J9Z4K7",
"recording_status": "uploaded",
"recording_format": "wav",
"recording_size": 1048576,
"playback_url": "https://cdn.60db.ai/recordings/...",
"expires_at": "2026-09-23T14:20:00Z"
}
}
}
{
"success": false,
"message": "This call was not recorded. Turn recording on before placing the call.",
"code": "RECORDING_UNAVAILABLE"
}
Click-to-Call
Get Recording URL
Mint a short-lived playback URL for a click-to-call’s recording
POST
/
dialer
/
click2call
/
{id}
/
recording
curl -X POST https://api.60db.ai/dialer/click2call/7d004ba2-565f-4ee2-9aa2-19523d8db7ae/recording \
-H "Authorization: Bearer your-api-key"
// 1. Has the audio landed yet?
const call = await fetch(
`https://api.60db.ai/dialer/click2call/${callId}?refresh=1`,
{ headers: { Authorization: `Bearer ${key}` } },
).then((r) => r.json());
// 2. Mint the URL
if (call.data.call.recording_available) {
const res = await fetch(
`https://api.60db.ai/dialer/click2call/${callId}/recording`,
{ method: 'POST', headers: { Authorization: `Bearer ${key}` } },
);
const { data } = await res.json();
console.log('Play at:', data.recording.playback_url);
}
res = requests.post(
f"https://api.60db.ai/dialer/click2call/{call_id}/recording",
headers={"Authorization": f"Bearer {os.environ['SIXTYDB_API_KEY']}"},
)
rec = res.json()["data"]["recording"]
print(rec["playback_url"], rec["expires_at"])
{
"success": true,
"data": {
"recording": {
"call_id": "7d004ba2-565f-4ee2-9aa2-19523d8db7ae",
"recording_id": "rec_01J9Z4K7",
"recording_status": "uploaded",
"recording_format": "wav",
"recording_size": 1048576,
"playback_url": "https://cdn.60db.ai/recordings/...",
"expires_at": "2026-09-23T14:20:00Z"
}
}
}
{
"success": false,
"message": "This call was not recorded. Turn recording on before placing the call.",
"code": "RECORDING_UNAVAILABLE"
}
Mint a playback URL for the recording of a click-to-call placed with
record: true.
This is a POST because it mints a credential — a signed URL to a customer’s conversation. That is not a safe, idempotent read, and it must not end up in a browser history, a proxy log or a prefetch. The URL expires in minutes and is never stored on our side; mint a new one when you need it.
{id} accepts the call_id, your reference_id, or the recording_id.
Ordering
Recording audio is produced by the call platform and uploaded after the call ends, so it lands a little later than the terminal event. Checkrecording_available on the call first — and pass ?refresh=1 when you do, which is what makes a finished call go look for audio that has since appeared:
curl "https://api.60db.ai/dialer/click2call/CALL_ID?refresh=1" \
-H "Authorization: Bearer $SIXTYDB_API_KEY"
Request
Headers
string
required
Bearer token with your API key
Path
string
required
The
call_id, the reference_id, or the recording_idResponse
object
Show properties
Show properties
string
The call this recording belongs to
string
Opaque recording id
string
e.g.
uploadedstring | null
Audio format, when the platform reports one
integer | null
Size in bytes, when the platform reports one
string
The signed URL. Short-lived — play or download it now, don’t persist it
string
ISO 8601 expiry
Errors
| Status | Code | Meaning |
|---|---|---|
| 404 | CALL_NOT_FOUND | No such call, reference or recording in this workspace |
| 404 | RECORDING_NOT_OWNED | The recording belongs to another user in your workspace |
| 404 | RECORDING_UNAVAILABLE | The call wasn’t recorded, or the platform hasn’t produced a recording for it |
| 409 | DIALER_NOT_PROVISIONED | Trunk not set up (Gate T) |
RECORDING_UNAVAILABLE reads as two different messages on purpose — “this call was not recorded” and “this call asked to be recorded, but no recording was produced” have different remedies. The first means turn record on before placing the call; the second is worth reporting rather than retrying.A recorded conversation belongs to whoever placed the call, so a teammate gets RECORDING_NOT_OWNED rather than the audio.Example
curl -X POST https://api.60db.ai/dialer/click2call/7d004ba2-565f-4ee2-9aa2-19523d8db7ae/recording \
-H "Authorization: Bearer your-api-key"
// 1. Has the audio landed yet?
const call = await fetch(
`https://api.60db.ai/dialer/click2call/${callId}?refresh=1`,
{ headers: { Authorization: `Bearer ${key}` } },
).then((r) => r.json());
// 2. Mint the URL
if (call.data.call.recording_available) {
const res = await fetch(
`https://api.60db.ai/dialer/click2call/${callId}/recording`,
{ method: 'POST', headers: { Authorization: `Bearer ${key}` } },
);
const { data } = await res.json();
console.log('Play at:', data.recording.playback_url);
}
res = requests.post(
f"https://api.60db.ai/dialer/click2call/{call_id}/recording",
headers={"Authorization": f"Bearer {os.environ['SIXTYDB_API_KEY']}"},
)
rec = res.json()["data"]["recording"]
print(rec["playback_url"], rec["expires_at"])
{
"success": true,
"data": {
"recording": {
"call_id": "7d004ba2-565f-4ee2-9aa2-19523d8db7ae",
"recording_id": "rec_01J9Z4K7",
"recording_status": "uploaded",
"recording_format": "wav",
"recording_size": 1048576,
"playback_url": "https://cdn.60db.ai/recordings/...",
"expires_at": "2026-09-23T14:20:00Z"
}
}
}
{
"success": false,
"message": "This call was not recorded. Turn recording on before placing the call.",
"code": "RECORDING_UNAVAILABLE"
}