Skill-ranked Polymarket data your agent or app can buy one call at a time. No API key, no account: just HTTP and a wallet with a little USDC.
Every paid endpoint works the same way:
402 Payment Required and the price. This is free.Check a price right now, for free:
curl -i "https://www.x402pulse.dev/v1/top-traders?period=month"
Payments are in USDC on Base (eip155:8453). You only pay for successful responses: any error is never charged.
What happens, step by step, every time your agent calls x402Pulse.
Your request arrives. Bad parameters get a free 400, and more than 60 calls a minute gets a free 429. You're never asked to pay for a request that can't succeed.
With no payment attached, x402Pulse answers 402 Payment Required. The PAYMENT-REQUIRED header says how much, in which token, on which network, and to which address.
Your client signs a USDC authorization and resends the request. x402Pulse asks its facilitator (Coinbase) to confirm the signature, amount and network are valid. No money moves yet.
x402Pulse builds the answer from Polymarket's public APIs (trades, leaderboards, positions, holders, markets), scores the wallets involved, and reuses recent results from its cache.
Only if the answer succeeded, the facilitator settles the payment on the blockchain: USDC moves from your wallet to x402Pulse. If anything failed, it never settles.
You get JSON with the data, plus a PAYMENT-RESPONSE header containing the receipt and transaction hash.
Any program that can make HTTP requests, an x402 client library (or your own code), and a wallet with a little USDC on Base.
No API key, no account, no subscription, no sign-up, and no ETH for gas. The facilitator pays the network fee.
From an empty folder to a paid answer in about ten minutes. Follow the steps in order and copy the commands exactly.
You need Node.js 20 or newer. Run this; it should print v20 or higher. If not, install it from nodejs.org.
node -v
mkdir my-pulse-agent && cd my-pulse-agent npm init -y npm pkg set type=module npm install @x402/fetch @x402/evm viem
This makes a brand-new wallet just for your agent and prints its private key and address.
node -e "import('viem/accounts').then(({generatePrivateKey,privateKeyToAccount})=>{const k=generatePrivateKey();console.log('private key:',k);console.log('address: ',privateKeyToAccount(k).address)})"Save the private key somewhere safe and never share it or paste it into chats, screenshots or GitHub. Anyone with it can spend the wallet's money. Use this wallet only for your agent, with small amounts.
Send a few dollars of USDC on Base to the address from step 3. Check the network says Base before sending. You don't need any ETH.
Create a file named agent.mjs in the folder, paste this in, and save it.
import { x402Client, wrapFetchWithPayment, x402HTTPClient } from "@x402/fetch";
import { registerExactEvmScheme } from "@x402/evm/exact/client";
import { privateKeyToAccount } from "viem/accounts";
const API = "https://www.x402pulse.dev";
const MAX_PRICE = 0.5; // never pay more than $0.50 for one call
// 1. Load the wallet from the AGENT_KEY setting (never write the key in this file).
const account = privateKeyToAccount(process.env.AGENT_KEY);
const client = new x402Client();
registerExactEvmScheme(client, { signer: account });
// 2. A guardrail: see each price and refuse anything above MAX_PRICE.
client.onBeforePaymentCreation(async ({ selectedRequirements }) => {
const price = Number(selectedRequirements.amount) / 1e6;
console.log("Price:", price, "USDC");
if (price > MAX_PRICE) return { abort: true, reason: "Too expensive" };
});
// 3. A fetch that pays automatically when it receives a 402.
const pay = wrapFetchWithPayment(fetch, client);
// 4. Ask who the most skilled traders are this month.
const res = await pay(API + "/v1/top-traders?period=month&limit=5");
console.log("Status:", res.status);
const body = await res.json();
if (res.ok) {
for (const t of body.data.traders) {
console.log(`#${t.rank} ${t.name ?? t.wallet} skill ${t.skill} (${t.label}) edge ${Math.round(t.edge * 100)} pts`);
}
const receipt = new x402HTTPClient(client).getPaymentSettleResponse((h) => res.headers.get(h));
console.log("Paid. Transaction:", receipt?.transaction);
} else if (res.status === 402) {
console.log("Not charged: the payment wasn't accepted. Check the wallet has USDC on the network shown in the 402 response.");
} else {
console.log("Not charged. Error:", body.error);
}Replace the key with your private key from step 3. Putting it in front of the command keeps it out of your files.
AGENT_KEY=0xYOUR_PRIVATE_KEY node agent.mjs
You should see something like this. The first run can take up to 30 seconds while wallets are scored.
Price: 0.05 USDC Status: 200 #1 primm skill 88 (Sharp) edge 13 pts #2 Kch-Temp skill 76 (Sharp) edge 6 pts … Paid. Transaction: 0x31a8…9169
That's a real payment: search the transaction on basescan.org to see it. Now swap the URL for any other endpoint below. If something goes wrong, see Troubleshooting.
All endpoints are GET, return JSON shaped as { data, cached }, and live under https://www.x402pulse.dev.
| Endpoint | Parameters | Returns | Price |
|---|---|---|---|
/v1/whales | minMinimum trade size in USD (default 1000) limitNumber of trades, 1 to 50 (default 20) | Recent large Polymarket trades, with 5- and 15-minute markets filtered out. | $0.02 |
/v1/wallet | addressPolymarket wallet address (0x…) | A wallet's track record: skill score, edge over the odds paid, win rate, return, specialty and largest open positions. | $0.05 |
/v1/top-traders | periodday, week, month or all (default month) categoryOptional: sports, politics, crypto, economy or other limitNumber of traders, 1 to 25 (default 10) | Top Polymarket traders re-ranked by skill (edge over the odds paid, return, consistency), not just total profit. Optionally within one category. | $0.05 |
/v1/smart-money | marketMarket link, market slug or condition ID | Which way skilled traders lean in a Polymarket market compared with its odds: the biggest holders, each scored for skill. | $0.20 |
/v1/skilled-whales | minMinimum trade size in USD (default 1000) limitNumber of trades, 1 to 50 (default 20) | Recent large Polymarket trades by Solid or Sharp traders only, each tagged with the trader's skill score. | $0.05 |
/v1/disagreements | categoryOptional: sports, politics, crypto, economy or other limitNumber of markets, 1 to 20 (default 5) | Busy open Polymarket markets where skilled traders' money disagrees most with the market's odds, with a confidence rating. | $0.35 |
market accepts a full polymarket.com link, a market slug, or a condition ID. If a link covers an event with several markets, you get a free 400 with choices[] to pick from.
What every number means, so your agent can explain its answers.
/v1/whales| Field | Type | Meaning |
|---|---|---|
trades[] | list | Largest recent trades, biggest first. |
wallet, name | text | Trader's Polymarket wallet and display name (null if none). |
side, outcome, price | text, text, 0–1 | BUY or SELL, which outcome, and the price paid (0.62 = 62¢). |
usd, shares | USD, number | Trade size in dollars and shares. |
market, slug, time, tx | text | Market question, its slug, trade time (ISO) and on-chain transaction. |
/v1/wallet| Field | Type | Meaning |
|---|---|---|
address, name | text | The wallet and its display name (null if none). |
score | object | The scorecard. See score fields below. |
openPositions[] | list | Largest live positions: market, outcome, shares, avgPrice, currentPrice, valueUsd, unrealizedPnlUsd. |
/v1/top-traders| Field | Type | Meaning |
|---|---|---|
traders[] | list | Traders ranked by skill. Each has the main score fields plus the ones below. |
profitRank | integer | Where they sat on Polymarket's profit leaderboard for the period. |
periodPnlUsd, periodVolumeUsd | USD | Profit and volume for the chosen period, from Polymarket. |
candidates | integer | How many leaderboard traders were scored to build the ranking. |
category | text or null | When set, scores use only each trader's bets in that category. |
/v1/smart-money| Field | Type | Meaning |
|---|---|---|
question, slug, outcomes[] | text, list | The market, and each outcome with its current price (0.41 = 41% implied chance). |
lean | object or null | outcome, share of skill-weighted money, marketPrice, vsMarket (share − price) and stance: in line with, more confident than, or less confident than the market. |
summary | text | One-sentence answer, ready to show a user. |
sides[] | list | Per outcome: price, sharpHolders, skillWeightedUsd and holders[] (wallet, name, valueUsd, skill, label, edge, winRate, roi). |
/v1/skilled-whales| Field | Type | Meaning |
|---|---|---|
trades[] | list | Large recent trades by Solid or Sharp traders only, biggest first. Same trade fields as /v1/whales. |
skill, label, edge, roi, specialty | score | The trader's skill score and its main parts. See score fields below. |
tradersScored | integer | How many distinct traders were scored (up to 25 of the biggest). |
/v1/disagreements| Field | Type | Meaning |
|---|---|---|
markets[] | list | Open yes/no markets, sorted by how far tempered skilled money is from the price, weighted by confidence. |
priceYes | 0–1 | The market's price for the first outcome (usually Yes). |
skilledYesShare | 0–1 | What skilled money implies for the first outcome, tempered toward the price so thin readings can't look extreme. |
rawSkilledYesShare | 0–1 | The untempered share of skill-weighted money on the first outcome. |
gap | −1 to 1 | skilledYesShare − priceYes. Positive: skilled money more bullish on Yes than the market; negative: more bullish on No. |
confidence | text | high (5+ skilled holders, $150K+ skill-weighted), medium (3+, $50K+) or low. |
skilledHolders, skilledUsd | integer, USD | How many Solid+ holders and how much skill-weighted money the reading rests on. |
scannedAt, marketsScanned | time, integer | When the busiest open markets were last scanned (every 15 minutes) and how many. |
Used in wallet scorecards, top traders and smart-money holders.
| Field | Type | Meaning |
|---|---|---|
skill | 0–100 | Overall skill score from edge, return, history size and consistency. |
label | text | Sharp (70+), Solid (45+), Mixed (25+), Weak, or Too few bets (under 10 finished bets). |
edge | number | Win rate minus the win rate the prices paid implied. 0.08 = won 8 points more often than the odds said. |
winRate | 0–1 | Share of finished bets that made money. |
expectedWinRate | 0–1 | Average price paid, i.e. the win rate the odds implied. |
roi | number | Realized profit divided by money invested. 0.25 = +25%. |
bets | integer | Finished bets scored (latest 200, losses included). |
realizedPnlUsd | USD | Profit or loss across the scored bets. |
biggestWinShare | 0–1 | Share of all winnings from the single best bet. High means one lucky hit. |
shortTermShare | 0–1 | Share of bets on 5- and 15-minute crypto markets, which lowers the score. |
specialty | text | Category with the most profit: sports, politics, crypto, economy, other, or null. |
Total profit mostly rewards whoever bets the most. The skill score asks a different question: did this trader beat the odds they paid?
Labels: Sharp 70+, Solid 45+, Mixed 25+, Weak below 25, and Too few bets under 10 finished bets.
For each outcome, x402Pulse takes the biggest holders (10 per side when paid, 3 in free samples) and scores each one. Only Solid or better holders count as skilled. Each skilled position is weighted by its dollar value times its skill score, and the outcome with the most skill-weighted money is the lean. The lean's share is then compared with that outcome's price: within 10 points is "in line with" the market, above is "more confident than," below is "less confident than."
The same pattern in TypeScript. One wrapped fetch handles the whole exchange, and a spending cap means your agent can never overpay.
npm install @x402/fetch @x402/evm viem
import { x402Client, wrapFetchWithPayment } from "@x402/fetch";
import { registerExactEvmScheme } from "@x402/evm/exact/client";
import { privateKeyToAccount } from "viem/accounts";
const client = new x402Client();
registerExactEvmScheme(client, {
signer: privateKeyToAccount(process.env.AGENT_KEY as `0x${string}`),
});
// Spending guardrail: refuse any single payment above $0.50.
client.onBeforePaymentCreation(async ({ selectedRequirements }) => {
if (Number(selectedRequirements.amount) / 1e6 > 0.5) {
return { abort: true, reason: "Over my per-call limit" };
}
});
const pay = wrapFetchWithPayment(fetch, client);
// Which way does skilled money lean on this market?
const market = "https://polymarket.com/event/…";
const res = await pay(
"https://www.x402pulse.dev/v1/smart-money?market=" + encodeURIComponent(market),
);
const { data } = await res.json();
console.log(data.summary);
// e.g. "Skilled holders lean Yes (72% of skill-weighted money, from 4 skilled
// holders), more confident than the market's 41%."x402 is plain HTTP, so any language works. Libraries exist for several, and the protocol is short enough to implement yourself:
402 response carries a PAYMENT-REQUIRED header: base64-encoded JSON listing the accepted payment (scheme, network, amount in USDC base units, asset, payTo).exact scheme describes (an EIP-3009 USDC transfer authorization on Base).PAYMENT-SIGNATURE header.200 plus a PAYMENT-RESPONSE header with the settlement receipt and transaction hash.The full specification is at docs.x402.org.
This service runs on Base mainnet with real USDC. Keep a small budget and a per-call cap in your client while you build.
Or try it by hand first: the Try page gives free samples in your browser.
Agents can find and understand x402Pulse without reading this page:
/catalog and /.well-known/x402-listing: every endpoint, price and parameter as JSON./llms.txt: this documentation as plain text, written for AI models to read.402 response includes a bazaar section with an example input, input schema and example output, which x402 directories such as the Coinbase Bazaar use for search.Every error is free: payment only settles when the response succeeds.
| Status | Cost | Meaning |
|---|---|---|
400 | free | Missing or invalid parameter. An ambiguous market link includes choices[] to pick from. |
402 | free | Payment required: read the PAYMENT-REQUIRED header, pay, and retry. |
404 | free | Wallet or market not found. |
429 | free | Too many requests from you (60 per minute by default). |
502 / 503 | free | Polymarket didn't respond or is busy. Retry after a short wait. |
The problems people actually run into, and the fix for each.
| What you see | Cause | Fix |
|---|---|---|
Status 402 after paying | Wallet | The wallet has no USDC on the right network. Check its USDC balance on the network shown in the 402 response (Base Sepolia while testing) and top it up. |
fetch failed / ECONNREFUSED | Address | The URL is wrong or the service is unreachable. Copy the address from this page exactly, including https://. |
invalid private key | Key | A private key starts with 0x followed by 64 characters, 66 in total, with no spaces or quotes inside. |
Over my per-call limit | Your cap | Your own spending guardrail refused the price. Raise the cap in your code if you meant to pay it. |
400 with choices[] | Free | Your market link covers several markets. Call again with one of the slugs in choices[]. |
404 market not found | Free | Check the link or slug for typos. Open it on polymarket.com to confirm it exists. |
429 rate limit | Free | More than 60 calls a minute. Slow down, or reuse answers: most data refreshes every few minutes anyway. |
Slow first answer | Normal | Top traders and smart money score many wallets the first time (up to ~30 seconds). Later calls come from the cache in milliseconds. |
A few ideas for products and agents on top of x402Pulse.
Before answering "will X happen?", check whether skilled money agrees with the market's odds and say so.
Show each market's odds next to its skilled lean, and highlight where they disagree.
Answer "is this wallet any good?" or "who's sharp this week?" in a group chat, paying a few cents per question.
Poll /v1/whales and enrich each big trade with the trader's skill score from /v1/wallet.
Turn weekly top traders and notable smart-money leans into a digest for readers.
Track how skilled-money leans compare with how markets actually resolve.
x402Pulse provides data and analytics built from public Polymarket activity. It is not financial or betting advice, and past performance doesn't predict future results. If you show x402Pulse data to people, say where it comes from and present it as information, not recommendations.
Wallets are identified by address and their public Polymarket display names only. Don't use the data to identify or contact the real people behind wallets.
x402Pulse is an independent service, not affiliated with Polymarket or the x402 Foundation. The API is versioned under /v1; breaking changes would ship as /v2. Network: eip155:8453.