The xAI adapter (daemon/halton_meter/adapters/xai.py) owns the host
api.x.ai. It meters both API surfaces xAI exposes:
| Path | Wire shape | Purpose |
|---|---|---|
/v1/chat/completions | OpenAI-compatible | The default surface most clients use |
/v1/messages | Anthropic-compatible | Drop-in for Anthropic SDK clients |
The two paths share request/response shapes with their progenitors.
The xAI adapter delegates parsing to the shape it sees and writes the
row with provider = "xai". Reports treat both as one provider.
Captured fields
provider = "xai"model— from the response (e.g.grok-4,grok-3-mini)input_tokens,output_tokens— from theusageblock in whichever wire shape the response carriedcost_usd_minor_units— against the active rate card
thinking_tokens is non-zero for Grok-4 reasoning calls when xAI
returns it under usage.reasoning_tokens. cache_* columns are zero
— xAI does not currently expose prompt-cache accounting in its usage
block.
Streaming
Both paths support stream=true. The adapter buffers, reads the final
usage event, writes the row. Truncated streams set
tokens_complete = false.
Tools that route through this adapter
| Tool | Path |
|---|---|
OpenAI SDK pointed at https://api.x.ai/v1 | /v1/chat/completions |
Anthropic SDK pointed at https://api.x.ai/v1 | /v1/messages |
curl https://api.x.ai/v1/... | Either |
| Cursor / Windsurf configured with an xAI base URL | /v1/chat/completions |
Verifying capture
$ halton-meter run -- curl -sS https://api.x.ai/v1/chat/completions \
-H "Authorization: Bearer $XAI_API_KEY" \
-d '{"model":"grok-3-mini","messages":[...]}'
$ halton-meter report --since 5m --by model Error classification
xAI’s API is OpenAI-compatible verbatim, including the error envelope
shape. The daemon routes provider=xai through the OpenAI classifier
without a separate adapter, so the
OpenAI table is the
mapping — including the HTTP 429 insufficient_quota → auth split.
Shipped in v0.3.0.
HTTP status is the primary signal; the error.type string match is
best-effort, since xAI does not publish the exact strings. If post-launch
traffic shows xAI diverging (e.g. rate_limit_exceeded versus
rate_limit_error), a thin alias map is added rather than forking the
adapter. For the bucket definitions, see
Error classification.
Host matching
api.x.ai is matched by exact equality. The legacy api.grok.x.ai
host is not in scope.