Skip to content
PALM SOUQ

FinOps guide · Billing

Billing LLM usage with Stripe meter events: a build guide

Create a Stripe meter, choose the unit, attach a usage price, send idempotent meter events per tenant, handle allowances and reconcile, with PALM SOUQ billing sync.

Nisha Pillai, Head of Customer Engineering3 min read
stripe.meter_event
event_name
llm_cost_cents
stripe_customer_id
cus_Q8r2...
value
41237
identifier
tg_2026-04-21_cus_Q8r2_1412
aggregation
sum
Tenant cost $412.37 reported as 41,237 cents

Procedure · 6 steps

  1. 1Choose the billing unitDecide whether customers are billed in tokens, in a work unit, or in cost-weighted units such as cents of model cost, and fix the conversion.
  2. 2Create a meterIn Stripe Billing create a meter with an event name, sum aggregation, and the payload keys for the customer ID and value.
  3. 3Create a usage price on the meterCreate a recurring usage-based price linked to the meter, with graduated tiers if the plan includes an allowance.
  4. 4Add the price to subscriptionsAttach the usage price to each customer subscription alongside the base fee price.
  5. 5Send idempotent meter eventsSend events per tenant with a stable identifier so retries never double count, mapping X-PalmSouq-Tenant to the Stripe customer ID.
  6. 6Reconcile before invoicingCompare Stripe meter totals with the attributed usage per tenant before invoices finalize and investigate any gap.

Stripe Billing supports usage-based prices through meters: you define a meter, attach a price to it, and send meter events as usage happens. Stripe aggregates the events per customer and bills them on the next invoice. This guide covers the decisions specific to LLM usage, which has more than one token class and more than one model price.

Step 1: choose the unit

Raw tokens are the obvious unit, but a token on one model can cost many times a token on another, and a cache read costs a fraction of an uncached input token. If you bill raw tokens at one price, your margin moves whenever the model mix moves.

The alternatives are a work unit (documents, runs, conversations) with a fixed price, or a cost-weighted unit that already reflects the model mix. A common cost-weighted choice is cents of model cost: PALM SOUQ prices each request per tenant, sums it, and reports it to Stripe as cents. A tenant whose month cost $412.37 reports 41,237 units, and the Stripe price per unit applies your markup.

Step 2: create the meter

Create a meter with an event name such as llm_cost_cents, sum aggregation, and the default payload keys: stripe_customer_id for the customer and value for the quantity. Pick the event name carefully; it is the contract between your metering layer and Stripe.

Step 3: price and attach

Create a recurring usage-based price linked to the meter. If the plan includes an allowance, use graduated tiers: the first tier covers the allowance at zero, the next tier carries the overage price. Add the price to each subscription next to the base fee, so the invoice shows the base fee and the overage as separate lines.

Step 4: send meter events

Each event names the customer, the value and a unique identifier. Stripe uses the identifier to deduplicate, which makes retries safe. Sending one event per model request works but generates a lot of events at scale; most teams aggregate per tenant over a short window and send one event per tenant per window, with an identifier derived from the tenant and the window.

import Stripe from "stripe";
const stripe = new Stripe(process.env.STRIPE_SECRET_KEY!);

await stripe.billing.meterEvents.create({
  event_name: "llm_cost_cents",
  identifier: "tg_2026-04-21_cus_Q8r2_1412",
  payload: { stripe_customer_id: "cus_Q8r2", value: "41237" },
});

Mapping tenants to Stripe customers

The simplest mapping is to use the Stripe customer ID as the tenant ID in X-PalmSouq-Tenant. If you use your own account IDs, keep a mapping table and make the billing sync look it up, never the application. PALM SOUQ billing sync stores the mapping per tenant and refuses to send events for tenants without one, raising an alert instead, so usage is never silently dropped or billed to the wrong account.

Step 5: reconcile

  • Before invoices finalize, compare Stripe's aggregated meter value per customer with the attributed usage per tenant for the same period.
  • Watch the period boundary: usage at 23:59 on the last day must land in the right invoice, so align the aggregation window with the billing period in UTC.
  • Keep the raw per-request ledger. If a customer disputes an overage, you can show them the requests, models and token counts behind it.

With PALM SOUQ billing sync

PALM SOUQ runs steps 4 and 5 for you. You connect Stripe, choose the meter and the unit (tokens, cost in cents, or a custom work unit), and map tenants. The gateway prices every request, aggregates per tenant, sends idempotent meter events, and shows a reconciliation view per billing period. The same ledger drives quotas, so the number that caps a tenant is the number that bills them.

Nisha Pillai

Head of Customer Engineering, PALM SOUQ

BITS Pilani. Previously solutions architect at Wipro for generative AI rollouts. Runs onboarding, breaker tuning workshops and the 15-minute demo.

Don't wait for a surprise $10,000 OpenAI invoice.

Route your agent traffic through PALM SOUQ in 2 minutes. Change one base URL, pass a tenant header, and every token is attributed and governed.

14-day free production trial · 100k requests included · no card required