# Binance Exploiter Tracker — machine-readable guide This site tracks one incident, `binance-exploiter` (a Binance hot-wallet theft). It is backed by a keyless, public, same-origin JSON API under `/v1`. Everything below is read-only GET/POST against this same host; there is no API key, no CORS restriction, and no authentication. ## Envelope Every response is one of: success: {"success": true, "data": , "meta": {"request_id": "..."}} error: {"success": false, "error": {"code": "...", "message": "..."}, "meta": {...}} Amounts are decimal strings (do not parse as float if you need exact precision). USD values are numbers or null; null means "not priced," not zero. Times are RFC 3339 UTC. ## Rate limits Per-source-IP. Responses carry X-RateLimit-Limit / -Remaining / -Reset; a 429 carries Retry-After (seconds). Reports: 10/hour/IP. Tracker endpoints: 120/minute/IP. ## List and screening endpoints (v0.2, always available) GET /v1/incident Incident metadata and current_version. Supports If-None-Match / 304. GET /v1/export?format=csv|json&include=listed|all&version= Full snapshot. Headers: X-EW-Version, X-EW-Content-SHA256 (verify this), X-EW-Incident. Signature headers present only if signing is enabled. GET /v1/changes?since_version=&limit=&cursor= Added/updated/removed entries for versions greater than since_version. GET /v1/addresses?chain=&status=listed|delisted|all&cursor=&limit= Paginated address list. meta.has_more / meta.next_cursor drive paging. GET /v1/addresses/{chain}/{address}?match=exact|evm_family Look up one address. evm_family also matches the same EOA on other EVM chains (eth, bsc, arbitrum, optimism, base, avalanche, polygon). POST /v1/screen Body: {"items":[{"chain":"eth","address":"0x..."}], "match":"exact", "include_delisted": false} Up to 1,000 items per call. match and include_delisted apply to the whole batch. Per-item errors (INVALID_ADDRESS, UNSUPPORTED_CHAIN) do not fail the batch. GET /v1/versions?limit= GET /v1/chains GET /v1/signing-keys ## Reports POST /v1/reports Body: {"type":"false_positive|incorrect_data|missing_address|other", "chain":"...", "address":"...", "description":"(10-4000 chars)", "evidence":["..."] (<=10), "reporter": {organization,name,email, telegram} (all optional, never shown publicly)} Returns {report_id, status: "received", status_url, notice}. A report never changes the list by itself. GET /v1/reports/{report_id} Status only; no contact details or free text. ## Tracker endpoints (v0.3, snapshot-based) All live under /v1/tracker, return the standard envelope, carry the snapshot time in header X-EW-Snapshot-At, and support ETag / 304. BEFORE THE FIRST SNAPSHOT IS PUBLISHED, every one of them returns 404 NOT_PUBLISHED — treat that the same as {"available": false, "items": []}. A section the producer did not fill returns 200 with "available": false (never zero values). GET /v1/tracker {incident, snapshot_id, generated_at, data_as_of, stale, list_version, current_list_version, price_basis, summary: {stolen_usd, held_usd, lost_usd, in_transit_usd, freezable_usd, frozen_usd, mixer_usd, untraced_usd, holding_addresses}, sections: {: {available, count}}} Poll this every 30s; re-fetch a section only when its count changes. GET /v1/tracker/holdings?chain=&min_usd= {available, items: [{chain, address, usd, last_activity_at, assets: [{symbol, contract, amount, usd, freezable}]}]} GET /v1/tracker/graph {available, nodes: [{id: "chain:address", chain, address, kind: attacker|victim|exchange|bridge|dex|mixer|service|unknown, label, hop}], edges: [{from, to, kind: transfer|bridge|swap|deposit|mixer, asset, amount, usd, tx_count, first_at, last_at, txs: ["0x...", ...]}]} GET /v1/tracker/movements?chain=&kind=&min_usd=&cursor=&limit= {available, items: [{at, chain, tx, from, to, from_kind, to_kind, to_label, asset, amount, usd, kind: transfer|xchain|swap|cex|mixer|stable}]} meta: {has_more, next_cursor}. limit default 100, max 500. GET /v1/tracker/chains {available, items: [{chain, in_usd, out_usd, internal_usd, held_usd, unpriced_transfers}]} GET /v1/tracker/distribution {available, items: [{chain, symbol, contract, amount, usd, freezable}]} GET /v1/tracker/reviewed {available, items: [{chain, address, category: exchange_deposit|bridge_vault|arbitrageur|poisoning|service|other, label, note}]} GET /v1/tracker/victims {available, items: [{chain, address, label}]} GET /v1/tracker/mixer {available, items: [{at, chain, tx, from, mixer, asset, amount, usd}]} GET /v1/tracker/frozen {available, items: [{chain, asset, amount, usd, by, at, reference}]} ## Block explorers used for links eth etherscan.io · bsc bscscan.com · arbitrum arbiscan.io · optimism optimistic.etherscan.io · base basescan.org · avalanche snowtrace.io · polygon polygonscan.com · btc mempool.space · tron tronscan.org (#/address/..., #/transaction/...) · solana solscan.io · xrp xrpscan.com ## Human pages (not API; return HTML) / overview /explorer address explorer /graph fund-flow graph /distribution fund distribution /movements recent movements /reviewed reviewed non-attacker /victims victim wallets /frozen frozen funds /screen war-room screen /check address check /report submit a report /developers human API docs /changelog changelog ## Minimal sync loop 1. GET /v1/export?format=csv once; verify X-EW-Content-SHA256; store X-EW-Version. 2. Poll GET /v1/incident with If-None-Match every ~60s. 3. When current_version grows, GET /v1/changes?since_version= and apply added/updated/removed in order; store to_version. 4. Poll GET /v1/tracker with If-None-Match every ~30s for the snapshot feed; re-fetch only the sections whose meta.sections[name].count changed.