Skip to main content
The 0xio Oracle serves OCT and token prices, swap quotes, price history, EVM address data for the 0xio wallets, and bridge analytics. The OCT price follows the wOCT/ETH Uniswap v4 pool on Ethereum live, priced in USD from the ETH/USD trades of Coinbase, Kraken, Bitstamp, Binance and Bybit (stablecoin quotes converted at live rates), updated within 250 ms of a trade, and is cross-checked against CoinGecko and DexScreener. Price history is stored in PostgreSQL for charts.

Base URL

Authentication

Reads need no API key. Every GET 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:
Keep your API key secret. Use it from your own server; never ship it in client-side code or a public repository.

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

Returns detailed service status including database and cache connectivity. Response:

Simple Liveness Probe

Returns a simple response for load balancer health checks. Response:

Prices

Get Token Price

Get the current spot price for a specific token. Parameters: Example:
Response:
The 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 polled coingecko and dexscreener prices; a source too far from the others is left out
  • spot: ETH (from the live ETH/USD feed) and SOL (Coinbase, then Kraken)
  • static: USDC and USDT, pegged at $1

Get All Prices

Get current prices for all supported tokens (OCT, WOCT, USDC, USDT, SOL, ETH). Example:
Response:

Get OCT Detailed Market Data

Get full aggregated market data for OCT including 24h change, volume, liquidity, and source breakdown. Example:
Response:

Get TWAP Prices

Get 5-minute time-weighted average prices for OCT and ETH alongside the current spot, plus the OCT spot-vs-TWAP deviation. Example:
Response:

Trading

Get Swap Quote

Get a swap quote with expected output amount and price impact. Query Parameters: Example:
Response:

Get AMM Reserves

Get current liquidity pool reserves. Example:
Response:

Simulate Trade (Operator)

Used by the solver to reserve liquidity or update local state before on-chain execution. Requires the operator key; any other key gets 403. Request Body:
Response:

Update Liquidity (Operator)

Adjust liquidity reserves, for example after a rebalancing. Requires the operator key; any other key gets 403. Request Body:
Response:

Chart Data

Get Price History

Get historical price data over a configurable time range. Points are downsampled to fit the range (e.g. 30d → ~1 point per 2h). Query Parameters: Example:
Response:
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

Latest transactions and ERC-20 transfers of an address. Query Parameters: 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.
  • transactions items: hash, timestamp, value, status and method; from, to and created_contract as { hash } or null; fee as { value } (wei) or null; raw_input; decoded_input as { 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_transfers items: transaction_hash, timestamp and log_index; from and to as { hash } or null; total as { value, decimals }; token as { 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_input is kept whole up to 522 characters (a selector and eight words) and cut to its 10 character selector beyond that, and dropped unless it is 0x and hex. parameters keeps the first 16. A parameter name or type is cut at 64 characters, method_call and a parameter value at 512 (a nested array or object longer than that becomes its JSON text, cut), and method_id at 10. A cut string ends with ….

EVM NFTs

ERC-721 and ERC-1155 tokens held by an address. Query Parameters: chain (a positive integer chain ID) and address (0x and 40 hex characters). Response:
  • contract is lowercase. tokenId and amount are decimal strings of at most 78 digits. standard is ERC-721 or ERC-1155.
  • name (token metadata) and collection (token name) are trimmed, stripped of control and bidi characters and capped at 80 characters, or null.
  • image is an https:// or ipfs:// 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). complete is 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: 400 on a bad chain or address, or a chain Blockscout does not serve; 503 when Blockscout fails.

EVM Tokens

ERC-20 tokens held by an address, each with a spam verdict. Query Parameters: 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).
  • contract is lowercase. decimals is an integer from 0 to 36 (other items are dropped). balance is a decimal string of at most 78 digits, and zero balances are skipped.
  • symbol (at most 11 characters) and name (at most 40) are trimmed and stripped of control, bidi and zero-width characters, or null when empty or longer.
  • price is Blockscout’s USD exchange rate when finite and above 0, else null.
  • logo is kept only as an https:// URL of at most 512 printable ASCII characters on raw.githubusercontent.com, assets.coingecko.com or coin-images.coingecko.com; null otherwise, and always null on a spam item. Never anything the token contract itself supplies.
  • verified says whether the contract source is verified. It is looked up only where it decides the verdict (unpriced tokens no other rule caught), else null.
  • spam is true when any rule below holds; spamReason is the first that matched, else null:
    1. flagged: Blockscout marks it as scam or spam.
    2. link: the name or symbol holds http, www. or a domain (a dot after a letter or digit, then 2 to 10 letters), such as t.me or x.com.
    3. 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).
    4. 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).
    5. unverified_unpriced: the contract is not verified and has no price.
    Rules 2 and 3 also see look-alike letters as Latin, and apply only to tokens with no market price, so a real token named after its site is not flagged.
  • Paging: follows Blockscout’s pages up to 200 items (5 pages, 20 seconds in total). complete is 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: 400 on a bad chain or address, or a chain Blockscout does not serve; 503 when 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 to POST /api/bridge/event. The read routes count a row only after the oracle has found that transfer on chain.

Report a Bridge Event

Public, no key. The body is JSON of at most 4 KB, and unknown fields are refused.
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_eth on the bridge vault whose Locked event has octra_addr as sender, the same amount and eth_addr as recipient.
  • claim: the Ethereum receipt succeeded, was sent to the bridge contract, is 12 blocks deep and holds a Minted event for the amount whose recipient (or the transaction’s sender) is eth_addr.
  • burn: the same receipt checks and a BurnToOctra event for the amount from eth_addr to octra_addr.
  • any_swap: Relay reports the request as settled, and one of its Ethereum transactions sends wOCT to octra_addr through 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 as total_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_wallets and unique_eth_wallets, plus by_source with the same totals for web (the bridge site) and extension (the 0xio Extension). Both keys are always present, and wallet counts are per source, so the two can overlap. The top-level source field 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; use by_source for the split. note describes what is counted. Cached 60 seconds.
  • /api/bridge/events: { events, count }, newest first. limit defaults to 50 (at most 500).
  • /api/bridge/chart: { data }, daily rows with ts, direction, event_type, amount_oct and source. Cached 120 seconds.
All three read rows found on chain, plus rows recorded before validation existed that were not quarantined. Volumes are in OCT, from amount_raw.

Metrics

Public. How live the OCT price is, for status displays, without price values: price updates in total and in the last minute, ETH/USD ticks, the venues feeding ETH/USD, whether the pool’s swaps arrive live, the sources in use, the confidence and how long ago the price last changed.

API Key Management

List Your Keys

List all API keys associated with your wallet address. Requires wallet signature for privacy. Query Parameters: Example:
Response:

Generate New Key

Generate a new API key. Requires a wallet signature, and the owner must be on the portal whitelist. Keys look like 0xio-<16 hex>-oracle. An owner can create at most 5 keys an hour (429 past that). Request Body:
Signature Message Format:
Example: 0xio-api-key:oct...:1706270400 Response:
Store your API key securely! It will only be shown once.
Use the Developer Portal to create keys easily - it handles wallet signing automatically.

Revoke Key by ID

Revoke one of your keys by the id from create or list. Signed by the owner wallet, so a lost or over-quota key can still be revoked. Signature Message Format:
Response:
Returns 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

Legacy revoke with the full key in the header. Kept for compatibility; prefer DELETE /api/keys/:id, which also works for a key that is over its quota. Headers:
Response:

Usage Report

Your keys’ usage over the last 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.

Code Examples

JavaScript/TypeScript

Python

Rust