Back to Documentation

Webhooks

Real-time notifications for message delivery, read receipts, and user interactions.

Overview

Webhooks allow your application to receive real-time notifications when events occur in the Inbox platform. Instead of polling our API, webhooks push data to your application as events happen.

Real-time

Receive events instantly as they happen

Secure

HMAC signature verification included

Reliable

Automatic retries with exponential backoff

Setting Up Webhooks

1. Create a Webhook Endpoint

Create an HTTP endpoint in your application to receive webhook events:

// Express.js example
app.post('/webhooks/inbox', express.raw({type: 'application/json'}), (req, res) => {
  const signature = req.headers['x-inbox-signature'];
  const payload = req.body;
  
  // Verify signature (see security section)
  if (!verifySignature(payload, signature)) {
    return res.status(401).send('Unauthorized');
  }
  
  const event = JSON.parse(payload);
  
  // Handle the event
  switch (event.type) {
    case 'message.delivered':
      handleMessageDelivered(event.data);
      break;
    case 'message.read':
      handleMessageRead(event.data);
      break;
    default:
      console.log('Unhandled event type:', event.type);
  }
  
  res.status(200).send('OK');
});

2. Register Your Webhook

Register your webhook endpoint with the Inbox API:

curl -X POST https://api.getinbox.app/v1/webhooks \
  -H "Authorization: Bearer YOUR_API_KEY" \
  -H "Content-Type: application/json" \
  -d '{
    "url": "https://yourapp.com/webhooks/inbox",
    "events": ["message.delivered", "message.read", "message.failed"],
    "description": "Production webhook endpoint"
  }'

3. Test Your Webhook

Send a test event to verify your endpoint is working:

curl -X POST https://api.getinbox.app/v1/webhooks/test \
  -H "Authorization: Bearer YOUR_API_KEY" \
  -H "Content-Type: application/json" \
  -d '{
    "webhook_id": "wh_1234567890",
    "event_type": "message.delivered"
  }'

Event Types

message.delivered

Triggered when a message is successfully delivered to the recipient's device.

{
  "id": "evt_1234567890",
  "type": "message.delivered",
  "created_at": "2025-01-15T10:25:03Z",
  "data": {
    "message_id": "msg_1234567890",
    "to": "+15551234567",
    "delivered_at": "2025-01-15T10:25:03Z",
    "device_id": "dev_abcdef123456"
  }
}

message.read

Triggered when a recipient opens and reads a message.

{
  "id": "evt_1234567891",
  "type": "message.read",
  "created_at": "2025-01-15T10:25:15Z",
  "data": {
    "message_id": "msg_1234567890",
    "to": "+15551234567",
    "read_at": "2025-01-15T10:25:15Z",
    "device_id": "dev_abcdef123456"
  }
}

message.failed

Triggered when a message fails to deliver after all retry attempts.

{
  "id": "evt_1234567892",
  "type": "message.failed",
  "created_at": "2025-01-15T10:30:00Z",
  "data": {
    "message_id": "msg_1234567890",
    "to": "+15551234567",
    "error_code": "recipient_unreachable",
    "error_message": "Recipient has not installed the Inbox app",
    "failed_at": "2025-01-15T10:30:00Z"
  }
}

message.action

Triggered when a recipient interacts with action buttons in a message.

{
  "id": "evt_1234567893",
  "type": "message.action",
  "created_at": "2025-01-15T10:26:00Z",
  "data": {
    "message_id": "msg_1234567890",
    "to": "+15551234567",
    "action": "confirm",
    "action_data": {
      "button_id": "btn_confirm",
      "custom_data": {"order_id": "A-123"}
    },
    "clicked_at": "2025-01-15T10:26:00Z"
  }
}

Security

⚠️ Always Verify Signatures

Webhook signatures prevent attackers from sending fake events to your endpoint. Always verify the signature before processing webhook data.

Signature Verification

Each webhook request includes an X-Inbox-Signature header with an HMAC-SHA256 signature:

const crypto = require('crypto');

function verifySignature(payload, signature, secret) {
  const expectedSignature = crypto
    .createHmac('sha256', secret)
    .update(payload, 'utf8')
    .digest('hex');
  
  const receivedSignature = signature.replace('sha256=', '');
  
  return crypto.timingSafeEqual(
    Buffer.from(expectedSignature, 'hex'),
    Buffer.from(receivedSignature, 'hex')
  );
}

// Usage
const isValid = verifySignature(
  req.body,
  req.headers['x-inbox-signature'],
  process.env.INBOX_WEBHOOK_SECRET
);

Best Practices

  • Use HTTPS: Always use HTTPS endpoints for webhooks
  • Verify signatures: Check HMAC signature on every request
  • Idempotency: Handle duplicate events gracefully
  • Respond quickly: Return 200 status within 10 seconds
  • Log events: Keep audit logs of all webhook events
  • Handle failures: Implement proper error handling

Retry Logic

If your webhook endpoint returns a non-2xx status code or times out, Inbox will retry the delivery using exponential backoff.

Retry Schedule

AttemptDelayTotal Time
1Immediate0s
230 seconds30s
32 minutes2m 30s
48 minutes10m 30s
532 minutes42m 30s
62 hours2h 42m 30s

After 6 failed attempts, the webhook is marked as failed and no further retries are attempted.

Testing Webhooks

Local Development

Use ngrok or similar tools to expose your local development server:

# Install ngrok
npm install -g ngrok

# Expose your local server
ngrok http 3000

# Use the HTTPS URL for your webhook endpoint
# https://abc123.ngrok.io/webhooks/inbox

Webhook Logs

View webhook delivery logs in your dashboard to debug issues:

curl -X GET https://api.getinbox.app/v1/webhooks/wh_123/logs \
  -H "Authorization: Bearer YOUR_API_KEY"

Webhook Management

List Webhooks

GET /v1/webhooks

Update Webhook

PUT /v1/webhooks/{id}

Delete Webhook

DELETE /v1/webhooks/{id}

Test Webhook

POST /v1/webhooks/test