Billing API

Manage Stripe subscriptions, create checkout sessions, and retrieve your firm's billing status. Billing endpoints require Stripe to be configured — they return 503 gracefully if Stripe keys are absent.

GET/api/v1/billing/status

Returns the firm's current subscription plan, status, trial expiry, and usage counters. Works even when Stripe is not configured — reads plan data from the database directly.

Response

FieldTypeDescription
planstringCurrent plan: trial, solo, practice, firm, enterprise
plan_statusstringStripe status: trialing, active, past_due, canceled
stripe_configuredbooleanWhether Stripe env vars are set
has_subscriptionbooleanWhether a Stripe subscription exists
trial_ends_atstring | nullISO timestamp when trial expires (null if not in trial)
current_period_endstring | nullISO timestamp of billing period end
usage.active_mattersnumberCount of currently active matters
usage.matter_limitnumberPlan limit for active matters
usage.uploads_this_monthnumberDocument uploads this calendar month
Response
{
  "plan": "practice",
  "plan_status": "active",
  "stripe_configured": true,
  "has_subscription": true,
  "trial_ends_at": null,
  "current_period_end": "2025-04-15T00:00:00.000Z",
  "usage": {
    "active_matters": 12,
    "matter_limit": 30,
    "uploads_this_month": 84
  }
}
POST/api/v1/billing/checkout

Creates a Stripe Checkout session for upgrading or starting a subscription. Returns a redirect URL — send the user there to complete payment.

Request Body

FieldTypeRequiredDescription
planstringYesTarget plan: solo, practice, or firm
billingstringNomonthly (default) or annual
Request
{
  "plan": "practice",
  "billing": "monthly"
}
Response
{
  "url": "https://checkout.stripe.com/pay/cs_live_abc123..."
}
Note: Returns 503 if Stripe is not configured. Returns 503if the plan's price ID env var is not set (e.g., STRIPE_PRICE_PRACTICE_MONTHLY).
POST/api/v1/billing/portal

Creates a Stripe Customer Portal session for self-serve subscription management (cancel, update payment method, download invoices). Returns a redirect URL.

No request body required. Requires an existing Stripe customer ID on the firm.

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