For the complete documentation index, see llms.txt. This page is also available as Markdown.

Request Tracing and Cost Headers

Every inference response carries the ids and, where it can, the price of the call that produced it. That is enough to attribute spend per request without polling a reporting endpoint afterwards β€” and enough to tie our records to yours when something needs explaining.

This works on all inference endpoints; it is a property of the transport, not of a particular model.

Attaching your own identifier

Send X-Client-Request-Id with the request and we store it, echo it back, and report it as client_request_id in Usage Logs. Use whatever identifies the work on your side β€” an order number, a job id, a customer reference.

curl -sS -D - -o /dev/null \
  --url 'https://api.aimlapi.com/v1/chat/completions' \
  --header 'Authorization: Bearer <YOUR_AIMLAPI_KEY>' \
  --header 'Content-Type: application/json' \
  --header 'X-Client-Request-Id: order-8f21c4' \
  --data '{"model": "openai/gpt-5", "messages": [{"role": "user", "content": "Hi"}]}'

The value must be 1–128 characters from A–Z, a–z, 0–9, ., _, : and -.

What comes back

Header
When it is present

x-inference-id

Always

x-client-request-id

When you sent a valid X-Client-Request-Id

x-aimlapi-credits-used

Non-streaming JSON responses

x-aimlapi-usd-spent

Non-streaming JSON responses

x-inference-id is the handle for everything downstream. It is the id the charge is recorded under, so it comes back as reference_id in GET /v2/billing/transactions and as inference_id in Usage Logs. For an asynchronous generation it is the same id that submit returned as generation_id, so a submit and its polls share one id.

x-aimlapi-credits-used is an integer count of credits; x-aimlapi-usd-spent is the same amount in USD.

All four headers are listed in Access-Control-Expose-Headers, so a browser can read them on a cross-origin response. Without that a fetch from the browser sees the response but not these headers.

When the cost is not in a header

Two response types deliberately carry no cost headers, because the price is not known by the time headers are sent.

Streaming responses. Headers flush before the first token, so the total cannot be there yet. The cost arrives in the final SSE chunk instead, under meta.usage:

Binary audio (wav). The cost only arrives in a summary after the audio itself, and holding the whole response back to fill in a header would mean buffering it in memory. Read the cost of these calls from Usage Logs instead.

The correlation headers β€” x-inference-id and x-client-request-id β€” are present in both cases; it is only the cost that moves.

On the poll routes of an asynchronous generation, the inference id is a value you supply as a query parameter. If it does not look like an id we could have issued, the header is left out rather than the request failed β€” so an absent x-inference-id on a poll means the id you polled with was malformed.

Following one request end to end

  1. Send the request with your own X-Client-Request-Id.

  2. Read x-inference-id from the response and keep it next to your own record.

  3. Later, find the request in Usage Logs β€” by client_request_id if you sent one, otherwise by inference_id β€” for its status, tokens and cost.

  4. Find the money it moved in GET /v2/billing/transactions, where the same inference id appears as reference_id.

Last updated

Was this helpful?