Why Us Features Apps Pricing FAQ Sign In → RU

Webhooks

A webhook is an HTTP request that WWPager sends to your URL whenever a new message arrives. This lets you process incoming mail in your own services in real time. The URL and signing secret are configured per address in the app (Email Clients section).

When it fires

WWPager sends a webhook for the following events:

Delivery

The request is sent via POST to your URL. The body is UTF-8 JSON (Content-Type: application/json). The following headers are included:

Payload format

The request body has the following structure:

{
  "id": "evt_8Kf2mQ1pZ0xW",
  "type": "email.received",
  "timestamp": "2026-06-16T12:34:56.789012Z",
  "data": {
    "message_id": "msg_123456",
    "email": "you@wwpnext.com",
    "from": "sender@example.com",
    "subject": "Привет!",
    "html": "<p>Текст письма в HTML</p>",
    "text": "Текст письма (plain)",
    "attachments": [
      {
        "filename": "invoice.pdf",
        "content_type": "application/pdf",
        "size": 102400
      }
    ],
    "headers": {
      "Message-ID": "<abc@example.com>",
      "Reply-To": "noreply@example.com",
      "In-Reply-To": "<prev@example.com>",
      "References": "<prev@example.com>"
    },
    "is_spam": false,
    "received_at": "2026-06-16T12:34:56Z"
  }
}

Signature (HMAC-SHA256)

To let you verify that the request came from WWPager and was not tampered with, every body is signed with a secret key. The secret is shown in the app next to the webhook setting. The signature is sent in the X-WWPager-Signature header and is computed as follows:

X-WWPager-Signature: sha256=3a7bd3e2360a3d29eea436fcfb7e44c735d117c42d1c1835420b6b9942dd4f1b

Verifying the signature

On your side, compute the HMAC of the received body with the same secret and compare it to the header using a constant-time comparison.

Python

import hmac, hashlib

def verify(raw_body: bytes, secret: str, signature_header: str) -> bool:
    expected = "sha256=" + hmac.new(
        secret.encode(), raw_body, hashlib.sha256
    ).hexdigest()
    return hmac.compare_digest(expected, signature_header)

Node.js

const crypto = require('crypto');

function verify(rawBody, secret, signatureHeader) {
  const expected = 'sha256=' + crypto
    .createHmac('sha256', secret)
    .update(rawBody)
    .digest('hex');
  const a = Buffer.from(expected);
  const b = Buffer.from(signatureHeader || '');
  return a.length === b.length && crypto.timingSafeEqual(a, b);
}

Response and retries

Your server must respond with a 2xx status code to acknowledge receipt. Any other code or a timeout counts as a delivery failure. Process webhooks idempotently: use the id field to guard against processing the same event twice.

Questions

If you have questions about integration, contact us: