# By call id, with an authoritative refresh
curl "https://api.60db.ai/dialer/click2call/7d004ba2-565f-4ee2-9aa2-19523d8db7ae?refresh=1" \
-H "Authorization: Bearer your-api-key"
# Or straight from your own reference
curl "https://api.60db.ai/dialer/click2call/crm-task-91823" \
-H "Authorization: Bearer your-api-key"
const res = await fetch(
`https://api.60db.ai/dialer/click2call/${callId}?refresh=1`,
{ headers: { Authorization: `Bearer ${process.env.SIXTYDB_API_KEY}` } },
);
const { data } = await res.json();
if (data.call.call_done) {
console.log(data.call.terminal_event, data.call.talk_seconds, data.call.cost_usd);
}
res = requests.get(
f"https://api.60db.ai/dialer/click2call/{call_id}",
params={"refresh": 1},
headers={"Authorization": f"Bearer {os.environ['SIXTYDB_API_KEY']}"},
)
call = res.json()["data"]["call"]
print(call["state"], call["terminal_event"], call["talk_seconds"])
{
"success": true,
"data": {
"call": {
"call_id": "7d004ba2-565f-4ee2-9aa2-19523d8db7ae",
"reference_id": "crm-task-91823",
"outbound_trunk_id": "00000000-0000-4000-8000-000000000000",
"did": "+917900000000",
"agent_number": "+919812345678",
"customer_number": "+919876543210",
"state": "completed",
"call_done": true,
"terminal_event": "call.completed",
"hangup_cause": "NORMAL_CLEARING",
"leg": null,
"error": null,
"error_detail": null,
"talk_seconds": 66,
"total_seconds": 92,
"start_time": "2026-09-23T14:11:27.134Z",
"answer_time": "2026-09-23T14:11:53.392Z",
"end_time": "2026-09-23T14:12:59.921Z",
"metadata": { "lead_id": "L-991" },
"record_requested": true,
"recording_id": "rec_01J9Z4K7",
"recording_status": "uploaded",
"recording_available": true,
"callback_url": "https://your-app.example.com/webhooks/qcall",
"callback_secret_last4": "oose",
"cost_usd": 0.0033,
"billing_status": "billed",
"placed_via": "api_key",
"created_by_user_id": 4021,
"api_key_id": 17,
"api_key_name": "crm-integration",
"created_at": "2026-09-23T14:11:27.134Z"
}
}
}
{
"success": false,
"message": "That call does not belong to this workspace.",
"code": "CALL_NOT_FOUND"
}
Click-to-Call
Get Click-to-Call
State, outcome, cost and recording status for one click-to-call
GET
/
dialer
/
click2call
/
{id}
# By call id, with an authoritative refresh
curl "https://api.60db.ai/dialer/click2call/7d004ba2-565f-4ee2-9aa2-19523d8db7ae?refresh=1" \
-H "Authorization: Bearer your-api-key"
# Or straight from your own reference
curl "https://api.60db.ai/dialer/click2call/crm-task-91823" \
-H "Authorization: Bearer your-api-key"
const res = await fetch(
`https://api.60db.ai/dialer/click2call/${callId}?refresh=1`,
{ headers: { Authorization: `Bearer ${process.env.SIXTYDB_API_KEY}` } },
);
const { data } = await res.json();
if (data.call.call_done) {
console.log(data.call.terminal_event, data.call.talk_seconds, data.call.cost_usd);
}
res = requests.get(
f"https://api.60db.ai/dialer/click2call/{call_id}",
params={"refresh": 1},
headers={"Authorization": f"Bearer {os.environ['SIXTYDB_API_KEY']}"},
)
call = res.json()["data"]["call"]
print(call["state"], call["terminal_event"], call["talk_seconds"])
{
"success": true,
"data": {
"call": {
"call_id": "7d004ba2-565f-4ee2-9aa2-19523d8db7ae",
"reference_id": "crm-task-91823",
"outbound_trunk_id": "00000000-0000-4000-8000-000000000000",
"did": "+917900000000",
"agent_number": "+919812345678",
"customer_number": "+919876543210",
"state": "completed",
"call_done": true,
"terminal_event": "call.completed",
"hangup_cause": "NORMAL_CLEARING",
"leg": null,
"error": null,
"error_detail": null,
"talk_seconds": 66,
"total_seconds": 92,
"start_time": "2026-09-23T14:11:27.134Z",
"answer_time": "2026-09-23T14:11:53.392Z",
"end_time": "2026-09-23T14:12:59.921Z",
"metadata": { "lead_id": "L-991" },
"record_requested": true,
"recording_id": "rec_01J9Z4K7",
"recording_status": "uploaded",
"recording_available": true,
"callback_url": "https://your-app.example.com/webhooks/qcall",
"callback_secret_last4": "oose",
"cost_usd": 0.0033,
"billing_status": "billed",
"placed_via": "api_key",
"created_by_user_id": 4021,
"api_key_id": 17,
"api_key_name": "crm-integration",
"created_at": "2026-09-23T14:11:27.134Z"
}
}
}
{
"success": false,
"message": "That call does not belong to this workspace.",
"code": "CALL_NOT_FOUND"
}
Read one click-to-call.
{id} accepts either the call_id or your own reference_id, so you can reconcile straight from your own records without storing ours.
Request
Headers
string
required
Bearer token with your API key
Path
string
required
The
call_id or the reference_idQuery
boolean
default:"false"
Ask the call platform for the authoritative state before answering. Accepts
1, true or yes.Off by default so a UI can poll this cheaply. Turn it on when you need the truth — it is what repairs a call whose terminal webhook never arrived, and what picks up a recording that has finished uploading. It only goes upstream when the call is unfinished, or finished-but-awaiting-recording; an upstream blip never fails the read.Response
200 OK withdata.call — the same object Place Click-to-Call returns.
Every field below lives under data.call. The ones worth reading first:
string
initiated (dialling), bridged (talking), completed, failed, rejected or unknownboolean
true once the outcome is final — this is the flag to gate your own state machine onstring | null
How it ended:
call.completed, call.not_answered, call.failed or call.temporaryfailedstring | null
Why:
NORMAL_CLEARING, NO_ANSWER, USER_BUSY, CALL_REJECTED, MAX_DURATION, ORIGINATOR_CANCEL, UNALLOCATED_NUMBER, NORMAL_CIRCUIT_CONGESTION, MEDIA_FAILURE, CARRIER_LINK_DOWNstring | null
On failures:
agent or customer — which side failedinteger | null
Bridged talk time. This is what is billed
integer | null
Seconds from admission to the end of the call
number | null
What this call cost.
null with billing_status: null means nothing was owedboolean
true when a playback URL can be mintedErrors
| Status | Code | Meaning |
|---|---|---|
| 404 | CALL_NOT_FOUND | No such call or reference in this workspace |
| 409 | DIALER_NOT_PROVISIONED | Trunk not set up (Gate T) |
Example
# By call id, with an authoritative refresh
curl "https://api.60db.ai/dialer/click2call/7d004ba2-565f-4ee2-9aa2-19523d8db7ae?refresh=1" \
-H "Authorization: Bearer your-api-key"
# Or straight from your own reference
curl "https://api.60db.ai/dialer/click2call/crm-task-91823" \
-H "Authorization: Bearer your-api-key"
const res = await fetch(
`https://api.60db.ai/dialer/click2call/${callId}?refresh=1`,
{ headers: { Authorization: `Bearer ${process.env.SIXTYDB_API_KEY}` } },
);
const { data } = await res.json();
if (data.call.call_done) {
console.log(data.call.terminal_event, data.call.talk_seconds, data.call.cost_usd);
}
res = requests.get(
f"https://api.60db.ai/dialer/click2call/{call_id}",
params={"refresh": 1},
headers={"Authorization": f"Bearer {os.environ['SIXTYDB_API_KEY']}"},
)
call = res.json()["data"]["call"]
print(call["state"], call["terminal_event"], call["talk_seconds"])
{
"success": true,
"data": {
"call": {
"call_id": "7d004ba2-565f-4ee2-9aa2-19523d8db7ae",
"reference_id": "crm-task-91823",
"outbound_trunk_id": "00000000-0000-4000-8000-000000000000",
"did": "+917900000000",
"agent_number": "+919812345678",
"customer_number": "+919876543210",
"state": "completed",
"call_done": true,
"terminal_event": "call.completed",
"hangup_cause": "NORMAL_CLEARING",
"leg": null,
"error": null,
"error_detail": null,
"talk_seconds": 66,
"total_seconds": 92,
"start_time": "2026-09-23T14:11:27.134Z",
"answer_time": "2026-09-23T14:11:53.392Z",
"end_time": "2026-09-23T14:12:59.921Z",
"metadata": { "lead_id": "L-991" },
"record_requested": true,
"recording_id": "rec_01J9Z4K7",
"recording_status": "uploaded",
"recording_available": true,
"callback_url": "https://your-app.example.com/webhooks/qcall",
"callback_secret_last4": "oose",
"cost_usd": 0.0033,
"billing_status": "billed",
"placed_via": "api_key",
"created_by_user_id": 4021,
"api_key_id": 17,
"api_key_name": "crm-integration",
"created_at": "2026-09-23T14:11:27.134Z"
}
}
}
{
"success": false,
"message": "That call does not belong to this workspace.",
"code": "CALL_NOT_FOUND"
}