Abrova
☰ Docs menu · Webhooks
Coming soon. Abrova Push is coming soon. This page describes how it will work; it can’t be used yet.

Webhooks

Receive real-time HTTP callbacks for push events — message.sent, delivered, failed, no_recipients, device.registered/updated/unregistered. HMAC signature verification, retry policy.

Last updated: 27 Oct 2026

Receive real-time HTTP callbacks when events occur.

Available Events#

message.sent

A send request was accepted for delivery (fired once per message, with success/failed counts)

message.delivered

A device confirmed receipt (fired once per device)

message.failed

The send failed (fired once per message)

message.no_recipients

No device matched the target — message not attempted

device.registered

New device registered

device.updated

Existing device re-registered or re-activated

device.unregistered

Device unregistered or deactivated

Create a Webhook#

Node.js SDK

typescript
import { AbrovaPush } from '@abrova/push-node';

const abrovaPush = new AbrovaPush({
  apiKey: 'ab_live_your_api_key',
  serverSecret: 'ab_srv_your_server_secret',
});

const webhook = await abrovaPush.webhooks.create({
  name: 'Analytics Webhook',
  url: 'https://your-server.com/webhooks/abrova-push',
  events: ['message.sent', 'message.delivered', 'message.failed'],
});
console.log('Webhook secret:', webhook.secret);

REST API

bash
curl -X POST "https://push-api.abrova.ir/webhooks" \
  -H "x-api-key: ab_live_your_api_key" \
  -H "x-server-secret: ab_srv_your_server_secret" \
  -H "Content-Type: application/json" \
  -d '{
    "name": "Analytics Webhook",
    "url": "https://your-server.com/webhooks/abrova-push",
    "events": ["message.sent", "message.delivered", "message.failed"]
  }'

Response

json
{
  "id": "wh_abc123",
  "name": "Analytics Webhook",
  "url": "https://your-server.com/webhooks/abrova-push",
  "events": ["message.sent", "message.delivered", "message.failed"],
  "secret": "whsec_xyz789...",
  "isActive": true,
  "maxRetries": 3,
  "timeoutMs": 5000,
  "createdAt": "2024-01-15T10:00:00Z"
}
Save the Secret.

Save the secret value — you'll need it to verify webhook signatures. If you don't pass your own secret, one is generated (whsec_...). You can rotate it with POST /webhooks/:id/regenerate-secret (abrovaPush.webhooks.regenerateSecret(id)).

Webhook Payload#

When an event occurs, we send a POST request to your URL with the headers X-AbrovaPush-Signature, X-AbrovaPush-Event and X-AbrovaPush-Webhook-Id, and this payload:

json
{
  "event": "message.sent",
  "timestamp": "2024-01-15T10:30:00Z",
  "webhookId": "wh_abc123",
  "data": {
    "messageId": "msg_xyz789",
    "type": "user",
    "target": "user_456",
    "title": "Hello!",
    "body": "Test message",
    "successCount": 2,
    "failedCount": 0,
    "status": "sent"
  }
}

The data object depends on the event:

  • message.sent / message.failed / message.no_recipients — messageId, type, target, title, body, successCount, failedCount, status
  • message.delivered — messageId, deviceId, title
  • device.registered / device.updated — deviceId, platform, userId, appIdentifier, isActive (or just deviceId, isActive when a device is re-activated)
  • device.unregistered — deviceId (plus isActive: false when deactivated)

Verify Webhook Signature#

Always verify the X-AbrovaPush-Signature header to ensure the webhook came from AbrovaPush.

javascript
const crypto = require('crypto');

function verifyWebhook(payload, signature, secret) {
  const expected = crypto
    .createHmac('sha256', secret)
    .update(payload)
    .digest('hex');

  return crypto.timingSafeEqual(
    Buffer.from(signature),
    Buffer.from(expected)
  );
}

// Express.js example
app.post('/webhooks/abrova-push', express.raw({ type: 'application/json' }), (req, res) => {
  const signature = req.headers['x-abrovapush-signature'];
  const payload = req.body.toString();

  if (!verifyWebhook(payload, signature, process.env.WEBHOOK_SECRET)) {
    return res.status(401).send('Invalid signature');
  }

  const event = JSON.parse(payload);

  switch (event.event) {
    case 'message.sent':
      // Record send event
      break;
    case 'message.delivered':
      // Record delivery
      break;
    case 'message.failed':
      // Handle failure
      break;
    case 'message.no_recipients':
      // Target had no registered device — mark the user as push-unreachable,
      // fall back to email/SMS, etc. Not a delivery failure.
      break;
  }

  res.status(200).send('OK');
});

Retry Policy#

If your endpoint returns a non-2xx status code or times out (default timeout 5 seconds, configurable with timeoutMs from 1000 to 30000), we'll retry with exponential backoff. With the default maxRetries of 3:

  • Attempt 1: Immediate
  • Attempt 2: After 1 second
  • Attempt 3: After 2 seconds
  • Attempt 4: After 4 seconds

After 4 failed attempts, the webhook delivery is marked as failed. Set maxRetries (1–10) when creating or updating the webhook to change the number of retries. Every attempt is logged — fetch the log with GET /webhooks/:id/logs?limit=50 (max 100) or abrovaPush.webhooks.getLogs(id).

List Webhooks#

Node.js SDK

typescript
const webhooks = await abrovaPush.webhooks.list();

REST API

bash
curl -X GET "https://push-api.abrova.ir/webhooks" \
  -H "x-api-key: ab_live_your_api_key" \
  -H "x-server-secret: ab_srv_your_server_secret"

Update Webhook#

Node.js SDK

typescript
await abrovaPush.webhooks.update('wh_abc123', {
  name: 'Updated Webhook',
  events: ['message.sent', 'device.registered'],
  isActive: true,
});

REST API

bash
curl -X PUT "https://push-api.abrova.ir/webhooks/wh_abc123" \
  -H "x-api-key: ab_live_your_api_key" \
  -H "x-server-secret: ab_srv_your_server_secret" \
  -H "Content-Type: application/json" \
  -d '{
    "name": "Updated Webhook",
    "events": ["message.sent", "device.registered"],
    "isActive": true
  }'

Delete Webhook#

Node.js SDK

typescript
await abrovaPush.webhooks.delete('wh_abc123');

REST API

bash
curl -X DELETE "https://push-api.abrova.ir/webhooks/wh_abc123" \
  -H "x-api-key: ab_live_your_api_key" \
  -H "x-server-secret: ab_srv_your_server_secret"

Test Webhook#

Send a test event to verify your webhook is configured correctly. The test delivery uses the message.sent event unless you pass another one ({ "event": "device.registered" } in the body, or abrovaPush.webhooks.test(id, 'device.registered')), and its data is { "test": true, "timestamp": "...", "message": "This is a test webhook delivery" }. The response is the delivery log entry (success, responseStatus, error, durationMs, ...).

Node.js SDK

typescript
const result = await abrovaPush.webhooks.test('wh_abc123');

REST API

bash
curl -X POST "https://push-api.abrova.ir/webhooks/wh_abc123/test" \
  -H "x-api-key: ab_live_your_api_key" \
  -H "x-server-secret: ab_srv_your_server_secret"
Was this page helpful?
Report a problem