WhatIsUp.dev
Comenzar
Esta página está disponible solo en inglés por ahora.

Webhooks

Webhooks are how WhatIsUp.dev tells you about things — incoming messages, instance state changes, delivery acks. You register one HTTPS URL per instance (or per customer), and we POST a signed JSON body whenever something happens.

The model

WhatsApp ──► Baileys ──► event_bus ──► BullMQ queue ──► worker ──► your endpoint
                                                       │
                                                       └─► webhook_deliveries (DB)

Every event is recorded in webhook_deliveries before we attempt to send. That row carries the full payload, the attempt count, and the last response status. It's queryable via the dashboard or the GET /v1/webhook-deliveries API.

Signature

Every outbound webhook carries an X-WhatIsUp-Signature header in the same shape Stripe uses:

X-WhatIsUp-Signature: t=1700000000,v1=<hex_hmac>

The HMAC is computed over <timestamp>.<raw_body> with your endpoint's signing secret. You verify it by recomputing and comparing in constant time. The full how-to lives at Webhooks → Signature verification.

Retries and backoff

Failed deliveries (anything that's not 2xx, including timeouts) are retried with exponential backoff + jitter:

AttemptDelay
1 (immediate)0s
2~10s
3~60s
4~5m
5~30m
6~2h
Finalgives up after attempt 6

The exact delay has random jitter to avoid thundering-herd retries when you push a fix and a backlog drains. Total retry budget is ~2.5 hours.

Idempotency

Every event carries an event_id (ULID) that's stable across retries. Use it as your dedupe key:

async function handleWebhook(req) {
  const eventId = req.body.event_id;
  if (await alreadyProcessed(eventId)) return res.status(200);
  // ... do the work ...
  await markProcessed(eventId);
}

Without dedupe, a slow ack from your side will cause the same event to be processed multiple times after retry.

Per-host concurrency

The worker caps how many requests can be in flight to any single host (default WEBHOOK_MAX_PER_HOST=4). If you have 50 instances all delivering to webhooks.example.com, only 4 are firing at once; the rest queue. This keeps a slow customer endpoint from saturating the worker on its own — your other endpoints keep flowing.

Payload retention

The webhook_deliveries.payload column is null'd by a sweeper after 7 days for successful deliveries and 30 days for failed/retrying ones. Metadata (status, attempt count, last response) sticks around for forensic queries. If you want longer payload retention, log it on your side.

Correlation IDs

Every webhook carries an X-WhatIsUp-Correlation-Id that lets you trace it back to whatever triggered it — usually a Fastify req.id from the API call that produced the event, or a generated ID for spontaneous events (incoming messages, state changes). Useful when you're trying to figure out which one of your test runs caused the spike in your logs.