Webhooks

🔔 Outbound Webhooks

 

Outbound Webhooks allow MessengerOS to notify your application in real time whenever something happens to a notification you sent — delivery confirmations, opens, clicks, bounces, unsubscribes, and more.

Instead of polling our API for status updates, you register a URL and we'll push an HTTP POST to it every time an event occurs.

 

⚙️ Step 1: Create a Webhook Configuration

Head over to Settings → Webhooks → Add Webhook in your MessengerOS account.
You'll need to provide:

  • URL — The HTTPS endpoint on your server that will receive the webhook POST requests.
  • Channels — Which channels to receive events for: email, sms, and/or whatsapp.

A secret key is automatically generated for you. Keep it safe — you'll use it to verify that incoming requests are genuinely from MessengerOS.

 

🔐 Step 2: Verify the Signature

Every webhook request we send includes an X-Signature header containing an HMAC-SHA256 signature of the raw request body, signed with your webhook secret:

X-Signature: sha256=<hmac_sha256_hex_of_request_body>
📋 Copy

To verify the signature on your end, compute the HMAC-SHA256 of the raw request body using your secret and compare it to the value in the header (after stripping the sha256= prefix). Here's how you'd do it in PHP:

$rawBody  = file_get_contents('php://input');
$secret   = 'your_webhook_secret_here';
$header   = $_SERVER['HTTP_X_SIGNATURE'] ?? '';

// Strip the "sha256=" prefix
$provided = str_replace('sha256=', '', $header);

// Compute expected signature
$expected = hash_hmac('sha256', $rawBody, $secret);

if (!hash_equals($expected, $provided)) {
    http_response_code(401);
    exit('Invalid signature');
}

// Signature is valid — process the payload
$payload = json_decode($rawBody, true);
📋 Copy

 

📦 Step 3: Understand the Payload

All webhook events share the same JSON structure:

{
    "status":                 "accepted",          // event type (see table below)
    "notification_origin_id": "your-unique-id",    // the ID you sent when creating the notification
    "recipient":              "user@example.com",  // email address or phone number
    "error":                  null                 // present only on failure events, null otherwise
}
📋 Copy

 

📋 Step 4: Handle the Events

The status field tells you what happened. Here are all possible values:


Email events
Status Description Error field
accepted The email was accepted to be sent to recipient and is queued for delivery. null
failed The email could not be delivered. Check the error field for details. Reason for failure (e.g. "MX record not found", "Delivery failed")
open The recipient opened the email. null
click The recipient clicked a link in the email. null
unsubscribed The recipient unsubscribed from all notifications. null
complaint The recipient marked the email as spam. null

SMS events
Status Description Error field
accepted The SMS was accepted to be sent to recipient and is queued for delivery. null
failed The SMS could not be sent. Check the error field for details. Reason for failure
Delivered The SMS was successfully delivered to the recipient's handset. null
Undelivered The SMS could not be delivered to the recipient. null

 

✅ Step 5: Respond to the Webhook

Your endpoint must return a 2xx HTTP status code (e.g. 200 OK) within 10 seconds to acknowledge that you received the event. If your endpoint does not respond with a 2xx status, the delivery will be marked as failed.

HTTP/1.1 200 OK

 

💡 Tips

  • Always use notification_origin_id when sending notifications — without it, no webhook will be dispatched for that notification.
  • Multiple webhook configs are supported. You can register several endpoints for the same project — each one will receive all matching events.
  • Per-channel filtering is supported. Configure each webhook to receive events only for the channels you care about (email, sms, whatsapp).
© MessengerOS