curl https://api.60db.ai/dialer/click2call/crm-task-91823/events \
-H "Authorization: Bearer your-api-key"
const res = await fetch(
`https://api.60db.ai/dialer/click2call/${callId}/events`,
{ headers: { Authorization: `Bearer ${process.env.SIXTYDB_API_KEY}` } },
);
const { data } = await res.json();
for (const e of data.events) {
const r = e.relay;
console.log(e.event, r ? `${r.delivered ? 'delivered' : 'pending'} (${r.attempts} attempts)` : 'no relay');
}
res = requests.get(
f"https://api.60db.ai/dialer/click2call/{call_id}/events",
headers={"Authorization": f"Bearer {os.environ['SIXTYDB_API_KEY']}"},
)
for e in res.json()["data"]["events"]:
relay = e["relay"] or {}
print(e["event"], e["sequence"], relay.get("status"), relay.get("delivered"))
{
"success": true,
"data": {
"call_id": "7d004ba2-565f-4ee2-9aa2-19523d8db7ae",
"reference_id": "crm-task-91823",
"callback_url": "https://your-app.example.com/webhooks/qcall",
"events": [
{
"event_id": "610c57d4-ab26-80e6-812a-20cd77bd2959",
"event": "call.answered",
"sequence": 1,
"status_code": 200,
"received_at": "2026-09-23T14:11:53.612Z",
"applied": true,
"apply_error": null,
"relay": {
"url": "https://your-app.example.com/webhooks/qcall",
"attempts": 1,
"status": 200,
"delivered": true,
"delivered_at": "2026-09-23T14:11:53.884Z",
"last_attempt_at": "2026-09-23T14:11:53.884Z",
"error": null
},
"payload": { "event": "call.answered", "sequence": 1, "data": { "call_id": "7d004ba2-565f-4ee2-9aa2-19523d8db7ae" } }
},
{
"event_id": "c4d79b8d-5b2d-8ff1-84b0-5943d59b21a0",
"event": "call.completed",
"sequence": 2,
"status_code": 200,
"received_at": "2026-09-23T14:13:00.104Z",
"applied": true,
"apply_error": null,
"relay": {
"url": "https://your-app.example.com/webhooks/qcall",
"attempts": 3,
"status": 502,
"delivered": false,
"delivered_at": null,
"last_attempt_at": "2026-09-23T14:19:11.002Z",
"error": null
},
"payload": { "event": "call.completed", "sequence": 2, "data": { "hangup_cause": "NORMAL_CLEARING" } }
}
]
}
}
Click-to-Call
List Call Events
Every event for one call, and what your own webhook replied to it
GET
/
dialer
/
click2call
/
{id}
/
events
curl https://api.60db.ai/dialer/click2call/crm-task-91823/events \
-H "Authorization: Bearer your-api-key"
const res = await fetch(
`https://api.60db.ai/dialer/click2call/${callId}/events`,
{ headers: { Authorization: `Bearer ${process.env.SIXTYDB_API_KEY}` } },
);
const { data } = await res.json();
for (const e of data.events) {
const r = e.relay;
console.log(e.event, r ? `${r.delivered ? 'delivered' : 'pending'} (${r.attempts} attempts)` : 'no relay');
}
res = requests.get(
f"https://api.60db.ai/dialer/click2call/{call_id}/events",
headers={"Authorization": f"Bearer {os.environ['SIXTYDB_API_KEY']}"},
)
for e in res.json()["data"]["events"]:
relay = e["relay"] or {}
print(e["event"], e["sequence"], relay.get("status"), relay.get("delivered"))
{
"success": true,
"data": {
"call_id": "7d004ba2-565f-4ee2-9aa2-19523d8db7ae",
"reference_id": "crm-task-91823",
"callback_url": "https://your-app.example.com/webhooks/qcall",
"events": [
{
"event_id": "610c57d4-ab26-80e6-812a-20cd77bd2959",
"event": "call.answered",
"sequence": 1,
"status_code": 200,
"received_at": "2026-09-23T14:11:53.612Z",
"applied": true,
"apply_error": null,
"relay": {
"url": "https://your-app.example.com/webhooks/qcall",
"attempts": 1,
"status": 200,
"delivered": true,
"delivered_at": "2026-09-23T14:11:53.884Z",
"last_attempt_at": "2026-09-23T14:11:53.884Z",
"error": null
},
"payload": { "event": "call.answered", "sequence": 1, "data": { "call_id": "7d004ba2-565f-4ee2-9aa2-19523d8db7ae" } }
},
{
"event_id": "c4d79b8d-5b2d-8ff1-84b0-5943d59b21a0",
"event": "call.completed",
"sequence": 2,
"status_code": 200,
"received_at": "2026-09-23T14:13:00.104Z",
"applied": true,
"apply_error": null,
"relay": {
"url": "https://your-app.example.com/webhooks/qcall",
"attempts": 3,
"status": 502,
"delivered": false,
"delivered_at": null,
"last_attempt_at": "2026-09-23T14:19:11.002Z",
"error": null
},
"payload": { "event": "call.completed", "sequence": 2, "data": { "hangup_cause": "NORMAL_CLEARING" } }
}
]
}
}
The forwarding half of the contract, made inspectable. This answers “did my system receive the completed event, and what did it reply?” — a question otherwise only answerable by reading server logs.
{id} accepts either the call_id or your reference_id. Events are returned oldest first.
Request
Headers
string
required
Bearer token with your API key
Path
string
required
The
call_id or the reference_idResponse
string
The call these events belong to
string
Your reference for that call
string | null
Where this call’s events are relayed.
null if the call was placed without onearray
Show properties
Show properties
string
Stable id for this event. The
x-qcall-event-id your endpoint sawstring
call.answered, call.completed, call.not_answered, call.failed or call.temporaryfailedinteger | null
1 for the first event of a call, 2 for the secondinteger | null
The platform’s status code for the event
string
ISO 8601 — when 60db received it
boolean
Whether the event has been folded into the call’s state
string | null
Why it hasn’t been, if it hasn’t
object
The full event body, exactly as relayed
object | null
Delivery to your endpoint;
null when the call had no callback_urlUndelivered relays are retried by a reconciler: up to 6 attempts, at least two minutes apart, abandoned once the event is 24 hours old. Retried on
408, 425, 429, any 5xx, and network or timeout errors — any other 4xx is treated as a permanent rejection.Errors
| 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
curl https://api.60db.ai/dialer/click2call/crm-task-91823/events \
-H "Authorization: Bearer your-api-key"
const res = await fetch(
`https://api.60db.ai/dialer/click2call/${callId}/events`,
{ headers: { Authorization: `Bearer ${process.env.SIXTYDB_API_KEY}` } },
);
const { data } = await res.json();
for (const e of data.events) {
const r = e.relay;
console.log(e.event, r ? `${r.delivered ? 'delivered' : 'pending'} (${r.attempts} attempts)` : 'no relay');
}
res = requests.get(
f"https://api.60db.ai/dialer/click2call/{call_id}/events",
headers={"Authorization": f"Bearer {os.environ['SIXTYDB_API_KEY']}"},
)
for e in res.json()["data"]["events"]:
relay = e["relay"] or {}
print(e["event"], e["sequence"], relay.get("status"), relay.get("delivered"))
{
"success": true,
"data": {
"call_id": "7d004ba2-565f-4ee2-9aa2-19523d8db7ae",
"reference_id": "crm-task-91823",
"callback_url": "https://your-app.example.com/webhooks/qcall",
"events": [
{
"event_id": "610c57d4-ab26-80e6-812a-20cd77bd2959",
"event": "call.answered",
"sequence": 1,
"status_code": 200,
"received_at": "2026-09-23T14:11:53.612Z",
"applied": true,
"apply_error": null,
"relay": {
"url": "https://your-app.example.com/webhooks/qcall",
"attempts": 1,
"status": 200,
"delivered": true,
"delivered_at": "2026-09-23T14:11:53.884Z",
"last_attempt_at": "2026-09-23T14:11:53.884Z",
"error": null
},
"payload": { "event": "call.answered", "sequence": 1, "data": { "call_id": "7d004ba2-565f-4ee2-9aa2-19523d8db7ae" } }
},
{
"event_id": "c4d79b8d-5b2d-8ff1-84b0-5943d59b21a0",
"event": "call.completed",
"sequence": 2,
"status_code": 200,
"received_at": "2026-09-23T14:13:00.104Z",
"applied": true,
"apply_error": null,
"relay": {
"url": "https://your-app.example.com/webhooks/qcall",
"attempts": 3,
"status": 502,
"delivered": false,
"delivered_at": null,
"last_attempt_at": "2026-09-23T14:19:11.002Z",
"error": null
},
"payload": { "event": "call.completed", "sequence": 2, "data": { "hangup_cause": "NORMAL_CLEARING" } }
}
]
}
}