Skip to main content
Two screens answer two different questions. Usage answers “what has this workspace been doing”. Activity answers “what happened to this request”. Usage is also where you land: it is the screen you see the moment you sign in, and the screen a workspace switch takes you back to. Both screens are shipped and live. Everything below, the figures, the filters and the fields on each row, is what these screens show today rather than what they are planned to show.

Usage: the shape of your spending

Usage reads one window at a time. The ranges are 24 hours, 7 days, 30 days, 90 days and 1 year, and it shows:
  • Totals for the window: requests, how many were served, how many were not, token counts including reasoning and cache reads and writes, and the cost summed from the per request charges.
  • The same window immediately before it, so a total can be read as a change rather than as a number on its own.
  • A series bucketed by hour on the 24 hour window and by day on the longer ones. A bucket with no requests carries a zero rather than being missing, so a gap in the chart never has to be interpreted.
  • Breakdowns by model, by provider, by key and by member.
  • Your balance, read from the one component allowed to compute it, beside the summed cost rather than derived from it.
How fast the credit is going. Beside the totals, Usage says what the window works out to per day, roughly how many days of credit that pace leaves, and the date the balance would run out at it. All three are the platform’s own arithmetic over the window you selected and the balance it already read, so changing the range changes the pace. A workspace spending very little reads “under a cent a day” rather than a true but useless zero, and a balance that would outlast ten years at the current pace says so instead of naming a date decades out. The panel is not drawn at all when there is nothing to project from: a window with no spend, or a balance already at zero. Two figures are worth knowing how to read. Freshness. The screen shows when the newest request inside the window started, as well as when the figures were read. The second tells you when we looked; only the first tells you how current the figures are. Windows longer than the retention window. Usage records are kept for 90 days, so a 1 year window shows what is still kept rather than a full year. Your statement is the record that goes back further, because ledger movements are never purged.
Breakdowns by key and by member are scoped to what you may see. An owner or admin sees every line. Everybody else sees the keys they are accountable for or named on, plus their own row. Totals, buckets, models and providers are whole for every member.

Activity: one row per request

Activity lists requests newest first, 25 to a page unless you choose 50 or 100, with the request id linking to the single request lookup. Each row carries when it ran, which door it came through (api or playground), the model, which provider answered, the outcome, the token counts, what it cost as dollars and how long it took. Paging is stable: rows are ordered by time with the request id as the tiebreak, so a row cannot swap sides of a page boundary between two reads and appear twice or not at all.

Filters

The filter panel narrows by model, by outcome and by date range, and the controls compose: all of them narrow the same list. It is a plain form, so a filtered view is an address you can bookmark or send to a colleague, and shortcuts for the last day, week and month write the date fields for you. The model list offered by the panel is the models this workspace has actually called, not a catalogue, and a model that has been renamed appears once: choosing it still matches the rows recorded under the name it used to have. Outcome narrows to one of four choices rather than to a code: any outcome, served, provider error, refused.

Three ways to see no rows

They mean different things and the screen says which:
  1. Nothing has ever run here. The workspace is new.
  2. The filter matched nothing. Rows exist and this narrowing excluded them. The table keeps its shape and offers a control to clear the filter.
  3. The range reaches past what we keep. It was never going to answer, so the screen names the retention window instead of inviting a narrower filter.

Reading a row

unknown is not zero. On the outcomes where a charge exists and final token counts never arrived, the count reads unknown. A real charge printed beside two zeros is the reading that files a billing bug, so a count nobody measured is never rendered as a measurement. A refusal shows a cost of zero. That is the point: turned away, charged nothing. No prompt, no reply. Neither is stored anywhere, so neither is on the row and neither can be recovered later. The single request view says so in as many words.

Look up one request

Every response carries x-uniblock-request-id, and every error envelope carries the same value as request_id. Paste it into the request id field in Activity, or open the row from the list, to get the single request view: the same fields as the row, plus the note that nothing else about the request was ever stored. One answer covers both ways to miss: a request id from another workspace and a request id that never existed both simply find nothing. That is by construction rather than by policy, so the lookup cannot be used to learn whether an id exists somewhere else. A request that has passed the 90 day retention window is answered by naming the window rather than by an empty row. The money movement for that request is still on your statement.

Reconcile a statement line with a request

A usage line on your statement carries our request id as its cause. That is the join:
1

Take the request id from the statement line

Every charge line names one.
2

Look it up in Activity

The single request view shows the model, the outcome, the token counts and the cost for that exact request.
3

Compare the figures

The charge on the usage record and the amount on the ledger line are the same money, matched by request id with no tolerance for a difference. If they do not agree, that is a defect on our side rather than something for you to reconcile. Quote the request id.
Two cases where a line carries more than the amount:
  • A charge with an explanation. Some lines carry a sentence saying the counts were not confirmed, that the provider reported none, or that the hold had already expired when the charge settled.
  • A served request with no cost figure. Where token counts never reached us, the request is settled against its hold and the usage row cannot yet say for how much. The totals name how many such requests fall in the window, so the cost totals read as incomplete rather than as complete. Your statement carries the real movement.

Next

View activity

A closer walkthrough of the Activity list: paging, filtering and looking up one request.

Usage and metering

The full field set, the outcome vocabulary and the retention rules.

Credits and billing

Statement lines, purchase annotations and the running ledger total.
Every response carries the same id on two headers: x-uniblock-request-id, which is ours, and x-request-id, which is the one the official OpenAI SDKs surface on their error objects. Every error envelope repeats it as request_id. Quote it when you ask us about a request. Without it we are guessing at which of your requests you mean.