ChainWard API
Check an address before you pay it. An address is the 0x… account a person, an AI agent or a contract uses on a blockchain. Everything on chainward.ai is also available over HTTP, and the public endpoints need no account and no key.
Base URL: https://api.chainward.ai. The free endpoints also work under https://chainward.ai/api/…; send paid requests to https://api.chainward.ai directly. The machine-readable spec is at /openapi.json. The counterparty check is verified on PayAPI Market, with a settled payment behind the listing.
Reading a verdict
Every check opens with a verdict: one decision and the one fact it rests on. Under it sits the evidence, each flag tied to the transactions behind it, and one line on what the check cannot see. Verdicts are read from on-chain behavior only, so Pay means nothing was found against paying, not that an address is safe.
A verdict has two names. label is a fixed value for your code to branch on; text is the wording to show a person. For an address:
| label | text | Means |
|---|---|---|
pay | Pay | Active in the last 30 days, with no high-severity flag. |
hold | Hold | A high-severity flag, or medium-severity flags that raise the signal band. The reason names the first one. |
unknown | Inactive | It has sent transactions before, but made no transfers in the last 30 days. |
unknown | No track record | No transfers in the last 30 days and no earlier activity found. |
unknown | Couldn't check | The data sources were down, so activity could not be read. Try again later. |
unknown | Payer hidden | A known relayer of the px402 privacy pool: it pays for agents it does not name, so the real payer can't be screened. |
Branch on label, not text: the unknown label has four wordings. The seller check uses real_demand, self_funded_demand, mixed and not_enough_data; the hire check uses hired_by_others, hired_by_own_circle and not_enough_data. Their text is the same words in plain case (Real demand, Hired by its own circle, and so on). A verdict in a report looks like this:
"verdict": {
"label": "hold",
"text": "Hold",
"reason": "USDC balance held in a dormant wallet: Holds 5451.386272 USDC while classified dormant (no transfers in the last 30 days; holds a balance from before the window).",
"limits": "On-chain behavior only. Absence of flags is not a clearance of the counterparty."
}Run a risk check (free)
curl -X POST https://api.chainward.ai/api/risk/check \
-H 'Content-Type: application/json' \
-d '{"target":"0x4baadba26c3c0bdef9e8faf173925d463aa53bb2","chain":"base"}'chainisbase(default) orbsc(BNB Chain).force_recheck: trueruns a new check on an address that already has a report (one forced re-check per address every 10 minutes).- The answer's
statusis one of:ready: a current report is inreport.stale: the report is out of date (over 24 hours old, or made by an older version of the checks). Re-run it free withforce_recheck: true.teaser: the first check of this address has started. You get a few public stats now; pollGET /api/risk/report/<address>until it stops answering 404.queued: a check is already running. PollGET /api/risk/check/<check_id>until its status isreadyorfailed.no_history: the address has no activity on that chain, so there is nothing to judge.
- A first check takes about a minute. Limits per IP: 30 requests a minute and 8 new checks an hour. Answers from an existing report, checks already running,
no_historyanswers and rejected requests don't count toward the 8. - On BNB Chain the check reads the last 14 days from public RPC nodes (the open servers anyone can query for chain data); the report says exactly what window it covered. Attestations are Base-only for now.
Read reports (free)
# the latest report for an address (add ?chain=bsc for BNB Chain; 404 if none)
curl https://api.chainward.ai/api/risk/report/0x4baadba26c3c0bdef9e8faf173925d463aa53bb2
# addresses on file, newest first (limit up to 100, page with offset)
curl 'https://api.chainward.ai/api/risk/library?sort=recent&limit=50&distinct=address'
# the EAS attestation ChainWard published on Base for an address, with the
# canonical JSON so you can recompute report_hash yourself
curl https://api.chainward.ai/api/risk/attestation/0x4baadba26c3c0bdef9e8faf173925d463aa53bb2Every report is also a public page at chainward.ai/report/<address>. An attestation is a signed record of the report's result, published on Base through EAS (the Ethereum Attestation Service), so any agent or contract can read it on-chain; see ChainWard Attest.
Pay per request over x402
x402 lets a program pay for a single API request with no account. The first request answers 402 Payment Required with the price; the client signs a USDC payment on Base and sends the request again with it; the data comes back. Any x402 client works. Payment settles only after the check succeeds, so a failed check is never charged. Send paid requests to https://api.chainward.ai directly, not through chainward.ai/api/…: a fresh check can take close to a minute.
| Endpoint | Price | Returns |
|---|---|---|
GET /api/risk/sanctions?address= | 0.01 USDC | Is the address on the US Treasury OFAC sanctions list? Hold if it is, Not listed otherwise, with the list's snapshot date. Any EVM chain. Cheap enough to run before every payment. Not listed is not a clearance; the counterparty check below reads behavior too. |
GET /api/risk/rugcheck?token= | 0.02 USDC | A rug check on a Base token, before you buy it. Who launched it and how (Clanker's factory and Virtuals' bonding curve are named when their contracts confirm the token), mints after the first issuance and how many went to the launch wallet, and what the launch wallet did: sanctions, its age at launch, its first funder, the share of supply it holds, whether it sent out 90% or more of the tokens it got at launch (within the hour or later), and how many tokens it launched through Clanker, Doppler and Zora in the busiest 24 hours around this one (5 or more answers review). When a launch was made for another wallet (Clanker's token admin, Zora's payout recipient or Doppler's vesting beneficiary), the wallet checks run on that wallet. Verdict hold, review or no_flags, which is not a clearance. It reads liquidity the launch wallet pulled from its pool (hold when it took back most of it); it is not a honeypot or holder check. An address that is not a token answers 400 NOT_A_TOKEN and is never charged: an empty address, or a contract that is not an ERC-20, is refused before payment. A token whose name or symbol passes for USDC, USDT or another well-known token through look-alike or hidden characters answers hold (imitates_known_token), even when it is not a full ERC-20. Every answer carries checked_at, cached and age_seconds, so you can tell a cached answer from a fresh one. Also at /api/risk/token?address=. People can run it free on the site: paste the token at chainward.ai/rugcheck. It also lists the labels our published investigations put on the launch wallet, and a strong one answers review. A launch wallet that launched 5 or more tokens through Clanker, Doppler or Zora within a day of a launch is labeled a serial launcher until 30 days after that launch, and the other checks show that label. |
GET /api/risk/x402?address= | 0.05 USDC | The counterparty check. The verdict with its reason, then the full report, no older than 24 hours (a fresh check runs if needed). Add &chain=bsc for a BNB Chain address; payment is still USDC on Base. /api/risk/x402/<address> also works. Like a sanctions match, a strong label from our published investigations or detectors answers hold, with the label as the reason (for example, one of a group of wallets that appear to be run together); a wallet with no label is not cleared. |
GET /api/risk/seller-demand?address= | 0.10 USDC | Real demand, Self-funded demand, Mixed or Not enough data for a seller, with the numbers behind it: how much of the top buyers' money traces back to the seller, how much it pays back, whether one wallet funds most buyers. On Base, payers behind the Meridian and Fluxa payment proxies are named; exchanges stay opaque. Add &chain=bsc for a BNB Chain seller. |
GET /api/risk/hires?agent=&chain=bsc | 0.10 USDC | Hired by others, Hired by its own circle or Not enough data for an ERC-8004 agent (an agent registered on-chain: pass its id, or its owner's address for all its agents) under BNB Chain's Set and Earn rule. Then every wallet that hired it in the last 30 days, and whether each is the owner, funded by it, or shares a funder with it. independent_within_limits means no link was found within 4 hops (4 transfers back), not proven independence. BNB Chain only. Free daily results for every agent hired since Oct 1: /set-and-earn. |
GET /api/paid/:slug/check?address= | 0.05 USDC | Is one wallet in a dataset: listed or not_listed, with the tier, the reason and the limit. |
GET /api/paid/:slug/file | 10 USDC | The full dataset behind a decode, as CSV. |
Dataset slugs today: termix-wallets and set-and-earn-week-one (GET /api/paid lists them). About to pay rewards or an airdrop to a list of wallets? Send us the list first: we flag the wallets that share a funder. Screening one wallet at a time from your own code? The wallet screening API is free for 1,000 lookups a month with a key. To see a price without paying, call an endpoint with no payment:
# no payment attached: answers 402 with the price
curl -i 'https://api.chainward.ai/api/risk/x402?address=0x4baadba26c3c0bdef9e8faf173925d463aa53bb2'The PAYMENT-REQUIRED header is base64-encoded JSON. Its amount is in USDC's smallest unit (6 decimals): 10000 is 0.01 USDC, 20000 is 0.02, 50000 is 0.05, 100000 is 0.10 and 10000000 is 10. The JSON body says the price in plain words. Discovery files for x402 clients: /.well-known/x402 and /openapi.json.
Sell over x402 yourself? A standard buyer (@x402/fetch with its default settings) can try your paid endpoints every day, without paying, and we email you the day a payment would fail, with the field to fix: the x402 endpoint watch. First check free, then $10 a month in USDC on Base.
Or pay from this page
Run the counterparty check with a wallet that holds USDC on Base. You sign one transfer authorization; the facilitator pays the gas.
Datasets
# what's for sale
curl https://api.chainward.ai/api/paid
# free (30 a minute): is one wallet in a dataset, and in which tier?
curl https://api.chainward.ai/api/paid/termix-wallets/lookup/0xb709860b8a1ce20019f3786d6982f773912bd286
# the row itself, verdict first, for agents: 0.05 USDC over x402 (answers 402 until paid)
curl 'https://api.chainward.ai/api/paid/termix-wallets/check?address=0xb709860b8a1ce20019f3786d6982f773912bd286'People can buy a dataset from any wallet at chainward.ai/paid/<slug>: send the price in USDC on Base, and the page checks the transfer and gives you a download link that works for 24 hours. No account.
MCP server
MCP (Model Context Protocol) lets an AI assistant such as Claude or Cursor call outside tools. Add ChainWard to your client's MCP config:
{
"mcpServers": {
"chainward": {
"command": "npx",
"args": ["-y", "chainward-mcp-server"]
}
}
}Or run it directly with npx -y chainward-mcp-server. Package: chainward-mcp-server on npm (MCP registry name io.github.saltxd/chainward, source on GitHub). Tools: check_counterparty, lookup_agent, get_agent_profile, get_agent_economics, get_observatory_overview, get_top_agents, get_activity_feed, list_decodes, find_decodes_for_address. Questions or listing requests: [email protected].
Agent monitoring (signed-in)
The original ChainWard dashboard still runs for signed-in wallets: register agent addresses, browse their transactions and balances, and get Discord, Telegram or webhook alerts. It uses an API key from Settings. See the monitoring API, the CLI and alert types.