API v1 · Robinhood Chain

the detector, in your own code.

Everything the site and the Discord rooms show — the verdict, the screener, wallet dossiers, the live signals — as JSON for your bots, your mirrors, your own screener. The door is the Engineer: 50 machines on shift in the wallet that owns the key. Nothing is bought; standing is read from the shift contract every five minutes. API v1 is not open yet — this page is the spec.

getting a key

1put 50 machines on a shift — hopiummachines.xyz/staking. Machines on shift count; union cards and machines at home do not.
2sign in with the same wallet on /account and create a key. Up to five keys, all sharing the wallet's budget.
3send it in the x-api-key header. Clock out below 50 and the key answers 403 within five minutes; clock back in and it works again within five.
curl -H "x-api-key: rh_…" https://detector.hopiummachines.xyz/api/v1/token/0x…

endpoints

GET /api/v1/token/{address}The verdict on a token. The detector's score (risk 0–100, band, every check with its detail), the ecosystem flag, and the holder census (holders, top-10 %, deployer %, supply float). A fresh cached verdict is free; a stale or missing one runs a fresh analysis inside the wallet's scan budget — past it you get the last verdict with `stale: true`, or 429 if there is none.
address — 0x-prefixed 40-hex address (any case) (required);
curl -H "x-api-key: rh_…" https://detector.hopiummachines.xyz/api/v1/token/0x…
GET /api/v1/screenThe screener. The same rows and filters as the site's screener: age, market cap, liquidity, holders, top-10 and deployer shares, bands, sources, sort, paging. Payload: `rows`, `runners`, `busted`, `total`, `scanned`, `now`.
ageMaxMin — max age in minutes; mcMin — min market cap, USD; mcAthMin — min all-time-high market cap, USD; liqMinEth — min liquidity, ETH; holdersMin — min holders; top10Max — max top-10 holders share, %; devMax — max deployer share, %; bands — comma list: fresh,low,medium,high,critical; sources — comma list: v2,v3,v4,pons; hideBusted — 1 to drop rugged/dumped rows; sort — age | mc | holders | run; limit — 1–100; offset — 0–500;
curl -H "x-api-key: rh_…" "https://detector.hopiummachines.xyz/api/v1/screen?ageMaxMin=60&liqMinEth=1&sort=holders&limit=50"
GET /api/v1/wallet/{address}A wallet dossier. Positions and swap history from the detector's own ledger, realized PnL, win rate, and the labels the tracker gave the wallet (smart, sniper, bundler, deployer, farm funder).
address — 0x-prefixed 40-hex address (any case) (required);
curl -H "x-api-key: rh_…" https://detector.hopiummachines.xyz/api/v1/wallet/0x…
GET /api/v1/signalsThe signals stream. Every card the detector posts, as it posts it: the row carries the token, the kind, the time and the card itself (`payload.embed`, Discord embed shape) plus a dossier url. Poll with the `next` id you got back; without `after` you get the newest 50.
after — the last id you have seen (from `next`); rows with a greater id follow, ascending; kinds — comma list of tracker, first_swap, surge, new_token, liquidity_pulled, score_drop, deployer_dump; limit — 1–100, default 100 with `after`, 50 without;
curl -H "x-api-key: rh_…" "https://detector.hopiummachines.xyz/api/v1/signals?after=12345&kinds=tracker,first_swap,surge"

Machine-readable: /api/v1/openapi.json (OpenAPI 3.1, public).

the signals stream

Every card the detector posts lands in the stream the moment it posts — kinds: tracker · first_swap · surge · new_token · liquidity_pulled · score_drop · deployer_dump. Poll it: the first call sends no after at all and gets the newest 50 with a next; every later call passes that next back and gets only what is new — starting at after=0 would replay the whole week, oldest first. The row is the card itself (payload.embed, Discord embed shape) plus payload.url, the token's dossier. The log keeps seven days.

next=
while true; do
  r=$(curl -s -H "x-api-key: rh_…" "https://detector.hopiummachines.xyz/api/v1/signals?kinds=tracker,first_swap,surge${next:+&after=$next}")
  echo "$r" | jq -c '.signals[] | {kind, token, symbol, at}'
  next=$(echo "$r" | jq .next)
  sleep 5
done

limits and errors

budget300 requests a minute per wallet, whatever the key. 30 of them may start a fresh token analysis; past that /token serves the last verdict with stale: true. Headers on every answer: x-ratelimit-limit, x-tier.
401no key, or an unknown one — { "error": "api key required" } / { "error": "api key unknown" }
403fewer than 50 machines on shift — { "error": "engineer tier required", "required": 50, "onShift": 12 }
429budget spent — { "error": "rate limited", "limit": 300 }; on /token with nothing cached: { "error": "scan budget exhausted", "limit": 30 }
503the shift contract could not be read — retry; nothing is cached from a failed read — { "error": "standing unavailable, retry" }
404API v1 is switched off on this deployment — { "error": "not found" }; this page stays up, the routes do not.
CORSAccess-Control-Allow-Origin: * — call it from a browser page if you like; the key is still the key.
API v1 — RUG DETECTOR