Base URL
Authentication
Reads need no API key. EveryGET route works without a key, limited per client IP. A valid key skips the IP limit and counts against its own monthly quota instead (10,000 calls a month unless your plan sets another). A retired or unknown key is treated as no key, so it falls back to the IP limit rather than failing.
Get a key from the Developer Portal when you need more than the IP limit allows, and send it in the x-api-key header:
Route Access
Any other write without a valid key gets
401. Quotas are per key, per calendar month (UTC), and reset on the 1st. “Operator key” routes are for the operator’s own services: any other key gets 403.
Scopes
A key can be limited to scopes when it is created. Each route group needs its scope:
An empty or missing scope list means all scopes.
Health Check
Full Health Check
Simple Liveness Probe
Prices
Get Token Price
Example:
source field indicates where the price came from:
aggregated(...): OCT and wOCT. The names in brackets are the sources that agreed:uniswap(the live pool price) leads while it agrees with the polledcoingeckoanddexscreenerprices; a source too far from the others is left outspot: ETH (from the live ETH/USD feed) and SOL (Coinbase, then Kraken)static: USDC and USDT, pegged at $1
Get All Prices
Get OCT Detailed Market Data
Get TWAP Prices
Trading
Get Swap Quote
Example:
Get AMM Reserves
Simulate Trade (Operator)
403.
Request Body:
Update Liquidity (Operator)
403.
Request Body:
Chart Data
Get Price History
Example:
The
time field on chart data points is a Unix timestamp in seconds (suitable for charting libraries like Lightweight Charts). Other endpoints (/health, /api/price/oct/details, /api/reserves) return timestamps in milliseconds.EVM Data
The 0xio wallets read EVM address data through these routes. They are read from Blockscout with the oracle’s own key, server side. Each call covers one chain, so a client can query chains in parallel and keep per-chain failures apart.EVM History
Response:
{ transactions, token_transfers }, Blockscout’s v2 items trimmed to the fields wallets read, under Blockscout’s own names. Every other field is dropped. Cached 60 seconds per chain and address.
transactionsitems:hash,timestamp,value,statusandmethod;from,toandcreated_contractas{ hash }or null;feeas{ value }(wei) or null;raw_input;decoded_inputas{ method_call, method_id, parameters: [{ name, type, value }] }or null. Contract names are not passed on; wallets read them per address with the explorer’s verified and scam flags.token_transfersitems:transaction_hash,timestampandlog_index;fromandtoas{ hash }or null;totalas{ value, decimals };tokenas{ address_hash }. Token names, symbols and logos are left out, so a wallet names a token only from its own list.- Caps: a scalar string is cut at 128 characters and a fee at 80.
raw_inputis kept whole up to 522 characters (a selector and eight words) and cut to its 10 character selector beyond that, and dropped unless it is0xand hex.parameterskeeps the first 16. A parameternameortypeis cut at 64 characters,method_calland a parametervalueat 512 (a nested array or object longer than that becomes its JSON text, cut), andmethod_idat 10. A cut string ends with….
EVM NFTs
chain (a positive integer chain ID) and address (0x and 40 hex characters).
Response:
contractis lowercase.tokenIdandamountare decimal strings of at most 78 digits.standardisERC-721orERC-1155.name(token metadata) andcollection(token name) are trimmed, stripped of control and bidi characters and capped at 80 characters, or null.imageis anhttps://oripfs://URL of at most 1024 characters, or null.- Tokens Blockscout flags as scam or spam are dropped.
- Paging: follows Blockscout’s pages up to 200 items (5 pages, 20 seconds in total).
completeis false when more remain or a later page failed. Cached 60 seconds per chain and address (10 seconds for a result cut short by a failed page). - Errors:
400on a bad chain or address, or a chain Blockscout does not serve;503when Blockscout fails.
EVM Tokens
chain (a positive integer chain ID) and address (0x and 40 hex characters).
Response: { items: [{ contract, symbol, name, decimals, balance, price, verified, spam, spamReason, logo }], complete }, in Blockscout’s order (highest USD value first).
-
contractis lowercase.decimalsis an integer from 0 to 36 (other items are dropped).balanceis a decimal string of at most 78 digits, and zero balances are skipped. -
symbol(at most 11 characters) andname(at most 40) are trimmed and stripped of control, bidi and zero-width characters, or null when empty or longer. -
priceis Blockscout’s USD exchange rate when finite and above 0, else null. -
logois kept only as anhttps://URL of at most 512 printable ASCII characters onraw.githubusercontent.com,assets.coingecko.comorcoin-images.coingecko.com; null otherwise, and always null on a spam item. Never anything the token contract itself supplies. -
verifiedsays whether the contract source is verified. It is looked up only where it decides the verdict (unpriced tokens no other rule caught), else null. -
spamis true when any rule below holds;spamReasonis the first that matched, else null:flagged: Blockscout marks it as scam or spam.link: the name or symbol holdshttp,www.or a domain (a dot after a letter or digit, then 2 to 10 letters), such ast.meorx.com.bait: the name or symbol holds claim, reward(s), airdrop, visit, free, voucher, bonus, gift, redeem or eligible as a word (camelCase split; airdrop, voucher and eligible anywhere).impersonation: the symbol, with look-alike Cyrillic, Greek and fullwidth letters mapped to Latin and case and spaces ignored, is ETH, WETH, USDC, USDT, DAI or WBTC on a chain where that token is listed (1, 4663, 8453, 42161, 10, 137) at a contract that is not the canonical one. OCT and WOCT apply on every chain; the only canonical one is wOCT on Ethereum (0x4647e1fe715c9e23959022c2416c71867f5a6e80).unverified_unpriced: the contract is not verified and has no price.
-
Paging: follows Blockscout’s pages up to 200 items (5 pages, 20 seconds in total).
completeis false when more remain or a later page failed. Cached 60 seconds per chain and address, 10 seconds when a page failed or verification lookups were left for the next call. -
Errors:
400on a bad chain or address, or a chain Blockscout does not serve;503when Blockscout fails or its plan does not cover the chain.
Bridge Analytics
The bridge site and the 0xio Extension report each step of a transfer toPOST /api/bridge/event. The read routes count a row only after the oracle has found that transfer on chain.
Report a Bridge Event
Response:
{ "status": "ok" }, or { "status": "duplicate" } when the row is already known. 400 with a short error on any rule above; 429 past the rate limit.
- Limits: 20 posts a minute per client IP and 300 a minute in total.
- Dedupe: an event whose
(event_type, tx_hash)already has a verified row, or a pending row with the same addresses and amount, is not stored again. At most 3 rows with different payloads may wait under one hash, and only one verified row is allowed per(event_type, tx_hash), so a fake posted first with a real hash cannot block or double the real event.
Verification
Every row starts unverified and is left out of every read. A background task checks rows newest first:- lock: the Octra contract receipt shows a successful
lock_to_ethon the bridge vault whoseLockedevent hasoctra_addras sender, the same amount andeth_addras recipient. - claim: the Ethereum receipt succeeded, was sent to the bridge contract, is 12 blocks deep and holds a
Mintedevent for the amount whose recipient (or the transaction’s sender) iseth_addr. - burn: the same receipt checks and a
BurnToOctraevent for the amount frometh_addrtooctra_addr. - any_swap: Relay reports the request as settled, and one of its Ethereum transactions sends wOCT to
octra_addrthrough the bridge for the amount (within 1%). - A row not on chain yet is checked again after 1, 2, 4 minutes and so on, at most 12 hours apart.
- Rows are never deleted. A row that breaks the rules, is contradicted by the chain twice, is under 7 days old and still not found after 8 checks, or whose hash another verified row already holds, is quarantined and read by no route. A row older than 7 days that is not found after 3 checks stays unverified instead.
Bridge Stats
/api/bridge/stats: totals such astotal_events,total_locks,total_burns,locks_24h,burns_24h,volume_locked_oct,volume_locked_24h_oct,volume_burned_oct,volume_burned_24h_oct,unique_octra_walletsandunique_eth_wallets, plusby_sourcewith the same totals forweb(the bridge site) andextension(the 0xio Extension). Both keys are always present, and wallet counts are per source, so the two can overlap. The top-levelsourcefield is a fixed"bridge_frontend_only", kept for older readers: it only says these are client-reported transfers rather than full on-chain totals, and does not name a client; useby_sourcefor the split.notedescribes what is counted. Cached 60 seconds./api/bridge/events:{ events, count }, newest first.limitdefaults to 50 (at most 500)./api/bridge/chart:{ data }, daily rows withts,direction,event_type,amount_octandsource. Cached 120 seconds.
amount_raw.
Metrics
API Key Management
List Your Keys
Example:
Generate New Key
0xio-<16 hex>-oracle. An owner can create at most 5 keys an hour (429 past that).
Request Body:
Signature Message Format:
0xio-api-key:oct...:1706270400
Response:
Revoke Key by ID
id from create or list. Signed by the owner wallet, so a lost or over-quota key can still be revoked.
Signature Message Format:
404 when the id does not exist or belongs to another wallet, 401 on a bad signature and 400 on an expired or malformed one.
Revoke Key with the Key Itself
DELETE /api/keys/:id, which also works for a key that is over its quota.
Headers:
Usage Report
days (1 to 365, default 30) with the latest logs requests (1 to 500, default 20). Signed by the owner wallet over 0xio-usage:{owner}:{timestamp}.
The key routes (POST /api/keys, GET /api/keys, DELETE /api/keys/:id) and GET /api/usage allow 60 calls a minute per client IP.
Error Responses
Error responses from the routes use the shape
{ "error": "message" }; a route’s own rate limit adds retry_after in seconds. A 401, 403 or 429 from the key check itself (no key over the IP limit, a missing scope, a key over its quota) carries no body.