Get started
Query the index
Read the settlement record over REST, read-only SQL, or the pre-computed rollups, and know which to reach for.
Everything Roundhouse knows is readable — the same public dataset backs every tier. Reading the
settlement index over the API takes a key; discovery does not: the capability layer
(/v0/unified*) and the service directory (/v0/endpoints) stay open with nothing configured,
and the website itself is browsable by anyone.
Pick a read path by how specific your question is.
| Your question | Use | Key |
|---|---|---|
| "Who sells X?" | GET /v0/endpoints?q=X, GET /v0/unified | None |
| "What is happening right now?" | GET /v0/flows | Required |
| "Tell me about this wallet" | GET /v0/agents/<w>, GET /v0/merchants/<w> | Required |
| "Show me the payment graph" | GET /v0/graph | Required |
Anything with a group by in it | POST /v0/sql | $0.005/query (x402) or paid-plan org key |
| Natural language, exploratory | AI playground | Query Units |
A key is one request away: GET /v0/test/x402 mints a personal 30-day key for one cent over
x402, and organisations create full-rate keys in the dashboard.
Fixed endpoints#
JSON over HTTP; send your key as authorization: Bearer rh_live_…. The full list with every
parameter is the API reference; these are the ones you will reach for first.
GET /v0/flows?limit=50 live flow of funds, newest first
GET /v0/transactions?limit=50 the global settlement feed
GET /v0/agents?q=<search> indexed ERC-8004 agents
GET /v0/agents/<wallet> one agent: identity + settlement stats
GET /v0/merchants/<wallet> one merchant: inbound volume, customers
GET /v0/entities/<wallet>/settlements raw settlements for one wallet
GET /v0/endpoints?q=<search> the priced service directory
GET /v0/leaderboard?limit=25 agents ranked by trust
GET /v0/facilitators who relays payments, and how much
GET /v0/graph?days=7 nodes and payer→payee edgesTwo paging conventions, and they are not interchangeable:
- Feeds use a cursor.
next_beforeis an opaque token encoding the whole sort key including its tiebreaker. Pass it back as?before=. Do not parse it, and do not construct one — a naiveblock_timecursor silently drops every row sharing the last row's timestamp, and on a 2-second chain most timestamps are shared. - The leaderboard uses an offset. A rank is a position, and
scoreis nullable, so there is nothing stable for a cursor to compare against.?offset=in,next_offsetout.
An empty array is a real answer. A failed read is not: a rejected query returns 503 upstream_unavailable naming the resource, never 200 {"flows": []}. On a settlement index "no
rows" reads as "nothing ever happened", which is the one lie the read path is built to prevent.
Read-only SQL#
For everything else. One statement, SELECT or WITH only, over the public data-layer tables.
curl -sL -X POST "https://api.roundhouseai.io/v0/sql" \
-H "authorization: Bearer $ROUNDHOUSE_KEY" \
-H 'content-type: application/json' \
-d '{
"sql": "select date_trunc('day', block_time) as day, count(*) as settlements, sum(amount_usd) as usd from settlements where block_time > now() - interval '14 days' group by 1 order by 1 desc"
}' | jqThe sandbox is enforced in the database, not in the request handler: a role that can read only the public tables, a read-only transaction, a statement timeout set by the tier you bought (15 seconds by default), and a hard 300-row cap. Write for those limits rather than discovering them — SQL over the index has the readable tables, the useful shapes, and the traps.
Use the rollups, not the raw table#
settlements has tens of millions of rows. An unbounded aggregate over it will hit the timeout.
The pre-computed views exist so you do not have to:
| View | Grain | Good for |
|---|---|---|
mv_entity_rollups | one row per wallet | lifetime inbound/outbound volume and counts |
mv_entity_daily | wallet × day | an activity trend for one counterparty |
mv_global_daily | day | the site-wide series behind /stats |
They refresh on a schedule, so they trail the tip of the chain by up to an hour. Read surfaces fold
in the newer settlements at read time, which is why a profile page and a raw mv_entity_rollups
query can differ by a few rows — the page is more current, not wrong.
Rate limits and keys#
The API is keyed. Anonymous access covers exactly two surfaces — the
Unified Services endpoints (/v0/unified*, no limit)
and the service directory (/v0/endpoints, 30/min per IP) — so an agent can always discover
and price services with nothing configured. Everything else answers 401 api_key_required
without a key. Limits are per endpoint class: aggregate (graph, leaderboard, entity profiles,
per-entity history, SQL) and feeds.
| Caller | Aggregate / minute | Feeds / minute | SQL |
|---|---|---|---|
| Anonymous | — (key required) | — (key required) | $0.005/query (x402) |
Trial key from /v0/test/x402 | 2 per key, for 30 days | 2 per key | $0.005/query (x402) |
| Trial key, registered identity (ERC-8004 or KYA) | 10 per key, for 30 days | 10 per key | $0.005/query (x402) |
| Organisation key, paid plan | plan rate per org | plan rate per org | 1 QU per query |
SQL is not included in the free plan or in the trial identity key — for those callers every query is its own $0.005 x402 payment.
Send a key as authorization: Bearer rh_live_… or x-api-key. Organisation keys are created and
managed in the dashboard; the trial key costs one cent, is bought by the paying
wallet itself, and needs no account at all.
Next steps#
- SQL over the index — the tables, and queries to copy
- The data model — what a settlement row actually contains
- Coverage and confidence — when to trust a number