Skip to main content
If you build a product on top of AI Reserve, your usage rolls up to one organization — but you usually want to know what each of your customers costs you. Customer attribution lets you tag every request with your own customer id (and, optionally, the feature that made the call). The gateway records both on the usage record for that request, and the portal’s Analytics page breaks spend down by customer. Tags are reporting-only. They never change which model serves a request, what it costs, or whether it is allowed. Requests without a tag behave exactly as before. There are two ways to get the customer id onto a request: tag each request yourself (the three options below, best when your own backend calls AI Reserve for many customers through one key), or hand each customer a customer key that carries the id for them.

Three ways to tag a request

The gateway reads the customer id from the first of these that is present, in this order: If you already pass user to the OpenAI SDK or metadata.user_id to the Anthropic SDK, you are done — the gateway picks those up with no code change and still forwards the fields to the provider unchanged. The header is for everything else (Bedrock-style /model/…/converse, text-to-speech, GPU endpoints) and for when you want one mechanism across every SDK.
On the Anthropic surface the SDK’s own metadata.user_id is enough:
When the requests come from the customer’s own systems — a reseller integration, a tenant you onboard with their own credentials — give that customer a customer key instead of asking them to tag anything. A customer key is one of your organization’s API keys bound to one customer id: every request made with it is billed to you and reported under that customer, with nothing to add to the request. Add the customer’s organization / sub-account and the key becomes a sub key that also splits the customer’s spend by their organizations (cust_8f3a2b › emea). Create them in the portal — Keys → Create key → One of your customers (enterprise admins) — or over the API with one of your organization-level keys:
The response carries the plaintext key exactly once. The customer then calls AI Reserve with it like any other key — same base URL, endpoints, and limits as your organization. A customer key’s binding always wins: if the customer’s code also sends x-aireserve-customer or user, the key’s customer is what gets reported. The x-aireserve-feature tag below still works on a customer key. Each customer key on the Keys page carries a Customer badge and a Spend for this customer link straight into Analytics, where a customer with sub keys expands into its organizations in the Spend by Customer card. Listing and revoking keys, the error codes, and the full schemas are on the Customer keys reference page.

The optional feature tag

x-aireserve-feature names the feature or action inside your product that made the call — draft-email, summarize-thread, nightly-sync. It is recorded next to the customer id on every usage record and comes along in exports, so you can later split one customer’s spend by what they used. It is header-only and entirely optional.

Limits and validation

Values are trimmed of surrounding whitespace. A tag that is empty, too long, or contains control characters is ignored — the request is served and billed normally, it just lands as untagged. Tagging never produces an error response. When the header is invalid but the body carries a valid user / metadata.user_id, the body value is used.
Use opaque ids, never emails or names. Send the identifier your own system uses for the customer (cust_8f3a2b, a UUID, a tenant slug). Tags are stored on usage records and appear in Analytics and in exports; personal data does not belong there.

Where it shows up

  • Analytics → Spend by Customer. The portal’s Analytics page gains a Spend by Customer card listing your top 25 customers in the selected date range by spend, with requests, tokens, and each customer’s share of spend. An (untagged) row holds every request that carried no customer id, so the table always reconciles with the period total. The card appears only once at least one request in the range carried a customer id; it follows the same date range and team/member filters as every other card.
  • CSV / JSON download. Each card downloads its own rows (endCustomerId, requests, tokens, spendUsd, spendShare), and the page-level Download all data (JSON) includes the same breakdown.
  • The API. GET /v1/customers/usage returns the same figures per customer — plus, once your organization has pricing rules, what each customer owes and your margin — and GET /v1/customers/{customerId}/usage drills into one customer. See Check the amount.
Requests whose results are produced by a background job after the call returns — image edits and video generation — are not attributed to a customer yet. Everything served inline (chat, messages, responses, image generation, speech, Bedrock-style converse, GPU chat completions) is.

Pricing you charge

Spend by Customer tells you what each customer cost you. Pricing rules add what each customer owes you: a rule is the price your organization charges for a slice of its tagged usage, and every matched request is priced with it, so revenue and margin sit next to cost in the usage API. Each rule has a scope (which customers and features it covers), a kind (how the amount is computed), and an effective window (the period of usage it prices). When several rules cover a request, the most specific scope wins: customer and feature, then customer only, then feature only, then all customers. Within one scope, the rule whose window covers the request’s UTC day and has the latest effective from wins, so a price change is a new rule with a later start — the old one keeps pricing the usage it covered. A window may start in the future (a scheduled price) and may be closed with an end date; closing it never rewrites history. Usage that no rule covers is reported at cost and flagged priced: false, so a gap in your price list shows up as a visible zero margin rather than a quietly wrong total. How the amounts come together:
  • Markup, per-request, and per-token rules are applied to each successful request and summed. A monthly flat fee is booked once per customer per UTC month, on the first day in that month with matched usage, and is never pro-rated.
  • Failed requests are never billed to a customer. They are left out of requests and the token counts. Their cost still counts toward cost_usd, so your cost reconciles with the rest of Analytics.
  • Amounts are USD with six decimals, rounded half away from zero once per request. Margin is billable − cost; margin percent is margin ÷ billable × 100, two decimals, and null when nothing was billable.
  • As soon as one rule applies to the period, every report row carries billable_usd, margin_usd, and margin_pct next to cost_usd (has_pricing_rules: true). The untagged bucket stays cost-only — nothing can be billed to a customer you did not name.
Pricing rules are reporting-only, like the tags themselves. They never change what AI Reserve charges your organization, and AI Reserve does not invoice your customers for you — the figures are there for you to bill from.

In the portal

Organization admins manage rules under Analytics → Customer pricing (also reachable from Set prices on the Spend by Customer card). The list shows every rule’s scope, price, window and status — Active, Scheduled, or Ended. Add rule asks who the price is for, then how you charge, and reads the rule back in one sentence before saving. Change price starts a new version and ends the current one where it begins; End stops a rule from now, or removes one that has not started yet. Once one rule covers the selected range, the Spend by Customer card adds Revenue and Margin (amount and percent) to every customer row, to each organization under it, and in a totals line; a By feature view breaks the same figures down by x-aireserve-feature tag. A negative margin is labelled Loss, a gross margin under 20% Low margin, usage that no rule covers No rule (shown at cost, with a link to add one), and a group where only some usage was priced Partly priced. The card’s CSV gains costUsd, revenueUsd, marginUsd, marginPct and priced columns. The figures are the ones GET /v1/customers/usage returns for the same range: the same engine prices both, so the portal and the API never disagree. Margin is an organization-wide figure — it is computed for the whole organization, not for a team or member filter — and, like the API, for ranges of up to 92 days.

Check the amount (API)

Two read endpoints return usage, cost, and — with pricing rules — billable amount and margin per customer, so your own billing or support tooling can answer “what does this customer owe?”. Both take your AI Reserve API key and are scoped to the organization that owns it. start is inclusive and end exclusive; both accept a UTC date (2026-10-01) or an RFC 3339 timestamp. Leave them out for the last 30 days. A period may span at most 92 days — longer ranges and malformed dates return 400. The customer id in the path is URL-encoded, exactly as you tagged it; an id you never tagged returns zeros, not 404.
A per-customer response for an organization with two rules — a 20% markup on this customer’s draft-email feature, and a $99 monthly flat fee for everything else the customer does:
The flat fee is booked on the customer’s first matched usage of the month and included in that row’s billable_usd; requests under a monthly flat rule add nothing per request. Had a feature matched no rule at all, its row would show billable_usd equal to cost_usd and priced: false. Both endpoints share your organization’s API rate limit and return the standard error shape — 401 for a missing key, 403 when a screen rejects it, 429 with Retry-After. Full request and response schemas are under Customers in the API reference.