What every trace stores
Every request writes one trace row: which model was requested and which actually served it, the routing reason and predicted difficulty/task type, token counts, cost breakdown (provider cost vs. our fee), routing and upstream latency, fallback path, cache hit/miss, and status. This is what backs /logs and /usage, visible only to your own account.
What a trace never stores
Your message content is not in the trace store. No prompt text, no completion text, no raw
message array — the schema has no column for it. The one content-derived field is
prefix_hash, a one-way SHA-256 hash
of your multi-turn prefix used only for cache/sticky-routing analytics — it can't be reversed back into your
text.
Attribution fields are the exception
If you send app-attribution headers
or the user field, those exact
strings (your app name, referrer, end-user id) are stored as given, since that's the point of sending them —
don't put anything in them you wouldn't want stored plainly.
The one place bodies are stored
The response cache is the single exception: it's opt-in per request, stores the full request/response body only for that entry, is always namespaced to your own org (never shared across tenants), skips tool/function-calling requests entirely, and expires on a TTL (default 5 minutes, capped at 24 hours). If you never send the opt-in header, none of this applies to you.
What the upstream provider sees
Your prompt is, of course, sent to whichever provider serves the request — that's inherent to getting a completion back. What that provider retains is governed by their own terms, not ours; we don't add a retention layer of our own on top beyond what's described above.