This page explains how Voice Call Status Reports work — i.e. how you get notified of each call's outcome (answered, failed, no answer, etc.) as it happens, without having to poll our API.
The flow has two parts:
- You configure a webhook once — tell us the URL (and optional token) where we should send updates.
- We send you a report automatically — every time a call in your campaign gets a status update, we push the result straight to that URL. No polling needed.
Step 1: Configure Your Webhook
Before you can receive any call status reports, a webhook must be registered for your username.
| Field | Type | Required | Description |
|---|---|---|---|
username | string | Yes | Your account username — reports for all voice campaigns under this username go to the same webhook. |
url | string (URL) | Yes | The HTTPS endpoint on your server that will receive the report. |
token | string | No | Sent as-is in the request headers on every delivery, so you can authenticate the incoming call (e.g. Authorization: Bearer xxxx). |
status | integer | — | 1 = active (webhook is live), 0 = paused. Only active webhooks receive reports. |
Only one active webhook per username is used at a time. If more than one is configured, the first active one found is used.
Reach out to enable/update your webhook URL and token, or use the webhook management endpoint if you've been given access to one.
Step 2: How the Report Is Sent
Once your webhook is active, here's what happens behind the scenes — no action needed from you:
- You launch a voice call campaign; each contact in it gets called.
- As call progress happens for a contact (e.g. it's answered, fails, or completes), our system generates a status report for that call.
- That report is sent as an HTTP
POSTrequest, in JSON, to your registered webhookurl. - If your
tokenis set, it's attached to the request so you can verify the call came from us. - Every attempt is logged on our side (URL called, payload sent, response received, success/failure) so delivery can be traced if something goes wrong on your end.
If no active webhook is found for your username at the time of sending, the report is simply not sent — it's logged internally as
Failed — No active webhook found.
Report Payload
This is exactly what lands on your webhook URL:
{
"event": "voice.status.update",
"providerMessageId": "VCAMP_20260728_987B57D2",
"receiver": "917987701494",
"status": "ANSWERED",
"status_code": 0,
"error_code": null,
"errorMessage": "NORMAL HANG UP",
"duration": 35
}
| Field | Type | Description |
|---|---|---|
event | string | Always voice.status.update for this webhook. |
providerMessageId | string | The campaign/request ID (request_id) this call belongs to. |
receiver | string | Recipient phone number (with country code, no +). |
status | string | Call status — see Delivery Status Reference below. |
status_code | integer | Numeric status code (0 = normal/success). |
error_code | integer | null | Error code if the call failed, otherwise null. |
errorMessage | string | Human-readable call outcome (e.g. NORMAL HANG UP). |
duration | integer | Call duration in seconds. |
Request Headers
| Header | Value |
|---|---|
Content-Type | application/json |
Authorization | Bearer <your_token> — sent only if a token is configured for your webhook |
token | Same token value, also sent as a raw header (for integrations that don't support Bearer auth) |
What You Should Return
Your endpoint just needs to respond with an HTTP 2xx status code to acknowledge receipt. Any response body is accepted — we log it for reference, but don't parse it.
{ "received": true }
Anything other than a 2xx response (or a timeout / connection error) is logged as Failed on our end.
Example: Receiving the Report (PHP)
<?php
// your-server.com/webhook/voice-status-report.php
$expectedToken = "Bearer your_secret_token"; // matches the token you registered
$authHeader = $_SERVER["HTTP_AUTHORIZATION"] ?? "";
if ($authHeader !== $expectedToken) {
http_response_code(401);
echo json_encode(["received" => false, "message" => "Invalid token"]);
exit;
}
$payload = json_decode(file_get_contents("php://input"), true);
$requestId = $payload["providerMessageId"] ?? "";
$receiver = $payload["receiver"] ?? "";
$status = $payload["status"] ?? "";
$duration = $payload["duration"] ?? 0;
if ($status === "ANSWERED") {
// e.g. mark this contact as reached in your own system
} else {
// e.g. mark as failed/no-answer, notify your team, retry logic, etc.
}
http_response_code(200);
echo json_encode(["received" => true]);
Delivery Status Reference
status value | Meaning |
|---|---|
ANSWERED | Call was answered by the receiver. |
FAILED | Call could not be completed. |
NO_ANSWER | Call was not picked up. |
BUSY | Receiver's line was busy. |
Confirm the full list of status values your system emits in production and update this table accordingly.
Notes
- Reports are sent per call/contact as their status updates — you'll get one webhook call per recipient in your campaign, not one per campaign.
- If your webhook URL is unreachable or returns an error, the failure is logged on our side; make sure your endpoint stays up and responds quickly (avoid long processing before sending back the
2xx). - Keep your token private — anyone with it could send fake reports to your endpoint pretending to be us. Rotate it if you suspect it's been exposed.
- Missed or failed deliveries can be reconciled anytime using the Voice Call Report API, which lets you pull the full status of a campaign using its
request_id.
