Overview
Webhooks notify your systems, in near real time, about Dunning business facts: charge paid, agreement accepted, dispute opened, notification delivered. Instead of polling the API from time to time, you register an HTTPS endpoint and receive each event as a JSON POST.

How it works
- A fact happens (e.g. payment identified).
- The event is persisted immutably — nothing is fire-and-forget.
- For each subscribing endpoint, the system schedules a delivery with an HMAC signature and sends it with automatic retry; each attempt is recorded with the request and response captured.
Registering an endpoint
On the dashboard's Webhooks screen (or via POST /api/v1/webhook-endpoints), provide:
- URL: must be
https://. URLs pointing to internal networks are rejected at registration (INVALID_WEBHOOK_URL, anti-SSRF protection). - Description (optional): what this endpoint is for.
- Events: pick from the catalog, grouped by category, with "select all" per group. An empty list subscribes to all events, including ones created in the future (the listing shows an "All events" badge).
- Authentication (optional): credentials Dunning presents to your endpoint (Basic, Bearer or a custom header), in addition to the HMAC signature that is always included. Details in Security.
At creation, the endpoint's secret (prefix whsec_) is displayed only once. It signs every delivery and can be rotated at any time.
What arrives at your endpoint
Each delivery is a POST with the payload:
{
"event": "charge.paid",
"timestamp": "2026-07-23T12:00:00.000Z",
"organizationId": "3f8a...",
"data": { "id": "...", "status": "paid", "...": "the serialized resource" }
}
And the headers:
Content-Type: application/json
User-Agent: Kobana-Dunning-Webhooks/1.0
X-Webhook-Event: charge.paid
X-Webhook-Event-Id: 3d1f0c9a-… (event UUID — the same across all retries)
X-Webhook-Delivery-Id: 9b2e4a10-… (delivery UUID — unique per event × endpoint)
X-Webhook-Attempt: 1 (attempt number)
X-Webhook-Timestamp: 2026-07-23T12:00:00.000Z
X-Webhook-Signature: t=<unix>,v1=<hmac-sha256 of "t.body" with the secret>
Respond 2xx to acknowledge receipt. Any other response (including redirects, which are not followed) counts as a failure and enters the retry cycle.
Testing the endpoint
After registering, fire a test event with POST /api/v1/webhook-endpoints/{id}/test: a webhook.test event travels the real pipeline (queue, signature, capture, retry) all the way to your consumer — without waiting for a business event to happen.
Best practices
- Respond fast, process later: queue the payload and return
200immediately (the delivery timeout is 10 seconds). - Treat it as at-least-once: retries can deliver the same event more than once; deduplicate by
X-Webhook-Event-Id(stable across attempts). - Always verify the signature, including the timestamp tolerance window (how to).
- Monitor the deliveries screen: failures and exhausted deliveries are visible per endpoint, with manual redelivery.
In this section
- Events — the full catalog with a sample payload, resource by resource.
- Security — HMAC signature, verification and request authentication.
- Deliveries and retry — capture, backoff, DLQ and manual redelivery.