Skip to main content
XIRA

XIRA API reference

XIRA turns messy market data into one clean, verifiable risk score per asset. This page explains what that means in plain terms, where to get the data, and how to check it for yourself.

An API is simply a set of web addresses that answer questions. Each address below is called an endpoint: you visit it, and it returns a JSON response your app (or you, in a browser) can read. The base URL for every endpoint is https://xira-api-production.up.railway.app.

The frontend is statically hosted; the API is a separate server with a 5-minute in-memory price cache. A cold Railway instance may take 30–60s to wake.

Endpoints

Every endpoint serves one job: the board, one asset, its history, market stats, alerts, or health. The interactive OpenAPI docs at /docs of the same origin let you try each one in the browser.

GET/api/assets/allAllAssetsResponse

The main board. Returns a risk score for every tracked market plus a one-line market summary.

?fresh=true forces a recalculation (requires the XIRA_ADMIN_TOKEN header)

data_source is 'live', 'partial', or 'mock' depending on data feed resolution.

GET/api/attestations/{symbol}AttestationResponse

The full record for one asset: its score, confidence, the five factor scores, the explanation, and the on-chain transaction when one was published.

symbol is case-insensitive; must be a tracked symbol (NVDAx, TSLAx, ...)

Read-only: serves the latest published attestation from the store. A GET never writes on-chain; publishing happens on the oracle's schedule.

GET/api/attestations/{symbol}/historyAttestationHistory

A trail of past scores for one asset, newest first. Useful for spotting trends.

?limit=N, 1–50, default 10

Historical entries include stored evidence_hash, model_version, data_source, and published status for full on-chain verifiability.

GET/api/assets/{symbol}AssetDetailResponse

A single asset's profile: which underlying ticker it tracks, its sector, the token address, and how the score moved since the last attestation.

symbol is case-insensitive

score_delta_24h compares the latest score with the previous one.

GET/api/assets/statsMarketStatsResponse

Market-level picture: the average score, how many assets sit in each risk band, and which markets score best and worst.

Served from the shared board cache.

GET/api/alertsAlertsResponse

Every market currently flagged as an anomaly, sorted from highest to lowest risk, with the reason for each flag.

Anomalies are factors scoring at elevated risk levels (e.g. volatility spikes, liquidity crunches).

GET/api/assets/healthHealthResponse

Service health: version, chain, contract address, tracked asset count, and whether live data is enabled.

The landing page's oracle card mirrors this data.

POST/api/assets/{symbol}/rescoreRescoreResponse

Force a fresh re-score for one market, bypassing the price cache. If the new score deviates past the publish threshold (default ±3), the attestation is signed on-chain and the transaction is returned in the response.

publish follows the same ±3 deviation rule as the heartbeat scheduler

Read-only until a meaningful change: scores within the threshold return the reason instead of a transaction.

GET/api/assets/history/stats{ status, database, stats }

SQLite store statistics (row counts per symbol).

Diagnostics.

GET/debug/data-sources{ use_live_data, cache_ttl, cached_tickers, cache_details, env_vars }

Per-ticker data source, cache age, and live-data flag.

Diagnostics; may be disabled in stricter deployments.

Example response

This is what one asset's record looks like. The important parts: risk_score (the 0–100 number), factors (why the number is what it is), and evidence_hash (the fingerprint that proves this record matches what was published onchain).

AttestationResponse

symbol · risk_score (0–100) · risk_level (LOW/MODERATE/ELEVATED/HIGH/CRITICAL) · confidence (37–100) · factors[5] · explanation · anomaly · anomaly_reason · evidence_hash (sha256 hex) · timestamp (unix) · model_version · data_source · data_freshness_ms · chain_tx? · chain_explorer? · chain_block? · chain_id?

FactorScore

name · label · score (0–100) · weight · description

AllAssetsResponse

generated_at · model_version · data_source · summary · assets[]

AttestationHistory

symbol · history[]

HealthResponse

status · version · chain · contract · tracked_assets · live_data · signer · scheduler (pass stats) · publisher (enabled, publishes, last publish/attempt, consecutive failures) · scheduler_stalled · publish_failing · publish_stale

{
  "symbol": "NVDAx",
  "risk_score": 62,
  "risk_level": "HIGH",
  "confidence": 83,
  "factors": [
    { "name": "momentum", "label": "Momentum", "score": 58, "weight": 0.25,
      "description": "Neutral: +0.12% (24h), +1.80% (7d)." }
  ],
  "explanation": "NVDAx shows high risk (score 62/100). ...",
  "anomaly": false,
  "anomaly_reason": "",
  "evidence_hash": "0x4d8a…",
  "timestamp": 1786471527,
  "model_version": "v1.0.0",
  "data_source": "finnhub",
  "data_freshness_ms": 4120,
  "chain_tx": "0xabf3…",
  "chain_explorer": "https://www.okx.com/web3/explorer/xlayer/tx/0xabf3…",
  "chain_block": 9480231,
  "chain_id": 196
}

On-chain contract

Every score is also published to a small program on the X Layer blockchain, so the number does not live only on one server. Anyone can read it there, and the stored fingerprint lets you confirm the API and the chain agree. The contract runs on X Layer X Layer (chain 196) at 0xDe28a2EEc95E3E9Dae6311966Ce2d8B45Db3d41E.

Think of it as a public notice board: the oracle posts the latest score for each market, and anyone can check the post. Read functions are open to everyone; only the oracle can write.

updateAttestation(asset, score, confidence, evidenceHash, modelVersion, anomaly, anomalyReason)

owner / authorized updater

Requires score ≤ 100 and confidence ≤ 100; reverts otherwise.

batchUpdateAttestations(inputs[])

owner / authorized updater

Write several attestations in one transaction.

getLatestAttestation(asset)

anyone · view

Returns the full stored attestation including evidenceHash and timestamp.

getHistory(asset)

anyone · view

Returns the last 20 attestations for an asset, oldest first.

getScore(asset)

anyone · view

The single uint8 risk score: one call, one number.

getScoreBatch(assets[])

anyone · view

Many scores in one call; O(n) read, no per-call fee.

getAllTrackedAssetsWithScores()

anyone · view

All registered symbols, their asset addresses, scores, and timestamps in one call.

getAllTrackedSymbols()

anyone · view

Symbol names registered by the owner.

registerAsset / setAuthorizedUpdater / transferOwnership

owner only

Admin surface for asset registration and updater rotation.

Agents (MCP tools)

AI agents can use the same data through MCP (Model Context Protocol) tools. Instead of reading a dashboard, an agent asks one of these tools and receives the answer directly, with the attestation behind it. Each tool maps one-to-one onto an endpoint.

xira_get_asset_risk

GET /api/attestations/{symbol} : Full attestation for one symbol.

xira_get_all_assets

GET /api/assets/all : All tracked assets with scores, factors, and market summary.

xira_get_asset_history

GET /api/attestations/{symbol}/history : Recent score trail for one symbol.

xira_get_alerts

GET /api/alerts : All currently flagged anomalies.

xira_get_market_stats

GET /api/assets/stats : Market-level risk statistics.

The tools are served over HTTP at https://xira-api-production.up.railway.app/mcp, so any MCP client can point straight at the hosted endpoint, no local server to run:

{
  "mcpServers": {
    "XIRA": {
      "url": "https://xira-api-production.up.railway.app/mcp"
    }
  }
}

Quickstart

REST endpoints need an API key, sent as an X-API-Key header. Health checks and the MCP endpoint stay open, so agents connect without one. To request a key, open an issue on GitHub.

export XIRA_KEY=xira_your_key_here

# one market
curl -H "X-API-Key: $XIRA_KEY" https://xira-api-production.up.railway.app/api/attestations/NVDAx

# the whole board
curl -H "X-API-Key: $XIRA_KEY" https://xira-api-production.up.railway.app/api/assets/all

# a score trail
curl -H "X-API-Key: $XIRA_KEY" "https://xira-api-production.up.railway.app/api/attestations/BAx/history?limit=20"

# market stats and alerts
curl -H "X-API-Key: $XIRA_KEY" https://xira-api-production.up.railway.app/api/assets/stats
curl -H "X-API-Key: $XIRA_KEY" https://xira-api-production.up.railway.app/api/alerts

# health + contract, no key needed
curl https://xira-api-production.up.railway.app/api/assets/health