onchain reputation, made legible

A REST API
for onchain trust.

Query any wallet's PROOF passport with a single HTTP request. No SDK required, no special authentication during preview — just curl.

Get a score in 5 seconds

Every endpoint lives under https://api.proof.demo/v1. Pass an address, get back a score.

curl
# Fetch a passport
curl https://api.proof.demo/v1/passport/0x7a3f...e2c1
GET /passport/:address

Returns the full passport for a given wallet address — score, tier, all six dimensions, metrics, and earned credentials. The same payload that powers the Passport page.

Path parameters
addressrequired string A valid EVM address (0x…) or an ENS name. ENS is resolved against mainnet.
Query parameters
chains string[] Comma-separated chain IDs to restrict the score to. Default: all indexed chains.
refresh boolean Force a recomputation, bypassing the cache. Counts as 5 requests against your rate limit.
Example response
json · 200 OK
{
  "address": "0x7a3f...e2c1",
  "ens": "vitalik.eth",
  "score": 847,
  "tier": "trusted",
  "dimensions": {
    "activity": 78,
    "history": 95,
    "diversity": 82,
    "defi": 88,
    "governance": 71,
    "risk": 98
  },
  "metrics": {
    "first_seen": "2017-06-14T08:21:00Z",
    "tx_count": 1847,
    "protocols": 34,
    "chains": 9,
    "lifetime_volume_usd": 2412304.5
  },
  "flags": [],
  "credentials": [
    "og_wallet_2017",
    "dao_voter",
    "lp_provider",
    "ens_holder"
  ],
  "computed_at": "2026-05-24T16:43:00Z",
  "model_version": "0.4.2"
}
GET /score/:address

Lightweight endpoint returning only the composite score and tier. Use this when you don't need the full breakdown — about 8× cheaper to call than /passport.

Example response
json · 200 OK
{
  "address": "0x7a3f...e2c1",
  "score": 847,
  "tier": "trusted"
}
POST /batch

Score up to 100 wallets in a single call. Useful for backfilling allowlists or analyzing the holders of a token.

Request body
json · request
{
  "addresses": [
    "0x7a3f...e2c1",
    "0x9d1b...4f8a",
    "0x2e5c...a9d3"
  ],
  "include_dimensions": true
}
Example response
json · 200 OK
{
  "results": [
    { "address": "0x7a3f...e2c1", "score": 847, "tier": "trusted" },
    { "address": "0x9d1b...4f8a", "score": 762, "tier": "trusted" },
    { "address": "0x2e5c...a9d3", "score": 412, "tier": "neutral" }
  ],
  "computed_at": "2026-05-24T16:43:00Z"
}
GET /tier/:address

Returns only the tier as a plain string. The cheapest endpoint — useful for smart contracts via an oracle or for gating logic that only needs categorical input.

text · 200 OK
trusted
GET /flags/:address

Returns only the risk flags. Returns an empty array if the wallet has none. Use this if you want to gate purely on risk rather than the full composite score.

json · 200 OK
{
  "address": "0xb04f...1e7b",
  "flags": [
    { "type": "sanctioned_counterparty", "severity": "high" },
    { "type": "mixer_interaction", "severity": "high" },
    { "type": "new_wallet", "severity": "low" }
  ]
}

Rate limits

During the preview, requests are limited per IP. Higher limits are available with an API key once the program graduates.

Free 60 requests / minute, 10,000 / day Keyed 600 requests / minute, 100,000 / day Enterprise Custom — contact us

Error codes

All errors return JSON of shape { "error": "code", "message": "human-readable" }.

400 invalid_address — not a valid EVM address or ENS name 404 not_indexed — wallet has zero activity on indexed chains 429 rate_limited — too many requests; check Retry-After header 500 indexer_unavailable — temporary; retry with backoff 503 computing — first-time score; retry in ~30s