API Reference
Screen and analyze any crypto wallet programmatically, with signed webhooks for continuous re-screening. Available on the Advanced and Enterprise plans. OpenAPI spec ↗
Authentication
Pass your API key in one of two ways:
# Header (recommended) X-Api-Key: wdna_your_key_here # Or as a Bearer token Authorization: Bearer wdna_your_key_here
Generate keys in Developer → API Keys. Keys are shown only once — store them securely.
Base URL
https://walletdna.com
Endpoints
The screening primitive: pass one address, or up to 25 in addresses, and get a decision your policy engine, Travel-Rule flow, or KYT step can act on. Optional thresholds map the risk score to review/block (sanctioned hits always block). Each address counts as one call.
Request
curl -X POST https://walletdna.com/api/v1/screen \
-H "X-Api-Key: wdna_your_key_here" \
-H "Content-Type: application/json" \
-d '{
"address": "0x722122dF12D4e14e13Ac3b6895a86e84145b6967",
"thresholds": { "review": 50, "block": 80 }
}'Response
{
"result": {
"address": "0x722122dF12D4e14e13Ac3b6895a86e84145b6967",
"chain": "ETH",
"riskScore": 96,
"riskLabel": "CRITICAL",
"decision": "block",
"sanctioned": { "hit": true, "authorities": ["OFAC"] },
"category": "sanctioned",
"entity": { "name": "Tornado Cash", "type": "Threat Actor" },
"screenedAt": "2026-06-22T18:30:00.000Z"
},
"thresholds": { "review": 50, "block": 80 }
}Batch: send {"addresses": ["0x…", "0x…"]} (max 25) → { "results": [...], "count": n }.
Request
curl -X POST https://walletdna.com/api/analyze \
-H "X-Api-Key: wdna_your_key_here" \
-H "Content-Type: application/json" \
-d '{"wallet": "1A1zP1eP5QGefi2DMPTfTL5SLmv7Divf6Y"}'Response
{
"wallet": "1A1zP1eP5QGefi2DMPTfTL5SLmv7Divf6Y",
"chain": "BTC",
"balance": "72.31337 BTC",
"confidence": "verified",
"entity": {
"name": "Satoshi Genesis Block",
"type": "Exchange",
"source": "walletdna-verified"
},
"tags": [
"Chain: BTC",
"Veteran wallet (since 2009)",
"Whale (72 BTC)"
],
"riskScore": {
"score": 12,
"label": "LOW",
"color": "#22c55e",
"factors": ["No risk signals detected"],
"breakdown": [...]
},
"analysisId": "uuid",
"evidence": [...],
"summary": "Unique DNA found for 1A1zP1…"
}Request
curl -X POST https://walletdna.com/api/analyze/batch \
-H "X-Api-Key: wdna_your_key_here" \
-H "Content-Type: application/json" \
-d '{
"wallets": [
"1A1zP1eP5QGefi2DMPTfTL5SLmv7Divf6Y",
"0xd8dA6BF26964aF9D7eEd9e03E53415D37aA96045"
]
}'Response
{
"results": [
{ "wallet": "1A1z...", "chain": "BTC", ... },
{ "wallet": "0xd8...", "chain": "ETH", ... }
],
"count": 2
}Webhooks — continuous re-screening
Register HTTPS endpoints in Developer → Webhooks. Any wallet you monitor is re-screened daily; when its risk crosses into high/critical or it lands on a sanctions list, WalletDNA POSTs a signed event so the change flows into your stack — you're not a one-time check, you're always on.
Event types
wallet.risk_changed · wallet.sanctioned · wallet.tainted_source
Payload
POST https://your-endpoint.example.com
WalletDNA-Event: wallet.sanctioned
WalletDNA-Signature: t=1750617000,v1=4f8c…hexhmac
{
"id": "evt_3f8c1d2e9a7b4c5d6e7f8a9b",
"type": "wallet.sanctioned",
"created": 1750617000,
"data": {
"address": "0x722122dF…6967",
"chain": "ETH",
"riskScore": 96,
"decision": "block",
"sanctioned": { "hit": true, "authorities": ["OFAC"] },
"previousScore": 41,
"monitorId": "uuid",
"reportUrl": "https://walletdna.com/report/uuid"
}
}Verify the signature
Recompute the HMAC over ${t}.${rawBody} with your endpoint secret (whsec_…) and compare to v1:
import crypto from "crypto";
function verify(rawBody, header, secret) {
const [t, v1] = header.split(",").map(p => p.split("=")[1]);
const expected = crypto.createHmac("sha256", secret)
.update(`${t}.${rawBody}`).digest("hex");
return crypto.timingSafeEqual(Buffer.from(expected), Buffer.from(v1));
}Return any 2xx to acknowledge. Reject if the timestamp is older than ~5 minutes to prevent replay.
Errors
| Status | Code | Meaning |
|---|---|---|
| 401 | Unauthorized | Missing or invalid API key |
| 403 | Forbidden | Plan doesn't include this endpoint |
| 429 | rate_limited | Monthly call limit reached |
| 400 | Bad Request | Missing or invalid wallet address |
Rate Limits
| Plan | Calls / month | Batch |
|---|---|---|
| Advanced | 10,000 | Yes (25 per request) |
| Enterprise | Unlimited | Yes (25 per request) |
Supported Chains
Chain is auto-detected from the address format. Supported: BTC, ETH, SOL, XRP, TRX, BNB, MATIC, LTC, ADA, DOT, AVAX, ATOM, XLM, BASE, ARB, OP, TON, SUI.
MCP Server — for AI agents
Drive WalletDNA from MCP-compatible clients (Claude Desktop, Cursor, agents). The server (in mcp/ in the repo) exposes analyze_wallet, trace_funds, and screen_wallets as tools.
{
"mcpServers": {
"walletdna": {
"command": "node",
"args": ["/path/to/walletdna/mcp/walletdna-mcp.mjs"],
"env": { "WALLETDNA_API_KEY": "wdna_your_key_here" }
}
}
}Run npm install in mcp/ first. trace_funds works without a key.
SDKs
Dependency-free official clients wrap screening, batch screening, webhook management, and HMAC signature verification. Source lives in sdks/ in the repo.
JavaScript / TypeScript
import { WalletDNA } from "walletdna-sdk";
const wdna = new WalletDNA(process.env.WALLETDNA_API_KEY);
const { decision } = await wdna.screen("0x722122dF12D4e14e13Ac3b6895a86e84145b6967");
if (decision === "block") rejectDeposit();Python
from walletdna import WalletDNA
wdna = WalletDNA(os.environ["WALLETDNA_API_KEY"])
verdict = wdna.screen("0x722122dF12D4e14e13Ac3b6895a86e84145b6967")
if verdict["decision"] == "block":
reject_deposit()No-code — Zapier & Make
Connect screening and webhook events to 7,000+ apps without writing code.
Zapier
The Zapier app (in integrations/zapier/) ships a Screen Wallet action and a Wallet Risk or Sanctions Change trigger. Authenticate with your wdna_… key, then build Zaps like: new row in Sheets → Screen Wallet → if block, alert Slack.
Make (HTTP + Webhooks)
No dedicated app needed — use Make's built-in modules:
- Screen: an HTTP → Make a request module, POST https://walletdna.com/api/v1/screen, header Authorization: Bearer wdna_…, JSON body { "address": "0x…" }. Branch on result.decision.
- Receive events: add a Webhooks → Custom webhook module, copy its URL, then register it once via POST /api/webhooks (or the SDK). Events arrive as { id, type, created, data }.
Verify the WalletDNA-Signature header on received events (see the Webhooks section). The SDKs do this for you.