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.
/api/assets/allAllAssetsResponseThe 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.
/api/attestations/{symbol}AttestationResponseThe 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.
/api/attestations/{symbol}/historyAttestationHistoryA 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.
/api/assets/{symbol}AssetDetailResponseA 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.
/api/assets/statsMarketStatsResponseMarket-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.
/api/alertsAlertsResponseEvery 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).
/api/assets/healthHealthResponseService health: version, chain, contract address, tracked asset count, and whether live data is enabled.
The landing page's oracle card mirrors this data.
/api/assets/{symbol}/rescoreRescoreResponseForce 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.
/api/assets/history/stats{ status, database, stats }SQLite store statistics (row counts per symbol).
Diagnostics.
/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).
AttestationResponsesymbol · 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?
FactorScorename · label · score (0–100) · weight · description
AllAssetsResponsegenerated_at · model_version · data_source · summary · assets[]
AttestationHistorysymbol · history[]
HealthResponsestatus · 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 / transferOwnershipowner 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_riskGET /api/attestations/{symbol} : Full attestation for one symbol.
xira_get_all_assetsGET /api/assets/all : All tracked assets with scores, factors, and market summary.
xira_get_asset_historyGET /api/attestations/{symbol}/history : Recent score trail for one symbol.
xira_get_alertsGET /api/alerts : All currently flagged anomalies.
xira_get_market_statsGET /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