API reference

Base URL https://kycwire.com/api. Authenticate with Authorization: Bearer <key> (or X-API-Key). JSON in, JSON out. OpenAPI 3.1.

POST /v1/screen

Screen one name against every active list. Any script — Cyrillic, Arabic, CJK are transliterated and matched through name dictionaries, not just string similarity.

curl -X POST https://kycwire.com/api/v1/screen \
  -H "Authorization: Bearer kw_…" -H "Content-Type: application/json" \
  -d '{"name": "Владимир Путин", "type": "Person", "birth_date": "1952"}'
{
  "id": "5d1f…", "match": true, "top_score": 1.0,
  "matches": [{"id": "ofac_sdn-35096", "score": 1.0, "level": "likely", "caption": "Vladimir Vladimirovich PUTIN",
               "matched_name": "Vladimir PUTIN", "type": "Person", "source": "ofac_sdn", "programs": ["RUSSIA-EO14024"],
               "countries": ["Russia"], "birth_dates": ["1952-10-07"], "features": {"name_match": 1.0, "dob_year_match": 1.0}, …}],
  "candidates_considered": 50, "took_ms": 84, "datasets": {"ofac_sdn": {"version": 3, "published": "2026-08-28"}, …},
  "quota_remaining": 199
}
fieldtypenotes
namestringrequired (unless identifiers given), ≤ 300 chars
typePerson · Organization · Vessel · Airplaneoptional; omit to search all types
birth_dateYYYY, YYYY-MM, YYYY-MM-DDpersons; a mismatch lowers the score
countrystringnationality / registration country
identifiers[{type, value}]passport, national id, IMO, registration, tax number — exact match ranks first
threshold0.5–1, default 0.70.7 = possible, ≥ 0.85 = likely
sources[ofac_sdn, ofac_cons, eu_fsf, uk_fcdo, un_sc]restrict lists
storebool, default truefalse keeps only a hash of the query in your audit trail

Python

import requests
r = requests.post("https://kycwire.com/api/v1/screen", headers={"Authorization": "Bearer kw_…"},
                  json={"name": "Gazprom Neft", "type": "Organization"})
for m in r.json()["matches"]:
    print(m["score"], m["id"], m["caption"], m["programs"])

Node

const r = await fetch("https://kycwire.com/api/v1/screen", {method: "POST",
  headers: {"Authorization": "Bearer kw_…", "Content-Type": "application/json"},
  body: JSON.stringify({name: "Kim Jong Un", type: "Person"})});
const {match, matches} = await r.json();

PHP

$ch = curl_init("https://kycwire.com/api/v1/screen");
curl_setopt_array($ch, [CURLOPT_POST => true, CURLOPT_RETURNTRANSFER => true,
  CURLOPT_HTTPHEADER => ["Authorization: Bearer kw_…", "Content-Type: application/json"],
  CURLOPT_POSTFIELDS => json_encode(["name" => "Sberbank", "type" => "Organization"])]);
$result = json_decode(curl_exec($ch), true);

Go

body, _ := json.Marshal(map[string]any{"name": "Ayman al Zawahiri", "type": "Person"})
req, _ := http.NewRequest("POST", "https://kycwire.com/api/v1/screen", bytes.NewReader(body))
req.Header.Set("Authorization", "Bearer kw_…"); req.Header.Set("Content-Type", "application/json")
resp, err := http.DefaultClient.Do(req)

GET /v1/entities/{id}

Full record: every alias with strong/weak flag, programs, identifiers, addresses, first/last seen, source and licence.

GET /v1/screenings · GET /v1/screenings/{id} · GET /v1/screenings.csv

Your audit trail: what was checked, when, against which dataset versions, with what result. Paginate with ?before=<created_at>; export everything for your auditor as CSV with ?since=2026-01-01&until=2026-04-01.

GET /v1/datasets

Public. Record counts, publication dates and load times per list — the same data as /status.

GET /v1/usage · GET /v1/plans

Quota for the current month; plan limits.

Errors

Non-2xx responses carry {"error": {"code", "message", "docs"}}. Codes: missing_api_key, invalid_api_key, invalid_input, quota_exceeded, rate_limited, not_found.

Scores

Scoring is nomenklatura logic-v2 (the algorithm behind OpenSanctions): name similarity across scripts, identifiers, and penalties for conflicting birth date, gender or country. Sources and update times are in every response under datasets.