← library
promptexample · tested🛒 E-commercev1 · published 2026-10-15 · updated 2026-11-03

Usage-based billing for an AI app

Meter LLM tokens per customer, sell prepaid credits, and invoice through Stripe using Metronome.

By Uplift Duo

Run it as a prompt

Paste this into any AI agent, or fetch it: curl -s https://uplift.page/api/v1/prompts/llm-usage-based-billing/raw

prompt.md
# Usage-based billing for an AI app

Bill every model call to the right customer with 0 lost or double-counted events (daily reconciliation within 1% of provider usage), block requests within 1 s when prepaid credits reach zero, and generate invoices automatically at period end.

## Recommended stack

- **Metronome (a Stripe product) + @metronome/sdk 3** - Rate cards, LLM token pricing, credits, invoicing. Stripe now routes usage-based and LLM token billing through Metronome, with model prices for OpenAI, Anthropic, and Google synced automatically (public preview).
- **Stripe (stripe-node 23)** - Payments, Checkout for credit top-ups, customer portal. Metronome sends invoices to Stripe for collection.
- **Postgres** - Usage outbox ledger and balance cache. Guarantees no usage event is lost when a function freezes or the billing API is down.
- **AI SDK 7** - Model calls and final usage numbers. onEnd (onFinish is a deprecated alias) reports normalized input, cache-read, cache-write and output tokens after the stream completes.

## Build steps

1. Pick the model: subscription with included credits plus overage, or prepaid credit packs. Define a custom pricing unit ("credits") and how each model converts to it.
2. In Metronome, create a rate card with managed AI provider pricing and your markup (or custom rates), a package with the monthly credit allocation, and provision each customer with contracts/create linked to their Stripe customer.
3. After each call finishes and the provider reports final usage, insert an outbox row: transaction_id = request id, customer_id, timestamp, event_type "token-billing", and properties model, provider, input_tokens, cached_input_tokens, output_tokens, cached_write_tokens, with each token counted in exactly one field.
4. With AI SDK 7, map usage.inputTokenDetails.noCacheTokens to input_tokens, cacheReadTokens to cached_input_tokens, cacheWriteTokens to cached_write_tokens and outputTokens (includes reasoning) to output_tokens. If you read raw provider usage instead, follow Metronome's per-provider rules (OpenAI: subtract cache reads and writes from input; Gemini: add thinking tokens to output; Anthropic: map directly).
5. A worker sends unsent rows to Metronome ingest in batches using the same transaction_id, retries on 5xx with backoff, and marks rows sent.
6. Before each request, check the cached balance minus local unsent usage; when it is zero or below, return 402 with a top-up link.
7. Handle top-ups with Stripe Checkout and a webhook that grants payment-gated credits.
8. Run a daily job comparing ledger totals, Metronome usage, and provider usage reports; alert on drift above 1%.

## Watch out for

- Sending usage before the stream ends misses output tokens. Send after final usage.
- Double-counting cached tokens: some providers include cache reads in the input total. Convert per provider.
- Fire-and-forget billing calls get lost on serverless freezes. Use the outbox.
- Checking balance only against the billing system lets users overspend during ingestion lag. Include local pending usage.

## Definition of done

- Replaying the same 1,000 synthetic usage events twice shows exactly 1,000 events in Metronome.
- A customer at zero credits gets 402 within 1 s.
- The invoice preview matches the ledger total within 1%.
- A Stripe test-mode top-up increases the customer's credit balance.
- The daily reconciliation job runs on a test day and reports drift under 1%.

The full prompt

Bill every model call to the right customer with 0 lost or double-counted events (daily reconciliation within 1% of provider usage), block requests within 1 s when prepaid credits reach zero, and generate invoices automatically at period end.

Recommended stack

  • Metronome (a Stripe product) + @metronome/sdk 3 - Rate cards, LLM token pricing, credits, invoicing. Stripe now routes usage-based and LLM token billing through Metronome, with model prices for OpenAI, Anthropic, and Google synced automatically (public preview).
  • Stripe (stripe-node 23) - Payments, Checkout for credit top-ups, customer portal. Metronome sends invoices to Stripe for collection.
  • Postgres - Usage outbox ledger and balance cache. Guarantees no usage event is lost when a function freezes or the billing API is down.
  • AI SDK 7 - Model calls and final usage numbers. onEnd (onFinish is a deprecated alias) reports normalized input, cache-read, cache-write and output tokens after the stream completes.

Build steps

  1. Pick the model: subscription with included credits plus overage, or prepaid credit packs. Define a custom pricing unit ("credits") and how each model converts to it.
  2. In Metronome, create a rate card with managed AI provider pricing and your markup (or custom rates), a package with the monthly credit allocation, and provision each customer with contracts/create linked to their Stripe customer.
  3. After each call finishes and the provider reports final usage, insert an outbox row: transaction_id = request id, customer_id, timestamp, event_type "token-billing", and properties model, provider, input_tokens, cached_input_tokens, output_tokens, cached_write_tokens, with each token counted in exactly one field.
  4. With AI SDK 7, map usage.inputTokenDetails.noCacheTokens to input_tokens, cacheReadTokens to cached_input_tokens, cacheWriteTokens to cached_write_tokens and outputTokens (includes reasoning) to output_tokens. If you read raw provider usage instead, follow Metronome's per-provider rules (OpenAI: subtract cache reads and writes from input; Gemini: add thinking tokens to output; Anthropic: map directly).
  5. A worker sends unsent rows to Metronome ingest in batches using the same transaction_id, retries on 5xx with backoff, and marks rows sent.
  6. Before each request, check the cached balance minus local unsent usage; when it is zero or below, return 402 with a top-up link.
  7. Handle top-ups with Stripe Checkout and a webhook that grants payment-gated credits.
  8. Run a daily job comparing ledger totals, Metronome usage, and provider usage reports; alert on drift above 1%.

Watch out for

  • Sending usage before the stream ends misses output tokens. Send after final usage.
  • Double-counting cached tokens: some providers include cache reads in the input total. Convert per provider.
  • Fire-and-forget billing calls get lost on serverless freezes. Use the outbox.
  • Checking balance only against the billing system lets users overspend during ingestion lag. Include local pending usage.

Definition of done

  • Replaying the same 1,000 synthetic usage events twice shows exactly 1,000 events in Metronome.
  • A customer at zero credits gets 402 within 1 s.
  • The invoice preview matches the ledger total within 1%.
  • A Stripe test-mode top-up increases the customer's credit balance.
  • The daily reconciliation job runs on a test day and reports drift under 1%.

Served from the uplift.page library and refreshed within 5 minutes of every update.