This page explains how GSM Delivery Reports work — i.e. how you get notified about the delivery status of SMS messages sent through the GSM SMS API, 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 delivery updates.
- We send you a report automatically — as messages progress through delivery, we push status updates straight to that URL. No polling needed.
Step 1: Configure Your Webhook
Before you can receive any delivery reports, a webhook must be registered for your username.
| Field | Type | Required | Description |
|---|---|---|---|
username | string | Yes | Your account username — reports for all messages sent 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). |
Only one active webhook per username is used at a time. If more than one is configured, the most recently updated active one wins.
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:
- As each message you sent moves through delivery, our system tracks its status.
- Once a message reaches a reportable state, a report is generated for it.
- That report is sent as an HTTP
POSTrequest, in JSON, to your registered webhookurl. - If your token is set, it's attached to the request so you can verify the call came from us.
- Each report is sent only once per message — once delivered (success or failure on our end), it won't be resent.
- 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.
Report Payload
This is exactly what lands on your webhook URL:
{
"event": "gsm.status.update",
"providerMessageId": "GSMCAMP_20260711_138476",
"receiver": "919912345678",
"status": "DELIVERED",
"status_code": 0,
"error_code": null,
"errorMessage": null
}
| Field | Type | Description |
|---|---|---|
event | string | Always "gsm.status.update". |
providerMessageId | string | The request_id returned when you originally sent the message. Use this to match the report back to your broadcast/message. |
receiver | string | The phone number this specific report is about. |
status | string | One of SENT, DELIVERED, or FAILED. |
status_code | integer | Numeric status code from the carrier, when available; otherwise 0. |
error_code | string / null | "DELIVERY_FAILED" when status is FAILED, otherwise null. |
errorMessage | string / null | A short human-readable failure reason when status is FAILED, otherwise null. |
Request Headers
| Header | Value |
|---|---|
Content-Type | application/json |
| Your configured token (if set) | sent as-is, e.g. Authorization: Bearer <your_token> |
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 }
Example: Receiving the Report (PHP)
<?php
// your-server.com/webhook/gsm-delivery-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);
$providerMessageId = $payload["providerMessageId"] ?? "";
$receiver = $payload["receiver"] ?? "";
$status = $payload["status"] ?? "";
$errorMessage = $payload["errorMessage"] ?? null;
if ($status === "DELIVERED") {
// e.g. mark this message as delivered in your own system
} elseif ($status === "SENT") {
// e.g. mark this message as sent, awaiting final delivery confirmation
} elseif ($status === "FAILED") {
// e.g. notify your team with $errorMessage
}
http_response_code(200);
echo json_encode(["received" => true]);
Delivery Status Reference
status value | Meaning |
|---|---|
SENT | Message has been sent out and is awaiting final delivery confirmation. |
DELIVERED | Message was successfully delivered to the recipient's handset. |
FAILED | Message could not be delivered. Check errorMessage for details. |
Notes
- Reports are generated per recipient, so a single broadcast to multiple contacts will produce a separate report for each phone number.
- 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.
