Statistics API
Use the public-testnet API origin. These endpoints describe indexed records and cached observations, not a guarantee that every external dependency or relayer is healthy.
Overall statistics
GET /api/v1/stats returns success: true with a data object:
overall.totalTransactions,overall.completedTransactions: sums of the overlapping chain buckets, not unique record counts. Casper-originated records contribute to both their EVM bucket and thecasperaggregate.overall.last24Hours.eth2casper,overall.last24Hours.casper2eth: sums of per-chain direction counts, also including the overlapping Casper aggregate. There is nototalfield. Use transaction-listpagination.total(with the relevant filters) for unique record counts; do not compare it for equality with these overall sums.byChain: chain-keyed records withtransactionsByStatus,volumes.byToken(volume,count) andlast24Hoursdirection counts.syncStates: chain-keyedlastBlockandlastSyncedAt. There is noisSyncedfield.
Optional chain accepts an enabled chain slug. Unknown values return 400. This filter belongs to statistics, not the transaction-list endpoint. Volumes are token-specific decimal amounts; do not add different token units as if they were one currency.
curl -fsS 'https://api.testnet.astralbeam.io/api/v1/stats?chain=sepolia'
curl -fsS 'https://api.testnet.astralbeam.io/api/v1/stats' |
jq '.data.overall | {totalTransactions, completedTransactions, last24Hours}'
Per-chain statistics
GET /api/v1/stats/chains returns a data array. Each entry has chainId, name, shortName and stats:
| Stats field | Type | Meaning |
|---|---|---|
total_count |
string or number | Indexed record count |
completed_count |
string or number | Completed record count |
last_tx_at |
string or null | Last record creation time |
evm_chain_name |
string, optional | Chain slug when an aggregate row exists |
Counts can be database integer strings; empty-chain defaults can be numeric zero. No completion-time, success-rate or 24-hour-volume fields are returned here.
curl -fsS 'https://api.testnet.astralbeam.io/api/v1/stats/chains' |
jq '.data[] | {chain: .shortName, total: .stats.total_count, completed: .stats.completed_count}'
Token flow
GET /api/v1/stats/token-flow returns success: true with a data object holding authoritative, deployment-independent transfer totals. Each canonical source event is stored once by the indexer, so these figures do not depend on how many relayers observed a transfer or on restarts. Shares the /stats rate limit and a 30-second cache.
series[]: one entry perdirection,txType(lock,burn_wrapped,burn,lock_native),sourceChain,contract(EVM locker address or the Casper TokenFactory package that emitted the event;legacyfor rows recorded before deployment identity was stored),evmChainId,evmChainName,tokenIdandsymbol. Tokens that share a symbol on different deployments are separate entries.invalidRowscounts rows excluded because their stored amount was not a canonical integer.sourceEvents,completedEvents: verified source events, and the subset whose destination transaction was discovered.sourceAmountRaw,completedAmountRaw: exact integer strings in the source denomination.sourceAmount,completedAmount: the same values as exact decimal strings in token units (no floating point).
coverage[]: one entry per configured scope (chain,contract) withsyncedBlock,earliestObservedBlock,startBlockandcomplete.completeistrueonly when the deployment's history is provably covered from its boundary; otherwisereasonexplains the gap (never_synced,start_block_not_configured,rows_precede_start_block,synced_before_start_block,backlog_draining). Treat incomplete scopes as partial history, not all-time totals.generatedAt: snapshot time.
These are cumulative counts and volumes. Current escrow balances and wrapped supply are contract reads served by GET /api/v1/tokens?includeLiquidity=true.
curl -fsS 'https://api.testnet.astralbeam.io/api/v1/stats/token-flow' |
jq '.data.series[] | {dir: .direction, type: .txType, chain: .evmChainName, token: .symbol, events: .sourceEvents, completed: .completedEvents, amount: .sourceAmount}'
Health and liveness
GET /api/v1/stats/health returns top-level fields, without a data envelope:
{"success": true, "status": "healthy", "checks": {"database": "ok", "indexers": {"sepolia": true}}, "timestamp": "2026-09-08T22:46:13.506Z"}
This is an illustrative reduced response. The indexer map reflects the expected configured chain/contract set, including incomplete configurations, not arbitrary historical sync rows. A true check requires successful required discovery within five minutes. The response also includes mode (full-ingestion or degraded recovery-only) and per-chain checks.ingestion configuration/discovery details. See the readiness contract; neither readiness nor a fresh recovery-loop timestamp certifies relayer availability or resolution of parked work.
| HTTP | status | Meaning |
|---|---|---|
| 200 | healthy |
Database accessible and every expected chain has configured, recent successful discovery |
| 503 | degraded |
Empty/partial configuration, missing sync rows, missing credentials or stale/absent required discovery |
| 503 | unhealthy |
Health query failed; success: false, checks.database: error |
GET /livez checks process liveness only. Use dependency health for readiness/monitoring, not to restart an otherwise live API because an external chain is behind.
async function bridgeHealth() {
const response = await fetch('https://api.testnet.astralbeam.io/api/v1/stats/health');
const body = await response.json();
if (![200, 503].includes(response.status)) throw new Error(`HTTP ${response.status}`);
return { httpStatus: response.status, status: body.status, checks: body.checks };
}
curl -sS 'https://api.testnet.astralbeam.io/api/v1/stats/health' | jq '{status, checks}'
Relayer statistics
GET /api/v1/stats/relayers returns success: true and a data array, populated from stored relayer statistics. Each row contains address, balances.eth (wei string or null), balances.cspr (motes string or null), attestationsSubmitted, lastSeen and isActive.
An empty array means no stored rows are available; it is not evidence that every relayer is down. This endpoint does not return a threshold, aggregate fleet totals or recentActivity. Use operator monitoring for fleet diagnosis.
Utility probes
GET /api/v1/stats/casper-node:data.isUp, nullablebuildVersion,chainSpecName,lastBlockHeight. A reachability failure can return HTTP 200 withisUp: false. Cached for 60 seconds.GET /api/v1/stats/bridge-fee:data.casperis null or{feeMotes: string, feeCspr: number};data.evmmaps chain slugs to null or{feeWei: string, nativeCurrency: string}. Missing/null means unavailable, not free. Cached for 60 seconds; recheck the contract fee before submitting.GET /api/v1/rates/{fiatId}/latest(alias/rates/{fiatId}/latest): proxies the CSPR.cloud rate response unchanged. USD is fiat ID 1 by default; other IDs require operator configuration. Unsupported IDs return 400, rate limits 429, missing configuration 503, and upstream failure 502. Successful responses are cached for 60 seconds.