POST https://api.airouter.io/v1/usage-reports reports the actual usage of completions executed after an AI Router selection. Usage reporting is the expected integration for selection customers. A routing decision records which model the router selected for a request; reporting each executed call against that decision connects the recommendation to its actual token usage.
Decisions without a usage report are estimated from your usage profile, see Usage and Billing.
decision_id.usage counters./v1/usage-reports.Do not put usage reporting in the completion request's hot path. Delivery can happen asynchronously after the provider response has returned. Pass through the provider response's usage values verbatim; do not count or estimate tokens in the client.
The Decision API returns decision_id as a top-level response field. Use candidates[0] for the preferred model and retain decision_id for usage reporting. If decision_id is null, the selection remains valid but its usage cannot be reported.
Integrations on the legacy selection path (/v1/chat/completions with model_routing: false) opt in with expose_decision_id: true; the decision id is then appended to the comma-separated response, see Chat Completions.
The relationship between decisions and reports is 1:n. A sticky decision can cover many downstream calls, such as one selection reused for an agent session or a pipeline step. Send one report for every executed provider call, using a new report_id for each call and the same decision_id for all calls covered by that selection.
Send an AI Router API key as a bearer token:
The authenticated key must belong to the team that owns the decision. Unknown decision ids and ids owned by another team are both reported as decision_not_found.
Submit up to 1,000 reports in one batch:
| Field | Type | Required | Description |
|---|---|---|---|
reports | array | Yes | Executed-call usage reports. The maximum batch size is 1,000. |
reports[].report_id | UUID | Yes | Client-generated idempotency identifier for this executed call. |
reports[].decision_id | UUID | Yes | Decision that governed the executed call. |
reports[].model | string | Yes | Model used for the executed call. |
reports[].input_tokens | non-negative integer | Yes | Input-token counter from the provider's usage object. |
reports[].output_tokens | non-negative integer | Yes | Output-token counter from the provider's usage object. |
reports[].latency_ms | non-negative integer or null | No | End-to-end provider call latency in milliseconds. |
Reports must arrive within seven days after the routing decision. Reports for expired decisions are rejected with decision_expired.
The token values below must come directly from the completion provider's usage object:
The endpoint returns 202 Accepted after processing the batch:
| Field | Type | Description |
|---|---|---|
accepted | integer | Reports newly accepted and stored. |
duplicate | integer | Reports already accepted under the same report_id, including duplicates within this batch. |
rejected | array | Reports rejected independently from the rest of the batch. |
rejected[].report_id | UUID | Client report identifier that was rejected. |
rejected[].reason | "decision_not_found" or "decision_expired" | Stable rejection reason. |
A rejected report does not prevent valid reports in the same batch from being accepted.
The client supplies report_id. Generate one UUID for each executed call and retain it across delivery attempts. Retrying with the same report_id is safe: the server absorbs repeat submissions as duplicates instead of counting usage twice. Retry freely after timeouts or transient failures rather than dropping reports.
AI Router stores usage counters, model and latency metadata only. Usage reports never contain prompt or response content.
Authorization: Bearer $AIROUTER_API_KEY
Content-Type: application/json
curl https://api.airouter.io/v1/usage-reports \
--request POST \
--header "Authorization: Bearer $AIROUTER_API_KEY" \
--header "Content-Type: application/json" \
--data '{
"reports": [
{
"report_id": "8c3a54b2-c4d8-4de8-a63d-d5e1327cc856",
"decision_id": "019c7f2e-2e30-7d10-b1e5-50aa75c49a36",
"model": "gemini-3.5-flash",
"input_tokens": 42,
"output_tokens": 117,
"latency_ms": 860
}
]
}'
{
"accepted": 1,
"duplicate": 0,
"rejected": []
}