Billing
Stripe is optional. Without it, teams stay on the free plan or operator-assigned tiers.
Plans
| Plan | Rate limit | Active inboxes | How |
|---|---|---|---|
| free | 60/min | 10 | Default (issue:key:db) |
| pro | 300/min | 100 | Stripe Checkout or operator |
| enterprise | 600/min | 500 | Operator · Dedicated Resend |
| legacy | 120/min | 500 | Single wrangler API_KEY |
Without Stripe (today)
npm run issue:key:db -- pilot-name
# free plan · dashboard works · no Upgrade button
Manual pro: operator runs npm run team:plan -- TEAM_ID pro.
With Stripe (Pro self-serve)
- Stripe product + recurring price →
STRIPE_PRICE_PRO - Webhook
POST /webhooks/stripe(see events below) - Worker secrets:
STRIPE_SECRET_KEY,STRIPE_WEBHOOK_SECRET,STRIPE_PRICE_PRO
npm run wizard:stripe
npm run wizard:stripe -- --deploy
npm run doctor:billing
Operator guide: STRIPE-SETUP.md
API
GET /v1/me → billing.stripeEnabled, canUpgrade
POST /v1/billing/checkout → { url } (admin scope, free plan)
POST /v1/billing/portal → { url } (existing Stripe customer)
Dashboard — Upgrade / Manage billing when Stripe is enabled.
Webhook events
checkout.session.completed→teams.plan = procustomer.subscription.updated/deleted→ downgrade when canceled
Enterprise
Not sold via Stripe checkout yet — contact
hello@webmailagent.com or operator
npm run team:plan -- TEAM_ID enterprise.