# Webhooks

> Signed HTTP callbacks when something happens in the buddy's world — HMAC-signed, 3 retries, 5-minute replay window.

Source: https://docs.hatched.live/docs/concepts/webhooks

Point Hatched at one of your endpoints and it will `POST` JSON whenever a
subscribed event fires — coin earned, badge awarded, streak milestone,
buddy evolved, etc. The signature is HMAC-SHA256 over `${timestamp}.${body}`
using the secret we show **once** at creation.

## Why webhooks

[Widgets](/docs/reference/widgets/buddy) cover the presentation layer;
webhooks cover the business layer. Unlock a course when a badge fires,
notify Slack on streak milestones, sync coins into your own ledger.

## Example

> Subscribe to `badge.awarded`. When "7 Day Streak" fires, your backend
> grants the user a premium feature for 24h.

## How to set it up

1. Add an endpoint under Settings → Webhooks and pick event types.
2. **Store the secret** — it is shown only at creation time. Rotating the
   secret requires re-subscribing.
3. On receipt, **verify HMAC** + timestamp, reject replays older than 5
   minutes.
4. Return 2xx quickly; non-2xx triggers retries at +5s, +30s, +5min.

See [Handle webhooks](/docs/guides/handle-webhooks) for a complete
verification example in Node.

## Gotchas

- Sign over the **raw body bytes**, not a re-serialized JSON. JSON parsers
  reorder keys, which breaks the signature.
- Delivery log keeps every attempt — use it when something looks off.
- Webhooks are not ordered. If you need strict ordering, write to a queue
  on your side and sequence from there.

## Related

- [Handle webhooks](/docs/guides/handle-webhooks) — signature verification, replay window, retries.
- [Webhook payloads](/docs/reference/webhook-payloads) — the shape of every event type.
- [Rule engine](/docs/concepts/rule-engine) — what produces the events you subscribe to.
