Token risk API · Base · x402
Can your bot sell it? Find out for one cent.
Send a new ERC-20 address on Base, get back SAFE, CAUTION or DANGER with the reasons behind it. The check simulates a buy and a sell, reads the tax, the owner's powers, the liquidity and the token's age. You pay per call in USDC over x402: no account, no API key.
- $0.01 per check
- $0.05 per batch of 10
- MCP tool for Claude Desktop & Cursor
Verdict receipt
- Simulated buy / sell
- both OK
- Buy tax / sell tax
- 0% / 0%
- Round trip cost
- 2.0%
- Ownership
- renounced
- Upgradeable proxy
- no
- Exit liquidity
- ~$1.0M
- LP lock
- unknown
- Token age
- > 30 days
checked 2026-11-01 · engine 0.1.0
Taken from the free /v1/sample endpoint. It is an established token, so this is what a clean result looks like; the API is built for tokens that launched hours or days ago.
Five things a bot needs to know before it buys
| aCan it be sold | A buy and a sell are simulated with eth_call state overrides against the best pool (Uniswap v2/v3/v4, Aerodrome). If the sell reverts, that is the strongest risk signal the API has. |
|---|---|
| bBuy & sell tax | Measured from the simulation, not read from the source. The round-trip loss (fees, hook taxes, slippage) is reported next to it. |
| cOwner powers | Whether ownership is renounced, and whether the contract exposes mint, blacklist, pause, fee setters, trading switches or limit setters. Detects EIP-1967 and similar upgradeable proxies. |
| dLiquidity | Exit depth in USD across pools, and whether the LP tokens are burned, locked by a known launchpad (Clanker, Zora), or unknown. |
| eToken age | How long ago the contract was created, plus creator signals: share of supply held, repeat deployers, fresh wallets. |
A label, a score, and the reasons in plain English
Buy and sell simulate cleanly and no abusive owner controls were found. It does not mean the price will hold.
Tradeable, but with risk signals such as taxes, active owner powers, thin liquidity or an upgradeable proxy.
For example a failed simulated sell, a tax of 50% or more, or no pool on the supported DEXes.
{
"address": "0x532f27101965dd16442E59d40670FaF5eBB142E4",
"chain": "base",
"verdict": "SAFE",
"score": 95,
"summary": "No blocking risks found: buy and sell simulate cleanly and no abusive owner controls detected.",
"reasons": [
"LP lock status unknown (position NFT); liquidity may be removable.",
"Buy and sell simulated OK; round trip costs 2.0%.",
"Exit liquidity ~$1.0M.",
"Ownership renounced.",
"Token is older than 30 days."
],
"findings": [
{
"id": "lp_unknown",
"severity": "low",
"penalty": 5,
"message": "LP lock status unknown (position NFT); liquidity may be removable."
},
{
"id": "roundtrip_ok",
"severity": "info",
"penalty": 0,
"message": "Buy and sell simulated OK; round trip costs 2.0%."
},
// 3 more findings omitted for display
],
"token": {
"name": "Brett",
"symbol": "BRETT",
"decimals": 18
},
"launchpad": null,
"flags": {
"trading": {
"canBuy": true,
"canSell": true,
"buyTaxPct": 0,
"sellTaxPct": 0,
"roundTripLossPct": 1.99,
"poolKind": "uniswap-v3"
},
"ownership": {
"owner": "0x0000000000000000000000000000000000000000",
"ownerSource": "owner()",
"renounced": true,
"capabilities": {
"tradingToggle": [
"enableTrading()"
],
"feeExemption": [
"excludeFromFees(address,bool)"
]
},
"proxy": {
"kind": "none"
}
},
"liquidity": {
"totalDepthUsd": 1036551,
"pools": [
{
"kind": "uniswap-v3",
"id": "0xBA3F945812a83471d709BCe9C3CA699A19FB46f7",
"quote": "0x4200000000000000000000000000000000000006",
"quoteSymbol": "WETH",
"depthQuote": 303.785329,
"depthUsd": 688673,
"lp": {
"status": "unknown"
},
"source": "factory"
},
// 7 more pools omitted for display
]
},
"creator": {},
"age": {
"olderThanDays": 30
}
},
"meta": {
"block": 53369630,
"checkedAt": "2026-11-01T10:23:28.499Z",
"latencyMs": 1274,
"engine": "0.1.0",
"partial": [],
"disclaimer": "Automated on-chain risk signals for Base, not financial advice. A SAFE verdict means no mechanical trap was detected, not that the price will hold."
}
}Real output of the free sample endpoint for an established token, checked 2026-11-01. Display-trimmed: some fields are removed and three findings and seven pools are left out. reasons is sorted most severe first; findings carries the same items with an id, a severity (critical, high, medium, low, info) and the score penalty. Batch calls return {"results": [...]} and report a per-address error instead of failing the whole call.
Three lines. The third one pays.
curl {{API_URL}}/v1/sample # 1. free: see the response shape
curl -i {{API_URL}}/v1/verdict/0xTOKEN # 2. HTTP 402 + USDC payment terms
node check.mjs 0xTOKEN # 3. signs the 402, retries, prints the verdict
- The sample and health endpoints need nothing.
- The 402 response carries the price, the USDC asset on Base and the pay-to address in its
PAYMENT-REQUIREDheader (base64 JSON). Any x402 client can read it. check.mjsis the short script below. It uses the standard@x402/fetchclient, so the wallet only signs a USDC transfer authorization for the exact price.
check.mjs (JavaScript, about 10 lines)
import { wrapFetchWithPaymentFromConfig } from "@x402/fetch";
import { ExactEvmScheme } from "@x402/evm";
import { privateKeyToAccount } from "viem/accounts";
// use a dedicated wallet that holds a few dollars of USDC on Base
const account = privateKeyToAccount(process.env.EVM_PRIVATE_KEY);
const pay = wrapFetchWithPaymentFromConfig(fetch, {
schemes: [{ network: "eip155:8453", client: new ExactEvmScheme(account) }],
});
const res = await pay(`{{API_URL}}/v1/verdict/${process.argv[2]}`);
console.log(JSON.stringify(await res.json(), null, 2));
Batch: up to 10 addresses for $0.05
curl -X POST {{API_URL}}/v1/verdict/batch \
-H 'content-type: application/json' \
-d '{"addresses": ["0xTOKEN1", "0xTOKEN2"]}' # same 402 flow; use `pay(url, { method: "POST", ... })`
Malformed addresses get HTTP 400 and addresses that are not tokens get 422. Failed checks are not settled, so you are not charged for them.
Give Claude Desktop or Cursor a check_base_token tool
Claude Desktop and Cursor cannot pay x402 invoices themselves, so the MCP server acts as the payer: it signs from a wallet you give it and enforces a per-call cap. Without a wallet the tool does not fail silently; it returns the 402 payment terms instead of a verdict.
{
"mcpServers": {
"canisell": {
"command": "npx",
"args": ["-y", "{{MCP_PACKAGE}}"],
"env": {
"VERDICT_API_URL": "{{API_URL}}",
"EVM_PRIVATE_KEY": "0x...key of a dedicated, low-balance wallet",
"MAX_PAYMENT_USD": "0.05"
}
}
}
}
Use a throwaway wallet funded with a few dollars of USDC on Base, never your main one. The key stays in your client config; it is only used locally to sign payments. The tool takes one argument, the token address, and returns the verdict JSON. If npx is not on the app's PATH, use its absolute path.
Pay for the calls you make. Nothing else.
One token
GET /v1/verdict/{address}
Batch of up to 10
POST /v1/verdict/batch
$0.005 per token, duplicates removed.
Free: / (service description), /v1/health (RPC reachability) and /v1/sample (example response). Payment is in USDC on Base through the x402 protocol: the server keeps no accounts or keys, a facilitator verifies and settles each payment. Results are cached for 60 seconds per address.
What this is not
- Heuristics, not advice. The output is automated on-chain risk signals. It is not financial advice and not an audit. A SAFE verdict means no mechanical trap was detected at that block, not that the price will hold or that the token cannot be rugged later.
- A snapshot. An owner who keeps powers can change the token after the check. Re-check before large trades; results are cached for 60 seconds.
- Base mainnet only (chain 8453), and ERC-20 tokens traded on Uniswap v2/v3/v4 or Aerodrome pools. Tokens that trade elsewhere may show as having no pool.
- The simulation is one size. The buy is simulated at roughly $20. Large orders can face more slippage, and some Uniswap v4 hooks treat a same-transaction buy and sell differently from a later sale; those cases can produce false positives or false negatives.
- Some facts are unknowable from the chain. LP lock status is often "unknown" for position-NFT liquidity. Off-chain signals (team, social, off-DEX transfers) are not looked at.
- Mechanics, not intent. The API reports signals for an address. It does not say who is behind a token or whether anyone meant harm.
- Early service. Engine 0.1.0, one operator, no uptime guarantee. A free
/v1/healthendpoint shows whether the service can reach the chain.