Plan capabilities
Which Hatched widgets, capabilities, and quotas land on which subscription tier. Auto-generated from packages/shared/src/pricing.ts.
This page is auto-generated from packages/shared/src/pricing.ts. The same
constant drives the backend PlanGuard, the pricing page, and dashboard
upgrade banners — so every gate you see in product is encoded below.
Plan keys (starter, growth, pro, enterprise) map to public names
Free, Growth, Pro, Enterprise. Backend guards always use the keys.
Widget × Plan
Which data-hatched-mount="…" values render successfully on each plan. A
gated widget mount still loads but the API will return 403 plan_feature_locked
(with details.required_plan and details.upgrade_url) until the customer
upgrades. If the plan covers the feature but an operator has turned it off in
Settings, the API instead returns 403 capability_disabled.
| Widget | Free (free) | Growth ($149/mo) | Pro ($499/mo) | Enterprise (custom) | Capability flag |
|---|---|---|---|---|---|
buddy | ✓ | ✓ | ✓ | ✓ | always available |
marketplace | — | ✓ | ✓ | ✓ | marketplace |
leaderboard | ✓ | ✓ | ✓ | ✓ | always available |
badges | ✓ | ✓ | ✓ | ✓ | badges |
streak | ✓ | ✓ | ✓ | ✓ | streaks |
path | — | — | ✓ | ✓ | paths |
tokens | ✓ | ✓ | ✓ | ✓ | tokens |
kudos | ✓ | ✓ | ✓ | ✓ | kudos |
group-quest | — | ✓ | ✓ | ✓ | group_quest |
feed | ✓ | ✓ | ✓ | ✓ | seesaw_bump |
mystery-box | — | ✓ | ✓ | ✓ | mystery_box |
league | — | ✓ | ✓ | ✓ | leagues |
council | — | — | — | ✓ | council |
hexad-survey | ✓ | ✓ | ✓ | ✓ | always available |
A widget marked always available has no capability flag — every tier
can mount it. leaderboard and feed-style surfaces fall here because
they read data the platform always produces.
Capability × Plan
Raw PlanFeatures matrix. Backend @RequiresCapability('foo') decorators
gate on these keys; the dashboard reads the same map to render locked-state
banners. New capabilities must be added to PlanFeatures in pricing.ts
before they can be referenced anywhere.
| Capability | Free (free) | Growth ($149/mo) | Pro ($499/mo) | Enterprise (custom) |
|---|---|---|---|---|
advanced_analytics | — | — | ✓ | ✓ |
badges | ✓ | ✓ | ✓ | ✓ |
boosters | — | ✓ | ✓ | ✓ |
cause_counter | ✓ | ✓ | ✓ | ✓ |
council | — | — | — | ✓ |
evolution | — | ✓ | ✓ | ✓ |
evolution_generative | — | ✓ | ✓ | ✓ |
founding_cohort | — | — | ✓ | ✓ |
gamification_planner | ✓ | ✓ | ✓ | ✓ |
generative_media | — | ✓ | ✓ | ✓ |
group_quest | — | ✓ | ✓ | ✓ |
hosted_surface | — | — | ✓ | ✓ |
kudos | ✓ | ✓ | ✓ | ✓ |
leagues | — | ✓ | ✓ | ✓ |
lottery | — | ✓ | ✓ | ✓ |
marketplace | — | ✓ | ✓ | ✓ |
mentorship | — | — | ✓ | ✓ |
multi_audience | — | — | ✓ | ✓ |
mystery_box | — | ✓ | ✓ | ✓ |
paths | — | — | ✓ | ✓ |
profile_pages | — | — | ✓ | ✓ |
profile_pages_v2 | — | ✓ | ✓ | ✓ |
seesaw_bump | ✓ | ✓ | ✓ | ✓ |
showroom | — | — | ✓ | ✓ |
streaks | ✓ | ✓ | ✓ | ✓ |
teams | ✓ | ✓ | ✓ | ✓ |
tokens | ✓ | ✓ | ✓ | ✓ |
wardrobe | ✓ | ✓ | ✓ | ✓ |
Quotas + support
| Plan | Events / month | Audiences | Welcome credits | Monthly credit grant | Support |
|---|---|---|---|---|---|
| Free (free) | 10,000 | 1 | 20 | 0 | community |
| Growth ($149/mo) | 500,000 | 1 | 0 | 50 | standard |
| Pro ($499/mo) | 5,000,000 | 3 | 0 | 250 | priority |
| Enterprise (custom) | Unlimited | Unlimited | 0 | Unlimited | sla |
Event quota counts inbound POST /events calls. Once a tenant hits the
monthly cap the API returns 402 event_quota_exceeded carrying the reset
window (details.reset_at, the first of the next UTC month) and an upgrade
link. It is not a 429 — do not retry with backoff; back off until the
reset or upgrade the plan. SDK consumers catch this as
EventQuotaExceededError — see Error handling.
When you change pricing
- Edit
packages/shared/src/pricing.ts—PLAN_MATRIX. - Run
pnpm --filter @hatched/docs generate:plan-matrixto regenerate this page. - Commit both files in the same PR.
generate-plan-matrix.ts --checkis part of CI so drift fails the build.