Sanctions, crypto wallet, email and IP screening for agents. Pay per check in USDC via x402.
Runs on your machine from its package; the steps are below.
At most: only reads or looks up information.
Odel charges nothing per call. The publisher may charge for its own service.
Runs locally over stdio
This server isn't hosted — your MCP client launches it from a package registry. Use one of the commands below, or drop the config into your client (e.g. Claude Desktop).
Run
npx -y payperscreen-mcp
MCP client config
{
"mcpServers": {
"payperscreen": {
"command": "npx",
"args": [
"-y",
"payperscreen-mcp"
]
}
}
}Pay-per-check compliance screening over x402. Sanctions names, crypto wallets, emails and IP addresses, paid per request in USDC on Base, Polygon or Arbitrum. No account, no API key, no contract.
https://api.payperscreen.com (docs, OpenAPI)This repo is the whole thing: the paid API, the website, the case queue and the list ingest. Use the hosted version, or run your own.
| Endpoint | Price | What it does |
|---|---|---|
GET /screen?name= | $0.02 | Fuzzy name match against OFAC SDN, UN Consolidated, EU Consolidated and UK Sanctions lists, refreshed daily. Each hit includes record ID, programmes, aliases and a date of birth / nationality / type comparison |
GET /context?name= | $0.05 | The same comparison for the top hit; now included in /screen, kept for existing integrations |
GET /screen-address?address= | $0.02 | Exact match against OFAC sanctioned addresses (with the listed party), Tether USDT freezes on Tron, and known hack proceeds. Each source is reported separately |
GET /screen-email?email= | $0.02 | Ten deterministic signals: MX, disposable domain, domain age, certificate history, DNSBL, typo-squat, role account, mailbox probe and more |
GET /screen-ip?ip= | $0.01 | Spamhaus ZEN and Tor exit node check (beta) |
No LLM anywhere in the scoring. Every result says which sources it checked.
Any x402 client works. The reference client is a single file:
PRIVATE_KEY=0x... node examples/agent-client.mjs screen "Jane Doe"
An unpaid request returns 402 Payment Required with the price; the client signs a USDC payment and retries.
The mcp/ folder is an MCP server (npx -y payperscreen-mcp) that gives an AI agent screen_name, screen_wallet, check_email and check_ip tools, paying per check from a wallet you configure, with a spending cap. See mcp/README.md.
claude mcp add payperscreen -e PAYPERSCREEN_PRIVATE_KEY=0xYOUR_KEY -- npx -y payperscreen-mcp
Two Node services from one repo, plus Postgres:
| Service | Entry | Port | What it is |
|---|---|---|---|
| API | compliance-api.js | 4025 | The paid x402 endpoints and list refresh |
| Site | payment-agent.js (npm start) | 4030 | Website, wallet payments, prepaid balance, case queue, admin |
npm install
psql "$DATABASE_URL" -f schema.sql
node compliance-api.js # API
npm start # website
API settings
| Variable | Needed | Purpose |
|---|---|---|
DATABASE_URL | yes | Postgres with the pg_trgm extension |
SELLER_ADDRESS | yes | Wallet that receives payments |
CDP_API_KEY_ID, CDP_API_KEY_SECRET | yes | Coinbase CDP facilitator (settles payments) |
AUTO_REFRESH_LISTS=1 | recommended | Refresh every list daily, starting 60 s after start |
TRONGRID_API_KEY | optional | Faster USDT-on-Tron freeze sync |
ETH_RPC_URL, BASE_RPC_URL, ARB_RPC_URL, OP_RPC_URL | optional | Node URLs that serve historical logs (e.g. Infura). Each one set switches on freeze coverage for that chain (USDT and USDC on Ethereum, USDC on Base, Arbitrum, Optimism); unset chains are skipped and not claimed |
PUBLIC_API_URL | optional | Public URL reported to x402 directories |
TOPUP_MIN_USD | optional | Minimum prepaid top-up (default 1.25) |
INTERNAL_API_KEY | recommended | Same random value (32+ characters) on both services. Prepaid-balance checks then come straight off the customer's balance via /internal/*, with no second on-chain payment |
SOLANA_PAY_TO | optional | A Solana address to receive USDC; when set, every paid route also accepts payment on Solana |
Site settings
| Variable | Needed | Purpose |
|---|---|---|
COMPLIANCE_API_URL | yes | Where the API runs |
BUYER_KEY | yes | Site wallet: pays the API for admin test checks (and for prepaid checks if INTERNAL_API_KEY isn't set) |
INTERNAL_API_KEY | recommended | Same value as on the API; prepaid checks then come off customers' balances directly |
ADMIN_CODE | yes | Code for /admin |
DB_PATH | yes in production | SQLite file for accounts, cases, balances (put it on a persistent volume) |
CONTACT_EMAIL, CONTACT_X, CONTACT_FACEBOOK | optional | Footer contact details |
ANALYTICS_SALT | optional | Salt for privacy-preserving visitor counts |
BASE_RPC_URL | optional | Verifies smart-contract wallet sign-ins |
| Source | Licence |
|---|---|
OFAC SDN and sdn_advanced.xml (US Treasury) | Public domain |
| UN Security Council Consolidated List | Public |
| EU Consolidated Financial Sanctions List | Public |
| UK Sanctions List (FCDO) | Open Government Licence |
| Stablecoin freezes | Read from the Tether USDT contract's public on-chain events on Tron (Ethereum and Circle USDC chains switch on when an RPC is set, see below) |
Known hack proceeds (data/hack-addresses.json) | Curated here from FBI notices (public domain) and published incident reports; each incident lists its sources |
| Crypto address fallback | 0xB10C/ofac-sanctioned-digital-currency-addresses, MIT |
A screening result is a lookup against the listed sources, not a compliance decision. "No match" means no match on those lists only. See the methodology for exactly what each check does and doesn't cover.
Issues and pull requests are welcome. Most useful right now: new public data sources (each kept as its own labelled result, never folded into "sanctioned"), and corrections to the hack list with a source link.
server.js, shop.js and check.js are early x402 experiments (a demo weather API), kept for reference; they aren't part of PayPerScreen.
MIT, see LICENSE.