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

# Credits and billing

> Check API usage, manage AI credits, and handle paid operation errors.

Boxpressd tracks normal API plan usage and paid AI credits separately. Catalog and GraphQL requests contribute to your application usage. Credit-gated AI operations reserve AI credits before work and settle the actual cost after the provider reports usage.

## Check billing state

Billing reads do not consume a billable usage unit.

| Method | Path | Returns |
| - | - | - |
| `GET` | `/v1/billing/status` | Application, plan period, usage, AI credit balance, and management URLs. |
| `GET` | `/v1/billing/usage` | Normalized usage for the current period. |
| `GET` | `/v1/billing/plans` | Active developer plans. |
| `GET` | `/v1/billing/credit-packs` | Current AI credit offers and the billing management URL. |

```bash theme={null}
curl "https://api.boxpressd.com/v1/billing/status" \
  --header "x-boxpressd-key: $BOXPRESSD_DEVELOPER_API_KEY"
```

```json theme={null}
{
  "data": {
    "subject": { "type": "application", "id": "app_2V7m" },
    "application": {
      "id": "app_2V7m",
      "name": "Band scanner",
      "environment": "development"
    },
    "period": {
      "startsAt": "2026-09-01T00:00:00.000Z",
      "endsAt": "2026-10-01T00:00:00.000Z"
    },
    "usage": {
      "requestCount": 184,
      "usedUnits": 184,
      "byCapability": { "rest": 172, "graphql": 12 }
    },
    "aiCredits": { "remaining": 742.3185 },
    "actions": {
      "manageBillingUrl": "https://developers.boxpressd.com/dashboard/billing",
      "buyCreditsUrl": "https://developers.boxpressd.com/dashboard/billing"
    },
    "synchronizationPending": false
  }
}
```

Treat `aiCredits.remaining: null` as temporarily unavailable. When `synchronizationPending` is `true`, show the management link and refresh later.

## How paid usage works

Each paid AI operation follows the same lifecycle:

1. The API checks the `api.ai` entitlement and reserves a configured credit ceiling.
2. The protected AI service performs the operation.
3. The API settles measured input, cached-input, output, and web-search usage.
4. The unused reservation returns to the spendable balance.

Provider prices, credit value, and audience pricing live in Boxpressd Payments. Your integration does not calculate the charge. Read `x-boxpressd-ai-credits-remaining` from the successful response when you want to update an on-screen balance immediately.

<Warning>
  Do not retry a paid operation with a new idempotency key after an uncertain network result. Retry the same logical operation with the same key so the server can prevent duplicate work.
</Warning>

## Enable AI access

Open your application’s **Billing** page in the [Developer Dashboard](https://developers.boxpressd.com/dashboard/billing). Select an available credit offer and complete the hosted Boxpressd Payments checkout. A completed purchase grants the configured AI entitlement and credits to the application billing account.

You can discover current offers without hard-coding prices:

```bash theme={null}
curl "https://api.boxpressd.com/v1/billing/credit-packs" \
  --header "x-boxpressd-key: $BOXPRESSD_DEVELOPER_API_KEY"
```

Use the returned management URL for checkout. Prices, pack sizes, and availability can change, so render the server response rather than embedding them in your application.

## Attribute end-user usage

Trusted backends can send `x-boxpressd-end-user-id` when they need application usage grouped by their own stable user identifier. Never put personal data, an email address, or a raw Boxpressd user ID in this header. Boxpressd hashes the value before storage.

When a trusted first-party integration supplies a validated delegated user, paid AI can reserve and settle both the application and user ledgers. A billing failure identifies the blocking scope as `developer` or `user`.

## Handle billing errors

```javascript theme={null}
if (response.status === 402 || response.status === 403) {
  const problem = await response.json();

  if (problem.manageBillingUrl) {
    // Present this URL to an authorized account owner.
    return { needsBilling: true, url: problem.manageBillingUrl };
  }

  return {
    needsBilling: true,
    scope: problem.billingScope,
    message: problem.message,
  };
}
```

Do not collect card details in your application to resolve an AI credit error. Send the account owner to the hosted billing flow.
