Sign in

Concepts

Attribution cuts

How a month of your spend is cut by key, project, route, tag and customer: one row per value, and every request in one row of each cut.

On this page

Attribution cuts a calendar month of your organization's spend by one label at a time: the key each request used, the project it named, the route it called, or the team, feature, customer or end user its tags declared. A cut is the priced record Meter keeps, the token counts your provider reported priced at the reference price list, added up per label. On the platform, the Attribution page cuts your spend by key, project and tag (Meter).

The seven cuts

Cut, as dim One row per Plan
key gateway key, named by its key_ id Team and above
project project named in x-recovea-project Team and above
route route the request called Team and above
team value of a team: tag Growth and above
feature value of a feature: tag Growth and above
customer value of a customer: tag Team and above
enduser value of an enduser: tag Growth and above
  • A key is named by its record id, never by its secret (Organization and keys).
  • A route is one of a fixed set of names, such as /v1/chat/completions or /v1/embeddings. A call with no name of its own in that set is grouped under an other route, such as /v1/other.
  • A tag cut reads the first tag of its namespace with a value after the prefix, in the order the request sent its tags, and keeps that value (The four namespaces). A request that carried two team: tags is in the first one's row only.
  • A project or a tag value is opaque. It is stored as Tags describes and returned byte for byte, never resolved to a person, a team or a company.

Every request is in one row of every cut

When a request is recorded, it is added to one row of each of the seven cuts for its month: one request, and its cost when it was priced. So every cut adds up to the same month, the same number of requests and the same spend, whichever label it is cut by.

That holds because a request that says nothing about a label still lands in a row of that cut. Two values are reserved for those rows:

  • unassigned, in the project cut, holds every request that named no project;
  • untagged, in each of the four tag cuts, holds every request that carried no tag of that namespace with a value after its prefix.

A request that sends the reserved word itself, unassigned as its project or untagged as a tag's value, lands in the same row. The untagged row of the customer cut is not a customer: no customer spending cap can refuse that traffic, so no cap, remainder or refusal is ever shown on it (the per-customer figures).

A request that was never recorded is in no cut: a call that never reached the gateway, a request refused before your provider was called, and a request passed through while the gateway failed open (What fails open).

What a row holds

Field What it is
dim the cut
value the key_ id, the project, the route or the tag's value, or a reserved value
requests every request recorded in the row that month, priced or not, whatever its status
spendMicroUsd what the priced ones cost at the reference price list, in integer microdollars; 1000000 is one dollar
spend the same figure as a display string
share the row's part of the cut's spend, from 0 to 1, rounded down to four decimal places; null when the cut's spend is zero

Rows come spend-descending, and rows with equal spend in the order of their value.

  • An unpriced request counts and adds nothing. A request on a model the price list has no price for, or one whose token counts your provider did not report, is in requests and adds nothing to spendMicroUsd (Meter).
  • share is a part of the cut. It is the row's spendMicroUsd divided by the sum of spendMicroUsd over every row the cut returned. With every request in one row, that sum is the month's spend, and a cut's shares add up to 1 or a little under it, since each is rounded down: 0.8809 is 88.09%.

The customer cut

The customer cut carries more on each row than the other six: which price lists priced that customer's requests in the month, how many could not be priced, the monthly cap that applies and what is left of it, and the last time a cap stopped that customer. The other six carry none of those keys, rather than a zero nobody counted. Every field is in the per-customer figures; the two about price lists, in short:

  • priceLists is "one" when one price list priced every priced request in the month, "more_than_one" when the month spans two lists, and "none" when no request was priced. It is null when the record holds no request under that row's value in the month, which is usually the untagged row.
  • priceListVersion names the one list when priceLists is "one", and is null otherwise.

Those keys come from each request's own record, because the monthly rows the cuts read know neither which list priced a request nor whether it went unpriced.

The customer cut is read to 10,001 rows: the 10,000-customer bound and the untagged row. Past that, the rows with the least spend are left off, and share is then a part of the rows returned. The customer cut is Team and above; on every plan, Free included, the count says how many customers were tagged in the month and what they cost in total.

The month

Every cut is one calendar month in UTC, asked for as period=YYYY-MM. A request belongs to the month in which it started. A missing or malformed period is refused with 400 and "The period query parameter must be a calendar month in YYYY-MM form."

On the wire

The cuts are platform routes. Owners, Admins, Members and Viewers can read them; the Billing role cannot.

One cut for one month
GET /platform/v1/attribution/cuts?dim=project&period=2026-10
The rows of that cut
[
  {
    "dim": "project",
    "value": "checkout",
    "requests": 1840,
    "spendMicroUsd": 7400000,
    "spend": "$7.40",
    "share": 0.8809
  },
  {
    "dim": "project",
    "value": "unassigned",
    "requests": 212,
    "spendMicroUsd": 1000000,
    "spend": "$1.00",
    "share": 0.119
  }
]

A cut above your plan answers 403, and the body carries nothing from the cut:

A cut above the plan
{ "locked": true, "requiredPlan": "Growth", "requestsMetered": 2052 }

requiredPlan is the cheapest plan that opens the cut, and requestsMetered is your organization's count of requests for the month. A dim that is not one of the seven is refused with 400.

Two more reads take the same period:

  • GET /platform/v1/attribution/export.csv writes cuts as CSV, with the columns dim,value,requests,spendMicroUsd,spend, where spend carries no currency sign. With dim, it is that one cut, on the plan that opens it. Without it, on Growth and above, it is all seven cuts in the order of the table above.
  • GET /platform/v1/attribution/analyzed, on Growth and above, is every cut at once. Each row carries its share and deltaPct: the change from the previous calendar month's spend under the same value, in whole percent with the fraction dropped, and null where the previous month holds no spend under that value or could not be read.

What a cut is, and what it is not

  • It is the record, not the bill. A cut adds up priced requests at the reference price list; the bill is your provider's invoice.
  • It groups by your labels. A request you did not label for the project cut or a tag cut sits in that cut's reserved row; nothing assigns it a label for you.