Webhooks

Webhooks let your application receive real‑time events when messages are received, sent or when sessions connect.

Configure a webhook URL

"function">curl "keyword">-X POST https://omdaa.com/api/v1/webhooks/set \
  "keyword">-H "Authorization: Bearer YOUR_JWT_TOKEN" \
  "keyword">-H "Content"keyword">-Type: application/json" \
  "keyword">-d '{
  "webhookUrl": "https://your class="keyword">-server.com/webhook",
  "events": ["message.incoming", "message.sent", "session.connected"]
}'

Example events

Incoming message message.incoming
{
  "event": "message.incoming",
  "data": {
    "messageId": "msg_123",
    "from": "966501234567",
    "message": "Hello",
    "timestamp": "2025-01-15T12:00:00Z"
  }
}
Sent message message.sent
{
  "event": "message.sent",
  "data": {
    "messageId": "msg_123",
    "to": "966501234567",
    "status": "sent",
    "timestamp": "2025-01-15T12:00:00Z"
  }
}
Session connected session.connected
{
  "event": "session.connected",
  "data": {
    "sessionId": "sess_123",
    "phoneNumber": "966501234567",
    "connectedAt": "2025-01-15T12:00:00Z"
  }
}

Verifying signatures

When you set a secret via POST /webhooks/set, every delivery includes:

  • X-Webhook-Signature: sha256=<hmac_hex>
  • X-Webhook-Timestamp (Unix seconds) to mitigate replay

Algorithm: HMAC_SHA256(secret, raw_request_body) over the exact UTF-8 JSON body. The secret is stored plaintext server-side for outbound HMAC and is never returned by GET /webhooks (only hasSecret: true). The test event works without a connected WhatsApp session.

Node.js
const crypto = require('crypto');
function verify(rawBody, signatureHeader, secret) {
  const expected = 'sha256=' + crypto.createHmac('sha256', secret).update(rawBody, 'utf8').digest('hex');
  const a = Buffer.from(signatureHeader || '');
  const b = Buffer.from(expected);
  return a.length === b.length && crypto.timingSafeEqual(a, b);
}
Python
import hmac, hashlib
def verify(raw_body: bytes, signature_header: str, secret: str) -> bool:
    digest = hmac.new(secret.encode(), raw_body, hashlib.sha256).hexdigest()
    expected = f"sha256={digest}"
    return hmac.compare_digest(signature_header or "", expected)
PHP
$raw = file_get_contents('php://input');
$sig = $_SERVER['HTTP_X_WEBHOOK_SIGNATURE'] ?? '';
$expected = 'sha256=' . hash_hmac('sha256', $raw, $secret);
$ok = hash_equals($expected, $sig);

Get Webhook Configuration

To get current webhook configuration:

"function">curl "keyword">-X GET "https://omdaa.com/api/v1/webhooks" \
  "keyword">-H "Authorization: Bearer YOUR_JWT_TOKEN"

Test Webhook

To test webhook connection:

"function">curl "keyword">-X GET "https://omdaa.com/api/v1/webhooks/test" \
  "keyword">-H "Authorization: Bearer YOUR_JWT_TOKEN"

Webhook Statistics

To get webhook statistics:

"function">curl "keyword">-X GET "https://omdaa.com/api/v1/webhooks/stats" \
  "keyword">-H "Authorization: Bearer YOUR_JWT_TOKEN"

Circuit Breaker

Omdaa API uses Circuit Breaker to protect webhooks from repeated failures:

Get Circuit Breaker State

"function">curl "keyword">-X GET "https://omdaa.com/api/v1/webhooks/circuit class="keyword">-breaker" \
  "keyword">-H "Authorization: Bearer YOUR_JWT_TOKEN"

Reset Circuit Breaker

"function">curl "keyword">-X POST "https://omdaa.com/api/v1/webhooks/circuit class="keyword">-breaker/reset" \
  "keyword">-H "Authorization: Bearer YOUR_JWT_TOKEN"

Available Events

message.incoming
Incoming message
message.sent
Message sent
message.delivered
Message delivered
message.read
Message read
session.connected
Session connected
session.disconnected
Session disconnected
group.created
Group created
group.updated
Group updated