Gateway usage and export
Usage shows spend, requests and each request's model, key, departments and end user. Monthly CSV export via console or gateway.usage.export; no prompt text.
The Usage tab#
AI Gateway › Usage is for workspace owners and admins. Choose a period and, if you like, one key. It shows spend, requests and success rate, a daily trend, spend by key and by model, how auto chose, and then each request: when it ran, the key, the model that answered and why, its tokens and its result. A refused request says which limit refused it.
End users#
An application that serves many people through one key can say who each request is for. The Gateway records it as the request's end user:
| Endpoint | Field |
|---|---|
/v1/chat/completions | user |
/v1/responses | user |
/v1/messages | metadata.user_id |
Only this identifier is recorded; nothing else in the request is stored for it, and the field is still passed to the provider unchanged. Use an id your own system understands, such as an employee number or a hashed address, rather than a name. A request without one is shown as having no end user.
Tags#
Tags label a request with what it was for, such as the team, the feature or the customer, so the Usage tab can split and filter spend by them. Send them as one JSON object in the X-AgentLab-Metadata header on any inference endpoint:
curl https://api.agentlab.cresclab.com/v1/chat/completions \
-H "Authorization: Bearer $AGENTLAB_API_KEY" \
-H "Content-Type: application/json" \
-H 'X-AgentLab-Metadata: {"team": "support", "feature": "summary"}' \
-d '{"model": "auto", "messages": [{"role": "user", "content": "Hello"}]}'With an SDK, pass the same header, for example in Python:
reply = client.chat.completions.create(
model="auto",
messages=[{"role": "user", "content": "Hello"}],
extra_headers={"X-AgentLab-Metadata": '{"team": "support", "feature": "summary"}'},
)On /v1/chat/completions and /v1/responses, OpenAI's own metadata body field is read as tags too, and is still passed to the provider unchanged. When a request sends both, they are joined; a key in both must have the same value. The header is never sent to the provider.
| Rule | Limit |
|---|---|
| Tags | At most 16 per request. |
| Keys | 1 to 64 letters, digits, _, . or -. |
| Values | Strings of 1 to 512 characters, without control characters. |
A request whose tags break a rule is refused with 400 invalid_metadata and a message naming the rule; tags are never dropped silently. On AI Gateway › Usage, choose Tag in the breakdown and pick a key to see spend by its values; select a value to narrow the whole page to it. The request details and the CSV export show each request's tags. Like the end user, tags are your own labels: do not put personal data or prompt text in them.
Export a month#
On the Usage tab, select Export CSV, choose a month and download it. The file has one row per request attempt, opens in Excel with its characters intact, and contains no prompt or response text.
| Column | Contents |
|---|---|
request_id | The request's id, as sent in its X-Request-Id header. |
attempt_id | This attempt. A request that auto judged first, or that was retried, has more than one. |
started_at | When the attempt started, UTC (ISO 8601). |
state | completed, failed, uncertain (usage never reported), dispatched or prepared. |
model | The model the attempt was sent to. |
decision | Why that model: explicit_pin for a named model, otherwise how auto decided. |
input_tokens, output_tokens | Measured tokens. Empty when the usage is not known. |
cached_read_tokens, cache_write_tokens | Prompt-cache tokens. Empty when the provider reported none. |
cost_usd | Cost at the catalog price of the model on that day. Empty when the usage or the price is unknown. |
key_id, key_name | The key that sent it. |
departments | The departments the key was charged to when the attempt started, separated by ; . |
end_user | The end user the request named, or empty. |
failure_code | Why the attempt did not answer, when the Gateway recorded one, such as inference_allowance_exceeded. |
tags | The request's tags as one JSON object, such as {"team":"support"}, or empty. |
An empty cell is unknown, never zero. Months are UTC calendar months. A cell that begins with =, +, -, @, a tab or a carriage return is prefixed with ' so a spreadsheet shows it rather than running it.
Export from code#
The same file comes from the gateway.usage.export procedure of the console API, page by page. Each call returns up to 5,000 rows as CSV text in content and a nextCursor; call again with that cursor until it is null, and join the content of every page in order. Only the first page carries the byte-order mark and the header row. The caller must be a workspace owner or admin.