x402 Leaderboard
Payment wires: every paid endpoint accepts x402 and MPP (Machine Payments Protocol) on the same 402 - see Paying with x402 and Paying with MPP. Agent402 is the applied layer of Agentic Finance: agents that pay and get paid on their own.
GET /api/leaderboard is the public, on-chain ranking of x402 sellers by
Base USDC settled volume. It answers with the top N of that board and
never the whole of it - 25 rows by default, 50 the ceiling, with
totalSellers in the response carrying how many are ranked in all, so a
seller you cannot find in the rows you were served may simply rank below
them. Only sellers that settled inside windowServed rank at all. It's the
third surface in Agent402's open x402
index - alongside /api/find (resolve a
task to a tool) and /api/route (the
neutral Smart Order Router across every seller).
| Surface | Free | What it returns |
|---|---|---|
GET /api/find?q={task} |
✅ | Best matching tools (route, price, schema, example) |
POST /api/route {query, top, include} |
✅ | Smart Order Router ranked over every x402 seller crawled (match → health → distinct payers → price); the response returns the top N and carries matched |
GET /api/leaderboard?top=N&include=external|all |
✅ | Top N of the on-chain ranking of x402 sellers by Base USDC settled volume (include=external, the default, leaves out this host's own row) - 25 default, 50 ceiling, totalSellers for the full count (?limit= is accepted as an alias of ?top=) |
Why on-chain volume
In an open marketplace, anyone can claim anything in a manifest. What you
can't fake is settlement on a public chain. Every x402 paid call leaves a
USDC Transfer log on Base. The leaderboard reads those logs directly - no
self-reports, no caches you have to trust, no API keys involved.
Pipeline
- Discovery - walk every page of the Coinbase CDP Bazaar
discovery/resourcesendpoint (limit=1000, page untilpagination.totalreached). Extract each seller'spayTowallet from listings whosenetworkis Base mainnet (eip155:8453/base) and whose asset is USDC. - On-chain scan - call Base USDC
eth_getLogsin chunks (CHUNK_BLOCKS, default9000blocks per call;WALLET_CHUNK, default200wallets per call) for theTransfer(_, payTo, _)topic across the active window. The window is the operator'sSPAN_BLOCKS; the hosted instance runs a 7d window (302400Base blocks at ~2s each), and sellers with bursty traffic show real revenue there that a tight scan would miss. Never assume the window: the response reports the blocks actually scanned inscannedBlocksand the human label inwindowLabel/windowServed. A chunk that fails after every RPC retry is skipped rather than aborting the scan; only an all-chunks-failed outage throws. - Per-call filter - a transfer counts as a paid call when its value
matches a price the seller publishes, up to the price-match ceiling reported
as
priceMatchMaxUsd(PRICE_MATCH_MAX_USD, default $25), or when it is at or under the flat ceiling reported asmaxCallUsd(MAX_CALL_USD, default $0.75). A transfer matching no published price above the flat ceiling, or matching one above the price-match ceiling, is funding, a swap, a gift card or a treasury move, and is skipped. - Aggregate - for each seller:
callsSettled(count),totalUsd(sum),uniqueBuyers(distinctfromaddresses). - Rank - by
totalUsd(thencallsSettled, then seller name) and assign arank1..N.
The snapshot refreshes hourly server-side. Requests hit the cache; if the refresh ever fails, the last good snapshot is preserved.
Calling it
# Top 10 of the rest of the ecosystem (the default excludes Agent402;
# top, or limit, defaults to 25 and is clamped to 1..50)
curl 'https://agent402.tools/api/leaderboard?top=10'
# The full board, with this host's own row included and flagged self: true
curl 'https://agent402.tools/api/leaderboard?top=25&include=all'
# Rank by call count instead of USD (default sort=usd)
curl 'https://agent402.tools/api/leaderboard?sort=calls'
# Window hint. One cached snapshot is served regardless of what you ask for;
# the response echoes your ask in `windowRequested` and what it actually
# served in `windowServed` / `windowLabel`, so the two can never be confused.
curl 'https://agent402.tools/api/leaderboard?window=24h'
Returns (the seller array is leaderboard, not rows):
{
"spec": "x402-leaderboard/1",
"asOf": "2026-07-30T03:44:45.814Z",
"scannedBlocks": 302400,
"windowLabel": "7d",
"maxCallUsd": 0.75,
"scannedSellers": 916,
"walletsQueried": 916,
"bazaarTotal": 15289,
"leaderboard": [
{
"rank": 1,
"name": "…",
"origins": ["https://…"],
"homepage": "https://…",
"endpoints": 12,
"wallet": "0x…",
"wallets": ["0x…"],
"walletCount": 1,
"network": "base",
"callsSettled": 412,
"totalUsd": 1.234,
"uniqueBuyers": 78
}
],
"cache": { "cachedAt": "…", "lastTriedAt": "…", "lastError": null, "refreshIntervalMs": 3600000 },
"include": "external",
"sortServed": "usd",
"windowRequested": "24h",
"windowServed": "7d",
"totalSellers": 745
}
Field notes that matter when you parse it:
leaderboardis the array. There is norowskey.- The display name is
name. There is noserviceNamekey. maxCallUsdis the flat per-call ceiling actually applied,priceMatchMaxUsdthe ceiling on price-matched transfers, andscannedBlocks/windowServedare the window actually scanned. Read them rather than hardcoding a ceiling or a window.settlementsAbovePerCallCeilingcounts transfers abovemaxCallUsdthat were kept because they matched a price the seller publishes;transfersSkippedOverCeilingcounts those dropped. A seller whose prices sit above the flat ceiling shows up in the first, not the second.- One seller can settle to several wallets:
walletis the primary,walletsis the full set, andwalletCountis its size.originslikewise lists every host origin collapsed into the row. totalSellersis the size of the full snapshot beforetopslicing, so you can tell "25 rows because I asked for 25" from "25 rows because that's all there is".
include=external (the default) excludes the operator's own payTo
(WALLET_ADDRESS), because this host's own row is inflated by its canary and
volume runs; include=all returns it, flagged self: true.
Tests & guarantees
scripts/test-x402-leaderboard.js- offline assertions covering the parsers, the asset/network filter, the ceiling cutoff, and the deterministic tie-break.
scripts/test-leaderboard-surface.js- locks the leaderboard surfacing into robots.txt, sitemap.xml, llms.txt, the service manifest, and the landing FAQ JSON-LD so a future deploy can't silently drop it.
Related
- x402-Index-and-Router - Smart Order Router that uses the same Bazaar walk
- Architecture - where the leaderboard sits relative to the indexer
/.well-known/x402- the service manifest now advertises the leaderboard in bothmachineReadableanddiscoveryblocks (refreshSeconds.leaderboard = 3600)