HatchedDocs
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.awarded

Verify 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 createdAt or carry sequence numbers in data if ordering matters.
  • Replay window on your end. Reject requests where t= in the Hatched-Signature header is older than 5 minutes to defend against replay attacks. The SDK's verifySignature does this automatically.