truvo

Truvo docs

How to read an Asset Passport, how fresh the data is, and how to use the API.

API reference · v1 · schema 1.0.0

REST API

A read-only REST API over the Truvo registry. Every response carries its schema version, the time it was observed, a freshness summary and source references. Missing values are null, never zero, empty string or a default “safe” status.

Base URLhttps://api.truvo.site(local: http://localhost:4000)

Response envelope

schema_version
Semver of the response schema. Breaking changes bump the major version and the /v path.
observed_at
When the server assembled this response. Field ages are relative to it.
freshness
fresh · stale · partial, the oldest observation, and which fields are stale.
references
Original source URLs backing the payload, for users to open themselves.
data
The payload.

Status vocabulary is defined in the methodology. Field statuses are recomputed against each field’s max_age_seconds at request time, so a cached client copy can go stale but the API will not report it as fresh.

GET/v1/assets

Search indexed and curated assets.

ParamTypeNotes
qstringSymbol, name, or full contract address. A ticker returns every contract using it.
statusenumverified · stale · conflicting · unknown · unverified
asset_typeenumstock_token · etf_token · stablecoin · wrapped_native · other
chain_idinteger4663 (Robinhood Chain) or 46630 (testnet)
limit, offsetintegerPagination. limit 1–100, default 50.
{
  "schema_version": "1.0.0",
  "observed_at": "2026-10-22T11:02:41.000Z",
  "freshness": null,
  "references": [],
  "data": {
    "items": [
      { "chain_id": 4663, "symbol": "TSLA", "status": "verified",
        "contract_address": "0xde40…0001",
        "ui_multiplier": "1.0",
        "completeness": { "present": 9, "total": 11 } },
      { "chain_id": 4663, "symbol": "TSLA", "status": "unverified",
        "contract_address": "0x7e5a…beef" }
    ],
    "total": 2, "limit": 50, "offset": 0
  }
}
GET/v1/assets/{chainId}/{address}

Fetch the full Asset Passport: claims with provenance, verifications, sources, events and known unknowns.

ParamTypeNotes
chainIdpathChain ID, e.g. 4663.
addresspath0x-prefixed 40-hex address. Case-insensitive; responses are lowercase.
{
  "schema_version": "1.0.0",
  "observed_at": "2026-10-22T11:02:41.000Z",
  "freshness": {
    "status": "stale",
    "oldest_observed_at": "2026-10-02T11:02:41.000Z",
    "stale_fields": ["price_feed"]
  },
  "references": ["https://docs.robinhood.com/chain/stock-tokens/"],
  "data": {
    "symbol": "AAPL",
    "status": "stale",
    "claims": [{
      "claim_type": "price_feed",
      "claim_value": "Chainlink AAPL/USD (multiplier-adjusted)",
      "status": "stale",
      "observed_at": "2026-10-13T11:02:41.000Z",
      "max_age_seconds": 604800,
      "source_ids": ["src_feed_00003"]
    }, {
      "claim_type": "redemption_terms",
      "claim_value": null,
      "status": "unknown"
    }]
  }
}
GET/v1/assets/{chainId}/{address}/sources

List the sources that support claims for this asset, with retrieval time, method, block number and content hash.

No query parameters.

{
  "schema_version": "1.0.0",
  "data": [{
    "id": "src_rh_docs_contracts",
    "source_type": "official_docs",
    "source_url": "https://docs.robinhood.com/chain/contracts/",
    "retrieved_at": "2026-10-22T09:02:41.000Z",
    "method": "http_fetch",
    "content_hash": "sha256:…"
  }]
}
GET/v1/assets/{chainId}/{address}/events

Detected changes: multiplier updates, metadata changes, feed re-pointing, conflicts and verification changes.

No query parameters.

{
  "schema_version": "1.0.0",
  "data": [{
    "event_type": "multiplier_changed",
    "detected_at": "2026-10-20T11:02:41.000Z",
    "previous_value": "1.000000",
    "new_value": "1.004120",
    "block_number": 17751110,
    "evidence": "src_rpc_uiMultiplier_00004"
  }]
}
GET/v1/health

API and dependency health: database, RPC, indexer lag and source pipeline.

No query parameters.

{
  "schema_version": "1.0.0",
  "data": {
    "state": "degraded",
    "components": [
      { "name": "rpc", "state": "degraded", "latency_ms": 842,
        "detail": "Public RPC rate-limited; served by fallback" }
    ],
    "indexer_head": { "block_number": 18442307, "chain_head": 18442310, "lag_blocks": 3 }
  }
}

Errors

{ "error": { "code": "not_found", "message": "No passport for 4663:0x…", "request_id": "req_7f3a91" } }
400invalid_addressAddress is not 0x + 40 hex characters, or chainId is not an integer.
400invalid_queryA filter value is outside its enum or range.
401unauthorizedOperator endpoint called without a valid operator token.
404not_foundNo passport for this chain + address. Not a verdict on the contract.
429rate_limitedToo many requests. See x-ratelimit-* headers and retry-after.
503dependency_unavailableDatabase unreachable. Never answered with cached data disguised as fresh.

Rate limits & API keys

  • Anonymous: 60 requests / minute per IP. With x-api-key: 600 / minute.
  • Every response includes x-request-id and x-ratelimit-limit / -remaining / -reset.
  • Operator endpoints under /v1/admin require a bearer token and write to the audit log.
  • No SLA is offered yet. An SLO will be set once a reliability baseline exists (PRD §17).