/Webhooks

Webhooks

Get notified in real time when a message is delivered, fails, or bounces.

Setting Up Webhooks

  1. Go to your app's Webhooks tab in the dashboard
  2. Click Create Webhook
  3. Enter your endpoint URL (must be HTTPS)
  4. Select which events you want to receive
  5. Save — a signing secret is generated automatically

Events

EventDescriptionChannel
message.queuedMessage queued for sendingSMS, Email
message.sentMessage submitted to carrierSMS, Email
message.deliveredCarrier confirmed deliverySMS, Email
message.failedDelivery failedSMS, Email
message.openedRecipient opened the emailEmail only
message.clickedRecipient clicked a linkEmail only
message.bouncedEmail bouncedEmail only
message.complainedRecipient marked as spamEmail only

Webhook Payload

{
  "event": "message.delivered",
  "message_id": "msg_7f3a2b9d1e4c",
  "recipient_id": "rcpt_4a8b2c1d",
  "recipient": "+233245972246",
  "status": "delivered",
  "timestamp": "2026-03-21T10:30:15Z",
  "metadata": {}
}

Verifying Webhooks

Every webhook includes two headers for verification:

  • X-SMSGist-Signature — HMAC-SHA256 signature (sha256={hex})
  • X-SMSGist-Timestamp — Unix timestamp (for replay protection)

The signature is computed as: HMAC-SHA256(timestamp + "." + body, secret)

Webhooks older than 5 minutes should be rejected.

Using the SDKs

Go

if zNotification.VerifyWebhookSignature(
    body,
    r.Header.Get("X-SMSGist-Signature"),
    r.Header.Get("X-SMSGist-Timestamp"),
    webhookSecret,
) {
    // Valid — process the event
}

PHP

use SMSGist\Webhook;

$isValid = Webhook::verifySignature(
    body: file_get_contents('php://input'),
    signature: $_SERVER['HTTP_X_SMSGIST_SIGNATURE'],
    timestamp: $_SERVER['HTTP_X_SMSGIST_TIMESTAMP'],
    secret: 'your-webhook-secret',
);

Node.js

import { Webhook } from '@smsgist/node';

const isValid = Webhook.verifySignature({
  body: rawBody,
  signature: req.headers['x-smsgist-signature'],
  timestamp: req.headers['x-smsgist-timestamp'],
  secret: 'your-webhook-secret',
});

Retry Policy

If your endpoint returns a non-2xx status code, we retry with exponential backoff:

AttemptDelay
15 seconds
25 minutes
330 minutes
42 hours
512 hours
624 hours

After 6 failed attempts, the webhook is marked as degraded and you'll see a warning in the dashboard.

Testing Webhooks

Use the Send Test Event button in the dashboard to fire a sample webhook to your endpoint. This helps verify your setup before going live.