Skip to main content
GET
Retrieve a recorded primary request charge
GET /api/v1/usage/requests/{request_id} returns the recorded cost and token usage for one primary charge from the last 24 hours. Capture X-Request-ID from the inference response headers before reading SSE and use the same API key for the lookup. No dates or other query parameters are accepted. For chat completions, omit the incoming X-Request-ID header and capture the server-generated ID from each response. Save it as soon as the response headers arrive, before consuming the stream; it is the ID to use for this lookup.

What cost means

cost is the exact amount recorded on the matching primary charge, expressed as a decimal string in currency (USD or XNO). The lookup does not recalculate prices. A recorded zero is returned as zero; a missing charge is never converted to zero. Refunds and separately billed extras, such as a separate search charge, are excluded. Components already incorporated in the primary charge’s amount remain included. This is the original recorded primary cost, not an all-in total or a net amount after refunds. A later refund does not reduce this field. A completed transaction record is also not proof that balance collection has finished. Tokens are recorded accounting values and may have been estimated for an interrupted stream. Missing, invalid or unsafe-sized counts are null. Reasoning tokens may already be included in output tokens; do not add them again. No prompts, responses, provider routing, internal identifiers or arbitrary transaction metadata are returned.

Availability and request IDs

The window is rolling, including across UTC midnight. A charge is eligible when its accounting timestamp is no more than the database’s current time and is strictly less than 24 hours old. expires_at is that timestamp plus 24 hours; access ends at that instant. This timestamp can precede insertion when delayed billing is replayed. Replay does not reset the lookup window. Financial records are retained; this endpoint simply stops exposing older charges. Billing can be asynchronous, especially after a disconnect, so the charge might not be available immediately. A charge recorded only after its window expires cannot be recovered through this endpoint. Expired, unavailable and inaccessible records all return the same 404; this does not prove that a request was free. If you supply your own X-Request-ID, use a unique value for every execution, including a retry that sends a new inference request. The header is a correlation ID, not an idempotency key: reusing it does not prevent another charge. After a disconnect, look up the original ID to recover its cost; retrying the lookup does not rerun inference. If you also retry inference, keep the two execution IDs separate. If more than one eligible primary charge matches within the window, the endpoint returns 409 ambiguous_request_id, without choosing one, summing different attempts, or returning their details. Uniqueness is checked within the window only; reusing an expired ID can resolve to a newer execution. Only completed primary charges with the exact stored public request ID are covered. Other endpoints are supported only when they persist that identity and key/issuer attribution. Related child IDs and archived records are not followed.

Authentication

The inference key can read only its own charges attributed to its originating account in the same NanoGPT tenant. Team-paid charges remain visible to the originating actor’s key; team ownership or membership does not grant broader access. Missing or inconsistent historical attribution can make a charge unavailable. Revoked/expired keys, deleted/merged issuers, and different keys cannot retrieve the original key’s charges. Rotation does not transfer access. Authentication is fresh and existing key Origin restrictions apply. Use Authorization or x-api-key; cookies, management credentials and partner tokens grant no access. Conflicting credentials are rejected; equivalent supported prefix/case forms are accepted.

Polling and errors

Make the first lookup about two seconds after a disconnect or completion. A 404 includes Retry-After: 30: wait at least 30 seconds, plus a small random delay, before the next lookup. Honor Retry-After on 429 and 503 responses too; do not cap a larger server-requested delay at 30 seconds. For a network failure without a response, back off with jitter from two seconds up to 30 seconds. Stop on 200. Stop and correct the request or seek support on 400, 401, 403 or 409; do not automatically rerun inference to resolve a billing lookup error. This API does not expose a finalized flag and clients do not need to keep polling for later refunds. Clients are responsible for polling and honoring retry delays. The shared budgets are 60 lookups/minute per key and 300/minute per trusted IP, including unsuccessful lookups. Coordinate polling across concurrent requests. If no charge appears, stop retries no later than 24 hours after the original request and retain its ID for support. This is a retry limit, not a promise that every billing record will become available within 24 hours. Every response uses Cache-Control: private, no-store, max-age=0, private/no-store CDN headers and Vary: Authorization, x-api-key.

Capture the ID before reading a stream

This JavaScript example saves the ID when the response headers arrive. Keep it even if reading the body fails. model and messages are the values from your normal chat request, and apiKey is your NanoGPT API key.
Use the HTTP response header, not a completion ID from a JSON body or SSE event. If the connection fails before headers arrive and no ID was captured, this endpoint cannot identify that execution for you. For a later lookup, use the same key and the captured ID:
Retry-After may contain seconds or an HTTP date; respect its full delay. For aggregate spend and refunds over a date range, use Usage.

Authorizations

Authorization
string
header
required

Bearer authentication header of the form Bearer <token>, where <token> is your auth token.

Path Parameters

request_id
string
required

X-Request-ID captured from response headers before disconnect. Prefer omitting the incoming header so the server generates one. This is not an idempotency key: use a distinct ID for each inference execution, including retries; repeated IDs may return 409.

Required string length: 1 - 128
Pattern: ^[A-Za-z0-9][A-Za-z0-9._:-]{0,127}$

Response

One recorded primary charge from the last 24 hours. All responses use private/no-store and Vary: Authorization, x-api-key.

object
string
required
Allowed value: "request_billing"
request_id
string
required
Required string length: 1 - 128
Pattern: ^[A-Za-z0-9][A-Za-z0-9._:-]{0,127}$
created_at
string<date-time>
required

Ledger accounting timestamp; not necessarily insertion time.

expires_at
string<date-time>
required

24 hours after the charge accounting timestamp. The record is unavailable at or after this instant; financial records are retained.

as_of
string<date-time>
required

Database statement snapshot time.

cost
string
required

Exact nonnegative amount recorded on the primary charge. Does not subtract refunds or add separately billed extras; not proof of balance collection.

Maximum string length: 121
Pattern: ^\d{1,80}(?:\.\d{1,40})?$
currency
enum<string>
required
Available options:
USD,
XNO
cost_scope
string
required
Allowed value: "primary_charge"
usage
object
required