Skip to main content

trackUsage

Record a usage event. Server-side tracking is recommended for accuracy — it can’t be bypassed or lost due to client issues.
await billing.trackUsage({
  customerId: "user_123",
  featureKey: "api_calls",
  quantity: 1,
});

Parameters

NameTypeRequiredDescription
customerIdstringYesCustomer external user ID
featureKeystringYesWhich feature was used
quantitynumberYesHow many units to track (must be > 0)
idempotencyKeystringNoPrevent duplicate tracking on retries
metadataRecord<string, any>NoAdditional context

Response

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):
await billing.trackUsage({
  customerId: "user_123",
  featureKey: "api_calls",
  quantity: 1,
  idempotencyKey: `api-call-${requestId}`,
});

getUsageMetrics

Fetch current usage metrics for a customer.
const metrics = await billing.getUsageMetrics("user_123", "api_calls");

Parameters

NameTypeRequiredDescription
customerIdstringYesCustomer external user ID
featureKeystringNoFilter to a specific feature

Response

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

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);
}