Webhooks overview
HMAC-signed, timestamp-bound webhooks fire on every state change, with retries and backoff — so you never poll.
Instead of polling, subscribe to webhooks. Hannu delivers a signed event on every state change, with retries and a full resource snapshot — so your handler never has to fetch to find out what happened.
Delivery shape
Every delivery is a JSON body with the event name and the full resource:
{
"id": "evt_3b9",
"type": "task.approved",
"data": { "id": "task_8f21", "state": "approved" }
}id— a stable event id; use it to make your handler idempotent.type— the event name (see the event catalogue).data— the full resource snapshot at the time of the event.
Guarantees
- Signed, always. Deliveries carry an HMAC signature over the timestamp and body. A delivery is never sent unsigned. See Signature verification.
- Retried with backoff. Failed deliveries retry on a schedule (1, 5, 30, 120, 600 minutes), then dead-letter and raise an internal alert.
- Idempotent on your side. Because retries can duplicate, dedupe on
id.
Return 2xx fast
Acknowledge with a 2xx as soon as you've stored the event, then process asynchronously. Slow handlers trigger retries.
Managing subscriptions
Webhook endpoints and their signing secrets are managed in the dashboard today — there's no public API for subscription CRUD yet. Create an endpoint there, copy its whsec_… secret, and verify every delivery against it.
Next
- Verify signatures — the exact scheme and a code sample.
- The event catalogue — which events fire and when.