API & MCP

    Wallet Reputation API

    The Wallet Reputation API lets exchanges, DeFi protocols, compliance teams and AI agents query a wallet's risk score, entity attribution and sanctions status programmatically. It reads ChainHint's own database of 48M+ attributed addresses instead of tracing the chain, which is why it suits real-time screening at deposit, withdrawal or payment time.

    Free tier — no key, no signup

    Call the endpoint with no credentials and you get 3 checks per IP per 24 hours. The response carries "tier": "free" and standardX-RateLimit-Limit / Remaining / Reset headers.

    bash
    curl "https://kjiwfwymnuzxriokhcjk.supabase.co/functions/v1/wallet-reputation?address=0x47666fab8bd0ac7003bce3f5c3585383f09486e2&chain=ethereum"

    API key — 10,000 requests per day

    Agency plan keys start with ch_live_ and are created in Settings → API Keys (up to 5 per account). Pass the key as a Bearer token or in X-Api-Key.

    bash
    curl "https://kjiwfwymnuzxriokhcjk.supabase.co/functions/v1/wallet-reputation?address=0x47666fab8bd0ac7003bce3f5c3585383f09486e2&chain=ethereum" \
      -H "Authorization: Bearer ch_live_YOUR_KEY"

    Response

    json
    {
      "address": "0x47666fab8bd0ac7003bce3f5c3585383f09486e2",
      "chain": "ethereum",
      "risk_score": 85,
      "risk_level": "critical",
      "category": "hacker",
      "entity": {
        "name": "Bybit Hack Exploiter",
        "category": "hacker",
        "subcategory": null,
        "verified": false,
        "attribution_unconfirmed": false,
        "operating_status": null,
        "actor": null,
        "freeze_requestable": false,
        "contact_source_verified": null,
        "contact_note": null,
        "label_trust": "verified",
        "heuristic_flag": null
      },
      "labels": ["Hacker/Exploiter", "Bybit Hack Exploiter"],
      "sanctions": { "hit": false, "complete": true },
      "screen_status": { "complete": true, "incomplete": [], "note": null },
      "restricted_assets": [],
      "agent": null,
      "evidence": [],
      "held_evidence": [],
      "is_contract": false,
      "found_in_db": true,
      "sources": ["chainhint:manual"],
      "checked_at": "2026-09-02T16:20:00.000Z",
      "tier": "free"
    }

    risk_level is one of clean · low · medium · high · critical · sanctioned · unknown — on the same 81 / 61 / 41 / 21 ladder as the address page and the Telegram bot, and risk_label carries the words they print (Low Risk · Moderate · Elevated · High Risk · Critical). unknown (with risk_score: null) means a screen that could have found something did not answer, and there was nothing else to score. It is a refusal, not a clearance. screen_status says which — { complete, incomplete[], note }, where incomplete holds any of sanctions · restricted_assets · address_record and note is one sentence naming the screen and the reason. sanctions.complete is the same fact for the sanctions screen alone, and sanctions.hit is null — not false — when that screen did not finish. A score the screens already raised is still printed: only a zero is refused.restricted_assets lists crypto-assets the wallet holds that are themselves prohibited (EU Annex LIII — A7A5), matched by contract and valued at par, each with a summary such as “holds EU-restricted asset A7A5 (Reg. (EU) 2025/2033 Art. 5ba)”; [] = checked, none; null = the chain could not be read. A holding is a property of the asset, never a sanctions hit on the holder. risk_score is the verdict the address page printed, outbound exposure included, as of risk_as_of — at most 24 hours old and from the current engine, otherwise recomputed. exposure_checked: false means outbound counterparties were not read, so the score is the known floor, not a full answer. agent is the agent-infrastructure overlay: { is_agent, kind, framework, label, summary, source_url } when the address is in ChainHint's registry of known autonomous-agent infrastructure — kind is one of launchpad · factory · router · facilitator · known_agent (agent-token launchpads, deployer factories, routers, payment facilitators, known agent wallets; is_agent is true only for known_agent) — else null. It is a registry fact you can check against the named contract at source_url, not a behavioural classification, and it does not move risk_score. evidence lists what each source actually establishes about the address — one item per finding, { class, authority, subject, document_ref, document_url, document_date, legal_basis, token, chain, first_seen_at }, where class is one of sanctions_designation · law_enforcement_attribution · issuer_freeze · national_seizure_order · industry_blocklist · analyst_verified. Only sanctions_designation sets sanctions.hit and the level sanctioned; an FBI attribution, an address frozen by Tether or Circle, or a national seizure order is not a sanctions designation — each lands in the high band and says so. [] = none; null = could not be read. held_evidence lists findings a third-party dataset reports that ChainHint has not yet read at the source — { class, authority, subject, reported_via, held_since, note }. They are a note, not evidence: they do not move risk_score, risk_level or sanctions.hit until reviewed. [] = none; null = could not be read. is_contract is boolean | null, and null means not recorded — never “not a contract”: this endpoint reads the stored address record and makes no live contract call, so null is “we hold no value for this address”. On the richer address-lookup endpoint (the lookup_address MCP tool) the same field is accompanied by contract_status — ok · unavailable · unsupported, the same vocabulary as goplus_status — where unavailable is “the provider refused the read” and unsupported is “this chain has no contract read here” (TRON, Solana). Both are is_contract: null, and neither claims anything about the address; only false with contract_status: "ok" says “measured, and it is not a contract”. entity.label_trust is verified · attributed · unverified · heuristic: only a verified label (a designation, law-enforcement attribution, seizure order, issuer freeze or analyst verification on the address — no entity source verifies by itself) floors or buckets other addresses; an attributed label (a named clustering / tracing source without evidence) carries entity.attribution = { method, publisher, note } — method is clustering · hackscan_trace · victim_report · public_label_registry — and is shown and counted, never scored. entity.heuristic_flag is { detector, status, note } when the label is a heuristic detector flag (Forta) — status is unverified · pending_review, the note reads “Flagged by a heuristic detector (Forta), unverified — not scored.” — else null; it never moves risk_score. When the free quota is used up, an autonomous agent can pay per call via x402: the endpoint answers 402 Payment Required with the terms — $0.10 USDC on Base — the agent re-requests with a signed X-PAYMENT header (EIP-3009), the payment is settled through a facilitator and the check runs. One payment, one call, no signup. Without a payment it falls back to 429 with anupgrade link and reset_at. Full reference, error shapes and Python / Node examples: WALLET_REPUTATION_API.md.

    AccessNo keyLimit3 checks / IP / 24hWhoAnyone — try it, wire it into an agent
    AccessPay-per-call (x402)Limit$0.10 USDC / call on Base, no signupWhoAI agents past the free tier
    AccessAgency keyLimit10,000 / day per key, 100 / min burstWhoExchanges, protocols, compliance teams
    AccessEnterpriseLimitCustomWhoContact us

    MCP Server

    chainhint-mcp is an MCP (Model Context Protocol) server that gives Claude Desktop, Claude Code, Cursor or any MCP-compatible agent three ChainHint tools. It runs straight from npm and needs no API key to start — every tool has a free allowance.

    Available Tools

    Toolcheck_wallet_riskWhat it returnsRisk score & level, entity, labels, sanctions hit — fast, database-onlyWithout a key3 / dayWith an Agency key10,000 / day
    Toollookup_addressWhat it returnsDeep report: risk factors, GoPlus flags, counterparty exposure by category, balance, tx countWithout a key10 / dayWith an Agency key100 / hour
    Toolget_trace_statusWhat it returnsPublic hack incident: loss, hops, where funds went (exchange / mixer / bridge / defi), attacker exposureWithout a keyUnlimitedWith an Agency keyUnlimited

    lookup_address carries the same verdict vocabulary as the REST endpoint above, in risk_verdict — { score, level, screen_status }, where score is null and level unknown when a screen that could have found something did not answer. Its older risk block is deprecated, removal 2026-12-31: it used to print 0 · clean in that case and is now null there instead, so risk.score throws rather than reading as a zero. Branch on risk_verdict, or on risk_status, not on it.

    Setup (Claude Desktop / Cursor / Claude Code)

    json
    // Claude Desktop: ~/Library/Application Support/Claude/claude_desktop_config.json
    // Cursor: .cursor/mcp.json       Claude Code: claude mcp add chainhint -- npx -y chainhint-mcp
    {
      "mcpServers": {
        "chainhint": {
          "command": "npx",
          "args": ["-y", "chainhint-mcp"]
        }
      }
    }

    To lift the free limits add "env": { "CHAINHINT_API_KEY": "ch_live_…" } to the entry. Get a key from Settings → API Keys (Agency plan).

    What the agent sees

    Ask "Is 0x47666fab… a known hacker?" and the model calls check_wallet_risk:

    bash
    ## Wallet Risk Report: 0x47666f...9486e2
    **Chain:** ethereum
    **Risk Score:** 85/100 — **CRITICAL**
    **Entity:** Bybit Hack Exploiter (hacker)
    **Labels:** Hacker/Exploiter, Bybit Hack Exploiter
    **In ChainHint DB:** yes (sources: chainhint:manual)
    Free tier: 2 of 3 checks left today — set CHAINHINT_API_KEY for 10,000/day.

    Ask "Where did the CoinEx hack funds go?" and it calls get_trace_status:

    bash
    ## Fund Trace: CoinEx
    **Status:** TRACED · **Loss:** $55.00M · **Date:** 2023-09-12
    ### Trace Graph
    **Hops traced:** 4 · **Addresses:** 124 · **Transfers:** 244
    ### Where the funds went (122 endpoints, $12.32M tracked)
    - **unknown**: $10.21M (82.9%) across 46 address(es) — Forta: Attacker, Cult DAO
    - **defi**: $2.09M (17.0%) across 72 address(es) — uniswap, Uniswap V3, Uniswap V2
    - **exchange**: $19.9K (0.2%) across 4 address(es) — KuCoin deposit, OKX deposit
    🔗 View full trace: https://chainhint.com/incident/9a1964d8-…

    Installation

    No install step — the config above runs the server from npm via npx. Source: github.com/seomarlboro/chainhint-mcp (MIT). To build locally:

    bash
    git clone https://github.com/seomarlboro/chainhint-mcp
    cd chainhint-mcp
    npm install && npm run build