> ## Documentation Index
> Fetch the complete documentation index at: https://docs.noxint.ai/llms.txt
> Use this file to discover all available pages before exploring further.

# The data contract

> How we solved the agent data problem: finished market facts with context, clocks, and typed refusals built into the wire format

Autonomous trading has a data problem, and it is not access. Anyone can get a
websocket. The problem is that every market API ships data shaped for a human
with a charting library, and agents are not humans. This page is the contract
that fixes it, and it is the reason Noxint exists.

## The problem

An agent does not need another raw venue payload. It needs a finished market
picture with units, clocks, baselines, and uncertainty intact, small enough to
live in a context window.

Raw payloads fail in both directions at once. They flood the model with
fields it will never use, and they omit the statistical meaning that turns a
number into an observation. Is 0.006% funding high? The payload does not say,
so the model guesses. Standardized datasets fail worse: a stale or missing
fact gets served as current, comparable, or zero, and the model trades on a
placeholder without knowing it.

The cost is measurable. In a BTC positioning comparison measured 2026-06-06,
four compact Noxint feeds used about 3,010 input tokens against roughly
204,100 for the mapped raw venue payloads. Same decision-relevant information,
about 1/68th of the context window. (That is a workload measurement, not a
universal guarantee, but it is the shape of the problem.)

## The four rules

Every response from the engine is normalized under four rules:

**Primary facts before standardized guesses.** Equity values originate from
filed statements, not from a reconstructed estimate of them.

**Context beside the value.** A measurement carries its own percentile and
typical band, so it arrives as `{"value": 12.3, "pctl": 84}` rather than a
bare number the model has to rank itself. The enrichment is the product: the
data ships pre-analyzed.

**Freshness is part of the fact.** Every response says when a value was
observed and when it next expects to change. An agent schedules its next read
instead of polling blind.

**Refusal before fabrication.** An unsupported, stale, incomparable, or
ambiguous value is omitted under a typed unavailable reason. Nothing is
filled with zero. An honest gap beats a confident lie, especially when the
reader is a model that cannot smell one.

## Contract guarantees

The wire contract holds these guarantees on every response:

* permanent, plane-qualified asset IDs;
* provider-neutral fields carrying their own provenance;
* UTC source-event clocks, where `as_of` is event time and never cache time;
* `status` limited to `live`, `delayed`, or `degraded`;
* filed values as exact decimal strings with explicit units;
* no trading advice and no fabricated fallback value.

## Asset identity

Every asset has one permanent ID, qualified by its plane. The grammar is
strict:

* crypto by slug: `crypto:bitcoin`
* crypto EVM token: `crypto:eip155-<chainId>:<0x…40 hex>` (lowercase hex)
* crypto Solana token: `crypto:solana:<mint>` (base58)
* US equity: `eq:<10-digit CIK>:<mnemonic>`, for example `eq:0000320193:aapl`

An ID never changes and never points at a different asset, so agents can store
them forever. Ticker aliases are input convenience only. When you hold a human
symbol, `resolve` is the entry point: it returns ranked candidates and warns
when a ticker collides with a distinct asset.

## A worked example

A trimmed `funding` response for Bitcoin:

```json theme={null}
{
  "data": {
    "asset_id": "crypto:bitcoin",
    "symbol": "BTC",
    "name": "Bitcoin",
    "class": "core",
    "as_of": "2026-07-13T08:00:00Z",
    "status": "live",
    "next_update_at": "2026-07-13T16:00:00Z",
    "baseline": { "window": "90d", "cadence": "8h", "n": 270 },
    "funding": {
      "rate_8h_pct": { "value": 0.006, "pctl": 87, "typical_low": 0.0021, "typical_high": 0.0049 },
      "funding_band": "leaning_long",
      "apr_pct": 6.57,
      "venue_spread_8h_pct": { "value": 0.004, "pctl": 62 }
    }
  }
}
```

Read it the way an agent does. The freshness clock is explicit: `as_of` is
source event time, `next_update_at` says when to look again. `rate_8h_pct` is
not a bare number: `pctl` ranks it at the 87th percentile against the stated
90-day `baseline`, and the typical band marks the ordinary range, so
"positioning is stretched long" falls out of the payload with zero inference.
When a fact cannot be proved it does not appear in `funding`; it moves to an
`unavailable` block under a typed reason with a blame class, and `provenance`
records where each served value came from. The model quotes the refusal
instead of inventing a value.

## Where the contract applies

Everywhere. The same contract feeds the HTTP API, the MCP tools, and the chat
analyst. A number you read in chat obeys the same freshness and refusal rules
as one your agent fetches at 3 a.m. See the
[operations overview](/api/operations/overview) for the endpoints that return
it.
