BroomVA

Billing API

Query usage, credit balance, and manage subscriptions programmatically.

Billing API

The Billing API provides access to credit balances, usage analytics, and subscription management. Billing data is scoped to organizations. The implementation is in the @broomva/billing package.

Get credit balance

GET /api/usage?orgId={orgId} -- Get the current credit balance and usage summary for an organization.

Requires: usage.read permission (any role).

Response

{
  "orgId": "org_abc123",
  "plan": "pro",
  "credits": {
    "allocated": 5000,
    "consumed": 1247,
    "remaining": 3753,
    "usagePercent": 25,
    "projectedDaysRemaining": 22
  },
  "period": {
    "start": "2026-03-01T00:00:00Z",
    "end": "2026-03-31T00:00:00Z"
  }
}
FieldTypeDescription
credits.allocatednumberMonthly credit budget (1 credit = 1 cent USD)
credits.consumednumberCredits used this billing period
credits.remainingnumberCredits available
credits.usagePercentnumberPercentage of allocation consumed
credits.projectedDaysRemainingnumberEstimated days until exhaustion (based on daily burn rate)

Get usage breakdown

GET /api/usage?orgId={orgId}&breakdown=model -- Get usage breakdown by model, member, or time period.

Query parameters

ParameterTypeDescription
orgIdstringOrganization ID
breakdownstringDimension: model, member, or daily
fromstringStart date (ISO 8601)
tostringEnd date (ISO 8601)

Response (breakdown=model)

{
  "breakdown": [
    {
      "model": "claude-sonnet-4-20250514",
      "provider": "anthropic",
      "requests": 142,
      "inputTokens": 284000,
      "outputTokens": 98000,
      "creditsConsumed": 876
    },
    {
      "model": "gpt-4o-mini",
      "provider": "openai",
      "requests": 89,
      "inputTokens": 156000,
      "outputTokens": 45000,
      "creditsConsumed": 201
    }
  ]
}

Response (breakdown=member)

{
  "breakdown": [
    {
      "userId": "user_abc",
      "name": "Jane Doe",
      "requests": 95,
      "creditsConsumed": 612
    },
    {
      "userId": "user_def",
      "name": "John Smith",
      "requests": 136,
      "creditsConsumed": 465
    }
  ]
}

Response (breakdown=daily)

{
  "breakdown": [
    {
      "date": "2026-03-20",
      "requests": 47,
      "creditsConsumed": 312
    },
    {
      "date": "2026-03-21",
      "requests": 52,
      "creditsConsumed": 287
    }
  ]
}

Get current plan

GET /api/tier?orgId={orgId} -- Get the current plan tier and its definition for an organization.

Requires: billing.read permission (admin or owner).

Response

{
  "tier": "pro",
  "name": "Pro",
  "creditsMonthly": 5000,
  "priceMonthly": 2900,
  "overagePolicy": "soft_limit"
}

The priceMonthly field is in cents (2900 = $29.00). The overagePolicy is one of:

PolicyDescription
hard_limitRequests blocked when credits reach 0
soft_limitRequests allowed up to 120% with warnings, then blocked
warnWarnings shown but requests rarely blocked

Check overage status

POST /api/tier -- Check whether a requested operation would trigger an overage.

Request body

{
  "orgId": "org_abc123",
  "requestedCost": 15
}

Response

{
  "inOverage": false,
  "overageAmount": 0,
  "policy": "soft_limit",
  "blocked": false,
  "message": "Within budget."
}

When blocked is true, the operation should not proceed. The message field contains a user-facing explanation suitable for display in the UI.

The chat endpoint calls the overage check internally before each model invocation. You only need to call this endpoint directly if you are building a custom client that needs to pre-check credit availability.

Create Stripe checkout session

POST /api/stripe/checkout -- Create a Stripe Checkout session for upgrading to a paid plan.

Requires: billing.update permission (owner only).

Request body

{
  "orgId": "org_abc123",
  "plan": "pro"
}

Response

{
  "url": "https://checkout.stripe.com/c/pay/cs_..."
}

Redirect the user to the returned URL to complete payment. After successful payment, Stripe sends a webhook to POST /api/stripe which activates the plan.

Access Stripe billing portal

POST /api/stripe/portal -- Create a Stripe billing portal session for managing payment methods and viewing invoices.

Requires: billing.update permission (owner only).

Request body

{
  "orgId": "org_abc123"
}

Response

{
  "url": "https://billing.stripe.com/p/session/..."
}

The billing portal allows the user to update payment methods, download invoices, and cancel subscriptions directly through Stripe's hosted UI.

Stripe webhook

POST /api/stripe -- Stripe webhook endpoint for subscription lifecycle events.

This endpoint is called by Stripe, not by your application. It validates the Stripe signature and processes events idempotently:

Webhook eventPlatform action
customer.subscription.createdActivate paid plan, set credit allocation
customer.subscription.updatedReflect plan changes (tier, credits)
customer.subscription.deletedDowngrade to free tier
invoice.payment_succeededConfirm payment
invoice.payment_failedSend notification to organization owner

Error responses

StatusCodeDescription
401unauthorizedMissing or invalid token
403forbiddenUser lacks billing.read or billing.update permission
404not_foundOrganization not found
402credits_exhaustedOperation blocked by overage policy

On this page