key:value pairs to any call (customer_id:acme, team:eu, env:prod), and they’re recorded on the call’s billing and metrics rows. From there you can group spend and token counts by any tag key.
Every call already carries built-in tags like model, so group_by=model works with no setup at all. Custom tags add your own dimensions on top.
There are three ways to attach tags. They differ only in where the tags travel — pick whichever your client can send:
Tag with the X-Opper-Tags header
Works on every gateway (/v3/compat) call. The value is comma-separated key:value pairs; spaces after commas are fine, and sending the header more than once accumulates pairs.
: (only the first colon splits key from value) but not ,.
A malformed header is rejected with a 400 rather than silently dropped, so a templating bug on your side can’t quietly produce untagged (unattributable) usage.
Tag with the SDK
Opper’s nativecall takes a tags object directly:
Python
Tag with the URL
Some clients let you configure nothing but a base URL — a coding agent’sANTHROPIC_BASE_URL, a vendor integration with a single “endpoint” field. For those, tags can ride in the URL path itself:
/v3/compat/..., so the client’s SDK appends its usual path (/chat/completions, /v1/messages, …) and every request through that base URL carries the tags:
session_idcomes free. Thesess_<uuid>segment (a lowercase UUIDv4 you generate) is recorded as asession_idtag on every call, so you can also pull usage for one session:GET /v2/analytics/usage?session_id=sess_.... This is howopper launchaccounts for each coding-agent session.- Percent-encode tag values. Values are URL path segments and are decoded exactly once — encode any character that would break a path (
/→%2F, and so on).
X-Opper-Tags header, the URL’s value wins for any key present in both.
Limits and validation
The same rules apply to all three mechanisms. Invalid tags fail the request with a400 — they are never silently dropped.
Slice usage by tag
Analytics API
GET /v2/analytics/usage aggregates cost (and any metadata fields you ask for) over time, and group_by=<tag key> splits every time bucket by that tag’s values:
null, so the rows always sum to your total spend — nothing hides just because it wasn’t tagged.
CLI
The Opper CLI wraps the same endpoint:Dashboard
The usage page at platform.opper.ai has a Tag filter that scopes the whole page — spend chart, breakdowns, attribution, CSV export — to onekey:value tag. The dropdown lists your organization’s recently seen tags, so anything you tag shows up there automatically.
The dashboard Tag filter is rolling out and may not be visible on your account yet. The analytics API and CLI above work today.
What’s next
Drop-in SDKs
Point your existing OpenAI, Anthropic, or Google SDK at the gateway.
Traces
Tags on spans make individual traces filterable, too.
Integrations
LiteLLM, Vercel AI SDK, and more — with per-tenant attribution built in.
Models & pricing
Per-token pricing for every model the gateway serves.