Reference
Webhook payloads
Every event type Hatched emits, with the shape of the payload you'll receive.
All webhook requests share the same envelope:
{
"deliveryId": "wh_01HX…",
"eventId": "evt_01HX…",
"type": "badge.awarded",
"customerId": "cus_01HX…",
"createdAt": "2026-04-22T10:30:00Z",
"data": { "...": "see per-type shapes below" }
}Headers on every delivery:
Hatched-Signature: t=<unix_seconds>,v1=<hex HMAC-SHA256 over `${t}.${rawBody}`>
Hatched-Delivery-Id: wh_01HX…
Hatched-Event-Type: badge.awardedVerify with WebhooksResource.verifySignature from @hatched/sdk-js — see
Handle webhooks.
Event types
buddy.hatched
Emitted when an egg's hatch operation completes.
{
"buddyId": "buddy_01…",
"userId": "user_42",
"configVersionId": "cfg_v12",
"image": { "url": "https://cdn.hatched.com/…", "stage": 1 }
}buddy.evolved
{
"buddyId": "buddy_01…",
"fromStage": 1,
"toStage": 2,
"image": { "url": "…", "stage": 2 }
}coin.earned / coin.spent
{
"buddyId": "buddy_01…",
"amount": 10,
"balanceAfter": 120,
"source": { "type": "event", "eventType": "lesson_completed" }
}token.earned / token.spent
{
"buddyId": "buddy_01…",
"tokenKey": "gem",
"amount": 1,
"balanceAfter": 3,
"source": { "type": "event", "eventType": "weekly_quiz_passed" }
}skill.leveled
{
"buddyId": "buddy_01…",
"skillKey": "pronunciation",
"fromLevel": 2,
"toLevel": 3,
"value": 65
}badge.ready / badge.awarded
badge.ready fires for manual badges awaiting review; badge.awarded
fires when the badge actually attaches.
{
"buddyId": "buddy_01…",
"badgeId": "badge_week_warrior",
"awardedAt": "2026-04-22T10:30:00Z"
}streak.ticked / streak.milestone / streak.burned
{
"buddyId": "buddy_01…",
"streakKey": "daily_lesson",
"count": 7,
"milestone": 7
}streak.milestone only fires on the configured thresholds. streak.burned
fires when the streak resets on a missed day.
marketplace.purchased / marketplace.equipped
{
"buddyId": "buddy_01…",
"itemId": "item_cowboy_hat",
"price": { "type": "coin", "amount": 50 }
}evolution.ready
{
"buddyId": "buddy_01…",
"nextStage": 2,
"conditions": { "xp": true, "badgeStreak7": true }
}leaderboard.snapshot.ready
{
"leaderboardId": "lb_weekly",
"snapshotId": "snap_01…",
"window": { "from": "…", "to": "…" }
}Delivery semantics
- At-least-once. Retries happen on non-2xx. Dedupe on
deliveryId. - No global ordering. Events for the same buddy tend to arrive in
order but don't rely on it — compare
createdAtor carry sequence numbers indataif ordering matters. - Replay window on your end. Reject requests where
t=in theHatched-Signatureheader is older than 5 minutes to defend against replay attacks. The SDK'sverifySignaturedoes this automatically.