{
"id": "whd_0d6f7a8b9c0d40b18293a4b5c6d7e8f3",
"type": "campaign.record.updated",
"created_at": "2026-10-26T10:31:00.000Z",
"data": {
"campaign_id": "cmp_7c1d2e3f4a5b4c6d8e9f0a1b2c3d4e5f",
"record": {
"id": "rec_1a2b3c4d5e6f40718293a4b5c6d7e8f9",
"campaign_id": "cmp_7c1d2e3f4a5b4c6d8e9f0a1b2c3d4e5f",
"seq": 1,
"phone": "+9198XXXXXX01",
"external_id": "LN-123",
"variables": {
"borrower_first_name": "Ravi",
"emi_amount": "4574",
"due_date": "2026-11-05",
"lender_name": "Credfin"
},
"source": "csv",
"source_row": 2,
"status": "completed",
"result": "success",
"result_detail": "confirmed_on_time",
"missing_variables": [],
"attempts_made": 2,
"callbacks_used": 0,
"next_attempt_number": null,
"next_attempt_at": null,
"next_is_callback": false,
"last_status": "completed",
"last_outcome": "confirmed_on_time",
"last_call_at": "2026-10-26T10:31:00.000Z",
"post_call": {
"payment_date": "2026-11-05"
},
"attempts": [
{
"attempt_number": 1,
"call_id": "call_0a1b2c3d4e5f40718293a4b5c6d7e8f1",
"scheduled_for": "2026-10-26T04:30:00.000Z",
"started_at": "2026-10-26T04:30:04.000Z",
"ended_at": "2026-10-26T04:30:49.000Z",
"status": "no_answer",
"outcome": null,
"duration_sec": 0,
"post_call": {},
"cost_micros": 0,
"decision": "instant_redial",
"callback": false
},
{
"attempt_number": 2,
"call_id": "call_0a1b2c3d4e5f40718293a4b5c6d7e8f2",
"scheduled_for": "2026-10-26T10:30:00.000Z",
"started_at": "2026-10-26T10:30:02.000Z",
"ended_at": "2026-10-26T10:31:00.000Z",
"status": "completed",
"outcome": "confirmed_on_time",
"duration_sec": 52,
"post_call": {
"payment_date": "2026-11-05"
},
"cost_micros": 4500000,
"decision": "done",
"callback": false
}
],
"paid_at": null,
"collected_micros": 0,
"closed_at": "2026-10-26T10:31:00.000Z",
"created_at": "2026-10-24T05:05:00.000Z",
"updated_at": "2026-10-26T10:31:00.000Z"
}
}
}Campaign record updated
Sent on every change of a record’s status and after every attempt, with the record as
GET /v1/campaigns/{campaignId}/records/{recordId} shows it. Records added to a running or paused campaign
are sent too, as pending. Use record.status, record.result and the last entry of record.attempts to
update your own systems.
{
"id": "whd_0d6f7a8b9c0d40b18293a4b5c6d7e8f3",
"type": "campaign.record.updated",
"created_at": "2026-10-26T10:31:00.000Z",
"data": {
"campaign_id": "cmp_7c1d2e3f4a5b4c6d8e9f0a1b2c3d4e5f",
"record": {
"id": "rec_1a2b3c4d5e6f40718293a4b5c6d7e8f9",
"campaign_id": "cmp_7c1d2e3f4a5b4c6d8e9f0a1b2c3d4e5f",
"seq": 1,
"phone": "+9198XXXXXX01",
"external_id": "LN-123",
"variables": {
"borrower_first_name": "Ravi",
"emi_amount": "4574",
"due_date": "2026-11-05",
"lender_name": "Credfin"
},
"source": "csv",
"source_row": 2,
"status": "completed",
"result": "success",
"result_detail": "confirmed_on_time",
"missing_variables": [],
"attempts_made": 2,
"callbacks_used": 0,
"next_attempt_number": null,
"next_attempt_at": null,
"next_is_callback": false,
"last_status": "completed",
"last_outcome": "confirmed_on_time",
"last_call_at": "2026-10-26T10:31:00.000Z",
"post_call": {
"payment_date": "2026-11-05"
},
"attempts": [
{
"attempt_number": 1,
"call_id": "call_0a1b2c3d4e5f40718293a4b5c6d7e8f1",
"scheduled_for": "2026-10-26T04:30:00.000Z",
"started_at": "2026-10-26T04:30:04.000Z",
"ended_at": "2026-10-26T04:30:49.000Z",
"status": "no_answer",
"outcome": null,
"duration_sec": 0,
"post_call": {},
"cost_micros": 0,
"decision": "instant_redial",
"callback": false
},
{
"attempt_number": 2,
"call_id": "call_0a1b2c3d4e5f40718293a4b5c6d7e8f2",
"scheduled_for": "2026-10-26T10:30:00.000Z",
"started_at": "2026-10-26T10:30:02.000Z",
"ended_at": "2026-10-26T10:31:00.000Z",
"status": "completed",
"outcome": "confirmed_on_time",
"duration_sec": 52,
"post_call": {
"payment_date": "2026-11-05"
},
"cost_micros": 4500000,
"decision": "done",
"callback": false
}
],
"paid_at": null,
"collected_micros": 0,
"closed_at": "2026-10-26T10:31:00.000Z",
"created_at": "2026-10-24T05:05:00.000Z",
"updated_at": "2026-10-26T10:31:00.000Z"
}
}
}Headers
The event type, same as the body's type.
call.ended, call.analyzed, call.status_changed, reachability.result, reachability.completed, campaign.started, campaign.paused, campaign.resumed, campaign.completed, campaign.canceled, campaign.record.updated, call.dispositioned, dialer.contact_updated Delivery id (whd_...), same as the body's id. Stays the same across retries of one delivery: use it to
drop duplicates.
t=<unix seconds>,v1=<hex HMAC-SHA256(secret, t + "." + raw body)>. t is the time of this delivery try.
Verify it before trusting the body (see the Webhooks tag and the event descriptions).
^t=\d+,v1=[0-9a-f]{64}$Always voice-gateway-webhooks/1.
"voice-gateway-webhooks/1"Body
Response
Any 2xx status, within 10 seconds, acknowledges the delivery (the body is ignored). Anything else (other statuses, timeouts, connection errors) is retried: 8 tries in total, 30 seconds after the first failure, then doubling (30 s, 1 min, 2 min, 4 min, 8 min, 16 min, 32 min; about 63 minutes in all). Redirects are not a supported answer.