Skip to content
Documentation

Telemetry schema

Bayeto reads 12 columns and nothing else. 4 are required; the rest sharpen the analysis where you have them, and each one that is missing makes a specific rule stand down rather than guess.

The columns

Header names are matched case-insensitively and ignoring punctuation, so input_tokens and inputTokens are the same column. Every spelling in the “also accepted” list below is read directly from the parser.

timestamprequiredISO 8601, or epoch seconds, or epoch milliseconds. A zone-less ISO value is read as UTC.

When the call happened. Drives windowing and regime detection. An ambiguous slash date (MM/DD versus DD/MM) is rejected as a row error rather than guessed.

also accepted: created · createdat · date · requestcreatedat · starttime · timestamp · ts

modelrequired

The provider model id exactly as you log it — gpt-4o, claude-sonnet-5, anthropic/claude-sonnet-5. Blank is a row error.

also accepted: model · modelname

input_tokensrequiredwhole tokens, zero or more

Uncached prompt tokens. If you also send cache_read_tokens, the engine adds them back to get the true prompt size — so this column is the uncached portion only.

also accepted: inputtokens · prompttokens · tokensprompt

output_tokensrequiredwhole tokens, zero or more

Completion tokens.

also accepted: completiontokens · outputtokens · tokenscompletion

applicationoptional

The subsystem or feature the call belongs to. This becomes a node in your architecture graph. Rows with no value are attributed to a single 'unattributed' application rather than dropped.

also accepted: app · application · applicationname · appname · userapikeyalias

cache_read_tokensoptionalwhole tokens, zero or more; absent means 0

Tokens served from a cached prefix. A call counts as a cache hit when this is above zero.

also accepted: cachedtokens · cachereadinputtokens · cachereadtokens

cache_write_tokensoptionalwhole tokens, zero or more; absent means 0

Tokens written into the cache.

also accepted: cachecreationinputtokens · cachewritetokens

cost_usdoptionalUS dollars as a decimal number — not cents, not euros

What the call cost, if your export carries it. Absent means Bayeto estimates it from the pinned model catalog and says so on screen.

also accepted: calculatedtotalcost · cost · costusd · responsecost · spend · totalcost · usage

latency_msoptionalMILLISECONDS. Fractions are rounded.

End-to-end call latency. Read the units twice: an export whose latency column is in seconds will be read as milliseconds, because nothing can safely tell 4.2 seconds from 4.2 milliseconds.

also accepted: durationms · latency · latencyms

provideroptional

Who served the call. When present it is treated as a logged fact rather than an inference, which is what lets the provider-arbitrage rule speak with more confidence.

also accepted: customllmprovider · litellmprovider · provider · providername

regionoptional

Where the call was served, if you know. Without it the cross-region rule stands down instead of guessing.

statusoptional

Per-call outcome, stored exactly as written. Classified at read time: a numeric status uses HTTP semantics, a known failure word counts as a failure, and anything absent or unrecognised counts as a success.

What the schema refuses

Anything not in the list above is never read, so there is nothing to strip later. That covers prompt and completion text, user and session identifiers, emails, trace ids, API keys, and request or response bodies — a column with one of those names is skipped before its value is touched.

Three refusals are deliberate enough to name. A value that is not a simple number or string is ignored even under an accepted column name, so a nested usage object from an OpenAI export cannot become a cost. LiteLLM’s bare user field is not accepted as an application name, because it may carry an end-user identifier. And nothing about your prompts is inferred from what is present: the schema has no place to put content, by design.

Web uploads are parsed in your browser. The file never leaves your machine; only normalized rows matching the table above are transmitted, and the server re-validates them with the same rules.

Two units that bite

Cost is US dollars, as a decimal number. Not cents, not euros. Bayeto displays euros and converts at a pinned rate it states on screen.

Latency is milliseconds. Some exports label a seconds column with the same name. Nothing can safely tell 4.2 seconds from 4.2 milliseconds, so the parser does not try — it reads what the column says it is. If your latency numbers look impossibly small on screen, that is the reason.

Rows the parser rejects

A row missing any required field, carrying a non-numeric token count, or dated ambiguously (03/04/2026 could be March or April) is reported as a row error and not ingested. A malformed row never becomes half-ingested. Ambiguous dates are rejected rather than guessed, because a guess would move traffic between days and quietly change every window in the analysis.

This describes the upload path. The live LiteLLM connector is a separate entrance with its own mapping and its own handling of bad events; if you are streaming rather than uploading, its behaviour is documented with the connector.

© 2026 Bayeto