API
POST /analyze
Analyze a wallet, a program or a token: who it is, how risky it is, the evidence, and its money in and out.
Request
| Field | Type | Meaning |
|---|---|---|
address | string | Required. A base58 Solana address. |
depth | integer | Recent transactions to read, 1 to 10,000. Default 1,000. Above 1,000 counts as a deep analysis. |
request.sh
1curl -X POST https://iriscan.app/api/analyze \2 -H "Authorization: Bearer $IRIS_KEY" \3 -H "Content-Type: application/json" \4 -d '{ "address": "sy88tvipKfaCTuVVeU2PczPa88hqgPfKnYQyCHboHP8", "depth": 5000 }'Most answers take a few seconds; a 10,000-transaction analysis up to about 20. Allow two minutes before timing out on your side.
Response
200 OK · response.json (abridged)
1{2 "address": "sy88tvipKfaCTuVVeU2PczPa88hqgPfKnYQyCHboHP8",3 "identity": { "type": "MEV_ARBITRAGE", "confidence": 0.95 },4 "risk": { "level": "LOW", "score": 10, "confidence": 0.3 },5 "summary": ["MEV arbitrage bot", "Bot", "Tips Jito", "Swaps on Jupiter"],6 "labels": [],7 "behaviors": [8 {9 "kind": "MEV_ARBITRAGE",10 "title": "MEV arbitrage bot",11 "description": "…",12 "confidence": 0.95,13 "examples": ["5Kq…", "3Ya…"]14 }15 ],16 "behavior": {17 "wallet_age_days": 212,18 "transaction_count": 4100000,19 "transaction_count_exact": false,20 "transactions_analyzed": 1000,21 "unique_counterparties": 38,22 "active": true23 },24 "activity": { "transfers": 41, "swaps": 902, "program_calls": 57 },25 "flows": { "inbound": { … }, "outbound": { … } },26 "meta": {27 "analyzed_at": "2026-09-29T10:12:03Z",28 "data_completeness": 0.9,29 "scope": "live",30 "warning": null,31 "depth": 100032 }33}Fields
The verdict
| Field | Type | Meaning |
|---|---|---|
identity.type | string | What it is: MEV_ARBITRAGE, EXCHANGE, DRAINER… or UNKNOWN. See Identities. |
identity.confidence | number | 0 to 1. |
risk.level | "LOW" | "MEDIUM" | "HIGH" | See Risk score. |
risk.score | number | 0 to 100. |
risk.confidence | number | 0 to 1: how sure the level is. |
summary | string[] | The takeaways, as the report shows them. |
Proof
| Field | Type | Meaning |
|---|---|---|
labels[] | Label | What the knowledge base knows: name, category, entity, role, source, source_url, confidence. |
behaviors[] | Behavior | Patterns found: kind, title, description, confidence, examples (signatures). See Behaviors. |
evidence[] | Evidence | Every finding in one list: type (external_label, behavior, counterparty_exposure), description, source, confidence, source_url. |
flagged_counterparties[] | Counterparty | Threats and sanctions it dealt with: address, label, labels, entity, source, interactions, received_from, sent_to, last_seen. |
known_counterparties[] | Counterparty | Exchanges, protocols and DEXes it dealt with. Same shape. |
Activity and money
| Field | Type | Meaning |
|---|---|---|
behavior | object | Wallet age in days, transaction_count (estimated unless transaction_count_exact), transactions_analyzed, unique_counterparties, active (a transaction in the last 30 days). |
activity | object | How the analyzed transactions split: transfers, swaps, program calls. |
flows.inbound / outbound | FlowSide | Transfers only: wallets, transactions, sol, usd (stablecoins), other_tokens, and top parties by value, each with lookalike. |
connections[] | Connection | Every counterparty with both directions: sol_in, usd_in, sol_out, usd_out, counts, dust_only, lookalike, and its latest transfers. |
swap_venues[] | SwapVenue | Where it swapped: program, name, swaps, what was sold and bought, and the recent swaps. |
balance | object | null | What it holds now: SOL, its dollar value, tokens and their value. |
balance_history[] | BalancePoint | time, sol, and sampled: true for the early points, false for the exact ones. |
Programs and tokens
When the address is a program, program holds its owner, calls and callers. When it is a mint, token holds its launch, trading, actors, holders and rug check, and identity.type is TOKEN.
Meta
| Field | Type | Meaning |
|---|---|---|
meta.scope | "live" | "database" | live: transactions were analyzed. database: only labels were available (not charged); meta.warning says why. |
meta.depth | number | The depth asked for. Fewer are read when the history is shorter. |
meta.data_completeness | number | 0 to 1: how much of what was needed could be read. |
meta.analyzed_at | string | ISO 8601, UTC. |
Using it to screen addresses
A simple policy before paying or accepting funds:
screen.py
1def screen(profile):2 risk = profile["risk"]3 if risk["level"] == "HIGH":4 return "block"5 if risk["level"] == "MEDIUM" or profile["flagged_counterparties"]:6 return "review"7 if profile["meta"]["scope"] != "live":8 return "review" # labels only: nothing was read9 return "allow"- Log the
evidencewith the decision: it is your record of why. - Cache a profile for a while rather than re-analyzing the same address on every payment.