Skip to main content
All endpoints below require an email-verified session unless stated otherwise.

GET /api/billing/overview

Summarises the caller’s balances, active subscription, latest usage transactions, and pay-as-you-go pricing table.
{
  "balances": [
    { "currency": "USD", "available": "42.50", "pendingAccrued": "3.10" }
  ],
  "activeSubscription": {
    "planId": "plan_enterprise",
    "planName": "Enterprise",
    "currency": "USD",
    "monthlyPrice": "299.00",
    "discount": "0.00",
    "activeFrom": "2024-05-01T00:00:00.000Z",
    "activeUntil": "2024-06-01T00:00:00.000Z",
    "bonuses": {
      "network": "1TB",
      "inputTokens": { "total": "10_000_000", "weights": { "gpt-4o-mini": "1" } }
    }
  },
  "transactions": [
    {
      "type": "usage",
      "id": "usage_123",
      "projectId": "proj_123",
      "projectSlug": "marketing-research",
      "unit": "cpu_seconds",
      "currency": "USD",
      "resourceAmount": "120",
      "unitPriceApplied": "0.001",
      "discountApplied": null,
      "bonusAppliedValue": null,
      "billedAmountDelta": "0.12",
      "pendingRemainder": "0.00",
      "occurredAt": "2024-05-21T13:02:18.000Z"
    },
    {
      "type": "top_up",
      "id": "top_456",
      "amount": "25",
      "currency": "USD",
      "occurredAt": "2024-05-20T08:10:00.000Z"
    }
  ],
  "usagePricing": [
    { "unit": "cpu_seconds", "currency": "USD", "price": "0.001" }
  ]
}

GET /api/billing/plans

Returns the plan catalog as configured in lib/billing/plans. Each plan view includes the Stripe price ID, marketing copy, and the computed monthly price/discount figures. No authentication required beyond optional sessions.

POST /api/billing/subscription

  • Body{ "priceId": "<stripe price id>" }.
  • Behavior – validates the price against the internal catalog, ensures currency compatibility with the active plan, calculates prorated credits for upgrades, and returns { url }, the Stripe Checkout session.
  • Errors – HTTP 400 for unknown price IDs, disallowed downgrades, or cross-currency switches. HTTP 500 if the checkout session cannot be created.

POST /api/billing/top-up

  • Body{ "amount": "25", "currency": "USD" }.
  • Response{ url } (Stripe Checkout session).
  • Validation – only the default currency is accepted. Amount must parse as a decimal string.

POST /api/billing/portal

Creates a Stripe billing-portal session so users can manage payment methods or cancel plans themselves. Returns { url }.

POST /api/stripe/webhook

Stripe sends signed events to this endpoint. Requirements:
  • Add the endpoint to your Stripe dashboard with the same signing secret configured in STRIPE_WEBHOOK_SECRET.
  • Send the raw body and stripe-signature header untouched; the handler uses them to validate the event.
  • Events: checkout.session.completed, customer.subscription.updated, customer.subscription.deleted, and any others you need for bookkeeping.
Responses follow Stripe’s convention: { "received": true } on success, HTTP 4xx/5xx otherwise. Errors are logged to help with debugging misconfigurations.