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

# Usage tracking

> Track metered usage from your server for reliable billing.

## trackUsage

Record a usage event. Server-side tracking is recommended for accuracy — it can't be bypassed or lost due to client issues.

```typescript theme={null}
await billing.trackUsage({
  customerId: "user_123",
  featureKey: "api_calls",
  quantity: 1,
});
```

### Parameters

| Name             | Type                  | Required | Description                           |
| ---------------- | --------------------- | -------- | ------------------------------------- |
| `customerId`     | `string`              | Yes      | Customer external user ID             |
| `featureKey`     | `string`              | Yes      | Which feature was used                |
| `quantity`       | `number`              | Yes      | How many units to track (must be > 0) |
| `idempotencyKey` | `string`              | No       | Prevent duplicate tracking on retries |
| `metadata`       | `Record<string, any>` | No       | Additional context                    |

### Response

```typescript theme={null}
interface TrackUsageResponse {
  success: boolean
  feature_key: string
  quantity: number
  recorded_at: string
  usage?: {
    consumed_units: number
    limit_units: number
    remaining_units: number
    period_start: string
    period_end: string
  }
}
```

### Idempotency

Pass an `idempotencyKey` to prevent duplicate events (e.g., from retries):

```typescript theme={null}
await billing.trackUsage({
  customerId: "user_123",
  featureKey: "api_calls",
  quantity: 1,
  idempotencyKey: `api-call-${requestId}`,
});
```

***

## getUsageMetrics

Fetch current usage metrics for a customer.

```typescript theme={null}
const metrics = await billing.getUsageMetrics("user_123", "api_calls");
```

### Parameters

| Name         | Type     | Required | Description                  |
| ------------ | -------- | -------- | ---------------------------- |
| `customerId` | `string` | Yes      | Customer external user ID    |
| `featureKey` | `string` | No       | Filter to a specific feature |

### Response

```typescript theme={null}
interface UsageMetricsResponse {
  metrics: UsageMetric[]
  customer_id: string
}

interface UsageMetric {
  feature_key: string
  feature_title: string
  product_name: string
  consumed: number
  limit: number
  remaining: number
  percentage_used: number
  period_start: string
  period_end: string
  resets_in_days: number
}
```

## Example: Track + check in one flow

```typescript theme={null}
export async function POST(request: Request) {
  const userId = getAuthenticatedUser(request);

  // Check if user has remaining quota
  const entitlement = await billing.checkEntitlement(userId, "api_calls");

  if (!entitlement.has_access) {
    return Response.json({ error: "Plan upgrade required" }, { status: 403 });
  }

  if (entitlement.usage !== null && entitlement.limit !== null && entitlement.usage >= entitlement.limit) {
    return Response.json({ error: "API call limit reached" }, { status: 429 });
  }

  // Do the work
  const result = await processApiCall(request);

  // Track the usage
  await billing.trackUsage({
    customerId: userId,
    featureKey: "api_calls",
    quantity: 1,
  });

  return Response.json(result);
}
```
