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

# Billing

> Credit billing system, organization accounts, and platform-wide cost reporting.

# Billing

Brainstormer uses a credit-based billing system. All external provider costs (AI completions, embeddings, vector operations, voice, storage) are converted to credits and deducted from the organization's wallet.

<Note>
  All API requests require a valid JWT token in the `Authorization: Bearer <token>` header. The API Gateway decodes the JWT and forwards auth context (`user-id`, `organization-id`, `user-email`, `x-platform-role`, `x-org-role`) as headers to downstream services.
</Note>

<Warning>
  This endpoint incurs provider cost and records a billing event via `record_external_cost_event()`. Credits are deducted from the organization's wallet based on the configured margin multiplier.
</Warning>

## Pricing Model

| Parameter           | Default Value | Description                          |
| ------------------- | ------------- | ------------------------------------ |
| `credit_value_usd`  | \$0.50        | 1 credit = \$0.50                    |
| `margin_multiplier` | 2.0x          | Charged cost = raw provider cost x 2 |

For each billable operation:

1. `charged_usd = raw_cost_usd * margin_multiplier`
2. `credits_burned = charged_usd / credit_value_usd`
3. Organization wallet is debited by `credits_burned`

**Example:** A chat completion with raw cost of $0.01 results in $0.02 charged, burning 0.04 credits.

***

## Platform Billing Summary (Superadmin)

<ParamField method="GET" path="/api/billing/summary" />

Get platform-wide billing summary with cost vs. revenue analysis.

<Warning>
  This endpoint requires **superadmin** access. Non-superadmin requests receive `403 Forbidden`.
</Warning>

### Query Parameters

<ParamField query="startDate" type="string">
  Start of reporting period (ISO 8601 datetime). Optional.
</ParamField>

<ParamField query="endDate" type="string">
  End of reporting period (ISO 8601 datetime). Optional.
</ParamField>

<ParamField query="organizationId" type="string">
  Filter to a specific organization UUID. Optional.
</ParamField>

### Response (200)

<ResponseField name="totals" type="object">
  Aggregate totals for the period.

  <Expandable title="Totals">
    <ResponseField name="totalRawCostUsd" type="number">Total raw provider costs.</ResponseField>
    <ResponseField name="totalChargedUsd" type="number">Total charged to organizations (with margin).</ResponseField>
    <ResponseField name="totalCreditsBurned" type="number">Total credits consumed.</ResponseField>
    <ResponseField name="margin" type="number">Revenue margin (charged - raw).</ResponseField>
  </Expandable>
</ResponseField>

<ResponseField name="dailyTrend" type="object[]">
  Day-by-day breakdown for charting.

  <Expandable title="Daily entry">
    <ResponseField name="date" type="string">Date (YYYY-MM-DD).</ResponseField>
    <ResponseField name="rawCostUsd" type="number">Raw cost for the day.</ResponseField>
    <ResponseField name="chargedUsd" type="number">Charged amount for the day.</ResponseField>
    <ResponseField name="creditsBurned" type="number">Credits burned for the day.</ResponseField>
  </Expandable>
</ResponseField>

<ResponseField name="providerRollup" type="object[]">
  Breakdown by provider (OpenRouter, Pinecone, ElevenLabs, etc.).

  <Expandable title="Provider entry">
    <ResponseField name="provider" type="string">Provider name.</ResponseField>
    <ResponseField name="totalRawCostUsd" type="number">Raw cost for this provider.</ResponseField>
    <ResponseField name="eventCount" type="number">Number of billable events.</ResponseField>
  </Expandable>
</ResponseField>

<ResponseField name="organizationRollup" type="object[]">
  Breakdown by organization.

  <Expandable title="Organization entry">
    <ResponseField name="organizationId" type="string">Organization UUID.</ResponseField>
    <ResponseField name="organizationName" type="string">Organization name.</ResponseField>
    <ResponseField name="totalCreditsBurned" type="number">Credits consumed.</ResponseField>
    <ResponseField name="totalChargedUsd" type="number">Amount charged.</ResponseField>
  </Expandable>
</ResponseField>

<ResponseField name="planMix" type="object[]">
  Distribution of organizations across billing plans.
</ResponseField>

<CodeGroup>
  ```bash curl theme={null}
  curl "https://your-domain.com/api/billing/summary?\
  startDate=2026-03-01T00:00:00Z&\
  endDate=2026-04-01T00:00:00Z" \
    -H "Authorization: Bearer $TOKEN"
  ```

  ```javascript JavaScript theme={null}
  const params = new URLSearchParams({
    startDate: "2026-03-01T00:00:00Z",
    endDate: "2026-04-01T00:00:00Z",
  });

  const response = await fetch(
    `https://your-domain.com/api/billing/summary?${params}`,
    { headers: { Authorization: `Bearer ${token}` } }
  );

  const summary = await response.json();
  ```
</CodeGroup>

***

## Billable Operations

The following operations are currently billed:

| Operation                    | Provider                                      | Description                    |
| ---------------------------- | --------------------------------------------- | ------------------------------ |
| `chat_completion`            | `openrouter`                                  | AI chat responses              |
| `welcome_message_generation` | `openrouter`                                  | Generated welcome messages     |
| `embedding_generate`         | `openai_embeddings` / `openrouter_embeddings` | Text and multimodal embeddings |
| `vector_upsert`              | `pinecone`                                    | Vector storage writes          |
| `vector_query`               | `pinecone`                                    | Vector search queries          |
| `vector_delete`              | `pinecone`                                    | Vector deletions               |
| `voice_clone`                | `elevenlabs`                                  | Voice cloning                  |
| `voice_tts`                  | `elevenlabs`                                  | Text-to-speech synthesis       |
| `voice_stt_transcription`    | `openai_whisper`                              | Speech-to-text                 |
| `file_store_put`             | `aws_s3`                                      | File uploads                   |
| `file_store_get`             | `aws_s3`                                      | File downloads                 |
| `file_egress`                | `aws_s3`                                      | File egress bandwidth          |

***

## Data Model

### Core Tables

| Table                           | Purpose                                               |
| ------------------------------- | ----------------------------------------------------- |
| `platform_billing_config`       | Single-row global pricing defaults                    |
| `platform_billing_plans`        | Plan catalog (starter, growth, scale)                 |
| `organization_billing_accounts` | Per-org plan + credit wallet                          |
| `organization_credit_ledger`    | Immutable credit transaction history                  |
| `external_cost_events`          | All billable provider events with raw/charged/credits |

### Atomic Billing Function

All billing writes happen through the `record_external_cost_event()` PostgreSQL function, which performs the entire flow in a single transaction:

1. Load billing defaults
2. Ensure org billing account exists
3. Lock wallet row
4. Calculate charged USD and credits burned
5. Update wallet balance
6. Insert cost event record
7. Insert ledger entry
8. Return billing result

This ensures wallet balances are always consistent under concurrent load.

***

## List Public Billing Plans

<ParamField method="GET" path="/api/auth/billing/plans" />

Returns the active billing plan catalog shown on the signup page. No authentication required.

### Response (200)

<ResponseField name="success" type="boolean" />

<ResponseField name="data.plans" type="object[]">
  Array of active plans.

  <Expandable title="Plan entry">
    <ResponseField name="code" type="string">Plan code, e.g. `free`, `starter`, `growth`, `enterprise`.</ResponseField>
    <ResponseField name="name" type="string">Human-readable plan name.</ResponseField>
    <ResponseField name="description" type="string | null">Short description shown on the signup card.</ResponseField>
    <ResponseField name="monthlyPriceUsd" type="number">Monthly price in USD.</ResponseField>
    <ResponseField name="monthlyCredits" type="number">Monthly credit allocation.</ResponseField>
    <ResponseField name="maxAgents" type="number | null">Maximum agents allowed, or `null` for unlimited.</ResponseField>
    <ResponseField name="maxKbs" type="number | null">Maximum knowledge bases allowed, or `null` for unlimited.</ResponseField>
    <ResponseField name="features" type="string[]">Marketing bullets. Used as-is for the enterprise plan.</ResponseField>
    <ResponseField name="sortOrder" type="number">Display order on the signup page.</ResponseField>
  </Expandable>
</ResponseField>

<CodeGroup>
  ```bash curl theme={null}
  curl "https://your-domain.com/api/auth/billing/plans"
  ```

  ```javascript JavaScript theme={null}
  const response = await fetch("https://your-domain.com/api/auth/billing/plans");
  const plans = (await response.json()).data.plans;
  ```
</CodeGroup>

***

## List Admin Billing Plans

<ParamField method="GET" path="/api/auth/admin/plans" />

Returns all billing plans for superadmin management. Requires **superadmin** access.

### Response (200)

<ResponseField name="plans" type="object[]">
  Array of all plans.

  <Expandable title="Plan entry">
    <ResponseField name="id" type="string">Plan UUID.</ResponseField>
    <ResponseField name="code" type="string">Plan code.</ResponseField>
    <ResponseField name="name" type="string">Plan name.</ResponseField>
    <ResponseField name="description" type="string | null">Plan description.</ResponseField>
    <ResponseField name="monthly_credits" type="number">Monthly credit allocation.</ResponseField>
    <ResponseField name="monthly_price_usd" type="number">Monthly price in USD.</ResponseField>
    <ResponseField name="max_agents" type="number | null">Maximum agents allowed.</ResponseField>
    <ResponseField name="max_kbs" type="number | null">Maximum knowledge bases allowed.</ResponseField>
    <ResponseField name="is_active" type="boolean">Whether the plan is active.</ResponseField>
    <ResponseField name="sort_order" type="number">Display order.</ResponseField>
  </Expandable>
</ResponseField>

***

## Update a Billing Plan

<ParamField method="PUT" path="/api/auth/admin/plans/:planId" />

Updates a billing plan. Requires **superadmin** access. The plan name is read-only.

### Body

<ParamField body="monthly_credits" type="number">
  Monthly credit allocation.
</ParamField>

<ParamField body="monthly_price_usd" type="number">
  Monthly price in USD.
</ParamField>

<ParamField body="max_agents" type="number | null">
  Maximum agents allowed. Pass `null` for unlimited.
</ParamField>

<ParamField body="max_kbs" type="number | null">
  Maximum knowledge bases allowed. Pass `null` for unlimited.
</ParamField>

<ParamField body="description" type="string">
  Plan description shown on signup cards.
</ParamField>

### Response (200)

<ResponseField name="success" type="boolean" />
