As-of-ledger & staleness

Reason about data freshness with meta.last_indexed_ledger, pin reads to a past ledger with as_of_ledger, and pull history over a ledger range.

Because Orion stores per-ledger snapshots of every entity, a read isn’t only “the latest state” — you can ask what a wallet looked like at an exact point in chain history, and reconstruct a range as a time series. Both build on one primitive: the ledger sequence number.

Freshness: meta.last_indexed_ledger

Every response carries a meta block describing how fresh the data is:

"meta": {
  "data_staleness_seconds": 4,
  "last_indexed_ledger": 3356416,
  "oracle_staleness_seconds": 12,
  "partial_result": false,
  "sources": ["soroban_rpc"],
  "attribution_confidence": 1.0,
  "response_time_ms": 18
}
FieldMeaning
last_indexed_ledgerThe ledger sequence this response reflects. The single anchor for “how current is this?”
data_staleness_secondsWall-clock age of the indexed data.
oracle_staleness_secondsAge of the prices used for USD values; null when no oracle was involved.
partial_resulttrue when some source was unavailable and the response is incomplete.
sourcesWhere the data came from: soroban_rpc, goldsky, or cache.
attribution_confidenceConfidence, 01, that activity was attributed to the right actor.

Use last_indexed_ledger, not the wall clock, as your notion of “now” — two responses with the same value describe the same chain state.

Point-in-time reads: as_of_ledger

Protocol-scoped position endpoints accept an as_of_ledger query parameter and return the wallet’s state at that ledger — the latest stored snapshot at or before it. The values were computed then, so the health factor and USD values you get back are the ones that were true at that ledger, not today’s numbers recomputed against old balances.

curl "https://query.orionhq.run/v1/users/GABC7XYZ.../positions/blend?as_of_ledger=3300000" \
  -H "x-orion-api-key: $ORION_KEY"

as_of_ledger is supported on the per-protocol reads (/positions/blend, /positions/aquarius, /positions/soroswap, /positions/{protocol}), on protocol reserves and tvl, on the history endpoints, and on the activity feed.

Note. The unified GET /v1/users/{address}/positions endpoint does not serve as_of_ledger — the parameter is rejected there. For a point-in-time portfolio, read per-protocol.

History over a ledger range

The Blend summary-history endpoint returns the account’s value and health as a series across a ledger window. Pass from_ledger and to_ledger for the raw snapshots in range:

curl "https://query.orionhq.run/v1/users/GABC7XYZ.../positions/blend/summary/history?from_ledger=3300000&to_ledger=3356416" \
  -H "x-orion-api-key: $ORION_KEY"
{
  "data": {
    "address": "GABC7XYZ...",
    "points": [
      {
        "ledger": 3300000,
        "timestamp": "2026-07-18T08:00:00Z",
        "supplied_usd": "1580.00",
        "borrowed_usd": "140.00",
        "health_factor": "1.79",
        "borrow_limit_pct": "0.14"
      },
      {
        "ledger": 3356416,
        "timestamp": "2026-07-23T09:12:44Z",
        "supplied_usd": "1620.00",
        "borrowed_usd": "137.45",
        "health_factor": "1.87",
        "borrow_limit_pct": "0.13"
      }
    ]
  },
  "meta": { "...": "response metadata" }
}

Each point’s valuation fields are read straight from the stored snapshot at that ledger — never re-priced or re-derived.

Bucketing a range

Raw snapshots can be dense. History endpoints bucket the series two ways; pick one axis per request:

  • Ledger buckets — set ledger_bucket to a bucket size with from_ledger/to_ledger. Buckets are cut on the ledger axis.
  • Time buckets — set interval (1h, 4h, or 1d) with from/to ISO-8601 timestamps. Buckets are cut on the wall-clock axis.

The Blend and Aquarius pool-history endpoints also accept a range shortcut that implies both a window and an interval:

rangeWindowBucket
24hlast 24 hours1h
7dlast 7 days4h
30dlast 30 days1d
curl "https://query.orionhq.run/v1/users/GABC7XYZ.../positions/blend/CCLBPEYS.../history?range=7d" \
  -H "x-orion-api-key: $ORION_KEY"

Gaps

A bucket with no snapshot is a real gap, and fill controls how it’s rendered:

fillBehavior
noneLeave the gap empty (the default).
locfLast-observation-carried-forward — repeat the previous known snapshot.

An locf bucket that precedes the account’s first-ever snapshot has nothing to carry forward: its ledger and value fields come back null rather than a fabricated zero. fill requires an active bucketed mode.