> ## Documentation Index
> Fetch the complete documentation index at: https://docs.browsary.com/llms.txt
> Use this file to discover all available pages before exploring further.

# Billing API

> Reference for balance queries, subscriptions, top-ups, and Stripe webhook processing.

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.

```json theme={null}
{
  "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.
