BroomVA

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 tierApproximate 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
};
PlanPolicyBehavior
Freehard_limitRequests return HTTP 402 (credits_exhausted) when credits reach 0. Upgrade to continue.
Prosoft_limitRequests are allowed up to 120% of your allocation with warnings. Blocked beyond that ceiling.
TeamwarnWarnings are shown but requests are rarely blocked. Overage is billed at the end of the period.
EnterprisewarnConfigured 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_prorations behavior.
  • 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 a PlanChangeNotAllowedError if 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 organization
  • createSubscription() -- creates a subscription with the plan's Price ID
  • updateSubscription() -- updates the subscription on plan changes
  • cancelSubscription() -- 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 eventPlatform action
customer.subscription.createdActivate paid plan, set credit allocation
customer.subscription.updatedReflect plan changes
customer.subscription.deletedDowngrade to free tier
invoice.payment_succeededConfirm payment, extend billing period
invoice.payment_failedSend 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)

On this page