Billing & Plans¶
For self-hosters: billing is optional. With Stripe disabled, Doable runs as a free internal tool — no plans, no credits, no paywalls. The rest of this page is relevant only if you (the operator) enable Stripe, or if you're using a hosted Doable instance that does.
Plans¶
The default tiers in the codebase (packages/shared/src/constants.ts) are:
| Plan | Use case |
|---|---|
| Free | Personal experimentation |
| Pro | Solo creators with regular use |
| Business | Teams with larger workloads, custom domains, more credits |
| Enterprise | Custom — talk to the operator |
Each plan defines limits like:
- AI credits per month
- Number of projects
- Number of workspace members
- Custom domains allowed
- Integrations allowed
You can edit these freely — they're just JSON constants.
Credits¶
Doable bills AI usage in credits. Roughly: 1 credit ≈ 1k tokens, scaled by model cost. The exact mapping is in packages/db/src/queries/credits.ts.
When credits run out:
- The chat panel shows an "out of credits" message.
- New AI requests return
{ "error": "credit_exhausted" }. - Workspace owners are nudged to top up.
Credits can be:
- Replenished monthly by your subscription plan.
- Bought ad-hoc as credit packs (one-time charges).
- Granted by an admin for promo / support reasons.
Subscriptions¶
Standard Stripe Checkout flow:
- Workspace Settings → Billing → Upgrade.
- Stripe Checkout opens.
- After payment, Stripe webhooks Doable; the workspace plan is upgraded.
To manage / cancel: Billing → Manage subscription opens the Stripe Customer Portal.
Setup for operators¶
In .env / docker/.env:
STRIPE_SECRET_KEY=sk_live_...
STRIPE_WEBHOOK_SECRET=whsec_...
STRIPE_PRO_MONTHLY_PRICE_ID=price_...
STRIPE_PRO_YEARLY_PRICE_ID=price_...
STRIPE_BUSINESS_MONTHLY_PRICE_ID=price_...
STRIPE_BUSINESS_YEARLY_PRICE_ID=price_...
In Stripe:
- Create products + prices for each plan tier.
- Add a webhook endpoint pointing to
https://<api>/billing/webhook. - Copy the signing secret into
STRIPE_WEBHOOK_SECRET.
Webhook events handled: see Webhooks → Stripe.
Disabling billing¶
Leave the Stripe env vars empty. The billing routes still respond, but:
- Plan limits are not enforced.
- Credit balances are tracked but never blocked.
- The "Upgrade" UI is hidden.
This is the right setup for internal/company self-hosting.
Invoices & taxes¶
Both come from Stripe. Doable doesn't store invoices itself — users can download them from the Customer Portal.
Refunds¶
Issue from the Stripe dashboard. Refunds don't claw back credits already spent.
Changing the plan structure¶
The plan limits are hard-coded in packages/shared/src/constants.ts. Edit and re-deploy. No DB migration needed for limit changes; only for adding/removing plan tiers themselves.