Webhooks
Webhooks allow you to receive real-time notifications about message delivery status.
Overview
When the status of your SMS changes (delivered, failed, etc.), we send an HTTP POST request to your configured webhook URL.
Setting Up Webhooks
- Log in to your dashboard
- Navigate to Settings → Webhooks
- Enter your webhook URL
- Select the events you want to receive
- Save your configuration
Webhook Events
| Event | Description |
|---|---|
message.sent | Message accepted by carrier |
message.delivered | Message delivered to recipient |
message.failed | Message delivery failed |
message.expired | Message expired before delivery |
Webhook Payload
All webhook requests are POST requests with JSON body:
{
"event": "message.delivered",
"timestamp": "2026-03-09T15:30:00Z",
"data": {
"messageId": "msg_abc123xyz789",
"recipient": "233200000000",
"senderId": "MyBusiness",
"status": "delivered",
"deliveredAt": "2026-03-09T15:30:00Z"
}
}Event Examples
Message Delivered
{
"event": "message.delivered",
"timestamp": "2026-03-09T15:30:00Z",
"data": {
"messageId": "msg_abc123",
"recipient": "233200000000",
"status": "delivered",
"deliveredAt": "2026-03-09T15:30:00Z"
}
}Message Failed
{
"event": "message.failed",
"timestamp": "2026-03-09T15:30:00Z",
"data": {
"messageId": "msg_abc123",
"recipient": "233200000000",
"status": "failed",
"error": "Invalid phone number",
"errorCode": "INVALID_RECIPIENT"
}
}Verifying Webhooks
All webhook requests include a signature header for verification:
X-Webhook-Signature: sha256=abc123...Verification Example (Node.js)
const crypto = require("crypto");
function verifyWebhook(payload, signature, secret) {
const expectedSignature = crypto
.createHmac("sha256", secret)
.update(payload)
.digest("hex");
return `sha256=${expectedSignature}` === signature;
}
// In your webhook handler
app.post("/webhook", (req, res) => {
const signature = req.headers["x-webhook-signature"];
const isValid = verifyWebhook(
JSON.stringify(req.body),
signature,
process.env.WEBHOOK_SECRET,
);
if (!isValid) {
return res.status(401).send("Invalid signature");
}
// Process the webhook
const { event, data } = req.body;
console.log(`Received ${event}:`, data);
res.status(200).send("OK");
});Retry Policy
If your webhook endpoint returns an error (non-2xx status), we retry:
| Attempt | Delay |
|---|---|
| 1st retry | 1 minute |
| 2nd retry | 5 minutes |
| 3rd retry | 30 minutes |
| 4th retry | 2 hours |
| 5th retry | 24 hours |
After 5 failed attempts, the webhook is marked as failed and no further retries are made.
Response Requirements
Your webhook endpoint should:
- Return a
2xxstatus code within 30 seconds - Respond with any body (body content is ignored)
- Be idempotent (handle duplicate deliveries gracefully)