Voice Call Status Report (Webhook)

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:

  1. You configure a webhook once — tell us the URL (and optional token) where we should send updates.
  2. 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.

FieldTypeRequiredDescription
usernamestringYesYour account username — reports for all voice campaigns under this username go to the same webhook.
urlstring (URL)YesThe HTTPS endpoint on your server that will receive the report.
tokenstringNoSent as-is in the request headers on every delivery, so you can authenticate the incoming call (e.g. Authorization: Bearer xxxx).
statusinteger1 = 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:

  1. You launch a voice call campaign; each contact in it gets called.
  2. As call progress happens for a contact (e.g. it's answered, fails, or completes), our system generates a status report for that call.
  3. That report is sent as an HTTP POST request, in JSON, to your registered webhook url.
  4. If your token is set, it's attached to the request so you can verify the call came from us.
  5. 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
}
FieldTypeDescription
eventstringAlways voice.status.update for this webhook.
providerMessageIdstringThe campaign/request ID (request_id) this call belongs to.
receiverstringRecipient phone number (with country code, no +).
statusstringCall status — see Delivery Status Reference below.
status_codeintegerNumeric status code (0 = normal/success).
error_codeinteger | nullError code if the call failed, otherwise null.
errorMessagestringHuman-readable call outcome (e.g. NORMAL HANG UP).
durationintegerCall duration in seconds.

Request Headers

HeaderValue
Content-Typeapplication/json
AuthorizationBearer <your_token> — sent only if a token is configured for your webhook
tokenSame 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 valueMeaning
ANSWEREDCall was answered by the receiver.
FAILEDCall could not be completed.
NO_ANSWERCall was not picked up.
BUSYReceiver'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.