{"openapi":"3.1.0","info":{"title":"Universal On-Chain KYC Attestation API","version":"2.0.0","description":"x402 AI agent identity and on-chain KYC attestation service. Verify a wallet once, get a permanent on-chain attestation any x402 API can read. \n\n**Endpoints and pricing:**\n- `POST /api/public/kyc/start` — $0.05 USDC (x402). Start a KYC session; returns a hosted verification URL. Attestation written automatically on completion.\n- `GET /api/public/kyc/status` — $0.01 USDC (x402). Authoritative on-chain attestation check, including revocation. Returns full attestation metadata.\n- `GET /api/public/kyc/sanctions` — $0.02 USDC (x402). Screen a verified wallet against 1.3M+ OpenSanctions entries (OFAC, EU, UN, 330+ sources). Non-PII only.\n- `GET /api/public/kyc/verified` — **Free, no auth, no x402.** Fast DB-only lookup. Returns `{ verified: true/false }`. Rate limited to 60 req/min per IP.\n\nAll paid endpoints use the x402 protocol: on first request the server returns HTTP 402. An x402-aware client signs a USDC payment and retries automatically. Solana is supported on /start/solana, /status/solana, and /sanctions/solana. Supported networks: Base, Polygon, Arbitrum, Solana.","x-guidance":"STEP 1 -- Quick check (free): GET /api/public/kyc/verified?wallet=<address>. No payment, no auth. Returns { verified: true/false } from DB. 60 req/min. STEP 2 -- Start KYC: POST /api/public/kyc/start with $0.05 USDC via x402. The paying wallet address is extracted automatically from the x402 payment-signature header -- no request body needed. Response: { kycUrl, walletAddress }. Open kycUrl in a browser to complete identity verification. STEP 3 -- Authoritative status: GET /api/public/kyc/status?wallet=<address> with $0.01 USDC. Cross-checks on-chain for revocation. When verified:true the attestation is valid -- use this to gate access. STEP 4 (optional) -- Sanctions: GET /api/public/kyc/sanctions?wallet=<address> with $0.02 USDC. Returns sanctioned (bool) and match details. No PII is ever returned. Use @x402/fetch (wrapFetchWithPayment) to handle the 402 challenge/response cycle automatically.","x-protocol":"x402 payment protocol: on first request the server returns HTTP 402 with a payment-required header (base64 JSON). An x402-aware client (e.g. @x402/fetch) reads the challenge, signs a USDC permit2 authorization (EVM) or SPL token transfer (Solana), attaches it as a payment-signature header, and retries automatically. The wallet address in the payment-signature is used as the payer identity.","contact":{"name":"Madhouse Wallet","url":"https://madhousewallet.com"}},"servers":[{"url":"https://kyc.madhousewallet.com","description":"Production"}],"tags":[{"name":"Free","description":"No payment required. No x402. No authentication. Rate limited to 60 req/min per IP."},{"name":"KYC — Start","description":"Start a KYC session. **$0.05 USDC** via x402. Returns a hosted verification URL; attestation is written on-chain automatically once the user completes identity verification."},{"name":"KYC — Status","description":"Authoritative on-chain KYC status check. **$0.01 USDC** via x402. Cross-checks for revocation. Returns full attestation metadata."},{"name":"KYC — Sanctions","description":"Sanctions screening against 1.3M+ entries (OFAC SDN, EU, UN, 330+ sources). **$0.02 USDC** via x402. Non-PII result only."}],"paths":{"/api/public/kyc/start":{"post":{"operationId":"startKyc","tags":["KYC — Start"],"summary":"Start KYC session · $0.05 USDC (Base / Polygon / Arbitrum)","description":"Begin identity verification for a wallet. Costs $0.05 USDC. The x402 payment header identifies the payer wallet -- no request body needed. Returns a hosted verification URL (open in browser) and the bound wallet address. Once the user completes identity verification, the on-chain attestation is written automatically. Any service can then call GET /api/public/kyc/status to confirm. Use verified:true to gate access. Accepts $0.05 USDC on Base, Polygon, or Arbitrum via CDP Facilitator.","x-payment-info":{"pricingMode":"fixed","price":"0.05","currency":"USD","protocols":["x402"],"network":"eip155:8453"},"x-payment-networks":[{"network":"eip155:8453","asset":"0x833589fCD6eDb6E08f4c7C32D4f71b54bdA02913","label":"USDC on Base"},{"network":"eip155:137","asset":"0x3c499c542cEF5E3811e1192ce70d8cC03d5c3359","label":"USDC on Polygon"},{"network":"eip155:42161","asset":"0xaf88d065e77c8cC2239327C5EDb3A432268e5831","label":"USDC on Arbitrum"}],"x-code-samples":[{"lang":"TypeScript","label":"Base (CDP, @x402/fetch)","source":"// Using @x402/fetch — x402 payment is handled automatically.\n// The client signs a USDC permit2 (EVM) or token transfer (Solana) and retries on 402.\n\nimport { wrapFetchWithPayment } from '@x402/fetch'\nimport { x402Client }           from '@x402/core/client'\nimport { registerExactEvmScheme } from '@x402/evm/exact/client'\nimport { toClientEvmSigner }    from '@x402/evm'\nimport { privateKeyToAccount }  from 'viem/accounts'\nimport { createPublicClient, http } from 'viem'\nimport { base }       from 'viem/chains'\n\nconst account    = privateKeyToAccount('0xYOUR_PRIVATE_KEY')\nconst rpcClient  = createPublicClient({ chain: base, transport: http('YOUR_ALCHEMY_RPC') })\nconst evmSigner  = toClientEvmSigner(account, rpcClient)\nconst client     = new x402Client()\nregisterExactEvmScheme(client, { signer: evmSigner })\n\nconst fetchWithPayment = wrapFetchWithPayment(fetch, client)\n\n// Pays $0.05 USDC on Base automatically, retries with payment-signature header.\nconst res  = await fetchWithPayment('https://kyc.madhousewallet.com/api/public/kyc/start', {\n  method: 'POST',\n  body: JSON.stringify({}),\n})\nconst data = await res.json()\nconsole.log(data)"}],"requestBody":{"required":false,"description":"No request body is needed. The payer wallet address is extracted from the x402 payment-signature header.","content":{"application/json":{"schema":{"type":"object","properties":{}},"example":{}}}},"responses":{"200":{"description":"KYC session created. Open kycUrl in a browser to complete identity verification.","content":{"application/json":{"schema":{"type":"object","required":["kycUrl","walletAddress"],"properties":{"kycUrl":{"type":"string","description":"Hosted identity verification URL. Open in a browser to complete document and selfie verification. EAS or SAS attestation is written automatically once verification completes.","example":"https://kyc.madhousewallet.com/verify/vs_1TajwgBbHYAruVQWKekyDXiN"},"walletAddress":{"type":"string","description":"Lowercase wallet address extracted from the x402 payment header and bound to this KYC session.","example":"0xef616c29859b101167f3ea6bb69faee733d573f7"}}},"example":{"kycUrl":"https://kyc.madhousewallet.com/verify/vs_1TajwgBbHYAruVQWKekyDXiN","walletAddress":"0xef616c29859b101167f3ea6bb69faee733d573f7"}}}},"402":{"description":"Payment required. The response includes a base64-encoded payment-required header describing the accepted payment options. Use an x402-aware client (e.g. @x402/fetch with wrapFetchWithPayment) to handle this automatically.","headers":{"payment-required":{"schema":{"type":"string"},"description":"Base64-encoded JSON describing accepted payment schemes, networks, asset addresses, and amounts.","example":"eyJ4NDAyVmVyc2lvbiI6MiwiZXJyb3IiOiJQYXltZW50IHJlcXVpcmVkIiwiYWNjZXB0cyI6W3sic2NoZW1lIjoiZXhhY3QiLCJuZXR3b3JrIjoiZWlwMTU1Ojg0NTMiLCJtYXhBbW91bnRSZXF1aXJlZCI6IjUwMDAwIiwicmVzb3VyY2UiOiJodHRwczovL2t5Yy5tYWRob3VzZXdhbGxldC5jb20vYXBpL3B1YmxpYy9reWMvc3RhcnQiLCJkZXNjcmlwdGlvbiI6IkJlZ2luIGlkZW50aXR5IHZlcmlmaWNhdGlvbiBmb3IgYSB3YWxsZXQuIENvc3RzICQwLjA1IFVTREMuIiwibWltZVR5cGUiOiJhcHBsaWNhdGlvbi9qc29uIiwicGF5VG8iOiIweFlPVVJfUEFZX1RPX0FERFJFU1MiLCJtYXhUaW1lb3V0U2Vjb25kcyI6MzAwLCJhc3NldCI6IjB4ODMzNTg5ZkNENmVEYjZFMDhmNGM3QzMyRDRmNzFiNTRiZEEwMjkxMyIsImV4dHJhIjp7Im5hbWUiOiJVU0QgQ29pbiIsInZlcnNpb24iOiIyIn19XX0="}}}}}},"/api/public/kyc/start/solana":{"post":{"operationId":"startKycSolana","tags":["KYC — Start"],"summary":"Start KYC session · $0.05 USDC (Solana)","description":"Begin identity verification for a wallet. Costs $0.05 USDC. The x402 payment header identifies the payer wallet -- no request body needed. Returns a hosted verification URL (open in browser) and the bound wallet address. Once the user completes identity verification, the on-chain attestation is written automatically. Any service can then call GET /api/public/kyc/status to confirm. Use verified:true to gate access. Accepts $0.05 USDC on Solana Mainnet via CDP Facilitator. The on-chain attestation is written to Solana Attestation Service (SAS) once verification completes.","x-payment-info":{"pricingMode":"fixed","price":"0.05","currency":"USD","protocols":["x402"],"network":"solana:5eykt4UsFv8P8NJdTREpY1vzqKqZKvdp"},"x-payment-networks":[{"network":"solana:5eykt4UsFv8P8NJdTREpY1vzqKqZKvdp","asset":"EPjFWdd5AufqSSqeM2qN1xzybapC8G4wEGGkZwyTDt1v","label":"USDC on Solana"}],"x-code-samples":[{"lang":"TypeScript","label":"Solana (CDP, @x402/fetch)","source":"// Solana uses @x402/svm instead of @x402/evm.\nimport { wrapFetchWithPayment } from '@x402/fetch'\nimport { x402Client }           from '@x402/core/client'\nimport { ExactSvmScheme }        from '@x402/svm/exact/client'\nimport { toClientSvmSigner }     from '@x402/svm'\nimport { createKeyPairSignerFromPrivateKeyBytes } from '@solana/kit'\nimport { base58 }                from '@scure/base'\n\nconst keyBytes    = base58.decode('YOUR_SOLANA_PRIVATE_KEY_BASE58')\nconst keypair     = await createKeyPairSignerFromPrivateKeyBytes(keyBytes)\nconst svmSigner   = toClientSvmSigner(keypair)\nconst SVM_NET     = 'solana:5eykt4UsFv8P8NJdTREpY1vzqKqZKvdp'\nconst client      = new x402Client()\nclient.register(SVM_NET, new ExactSvmScheme(svmSigner, { rpcUrl: 'YOUR_ALCHEMY_SOLANA_RPC' }))\n\nconst fetchWithPayment = wrapFetchWithPayment(fetch, client)\n\n// Pays $0.05 USDC on Solana automatically.\nconst res  = await fetchWithPayment('https://kyc.madhousewallet.com/api/public/kyc/start/solana', { method: 'POST' })\nconst data = await res.json()  // { kycUrl, walletAddress }\nconsole.log(data)"}],"requestBody":{"required":false,"description":"No request body is needed.","content":{"application/json":{"schema":{"type":"object","properties":{}},"example":{}}}},"responses":{"200":{"description":"KYC session created.","content":{"application/json":{"schema":{"type":"object","required":["kycUrl","walletAddress"],"properties":{"kycUrl":{"type":"string","description":"Hosted identity verification URL. Open in a browser to complete document and selfie verification. EAS or SAS attestation is written automatically once verification completes.","example":"https://kyc.madhousewallet.com/verify/vs_1TajwgBbHYAruVQWKekyDXiN"},"walletAddress":{"type":"string","description":"Lowercase wallet address extracted from the x402 payment header and bound to this KYC session.","example":"0xef616c29859b101167f3ea6bb69faee733d573f7"}}},"example":{"kycUrl":"https://kyc.madhousewallet.com/verify/vs_1TajwgBbHYAruVQWKekyDXiN","walletAddress":"0xef616c29859b101167f3ea6bb69faee733d573f7"}}}},"402":{"description":"Payment required. The response includes a base64-encoded payment-required header describing the accepted payment options. Use an x402-aware client (e.g. @x402/fetch with wrapFetchWithPayment) to handle this automatically.","headers":{"payment-required":{"schema":{"type":"string"},"description":"Base64-encoded JSON describing accepted payment schemes, networks, asset addresses, and amounts.","example":"eyJ4NDAyVmVyc2lvbiI6MiwiZXJyb3IiOiJQYXltZW50IHJlcXVpcmVkIiwiYWNjZXB0cyI6W3sic2NoZW1lIjoiZXhhY3QiLCJuZXR3b3JrIjoiZWlwMTU1Ojg0NTMiLCJtYXhBbW91bnRSZXF1aXJlZCI6IjUwMDAwIiwicmVzb3VyY2UiOiJodHRwczovL2t5Yy5tYWRob3VzZXdhbGxldC5jb20vYXBpL3B1YmxpYy9reWMvc3RhcnQiLCJkZXNjcmlwdGlvbiI6IkJlZ2luIGlkZW50aXR5IHZlcmlmaWNhdGlvbiBmb3IgYSB3YWxsZXQuIENvc3RzICQwLjA1IFVTREMuIiwibWltZVR5cGUiOiJhcHBsaWNhdGlvbi9qc29uIiwicGF5VG8iOiIweFlPVVJfUEFZX1RPX0FERFJFU1MiLCJtYXhUaW1lb3V0U2Vjb25kcyI6MzAwLCJhc3NldCI6IjB4ODMzNTg5ZkNENmVEYjZFMDhmNGM3QzMyRDRmNzFiNTRiZEEwMjkxMyIsImV4dHJhIjp7Im5hbWUiOiJVU0QgQ29pbiIsInZlcnNpb24iOiIyIn19XX0="}}}}}},"/api/public/kyc/status":{"get":{"operationId":"getKycStatus","tags":["KYC — Status"],"summary":"KYC attestation status · $0.01 USDC (Base / Polygon / Arbitrum)","description":"Check KYC attestation status for any wallet. Costs $0.01 USDC. Pass ?wallet=0x... to check any address, or omit to check the paying wallet itself (payer address is read from the x402 payment header). Any service can call this to gate access to their platform. Returns verified (bool), chain, attestationHash, txHash, easUID, verifiedAt, verificationMethods, and riskScore. Accepts $0.01 USDC on Base, Polygon, or Arbitrum via CDP Facilitator.","x-payment-info":{"pricingMode":"fixed","price":"0.01","currency":"USD","protocols":["x402"],"network":"eip155:8453"},"x-payment-networks":[{"network":"eip155:8453","asset":"0x833589fCD6eDb6E08f4c7C32D4f71b54bdA02913","label":"USDC on Base"},{"network":"eip155:137","asset":"0x3c499c542cEF5E3811e1192ce70d8cC03d5c3359","label":"USDC on Polygon"},{"network":"eip155:42161","asset":"0xaf88d065e77c8cC2239327C5EDb3A432268e5831","label":"USDC on Arbitrum"}],"x-code-samples":[{"lang":"TypeScript","label":"Check any wallet (Base, @x402/fetch)","source":"// Using @x402/fetch — x402 payment is handled automatically.\n// The client signs a USDC permit2 (EVM) or token transfer (Solana) and retries on 402.\n\nimport { wrapFetchWithPayment } from '@x402/fetch'\nimport { x402Client }           from '@x402/core/client'\nimport { registerExactEvmScheme } from '@x402/evm/exact/client'\nimport { toClientEvmSigner }    from '@x402/evm'\nimport { privateKeyToAccount }  from 'viem/accounts'\nimport { createPublicClient, http } from 'viem'\nimport { base }       from 'viem/chains'\n\nconst account    = privateKeyToAccount('0xYOUR_PRIVATE_KEY')\nconst rpcClient  = createPublicClient({ chain: base, transport: http('YOUR_ALCHEMY_RPC') })\nconst evmSigner  = toClientEvmSigner(account, rpcClient)\nconst client     = new x402Client()\nregisterExactEvmScheme(client, { signer: evmSigner })\n\nconst fetchWithPayment = wrapFetchWithPayment(fetch, client)\n\n// Pays $0.01 USDC on Base automatically, retries with payment-signature header.\nconst res  = await fetchWithPayment('https://kyc.madhousewallet.com/api/public/kyc/status?wallet=0xef616c29859b101167f3ea6bb69faee733d573f7', {\n})\nconst data = await res.json()\nconsole.log(data)"},{"lang":"TypeScript","label":"Check own wallet (payer address, Base)","source":"// Using @x402/fetch — x402 payment is handled automatically.\n// The client signs a USDC permit2 (EVM) or token transfer (Solana) and retries on 402.\n\nimport { wrapFetchWithPayment } from '@x402/fetch'\nimport { x402Client }           from '@x402/core/client'\nimport { registerExactEvmScheme } from '@x402/evm/exact/client'\nimport { toClientEvmSigner }    from '@x402/evm'\nimport { privateKeyToAccount }  from 'viem/accounts'\nimport { createPublicClient, http } from 'viem'\nimport { base }       from 'viem/chains'\n\nconst account    = privateKeyToAccount('0xYOUR_PRIVATE_KEY')\nconst rpcClient  = createPublicClient({ chain: base, transport: http('YOUR_ALCHEMY_RPC') })\nconst evmSigner  = toClientEvmSigner(account, rpcClient)\nconst client     = new x402Client()\nregisterExactEvmScheme(client, { signer: evmSigner })\n\nconst fetchWithPayment = wrapFetchWithPayment(fetch, client)\n\n// Pays $0.01 USDC on Base automatically, retries with payment-signature header.\nconst res  = await fetchWithPayment('https://kyc.madhousewallet.com/api/public/kyc/status', {\n})\nconst data = await res.json()\nconsole.log(data)"}],"parameters":[{"name":"wallet","in":"query","required":false,"description":"EVM wallet address (0x followed by 40 hex chars) or Solana public key (base58, 32-44 chars) to look up. If omitted, the address of the paying wallet (extracted from the x402 payment-signature header) is used.","example":"0xef616c29859b101167f3ea6bb69faee733d573f7","schema":{"type":"string"}}],"responses":{"200":{"description":"KYC status for the queried wallet.","content":{"application/json":{"schema":{"type":"object","required":["walletAddress","verified"],"properties":{"walletAddress":{"type":"string","description":"The queried wallet address.","example":"0xef616c29859b101167f3ea6bb69faee733d573f7"},"verified":{"type":"boolean","description":"True if the wallet has a valid, non-revoked on-chain attestation. Use this to gate access to KYC-required services.","example":true},"chain":{"type":"string","description":"Chain the attestation was written to: base, arbitrum, polygon, or solana. Null if not yet attested.","example":"base"},"attestationHash":{"type":"string","description":"keccak256 hash of the attestation payload. Null if not yet attested.","example":"0x3b4f2e9c1a8d7f6e5c4b3a291807f6e5d4c3b2a19f8e7d6c5b4a3928170f6e5"},"txHash":{"type":"string","description":"Transaction hash of the EAS write on EVM chains. Null for Solana or if not yet attested.","example":"0xa1b2c3d4e5f6a1b2c3d4e5f6a1b2c3d4e5f6a1b2c3d4e5f6a1b2c3d4e5f6a1b2"},"easUID":{"type":"string","description":"EAS attestation UID (bytes32 hex). Null for Solana or if not yet attested.","example":"0x9f8e7d6c5b4a392817061504030201009f8e7d6c5b4a39281706150403020100"},"sasAttestationAddress":{"type":"string","description":"SAS attestation PDA address on Solana. Null for EVM chains.","example":null},"verifiedAt":{"type":"number","description":"Unix timestamp when identity verification completed. Null if not yet attested.","example":1716500000},"verificationMethods":{"type":"object","description":"documentType (passport, driving_license, id_card) and selfieCheck (verified, unverified, failed). Null if not yet attested.","example":{"documentType":"passport","selfieCheck":"verified"}},"riskScore":{"type":"string","description":"Identity risk score: low, high, or null.","example":"low"}}},"example":{"walletAddress":"0xef616c29859b101167f3ea6bb69faee733d573f7","verified":true,"chain":"base","attestationHash":"0x3b4f2e9c1a8d7f6e5c4b3a291807f6e5d4c3b2a19f8e7d6c5b4a3928170f6e5","txHash":"0xa1b2c3d4e5f6a1b2c3d4e5f6a1b2c3d4e5f6a1b2c3d4e5f6a1b2c3d4e5f6a1b2","easUID":"0x9f8e7d6c5b4a392817061504030201009f8e7d6c5b4a39281706150403020100","sasAttestationAddress":null,"verifiedAt":1716500000,"verificationMethods":{"documentType":"passport","selfieCheck":"verified"},"riskScore":"low"}}}},"400":{"description":"Bad request. wallet param provided but is not a valid EVM (0x...) or Solana (base58) address."},"402":{"description":"Payment required. The response includes a base64-encoded payment-required header describing the accepted payment options. Use an x402-aware client (e.g. @x402/fetch with wrapFetchWithPayment) to handle this automatically.","headers":{"payment-required":{"schema":{"type":"string"},"description":"Base64-encoded JSON describing accepted payment schemes, networks, asset addresses, and amounts.","example":"eyJ4NDAyVmVyc2lvbiI6MiwiZXJyb3IiOiJQYXltZW50IHJlcXVpcmVkIiwiYWNjZXB0cyI6W3sic2NoZW1lIjoiZXhhY3QiLCJuZXR3b3JrIjoiZWlwMTU1Ojg0NTMiLCJtYXhBbW91bnRSZXF1aXJlZCI6IjUwMDAwIiwicmVzb3VyY2UiOiJodHRwczovL2t5Yy5tYWRob3VzZXdhbGxldC5jb20vYXBpL3B1YmxpYy9reWMvc3RhcnQiLCJkZXNjcmlwdGlvbiI6IkJlZ2luIGlkZW50aXR5IHZlcmlmaWNhdGlvbiBmb3IgYSB3YWxsZXQuIENvc3RzICQwLjA1IFVTREMuIiwibWltZVR5cGUiOiJhcHBsaWNhdGlvbi9qc29uIiwicGF5VG8iOiIweFlPVVJfUEFZX1RPX0FERFJFU1MiLCJtYXhUaW1lb3V0U2Vjb25kcyI6MzAwLCJhc3NldCI6IjB4ODMzNTg5ZkNENmVEYjZFMDhmNGM3QzMyRDRmNzFiNTRiZEEwMjkxMyIsImV4dHJhIjp7Im5hbWUiOiJVU0QgQ29pbiIsInZlcnNpb24iOiIyIn19XX0="}}}}}},"/api/public/kyc/status/solana":{"get":{"operationId":"getKycStatusSolana","tags":["KYC — Status"],"summary":"KYC attestation status · $0.01 USDC (Solana)","description":"Check KYC attestation status for any wallet. Costs $0.01 USDC. Pass ?wallet=0x... to check any address, or omit to check the paying wallet itself (payer address is read from the x402 payment header). Any service can call this to gate access to their platform. Returns verified (bool), chain, attestationHash, txHash, easUID, verifiedAt, verificationMethods, and riskScore. Accepts $0.01 USDC on Solana Mainnet via CDP Facilitator.","x-payment-info":{"pricingMode":"fixed","price":"0.01","currency":"USD","protocols":["x402"],"network":"solana:5eykt4UsFv8P8NJdTREpY1vzqKqZKvdp"},"x-payment-networks":[{"network":"solana:5eykt4UsFv8P8NJdTREpY1vzqKqZKvdp","asset":"EPjFWdd5AufqSSqeM2qN1xzybapC8G4wEGGkZwyTDt1v","label":"USDC on Solana"}],"x-code-samples":[{"lang":"TypeScript","label":"Solana (CDP, @x402/fetch)","source":"// Using @x402/fetch — x402 payment is handled automatically.\n// The client signs a USDC permit2 (EVM) or token transfer (Solana) and retries on 402.\n\nimport { wrapFetchWithPayment } from '@x402/fetch'\nimport { x402Client }           from '@x402/core/client'\nimport { registerExactEvmScheme } from '@x402/evm/exact/client'\nimport { toClientEvmSigner }    from '@x402/evm'\nimport { privateKeyToAccount }  from 'viem/accounts'\nimport { createPublicClient, http } from 'viem'\nimport { base }       from 'viem/chains'\n\nconst account    = privateKeyToAccount('0xYOUR_PRIVATE_KEY')\nconst rpcClient  = createPublicClient({ chain: base, transport: http('YOUR_ALCHEMY_RPC') })\nconst evmSigner  = toClientEvmSigner(account, rpcClient)\nconst client     = new x402Client()\nregisterExactEvmScheme(client, { signer: evmSigner })\n\nconst fetchWithPayment = wrapFetchWithPayment(fetch, client)\n\n// Pays $0.01 USDC on Solana automatically, retries with payment-signature header.\nconst res  = await fetchWithPayment('https://kyc.madhousewallet.com/api/public/kyc/status/solana?wallet=7xKXtg2CW87d97TXJSDpbD5jBkheTqA83TZRuJosgAsU', {\n})\nconst data = await res.json()\nconsole.log(data)"}],"parameters":[{"name":"wallet","in":"query","required":false,"description":"EVM wallet address (0x followed by 40 hex chars) or Solana public key (base58, 32-44 chars) to look up. If omitted, the address of the paying wallet (extracted from the x402 payment-signature header) is used.","example":"0xef616c29859b101167f3ea6bb69faee733d573f7","schema":{"type":"string"}}],"responses":{"200":{"description":"KYC status for the queried wallet.","content":{"application/json":{"schema":{"type":"object","required":["walletAddress","verified"],"properties":{"walletAddress":{"type":"string","description":"The queried wallet address.","example":"0xef616c29859b101167f3ea6bb69faee733d573f7"},"verified":{"type":"boolean","description":"True if the wallet has a valid, non-revoked on-chain attestation. Use this to gate access to KYC-required services.","example":true},"chain":{"type":"string","description":"Chain the attestation was written to: base, arbitrum, polygon, or solana. Null if not yet attested.","example":"base"},"attestationHash":{"type":"string","description":"keccak256 hash of the attestation payload. Null if not yet attested.","example":"0x3b4f2e9c1a8d7f6e5c4b3a291807f6e5d4c3b2a19f8e7d6c5b4a3928170f6e5"},"txHash":{"type":"string","description":"Transaction hash of the EAS write on EVM chains. Null for Solana or if not yet attested.","example":"0xa1b2c3d4e5f6a1b2c3d4e5f6a1b2c3d4e5f6a1b2c3d4e5f6a1b2c3d4e5f6a1b2"},"easUID":{"type":"string","description":"EAS attestation UID (bytes32 hex). Null for Solana or if not yet attested.","example":"0x9f8e7d6c5b4a392817061504030201009f8e7d6c5b4a39281706150403020100"},"sasAttestationAddress":{"type":"string","description":"SAS attestation PDA address on Solana. Null for EVM chains.","example":null},"verifiedAt":{"type":"number","description":"Unix timestamp when identity verification completed. Null if not yet attested.","example":1716500000},"verificationMethods":{"type":"object","description":"documentType (passport, driving_license, id_card) and selfieCheck (verified, unverified, failed). Null if not yet attested.","example":{"documentType":"passport","selfieCheck":"verified"}},"riskScore":{"type":"string","description":"Identity risk score: low, high, or null.","example":"low"}}},"example":{"walletAddress":"0xef616c29859b101167f3ea6bb69faee733d573f7","verified":true,"chain":"base","attestationHash":"0x3b4f2e9c1a8d7f6e5c4b3a291807f6e5d4c3b2a19f8e7d6c5b4a3928170f6e5","txHash":"0xa1b2c3d4e5f6a1b2c3d4e5f6a1b2c3d4e5f6a1b2c3d4e5f6a1b2c3d4e5f6a1b2","easUID":"0x9f8e7d6c5b4a392817061504030201009f8e7d6c5b4a39281706150403020100","sasAttestationAddress":null,"verifiedAt":1716500000,"verificationMethods":{"documentType":"passport","selfieCheck":"verified"},"riskScore":"low"}}}},"400":{"description":"Bad request. wallet param provided but is not a valid EVM (0x...) or Solana (base58) address."},"402":{"description":"Payment required. The response includes a base64-encoded payment-required header describing the accepted payment options. Use an x402-aware client (e.g. @x402/fetch with wrapFetchWithPayment) to handle this automatically.","headers":{"payment-required":{"schema":{"type":"string"},"description":"Base64-encoded JSON describing accepted payment schemes, networks, asset addresses, and amounts.","example":"eyJ4NDAyVmVyc2lvbiI6MiwiZXJyb3IiOiJQYXltZW50IHJlcXVpcmVkIiwiYWNjZXB0cyI6W3sic2NoZW1lIjoiZXhhY3QiLCJuZXR3b3JrIjoiZWlwMTU1Ojg0NTMiLCJtYXhBbW91bnRSZXF1aXJlZCI6IjUwMDAwIiwicmVzb3VyY2UiOiJodHRwczovL2t5Yy5tYWRob3VzZXdhbGxldC5jb20vYXBpL3B1YmxpYy9reWMvc3RhcnQiLCJkZXNjcmlwdGlvbiI6IkJlZ2luIGlkZW50aXR5IHZlcmlmaWNhdGlvbiBmb3IgYSB3YWxsZXQuIENvc3RzICQwLjA1IFVTREMuIiwibWltZVR5cGUiOiJhcHBsaWNhdGlvbi9qc29uIiwicGF5VG8iOiIweFlPVVJfUEFZX1RPX0FERFJFU1MiLCJtYXhUaW1lb3V0U2Vjb25kcyI6MzAwLCJhc3NldCI6IjB4ODMzNTg5ZkNENmVEYjZFMDhmNGM3QzMyRDRmNzFiNTRiZEEwMjkxMyIsImV4dHJhIjp7Im5hbWUiOiJVU0QgQ29pbiIsInZlcnNpb24iOiIyIn19XX0="}}}}}},"/api/public/kyc/sanctions":{"get":{"operationId":"screenSanctions","tags":["KYC — Sanctions"],"summary":"Sanctions screening · $0.02 USDC (Base / Polygon / Arbitrum)","description":"Screen a KYC-verified wallet against OpenSanctions -- 1.3M+ entities from OFAC SDN, EU Financial Sanctions, UN Consolidated List, and 330+ sources. Costs $0.02 USDC. Pass ?wallet=0x... to check any verified address, or omit to check the paying wallet itself. Returns sanctioned (bool), matchCount, and non-PII entity details (caption, entity type, risk topics, source datasets). No PII is returned. Accepts $0.02 USDC on Base, Polygon, or Arbitrum via CDP Facilitator.","x-payment-info":{"pricingMode":"fixed","price":"0.02","currency":"USD","protocols":["x402"],"network":"eip155:8453"},"x-payment-networks":[{"network":"eip155:8453","asset":"0x833589fCD6eDb6E08f4c7C32D4f71b54bdA02913","label":"USDC on Base"},{"network":"eip155:137","asset":"0x3c499c542cEF5E3811e1192ce70d8cC03d5c3359","label":"USDC on Polygon"},{"network":"eip155:42161","asset":"0xaf88d065e77c8cC2239327C5EDb3A432268e5831","label":"USDC on Arbitrum"}],"x-code-samples":[{"lang":"TypeScript","label":"Screen a wallet (Base, @x402/fetch)","source":"// Using @x402/fetch — x402 payment is handled automatically.\n// The client signs a USDC permit2 (EVM) or token transfer (Solana) and retries on 402.\n\nimport { wrapFetchWithPayment } from '@x402/fetch'\nimport { x402Client }           from '@x402/core/client'\nimport { registerExactEvmScheme } from '@x402/evm/exact/client'\nimport { toClientEvmSigner }    from '@x402/evm'\nimport { privateKeyToAccount }  from 'viem/accounts'\nimport { createPublicClient, http } from 'viem'\nimport { base }       from 'viem/chains'\n\nconst account    = privateKeyToAccount('0xYOUR_PRIVATE_KEY')\nconst rpcClient  = createPublicClient({ chain: base, transport: http('YOUR_ALCHEMY_RPC') })\nconst evmSigner  = toClientEvmSigner(account, rpcClient)\nconst client     = new x402Client()\nregisterExactEvmScheme(client, { signer: evmSigner })\n\nconst fetchWithPayment = wrapFetchWithPayment(fetch, client)\n\n// Pays $0.02 USDC on Base automatically, retries with payment-signature header.\nconst res  = await fetchWithPayment('https://kyc.madhousewallet.com/api/public/kyc/sanctions?wallet=0xef616c29859b101167f3ea6bb69faee733d573f7', {\n})\nconst data = await res.json()\nconsole.log(data)"}],"x-response-examples":{"clean":{"walletAddress":"0xef616c29859b101167f3ea6bb69faee733d573f7","sanctioned":false,"matchCount":0,"matches":[]},"match":{"walletAddress":"0xef616c29859b101167f3ea6bb69faee733d573f7","sanctioned":true,"matchCount":1,"matches":[{"caption":"Viktor Anatolijevitch BOUT","countries":["ru","ua"],"entityType":"Person","topics":["sanction","debarment"],"datasets":["us_ofac_sdn","eu_financial_sanctions_files","un_sc_sanctions"]}]}},"parameters":[{"name":"wallet","in":"query","required":false,"description":"EVM wallet address (0x followed by 40 hex chars) or Solana public key (base58, 32-44 chars) to look up. If omitted, the address of the paying wallet (extracted from the x402 payment-signature header) is used.","example":"0xef616c29859b101167f3ea6bb69faee733d573f7","schema":{"type":"string"}}],"responses":{"200":{"description":"Sanctions result. sanctioned:false means the identity is clean against all screened lists.","content":{"application/json":{"schema":{"type":"object","required":["walletAddress","sanctioned","matchCount","matches"],"properties":{"walletAddress":{"type":"string","description":"The queried wallet address.","example":"0xef616c29859b101167f3ea6bb69faee733d573f7"},"sanctioned":{"type":"boolean","description":"True when one or more sanctioned entities matched. False means clean.","example":false},"matchCount":{"type":"number","description":"Number of distinct sanctioned entities that matched. Common names without additional filters may return multiple matches.","example":0},"matches":{"type":"array","description":"Each matched entity has caption (display name), countries (ISO-2 list), entityType (Person/Company/Organization), topics (sanction/debarment/role.pep/etc.), and datasets (source lists, e.g. us_ofac_sdn). Empty when sanctioned: false.","example":[]}}},"example":{"walletAddress":"0xef616c29859b101167f3ea6bb69faee733d573f7","sanctioned":false,"matchCount":0,"matches":[]}}}},"400":{"description":"Bad request. wallet param provided but is not a valid EVM (0x...) or Solana (base58) address."},"402":{"description":"Payment required. The response includes a base64-encoded payment-required header describing the accepted payment options. Use an x402-aware client (e.g. @x402/fetch with wrapFetchWithPayment) to handle this automatically.","headers":{"payment-required":{"schema":{"type":"string"},"description":"Base64-encoded JSON describing accepted payment schemes, networks, asset addresses, and amounts.","example":"eyJ4NDAyVmVyc2lvbiI6MiwiZXJyb3IiOiJQYXltZW50IHJlcXVpcmVkIiwiYWNjZXB0cyI6W3sic2NoZW1lIjoiZXhhY3QiLCJuZXR3b3JrIjoiZWlwMTU1Ojg0NTMiLCJtYXhBbW91bnRSZXF1aXJlZCI6IjUwMDAwIiwicmVzb3VyY2UiOiJodHRwczovL2t5Yy5tYWRob3VzZXdhbGxldC5jb20vYXBpL3B1YmxpYy9reWMvc3RhcnQiLCJkZXNjcmlwdGlvbiI6IkJlZ2luIGlkZW50aXR5IHZlcmlmaWNhdGlvbiBmb3IgYSB3YWxsZXQuIENvc3RzICQwLjA1IFVTREMuIiwibWltZVR5cGUiOiJhcHBsaWNhdGlvbi9qc29uIiwicGF5VG8iOiIweFlPVVJfUEFZX1RPX0FERFJFU1MiLCJtYXhUaW1lb3V0U2Vjb25kcyI6MzAwLCJhc3NldCI6IjB4ODMzNTg5ZkNENmVEYjZFMDhmNGM3QzMyRDRmNzFiNTRiZEEwMjkxMyIsImV4dHJhIjp7Im5hbWUiOiJVU0QgQ29pbiIsInZlcnNpb24iOiIyIn19XX0="}}},"404":{"description":"No on-chain KYC record found for this wallet address. The wallet must have completed identity verification first."},"503":{"description":"Upstream service temporarily unavailable. Retry the request."}}}},"/api/public/kyc/verified":{"get":{"operationId":"isWalletVerified","tags":["Free"],"summary":"Quick wallet KYC check — FREE · No auth · No x402","description":"Fast DB-only lookup that returns whether a wallet address has a completed on-chain KYC attestation. No x402 payment required. No on-chain read — result comes from the local index. Use this for lightweight checks where speed matters and a cached DB result is acceptable. For authoritative on-chain verification (revocation check included) use GET /api/public/kyc/status. Rate limited to 60 requests per minute per IP.","parameters":[{"name":"wallet","in":"query","required":true,"description":"EVM wallet address (0x + 40 hex chars) or Solana public key (base58, 32-44 chars).","example":"0xef616c29859b101167f3ea6bb69faee733d573f7","schema":{"type":"string"}}],"responses":{"200":{"description":"Verification result. verified:true means the wallet has a completed on-chain attestation in the DB.","content":{"application/json":{"schema":{"type":"object","required":["wallet","verified"],"properties":{"wallet":{"type":"string","description":"The queried wallet address (lowercased).","example":"0xef616c29859b101167f3ea6bb69faee733d573f7"},"verified":{"type":"boolean","description":"True if the wallet has a completed on-chain KYC attestation. False if unknown or not yet verified.","example":true}}},"example":{"wallet":"0xef616c29859b101167f3ea6bb69faee733d573f7","verified":true}}},"headers":{"X-RateLimit-Limit":{"schema":{"type":"string"},"description":"Max requests per window (60)."},"X-RateLimit-Remaining":{"schema":{"type":"string"},"description":"Requests remaining in current window."},"X-RateLimit-Reset":{"schema":{"type":"string"},"description":"Seconds until the window resets."}}},"400":{"description":"Missing or invalid ?wallet= param."},"429":{"description":"Rate limit exceeded. Max 60 requests per minute per IP.","content":{"application/json":{"schema":{"type":"object","properties":{"error":{"type":"string"},"retryAfterMs":{"type":"number","description":"Milliseconds until the rate limit resets."}}}}},"headers":{"Retry-After":{"schema":{"type":"string"},"description":"Seconds until requests are accepted again."}}}}}},"/api/public/kyc/sanctions/solana":{"get":{"operationId":"screenSanctionsSolana","tags":["KYC — Sanctions"],"summary":"Sanctions screening · $0.02 USDC (Solana)","description":"Screen a KYC-verified wallet against OpenSanctions -- 1.3M+ entities from OFAC SDN, EU Financial Sanctions, UN Consolidated List, and 330+ sources. Costs $0.02 USDC. Pass ?wallet=0x... to check any verified address, or omit to check the paying wallet itself. Returns sanctioned (bool), matchCount, and non-PII entity details (caption, entity type, risk topics, source datasets). No PII is returned. Accepts $0.02 USDC on Solana Mainnet via CDP Facilitator.","x-payment-info":{"pricingMode":"fixed","price":"0.02","currency":"USD","protocols":["x402"],"network":"solana:5eykt4UsFv8P8NJdTREpY1vzqKqZKvdp"},"x-payment-networks":[{"network":"solana:5eykt4UsFv8P8NJdTREpY1vzqKqZKvdp","asset":"EPjFWdd5AufqSSqeM2qN1xzybapC8G4wEGGkZwyTDt1v","label":"USDC on Solana"}],"x-code-samples":[{"lang":"TypeScript","label":"Solana (CDP, @x402/fetch)","source":"// Using @x402/fetch — x402 payment is handled automatically.\n// The client signs a USDC permit2 (EVM) or token transfer (Solana) and retries on 402.\n\nimport { wrapFetchWithPayment } from '@x402/fetch'\nimport { x402Client }           from '@x402/core/client'\nimport { registerExactEvmScheme } from '@x402/evm/exact/client'\nimport { toClientEvmSigner }    from '@x402/evm'\nimport { privateKeyToAccount }  from 'viem/accounts'\nimport { createPublicClient, http } from 'viem'\nimport { base }       from 'viem/chains'\n\nconst account    = privateKeyToAccount('0xYOUR_PRIVATE_KEY')\nconst rpcClient  = createPublicClient({ chain: base, transport: http('YOUR_ALCHEMY_RPC') })\nconst evmSigner  = toClientEvmSigner(account, rpcClient)\nconst client     = new x402Client()\nregisterExactEvmScheme(client, { signer: evmSigner })\n\nconst fetchWithPayment = wrapFetchWithPayment(fetch, client)\n\n// Pays $0.02 USDC on Solana automatically, retries with payment-signature header.\nconst res  = await fetchWithPayment('https://kyc.madhousewallet.com/api/public/kyc/sanctions/solana?wallet=7xKXtg2CW87d97TXJSDpbD5jBkheTqA83TZRuJosgAsU', {\n})\nconst data = await res.json()\nconsole.log(data)"}],"parameters":[{"name":"wallet","in":"query","required":false,"description":"EVM wallet address (0x followed by 40 hex chars) or Solana public key (base58, 32-44 chars) to look up. If omitted, the address of the paying wallet (extracted from the x402 payment-signature header) is used.","example":"0xef616c29859b101167f3ea6bb69faee733d573f7","schema":{"type":"string"}}],"responses":{"200":{"description":"Sanctions result.","content":{"application/json":{"schema":{"type":"object","required":["walletAddress","sanctioned","matchCount","matches"],"properties":{"walletAddress":{"type":"string","description":"The queried wallet address.","example":"0xef616c29859b101167f3ea6bb69faee733d573f7"},"sanctioned":{"type":"boolean","description":"True when one or more sanctioned entities matched. False means clean.","example":false},"matchCount":{"type":"number","description":"Number of distinct sanctioned entities that matched. Common names without additional filters may return multiple matches.","example":0},"matches":{"type":"array","description":"Each matched entity has caption (display name), countries (ISO-2 list), entityType (Person/Company/Organization), topics (sanction/debarment/role.pep/etc.), and datasets (source lists, e.g. us_ofac_sdn). Empty when sanctioned: false.","example":[]}}},"example":{"walletAddress":"0xef616c29859b101167f3ea6bb69faee733d573f7","sanctioned":false,"matchCount":0,"matches":[]}}}},"400":{"description":"Bad request. wallet param provided but is not a valid EVM (0x...) or Solana (base58) address."},"402":{"description":"Payment required. The response includes a base64-encoded payment-required header describing the accepted payment options. Use an x402-aware client (e.g. @x402/fetch with wrapFetchWithPayment) to handle this automatically.","headers":{"payment-required":{"schema":{"type":"string"},"description":"Base64-encoded JSON describing accepted payment schemes, networks, asset addresses, and amounts.","example":"eyJ4NDAyVmVyc2lvbiI6MiwiZXJyb3IiOiJQYXltZW50IHJlcXVpcmVkIiwiYWNjZXB0cyI6W3sic2NoZW1lIjoiZXhhY3QiLCJuZXR3b3JrIjoiZWlwMTU1Ojg0NTMiLCJtYXhBbW91bnRSZXF1aXJlZCI6IjUwMDAwIiwicmVzb3VyY2UiOiJodHRwczovL2t5Yy5tYWRob3VzZXdhbGxldC5jb20vYXBpL3B1YmxpYy9reWMvc3RhcnQiLCJkZXNjcmlwdGlvbiI6IkJlZ2luIGlkZW50aXR5IHZlcmlmaWNhdGlvbiBmb3IgYSB3YWxsZXQuIENvc3RzICQwLjA1IFVTREMuIiwibWltZVR5cGUiOiJhcHBsaWNhdGlvbi9qc29uIiwicGF5VG8iOiIweFlPVVJfUEFZX1RPX0FERFJFU1MiLCJtYXhUaW1lb3V0U2Vjb25kcyI6MzAwLCJhc3NldCI6IjB4ODMzNTg5ZkNENmVEYjZFMDhmNGM3QzMyRDRmNzFiNTRiZEEwMjkxMyIsImV4dHJhIjp7Im5hbWUiOiJVU0QgQ29pbiIsInZlcnNpb24iOiIyIn19XX0="}}},"404":{"description":"No on-chain KYC record found for this wallet address. The wallet must have completed identity verification first."},"503":{"description":"Upstream service temporarily unavailable. Retry the request."}}}}}}