Wallet screening checks a crypto wallet address for AML risk before you accept funds from it or pay out to it. A screening returns a normalized assessment: risk score, severity, sanctions exposure, source and destination of funds, and risk_drivers - the adverse counterparties behind the score, with amounts. Large exposure breakdowns are truncated to the riskiest entries plus the largest remaining positions.
severity is the band of risk_score: UNKNOWN (0-9), LOW (10-39), MEDIUM (40-69), HIGH (70-89), CRITICAL (90-100). UNKNOWN is the lowest band, not a missing result: a clean address typically comes back as risk_score: 0 with severity: UNKNOWN.
Screening is on demand and independent of everything else - it takes a wallet address, not a user or a transaction. To screen an actual transfer against your own rules, use Transaction Monitoring instead.
In sandbox, requests past your monthly free quota are rejected with 429. In production, each successful screening records a billable usage event.
Risk drivers
risk_drivers answers which counterparty caused this result and for how much, so nobody has to add up dozens of exposure rows by hand. Each entry groups one counterparty across both directions and sums it. Entries are ordered by amount, largest first.
Every driver carries two shares, and they are measured against different denominators:
| Field | Denominator |
|---|---|
pct_of_attributed_exposure | volume attributed to a named entity - the same base the per-entry percentage fields use |
pct_of_total_volume | the wallet's entire lifetime volume, attributed or not |
attributed_coverage reports that gap directly, per direction. On a real wallet, well under half of the volume is typically attributed to a named entity, so the two shares can differ by an order of magnitude for the same exposure. Quote pct_of_total_volume when describing the wallet as a whole.
The two shares are not additive with each other, and neither is the sum of the incoming and outgoing percentage values on the exposure rows - those are shares of their own direction's attributed total, not of the wallet.
Every figure in risk_drivers is arithmetic over the exposure rows in the same response: filter, group, sum, divide. Nothing in it reweighs risk_score, severity or the reported categories, and nothing in it is a recommendation. enrichment_version names the revision of that arithmetic, so a case reopened later can be told which revision produced its summary.
Reading a high score with no drivers
risk_drivers can be empty on a HIGH or CRITICAL result. That is a real outcome rather than an error: the score is graded on an exposure model that does not always name a counterparty, and a wallet whose funds are largely unattributed leaves little for the breakdown to show.
Read attributed_coverage before drawing a conclusion. A wallet with 1% of inbound volume attributed has almost no trail to follow in the breakdown, and such a result warrants review rather than either clearance or rejection.
dominant_risk_category_source says where the category name came from: reported when it arrived with the screening result, and derived when we identified it from the exposure rows because the result did not name one.
Wallet ownership proofs
Screening tells you whether an address is risky; an ownership proof tells you whether one of your users actually controls it. You supply the address and the email of an existing end user of yours, and we email that user a hosted link where they sign a one-time message with their wallet (EIP-191 personal_sign - no gas, nothing broadcast on-chain). The signer is recovered and checked against the address server-side, and the request moves from PENDING to VERIFIED. The link is also returned in the response so you can deliver it yourself.
The email must belong to a known end user of your account, otherwise the call returns 404. The same mechanism backs the self-hosted counterparty flow in Travel Rule.
In this section
| Endpoint | What it does |
|---|---|
POST /screening/wallet | Screen a wallet address and store the result |
GET /screening/wallets | List past screenings, filterable by address, chain, severity, reference |
GET /screening/wallets/{screening_id} | Fetch one stored screening |
POST /screening/wallet-ownership/requests | Ask a user to prove they control a self-hosted wallet |
GET /screening/wallet-ownership/requests | List proof requests, filterable by address and status |
POST /screening/wallet-ownership/requests/{request_id}/cancel | Invalidate a pending proof link |