curl -X POST 'https://verification.didit.me/v3/wallet-screening/' \
-H 'x-api-key: YOUR_API_KEY' \
-H 'Content-Type: application/json' \
-d '{
"wallet_address": "0x28c6c06298d514db089934071355e5743bf21d60",
"blockchain": "ETH"
}'import os
import requests
resp = requests.post(
'https://verification.didit.me/v3/wallet-screening/',
headers={'x-api-key': os.environ['DIDIT_API_KEY']},
json={
'wallet_address': '0x28c6c06298d514db089934071355e5743bf21d60',
'blockchain': 'ETH',
},
timeout=20,
)
resp.raise_for_status()
result = resp.json()
print(result['risk_score'], result['severity'], result['sanctions_hit'])const result = await fetch('https://verification.didit.me/v3/wallet-screening/', {
method: 'POST',
headers: {
'x-api-key': process.env.DIDIT_API_KEY,
'Content-Type': 'application/json',
},
body: JSON.stringify({
wallet_address: '0x28c6c06298d514db089934071355e5743bf21d60',
blockchain: 'ETH',
}),
}).then((r) => r.json());
console.log(result.risk_score, result.severity, result.sanctions_hit);<?php
$curl = curl_init();
curl_setopt_array($curl, [
CURLOPT_URL => "https://verification.didit.me/v3/wallet-screening/",
CURLOPT_RETURNTRANSFER => true,
CURLOPT_ENCODING => "",
CURLOPT_MAXREDIRS => 10,
CURLOPT_TIMEOUT => 30,
CURLOPT_HTTP_VERSION => CURL_HTTP_VERSION_1_1,
CURLOPT_CUSTOMREQUEST => "POST",
CURLOPT_POSTFIELDS => json_encode([
'wallet_address' => '0x28c6c06298d514db089934071355e5743bf21d60',
'blockchain' => 'ETH'
]),
CURLOPT_HTTPHEADER => [
"Content-Type: application/json",
"x-api-key: <api-key>"
],
]);
$response = curl_exec($curl);
$err = curl_error($curl);
curl_close($curl);
if ($err) {
echo "cURL Error #:" . $err;
} else {
echo $response;
}package main
import (
"fmt"
"strings"
"net/http"
"io"
)
func main() {
url := "https://verification.didit.me/v3/wallet-screening/"
payload := strings.NewReader("{\n \"wallet_address\": \"0x28c6c06298d514db089934071355e5743bf21d60\",\n \"blockchain\": \"ETH\"\n}")
req, _ := http.NewRequest("POST", url, payload)
req.Header.Add("x-api-key", "<api-key>")
req.Header.Add("Content-Type", "application/json")
res, _ := http.DefaultClient.Do(req)
defer res.Body.Close()
body, _ := io.ReadAll(res.Body)
fmt.Println(string(body))
}HttpResponse<String> response = Unirest.post("https://verification.didit.me/v3/wallet-screening/")
.header("x-api-key", "<api-key>")
.header("Content-Type", "application/json")
.body("{\n \"wallet_address\": \"0x28c6c06298d514db089934071355e5743bf21d60\",\n \"blockchain\": \"ETH\"\n}")
.asString();require 'uri'
require 'net/http'
url = URI("https://verification.didit.me/v3/wallet-screening/")
http = Net::HTTP.new(url.host, url.port)
http.use_ssl = true
request = Net::HTTP::Post.new(url)
request["x-api-key"] = '<api-key>'
request["Content-Type"] = 'application/json'
request.body = "{\n \"wallet_address\": \"0x28c6c06298d514db089934071355e5743bf21d60\",\n \"blockchain\": \"ETH\"\n}"
response = http.request(request)
puts response.read_body{
"provider": "merklescience",
"screening_type": "WALLET_SCREENING",
"risk_score": 72,
"severity": "HIGH",
"status": "SCREENED",
"summary": "Merkle Science risk: High (4/5). Dominant risk: mixer",
"wallet_address": "0x28c6c06298d514db089934071355e5743bf21d60",
"blockchain": "ETH",
"sanctions_hit": true,
"dominant_risk_category": "mixer",
"source_of_funds": [
{
"category": "exchange_licensed",
"entity_name": "Binance.com",
"entity_type": "Exchange",
"entity_subtype": "Mandatory KYC and AML",
"exposure_direction": "incoming",
"exposure_type": "direct",
"is_direct": true,
"amount_usd": 18420.55,
"percentage": 61.4,
"hops": 0,
"country": "SC"
},
{
"category": "mixer",
"entity_name": "Tornado Cash",
"entity_type": "Mixer",
"entity_subtype": "OFAC SDN",
"exposure_direction": "incoming",
"exposure_type": "indirect",
"is_direct": false,
"amount_usd": 11580.2,
"percentage": 38.6,
"hops": 2,
"country": "RU"
}
],
"destination_of_funds": [
{
"category": "exchange_licensed",
"entity_name": "Coinbase",
"entity_type": "Exchange",
"entity_subtype": "Mandatory KYC and AML",
"exposure_direction": "outgoing",
"exposure_type": "direct",
"is_direct": true,
"amount_usd": 30000.75,
"percentage": 100,
"hops": 0,
"country": "US"
}
],
"counterparty_connections": [
{
"entity_name": "Tornado Cash",
"entity_type": "Mixer",
"entity_subtype": "OFAC SDN",
"risk_level": "CRITICAL",
"categories": [
"mixer"
],
"received_usd": 11580.2,
"sent_usd": 0,
"received_hops": 2,
"sent_hops": 0,
"percentage": 38.6,
"is_direct": false,
"country": "RU"
}
],
"report_signature": "3f9c2e1a7b4d6f80c5e9a1b2d3f4e5061728394a5b6c7d8e9f0a1b2c3d4e5f6"
}Screen Wallet
Run on-demand AML screening for a single crypto wallet/address without creating a transaction. Resolves your application’s configured blockchain analytics provider, screens the address synchronously, and returns the normalised risk result. LIGHTNING is available only with an Elliptic or Chainalysis BYOK connection added through Marketplace. Nothing is written to the transactions table. One AML monitoring usage is billed per successful screening (sandbox applications are not billed).
curl -X POST 'https://verification.didit.me/v3/wallet-screening/' \
-H 'x-api-key: YOUR_API_KEY' \
-H 'Content-Type: application/json' \
-d '{
"wallet_address": "0x28c6c06298d514db089934071355e5743bf21d60",
"blockchain": "ETH"
}'import os
import requests
resp = requests.post(
'https://verification.didit.me/v3/wallet-screening/',
headers={'x-api-key': os.environ['DIDIT_API_KEY']},
json={
'wallet_address': '0x28c6c06298d514db089934071355e5743bf21d60',
'blockchain': 'ETH',
},
timeout=20,
)
resp.raise_for_status()
result = resp.json()
print(result['risk_score'], result['severity'], result['sanctions_hit'])const result = await fetch('https://verification.didit.me/v3/wallet-screening/', {
method: 'POST',
headers: {
'x-api-key': process.env.DIDIT_API_KEY,
'Content-Type': 'application/json',
},
body: JSON.stringify({
wallet_address: '0x28c6c06298d514db089934071355e5743bf21d60',
blockchain: 'ETH',
}),
}).then((r) => r.json());
console.log(result.risk_score, result.severity, result.sanctions_hit);<?php
$curl = curl_init();
curl_setopt_array($curl, [
CURLOPT_URL => "https://verification.didit.me/v3/wallet-screening/",
CURLOPT_RETURNTRANSFER => true,
CURLOPT_ENCODING => "",
CURLOPT_MAXREDIRS => 10,
CURLOPT_TIMEOUT => 30,
CURLOPT_HTTP_VERSION => CURL_HTTP_VERSION_1_1,
CURLOPT_CUSTOMREQUEST => "POST",
CURLOPT_POSTFIELDS => json_encode([
'wallet_address' => '0x28c6c06298d514db089934071355e5743bf21d60',
'blockchain' => 'ETH'
]),
CURLOPT_HTTPHEADER => [
"Content-Type: application/json",
"x-api-key: <api-key>"
],
]);
$response = curl_exec($curl);
$err = curl_error($curl);
curl_close($curl);
if ($err) {
echo "cURL Error #:" . $err;
} else {
echo $response;
}package main
import (
"fmt"
"strings"
"net/http"
"io"
)
func main() {
url := "https://verification.didit.me/v3/wallet-screening/"
payload := strings.NewReader("{\n \"wallet_address\": \"0x28c6c06298d514db089934071355e5743bf21d60\",\n \"blockchain\": \"ETH\"\n}")
req, _ := http.NewRequest("POST", url, payload)
req.Header.Add("x-api-key", "<api-key>")
req.Header.Add("Content-Type", "application/json")
res, _ := http.DefaultClient.Do(req)
defer res.Body.Close()
body, _ := io.ReadAll(res.Body)
fmt.Println(string(body))
}HttpResponse<String> response = Unirest.post("https://verification.didit.me/v3/wallet-screening/")
.header("x-api-key", "<api-key>")
.header("Content-Type", "application/json")
.body("{\n \"wallet_address\": \"0x28c6c06298d514db089934071355e5743bf21d60\",\n \"blockchain\": \"ETH\"\n}")
.asString();require 'uri'
require 'net/http'
url = URI("https://verification.didit.me/v3/wallet-screening/")
http = Net::HTTP.new(url.host, url.port)
http.use_ssl = true
request = Net::HTTP::Post.new(url)
request["x-api-key"] = '<api-key>'
request["Content-Type"] = 'application/json'
request.body = "{\n \"wallet_address\": \"0x28c6c06298d514db089934071355e5743bf21d60\",\n \"blockchain\": \"ETH\"\n}"
response = http.request(request)
puts response.read_body{
"provider": "merklescience",
"screening_type": "WALLET_SCREENING",
"risk_score": 72,
"severity": "HIGH",
"status": "SCREENED",
"summary": "Merkle Science risk: High (4/5). Dominant risk: mixer",
"wallet_address": "0x28c6c06298d514db089934071355e5743bf21d60",
"blockchain": "ETH",
"sanctions_hit": true,
"dominant_risk_category": "mixer",
"source_of_funds": [
{
"category": "exchange_licensed",
"entity_name": "Binance.com",
"entity_type": "Exchange",
"entity_subtype": "Mandatory KYC and AML",
"exposure_direction": "incoming",
"exposure_type": "direct",
"is_direct": true,
"amount_usd": 18420.55,
"percentage": 61.4,
"hops": 0,
"country": "SC"
},
{
"category": "mixer",
"entity_name": "Tornado Cash",
"entity_type": "Mixer",
"entity_subtype": "OFAC SDN",
"exposure_direction": "incoming",
"exposure_type": "indirect",
"is_direct": false,
"amount_usd": 11580.2,
"percentage": 38.6,
"hops": 2,
"country": "RU"
}
],
"destination_of_funds": [
{
"category": "exchange_licensed",
"entity_name": "Coinbase",
"entity_type": "Exchange",
"entity_subtype": "Mandatory KYC and AML",
"exposure_direction": "outgoing",
"exposure_type": "direct",
"is_direct": true,
"amount_usd": 30000.75,
"percentage": 100,
"hops": 0,
"country": "US"
}
],
"counterparty_connections": [
{
"entity_name": "Tornado Cash",
"entity_type": "Mixer",
"entity_subtype": "OFAC SDN",
"risk_level": "CRITICAL",
"categories": [
"mixer"
],
"received_usd": 11580.2,
"sent_usd": 0,
"received_hops": 2,
"sent_hops": 0,
"percentage": 38.6,
"is_direct": false,
"country": "RU"
}
],
"report_signature": "3f9c2e1a7b4d6f80c5e9a1b2d3f4e5061728394a5b6c7d8e9f0a1b2c3d4e5f6"
}Authorizations
Body
The crypto address or network identifier to screen. Must match the selected network (e.g. a 0x-prefixed 40-hex-char address for EVM chains). Alias: address.
"0x28c6c06298d514db089934071355e5743bf21d60"
Asset / network identifier. One of: BTC, LIGHTNING, ETH, LTC, XRP, BCH, DOGE, TRX, SOL, MATIC, BNB, USDT, USDC. LIGHTNING requires an Elliptic or Chainalysis BYOK connection added through Marketplace. Alias: currency.
BTC, LIGHTNING, ETH, LTC, XRP, BCH, DOGE, TRX, SOL, MATIC, BNB, USDT, USDC "ETH"
Optional. Whether the address is being screened as an inbound (deposit) or outbound (withdrawal) counterparty. Accepts inbound, outbound, deposit, or withdrawal. Defaults to a neutral pre-transfer screen when omitted. This is passed to the provider as context only; it does not change the returned risk_score, severity, or the source_of_funds/destination_of_funds breakdowns, which are always both returned regardless of direction. Changing or omitting direction therefore does not require re-screening an address.
inbound, outbound, deposit, withdrawal Response
The normalised wallet screening result.
Provider that performed the screening (e.g. merklescience, crystal).
Always WALLET_SCREENING for this endpoint.
WALLET_SCREENING Normalised 0-100 risk score. Higher means greater exposure to risky entities.
Risk bucket derived from risk_score: 0-9 UNKNOWN, 10-39 LOW, 40-69 MEDIUM, 70-89 HIGH, 90-100 CRITICAL. UNKNOWN is the lowest band, not a separate no-data state: risk_score 0 (the common clean-address case) means no adverse assessment, while a non-zero score in the 1-9 range is a real but sub-LOW signal - read the risk_score, not just the band. Never treat UNKNOWN as an affirmative low-risk or clear rating; do not display it as a pass.
UNKNOWN, LOW, MEDIUM, HIGH, CRITICAL Screening outcome status.
SCREENED, PENDING, ERROR Human-readable summary of the screening result.
The screened address, echoed back.
The blockchain that was screened.
True if the address has direct or indirect sanctions exposure.
Highest-weighted high-risk category, or null when none is dominant (e.g. sanctioned, mixer, stolen_funds).
Where the address received funds from, attributed by entity. Each entry is an exposure breakdown.
Show child attributes
Show child attributes
Where the address sent funds to, attributed by entity. Same item shape as source_of_funds with exposure_direction = outgoing.
Show child attributes
Show child attributes
Direct and indirect counterparty entities with received/sent amounts and risk levels.
Show child attributes
Show child attributes
Opaque HMAC-SHA256 signature over this exact result, scoped to your application. Not meaningful on its own — repost the full response body, unmodified and including this field, to POST /v3/wallet-screening/pdf/ to render it as a PDF. The PDF endpoint rejects the request with 400 if report_signature is missing or if any signed field (e.g. risk_score, severity, sanctions_hit) was edited before repost.
Ranked explanation of risk_score: what produced this verdict. Providers grade an address on their own model and return only a verdict (Merkle Science returns an integer 0-5), so the score alone is not actionable. Ordered high-risk first, then by the value that moved through each driver, capped at the five strongest; source_of_funds and destination_of_funds always carry the complete breakdown. A high risk_score with no is_high_risk entry means the provider reported no sanctions or attributed-entity match and graded the address purely on its own exposure model - summary states this explicitly.
Show child attributes
Show child attributes