WidthDART
Sign In

API Reference

Browse and test Width AML API endpoints

Base URLhttps://api.trustin.bond

POSThttps://api.trustin.bond/api/v3/screen/kya

KYA Screen (v3)

Chainalysis-aligned address screening. Runs the same ruleset detection engine as the Screening page and returns a Chainalysis-compatible response (with our extensions). Sync (default) returns the full result; async returns a job_id to poll — mode=async responds with data:{job_id, type:'kya', status:'PENDING'}. Defaults to the builtin KYA ruleset when ruleset_id=0. Auth (required — anonymous calls are rejected): API key via ?apikey=, the X-Api-Key header, or Authorization: Bearer <JWT> (same as v2). Rate limit: up to 300 concurrent in-flight requests per endpoint; beyond that a request waits up to 60s for a slot, then returns HTTP 429 {"code":429,"msg":"out of max connections"} — back off and retry, or use mode=async for high concurrency (result polling is not rate-limited).

Request Parameters

chain_namestringrequired

Blockchain network

addressstringrequired

Wallet address to screen

tokenstring

Token type

inflow_hopsnumber

Inflow tracing depth (0–5)

outflow_hopsnumber

Outflow tracing depth (0–5)

min_timestampnumber

Start time filter (Unix ms). Omit for the full history. Narrowing the window makes the upstream investigation noticeably slower, so set it only when you need it

max_timestampnumber

End time filter (Unix ms). Default: current time

min_amountnumber

Minimum transfer amount to consider

max_nodes_per_hopnumber

Max nodes expanded per hop

force_time_sequenceboolean

Require every hop on a path to be no later than the one before it, so funds can only have moved forward in time. Paths are then read from the time-sequence layer, which is a strict subset of the raw one — expect fewer paths and a slower first run while the layer is built

ruleset_idnumber

0 = default builtin KYA ruleset

scoring_ruleset_idnumber

Scoring ruleset driving the fund-attribution score (ruleset_type=scoring). 0 = the user's own scoring ruleset, else the builtin default

cex_immuneboolean

Treat a plain CEX (exchange) deposit address as clean: returns no hits and score 0 instead of screening its history. A CEX that also carries other high-risk labels (e.g. Sanctioned CEX, Sanctions, Mixers) is still screened normally

force_runboolean

Re-run the investigation instead of reusing the one an identical earlier submit produced. gloomis dedups at the investigation level, so screening the same subject with the same parameters returns the earlier graph and misses anything that moved since. Costs a full investigation, so leave it off unless you need the chain re-read

modestring

sync returns the full result immediately; async returns a job_id to poll via Get Screen Result

Request Code
curl -X POST 'https://api.trustin.bond/api/v3/screen/kya?apikey=YOUR_API_KEY' \
  -H 'Content-Type: application/json' \
  -d '{
  "chain_name": "",
  "address": "",
  "token": "",
  "inflow_hops": 0,
  "outflow_hops": 0,
  "min_timestamp": 0,
  "max_timestamp": 0,
  "min_amount": 0,
  "max_nodes_per_hop": 0,
  "force_time_sequence": false,
  "ruleset_id": 0,
  "scoring_ruleset_id": 0,
  "cex_immune": false,
  "force_run": false,
  "mode": ""
}'

Run the request to see the response here.

Response Fields
addressstring

The queried wallet address

chainstring

Blockchain network (Ethereum / Tron)

riskstring

Our risk vocabulary: critical / high / medium / low

riskScorenumber

Numeric risk score (0–100), mapped one-to-one from riskLevel (higher = riskier): critical = 90, high = 80, medium = 60, low = 10. It is 0 only when no rule is triggered (riskLevel then defaults to "low") — so riskLevel "low" with riskScore 0 means clean / no hits, whereas riskScore 10 means a low-severity rule fired.

riskReasonstring

Human-readable summary of the highest-severity finding

clusterobject

Cluster attribution for the address (Chainalysis-style). Empty name/category when unresolved

addressTypestring

Address entity type (e.g. exchange, mixer). Empty string if unresolved

addressIdentificationsobject[]▲ hide

What the address IS — identity-level findings derived from self-hits (e.g. the address itself is sanctioned)

[].categorystring

Identification category (e.g. "Sanctions")

[].namestring

Short identification name

[].descriptionstring

Human-readable description

exposuresobject[]▲ hide

Aggregated exposure amounts by category and direction, derived from path hits

[].categorystring

Exposure category (e.g. "Sanctions", "Cybercrime")

[].directionstring

Fund flow direction: inflow or outflow

[].valuenumber

Exposure amount in token units

hitsobject[]▲ hide

Per-hit rule match detail with path evidence (our extension — not part of the Chainalysis spec)

[].ruleCodestring

Unique rule code (e.g. "KYA_SANCTION_EXPOSURE")

[].ruleNamestring

Rule name

[].categorystring

Rule category (e.g. "Sanctions", "Cybercrime")

[].riskLevelstring

Rule risk level: low / medium / high / critical

[].actionstring

Recommended action: block / review / alert / monitor

[].directionstring

Reserved direction field (empty for KYA self/path hits)

[].pathFlowstring

Path flow direction: inflow or outflow

[].hopsnumber

Number of hops from the risk entity to the target address

[].opponentAddressstring

The risk entity address at the other end of the path

[].maxAmountnumber

Maximum transfer amount on this path

[].pathNodesstring[]

Ordered address list from opponent → target

rulesTriggeredstring[]

Rule codes triggered across all hits

rulesetIdnumber

The ruleset ID used for detection

totalPathsnumber

Total number of fund paths analyzed

hitPathsnumber

Number of paths that matched at least one rule

inflowRiskAmountnumber

Contaminated inflow amount across unique hit inbound paths (token units)

inflowRiskRatenumber

inflowRiskAmount / total inflow path amount, range 0–1

outflowRiskAmountnumber

Risk outflow amount across unique hit outbound paths (token units)

outflowRiskRatenumber

outflowRiskAmount / total outflow path amount, range 0–1

scoreobject▲ hide

Fund-attribution risk score (资金占比评分). score = Σ (base × severity weight × fund ratio), where fund ratio is the deduped risky amount ÷ the address's total on-chain flow. Null when the graph had no flow totals.

.scorenumber

0–100 (null when denominators unavailable)

.verdictstring

accept / review / edd / block (banded: 0-20 accept, 20-50 review, 50-80 edd, 80-100 block)

.selfHitboolean

True when the subject itself is flagged (score = self-hit score × severity weight)

.components[]object[]

Per-cell breakdown: each = base × weight × ratio = points

.r1 / .r2 / .rOutnumber

Direct-in / indirect-in / out flow ratios (0–1)

.totalIn / .totalOutnumber

The on-chain token volume used as the denominator

.hitPaths / .riskyEdgesnumber

Hit path count / deduped risky edge count

scoreOverviewobject▲ hide

The address's on-chain activity behind the score: full token volume (the denominator) + tx counts + balance + activity window. Absent when the chain-volume fetch failed.

.addressstring

The screened address

.tokenstring

Token (usdt / usdc)

.inTotal / .outTotalnumber

Total token inflow / outflow

.inCount / .outCountnumber

Transfer counts in / out

.balancenumber

Current token balance (null when unavailable)

.firstTs / .lastTsnumber

Earliest / latest transfer timestamp (ms)

.truncatedboolean

True when the volume hit the provider page cap — the ratio is then conservative

Example Response

Response
{
"code": 0,
"msg": "success",
"data": {
"address": "TSz3nv8...",
"chain": "Tron",
"score": {
"score": 26.6,
"verdict": "review",
"selfHit": false,
"components": [
{
"direction": "in",
"hopBucket": "direct",
"severity": "critical",
"base": 80,
"weight": 1,
"amount": 185434.99,
"rawAmount": 185434.99,
"ratio": 0.266,
"points": 26.6
}
]
,
"r1": 0.266,
"r2": 0,
"rOut": 0,
"directAmount": 185434.99,
"indirectAmount": 0,
"outflowAmount": 0,
"totalIn": 696674.38,
"totalOut": 696674.38,
"hitPaths": 24,
"riskyEdges": 6
}
,
"scoreOverview": {
"address": "TSz3nv8...",
"token": "usdt",
"inTotal": 696674.38,
"outTotal": 696674.38,
"inCount": 58,
"outCount": 50,
"balance": 0,
"firstTs": 1694818383000,
"lastTs": 1781415093000,
"truncated": false
}
,
"subjectTags": [
{
"primaryCategory": "Sanctions",
"tertiaryCategory": "OFAC"
}
]
,
"hits": [
{
"ruleCode": "KYA_SANCTION_EXPOSURE",
"ruleName": "Exposure to sanctioned address",
"category": "Sanctions",
"riskLevel": "critical",
"action": "block",
"direction": "",
"pathFlow": "inflow",
"hops": 2,
"opponentAddress": "T...",
"maxAmount": 115776,
"pathNodes": []
}
]
,
"rulesTriggered": [
"KYA_SANCTION_EXPOSURE"
]
,
"rulesetId": 1,
"totalPaths": 8,
"hitPaths": 8,
"inflowRiskAmount": 0,
"inflowRiskRate": 0,
"outflowRiskAmount": 0,
"outflowRiskRate": 0,
"risk": "critical",
"riskScore": 90,
"riskReason": "Critical: Exposure to sanctioned address (KYA_SANCTION_EXPOSURE)",
"cluster": {
"name": "",
"category": ""
}
,
"addressType": "",
"addressIdentifications": [
{
"category": "Sanctions",
"name": "Address is a sanctioned entity",
"description": "..."
}
]
,
"exposures": [
{
"category": "Sanctions",
"direction": "inflow",
"value": 68223
}
,
{
"category": "Cybercrime",
"direction": "inflow",
"value": 53687
}
]
}
}