Documentation center
API and integrations

Webhooks: receive account events

Configure destinations, verify signatures and track deliveries.

Customer area technical documentation

Examples use fictional data and do not execute requests on this page. Never enter your real credential here.

Register a destination

The owner with a verified email opens Account → API and integrations → Webhooks → Add webhook. Enter a name, URL and events; set the low balance threshold when applicable. There are up to 10 active destinations per account. The URL must use HTTPS on port 443 with public IPv4, without credentials, query parameters or fragments. Save the secret shown only once, configure it in the receiver and use Send test.

Choose events

Events use POST and application/json with identifiers and minimal data. They do not send full ticket messages or credentials. Old replies and already completed installations are not backfilled when registering a destination.

Permissions and details

server.installation.completed
server_key
ticket.reply.created
ticket_id, reply_id, from_support
balance.low
balance, threshold and currency when crossing below the threshold; no retroactive alert if the balance was already low.

JSON

{
  "id": "00000000-0000-4000-8000-000000000001",
  "type": "ticket.reply.created",
  "created_at": "2026-10-17T12:00:00Z",
  "account_id": 123,
  "data": {
    "ticket_id": 456,
    "reply_id": 789,
    "from_support": true
  }
}

Verify the signature

WordPane-Signature uses t=TIMESTAMP,v1=SIGNATURE. Compute HMAC-SHA256 over timestamp + "." + raw body, compare in constant time and reject differences greater than 5 minutes. WordPane-Event-Id must match id in the body. The example uses native Node.js modules.

Node.js

import { createHmac, timingSafeEqual } from 'node:crypto';

export function verifyWordPane(rawBody, headers, secret, now = Date.now()) {
  const match = /^t=(\d+),v1=([a-f0-9]{64})$/.exec(
    headers['wordpane-signature'] ?? ''
  );
  if (!Buffer.isBuffer(rawBody) || !match || !secret) return null;
  if (Math.abs(now / 1000 - Number(match[1])) > 300) return null;
  const expected = createHmac('sha256', secret)
    .update(match[1] + '.').update(rawBody).digest();
  const received = Buffer.from(match[2], 'hex');
  if (!timingSafeEqual(expected, received)) return null;
  try {
    const event = JSON.parse(rawBody.toString('utf8'));
    return event && typeof event.id === 'string'
      && event.id === headers['wordpane-event-id'] ? event : null;
  } catch { return null; }
}

Acknowledge without processing twice

Respond with HTTP 2xx after validating and durably recording the event. Use id for deduplication. There are up to 6 automatic attempts with increasing delays; the ID is preserved and each attempt gets a newly timestamped signature. Redirects are not followed. The connection timeout is 5 seconds and the total is 10 seconds.

Edit, rotate the secret or retry

Edit changes the name, URL, events and balance threshold while preserving the secret. Changing the URL cancels previous pending or failed deliveries. Removing an event cancels its pending or failed deliveries. Rotating the secret immediately invalidates the previous one: configure the new secret in the receiver. Editing or rotating is not allowed during an in-flight delivery.

Alerts and history retention

Monitoring checks recurring failures every 5 minutes and alerts the owner through the bell, without email or WhatsApp. The same incident does not repeat notices while open; new occurrences respect a minimum 24-hour interval. Internal monitoring depends on the scheduler and does not replace external availability monitoring.

Updated on October 17, 2026.

Consult other guides