Billing & Plans
Plans, credits, usage metering, and Stripe-powered billing.
Billing & Plans
BroomVA uses a credit-based billing system where 1 credit equals 1 cent USD. Each plan allocates a monthly credit budget that is consumed by API calls, chat messages, and agent executions. Billing is managed through Stripe.
Plans
The plan definitions are maintained in the @broomva/billing package (plans.ts). These are the current tiers:
Free — $0/month
50 credits ($0.50) per month. Community models (OpenRouter, Ollama). Personal workspace. Hard credit limit — blocked when exhausted.
Pro — $29/month
5,000 credits ($50.00) per month. All models (Claude, GPT, Gemini). Console access. Soft limit — 120% ceiling with warnings.
Team — $99/seat/month
20,000 credits ($200.00) per month. Shared team workspace. API keys, member management. Warning-only overage policy.
Enterprise — Custom pricing
Custom credit allocation. Managed Life instances. SLA guarantees. Dedicated support. Contact sales@broomva.tech.
Plan definitions (from source)
The billing package defines each plan as a PlanDefinition:
// From @broomva/billing — plans.ts
const PLAN_DEFINITIONS = {
free: {
tier: "free",
name: "Free",
creditsMonthly: 50, // $0.50
priceMonthly: 0, // $0.00
},
pro: {
tier: "pro",
name: "Pro",
creditsMonthly: 5000, // $50.00
priceMonthly: 2900, // $29.00
},
team: {
tier: "team",
name: "Team",
creditsMonthly: 20000, // $200.00
priceMonthly: 9900, // $99.00/seat
},
enterprise: {
tier: "enterprise",
name: "Enterprise",
creditsMonthly: 0, // Custom
priceMonthly: 0, // Custom
},
};Each plan maps to a Stripe Product and Price ID in production. The billing package itself does not import Stripe directly -- it receives a StripeAdapter interface that the platform provides.
Credits
Credits are the internal unit of account for all platform usage. Every interaction with the platform -- sending a chat message, making an API call, running an agent -- costs credits proportional to the compute consumed.
How credits are consumed
Credit cost is determined by the model used and the number of tokens processed:
| Model tier | Approximate cost |
|---|---|
| Small models (Haiku, GPT-4o-mini, Flash) | ~1 credit per 10K tokens |
| Medium models (Sonnet, GPT-4o) | ~3 credits per 10K tokens |
| Large models (Opus, o1) | ~15 credits per 10K tokens |
| Local models (Ollama) | 0 credits (self-hosted) |
Token counts include both input and output tokens. Cached input tokens may be charged at a reduced rate depending on the provider.
Credit balance
Your credit balance is visible in the console dashboard. The billing package tracks a CreditBalance with:
- Allocated -- your plan's monthly credit budget
- Consumed -- credits used so far this period
- Remaining -- credits available for the rest of the period
- Usage percent -- percentage of allocation consumed
- Projected days remaining -- estimated days until credits are exhausted, based on your daily burn rate
Billing period
Credits reset on the first day of each billing period (30-day cycles starting from your subscription date). Unused credits do not roll over.
Overage handling
Each plan has a different overage policy that determines what happens when you approach or exceed your credit allocation. The policies are defined in the @broomva/billing package:
// From @broomva/billing — credits.ts
const PLAN_OVERAGE_POLICY: Record<PlanTier, OveragePolicy> = {
free: "hard_limit", // Blocked when credits are exhausted
pro: "soft_limit", // Warning, then blocked at 120%
team: "warn", // Warnings but rarely blocked
enterprise: "warn", // Custom configuration
};| Plan | Policy | Behavior |
|---|---|---|
| Free | hard_limit | Requests return HTTP 402 (credits_exhausted) when credits reach 0. Upgrade to continue. |
| Pro | soft_limit | Requests are allowed up to 120% of your allocation with warnings. Blocked beyond that ceiling. |
| Team | warn | Warnings are shown but requests are rarely blocked. Overage is billed at the end of the period. |
| Enterprise | warn | Configured during provisioning. Typically warning-only with custom ceilings. |
The overage check returns an OverageResult:
interface OverageResult {
inOverage: boolean;
overageAmount: number; // cents, 0 if not in overage
policy: OveragePolicy;
blocked: boolean;
message: string; // user-facing explanation
}When a request is blocked due to credit exhaustion, the API returns HTTP 402 with error code credits_exhausted. The chat UI displays a prompt to upgrade your plan or wait for the next billing period.
Plan changes
You can upgrade or downgrade your plan at any time from the console. The changePlan() function in @broomva/billing orchestrates the change:
- Upgrades take effect immediately. Your credit balance is increased by the difference between the new and old allocations (prorated for the remainder of the billing period). Stripe creates prorated charges via
create_prorationsbehavior. - Downgrades take effect immediately. Your remaining credits are capped at the new allocation if they exceed it. The Stripe subscription is updated without proration.
- Lateral changes (same tier) are no-ops.
- Enterprise upgrades require a conversation with our sales team. The
changePlan()function throws aPlanChangeNotAllowedErrorif you attempt to upgrade to enterprise programmatically. Contact sales@broomva.tech.
Every plan change is recorded in the audit log with the previous plan, new plan, direction, and credit adjustment.
Payment methods
Payments are processed through Stripe. You can add a credit card or debit card from the console billing page. Stripe handles PCI compliance -- BroomVA never stores card details directly.
The billing package uses a StripeAdapter interface to abstract Stripe operations:
createCustomer()-- creates a Stripe customer for the organizationcreateSubscription()-- creates a subscription with the plan's Price IDupdateSubscription()-- updates the subscription on plan changescancelSubscription()-- cancels the subscription on downgrade to free
Stripe webhooks
The platform processes Stripe webhook events at POST /api/stripe to keep billing state synchronized:
| Webhook event | Platform action |
|---|---|
customer.subscription.created | Activate paid plan, set credit allocation |
customer.subscription.updated | Reflect plan changes |
customer.subscription.deleted | Downgrade to free tier |
invoice.payment_succeeded | Confirm payment, extend billing period |
invoice.payment_failed | Send notification to organization owner |
Webhook events are validated using the Stripe signature and processed idempotently.
Invoices
Monthly invoices are generated by Stripe and available from the console billing page. Each invoice shows:
- Base subscription charge
- Any overage charges (for soft-limit plans)
- Applied discounts or credits
- Tax (if applicable)