Sanctions-screen a name against the OFAC, EU and UN lists
OFAC SDN and Consolidated, the EU and UN lists screened in full with aliases — named match types, a dated snapshot, and no counterparty data leaving the service.
By Matthias Begot · · Updated
An agent about to onboard a supplier, pay a beneficiary or sign a contract has to
answer one question first: does this name appear on the official designation
lists? GET /screen/entity answers it against four
lists in full — OFAC SDN, OFAC Consolidated, the EU financial sanctions list
and the UN Security Council list — comparing every name each list publishes,
primary names and aliases. Every hit carries the list that published it, its
programmes and its designation date; the verdict is hit, weak_hit or
no_hit, and the match is described by a named type from a closed set, never
an opaque score. The reason that last point matters more than it sounds: an agent
cannot act on a similarity percentage, but it can branch on “this was the list’s
primary name” versus “two tokens overlapped”.
OFAC’s own free tool tells automated systems to stay away
The obvious objection to a paid screening call is that OFAC publishes a free search tool. OFAC has answered that objection itself, and the answer is unambiguous:
Sanctions List Search is a free tool provided by OFAC to assist the public in complying with sanctions programs. It is intended to be used by individual users that are looking for potential matches on OFAC’s sanctions lists. It should not be utilized by automated systems that are configured to continually run searches through the tool.
An autonomous agent is precisely an automated system configured to continually run searches. The FAQ’s own remedy is to work from the published data files instead — which is exactly what this endpoint does: the four lists are ingested into a local snapshot and queried there.
There is a second reason not to point automation at that tool, and OFAC states it
too. The web tool’s fuzzy logic combines
Soundex and Jaro-Winkler with a newer algorithm,
and OFAC warns that “users are to advised that they are using a free service at
their own risk”, recommending baseline re-testing whenever the tool changes.
Phonetic scoring that the provider may re-tune is a poor foundation for a control
an agent runs unattended. GET /screen/entity takes the opposite approach:
deterministic matching, no edit distance, no phonetics, on a normalized form
that is returned to you in query.normalized so the comparison is reproducible.
Four lists, because a designation you do not screen is a designation you miss
A checker built around the SDN list answers a narrower question than the one an agent has to act on. An entity designated by the EU and not by OFAC is a hit on one list and a silence on the other — and inside the EU, acting on that silence is now a criminal-law problem, not just a policy one: Directive (EU) 2024/1226 set minimum rules criminalising the violation and circumvention of Union restrictive measures across all member states, with a transposition deadline of 20 May 2025.
Aliases are the other half of the coverage problem. Screening only primary names misses the names a designated party actually trades under. Here, aliases are first-class: they produce their own hits, each sourced to the list that published them.
The match type is the part an agent can actually branch on
A live capture makes the point better than any description. Screening
Kim Jong Un returns 10 matches, and exactly one of them is the person you
were thinking of:
list_source | matched_name | match_type |
|---|---|---|
| OFAC-SDN | Jong Un KIM | all_tokens |
| OFAC-SDN | Yo Jong KIM | partial_tokens |
| OFAC-SDN | Jong Man KIM | partial_tokens |
| EU-FSF | Jung Jong Kim | partial_tokens |
| UN | KIM JONG SIK | partial_tokens |
| … | … | partial_tokens |
Nine of the ten are other people named Kim. A scoring engine would hand back ten rows and a number; here the distinction is named in the data, and it lines up with OFAC’s own procedure for assessing a match, whose third step is blunt: “Is just one of two or more names matching (i.e., just the last name)? If yes, you do not have a valid match.”
The enumeration is closed and ordered by severity — exact, exact_alias,
exact_weak_alias, all_tokens, partial_tokens — and verdict_basis tells
you which types actually drove the verdict. Nothing else exists; there is no
hidden score behind them.
Filters remove candidates; they never manufacture confidence
Adding birth_year=1984 to the same query narrows those 10 matches to 3,
keeping Jong Un KIM (OFAC-SDN, programme DPRK3, designated 2016-07-06, birth
date published as 08 Jan 1984). The two survivors alongside it are instructive:
their lists publish no birth date at all, and they are kept anyway.
That is the deliberate rule for every filter — kind, country, birth_year.
A filter only ever removes candidates, and only on data the list published in a
comparable form. An entity whose country the list never published stays a
candidate. A false negative in this domain costs far more than one candidate too
many.
Weak aliases: OFAC’s position, and the flag that encodes it
OFAC flags some aliases as weak — “a relatively broad or generic alias that may generate a large volume of false hits”, such as nicknames, noms-de-guerre and common acronyms (FAQ 122) — and is explicit about what it expects you to do with them:
OFAC does not expect that persons will screen for weak AKAs, but expects that such AKAs may be used to help determine whether a “hit” arising from other information is accurate.
The include_weak parameter encodes exactly that. Weak matches — a source-flagged
weak alias, or partial token coverage — are always returned in hits[], so
you can use them to corroborate a hit the way OFAC describes. The flag decides
only whether they count towards verdict: left at its default, a name matched
only weakly comes back weak_hit; set to true, the same call returns the
same hits with hit. It is a caller policy, not a property of the name, and
it can only make the service stricter — never blinder.
no_hit is a paid answer, and it says what it was rendered against
The x402 golden rule is that the agent pays for the answer to its question.
“This name matches nothing on these lists, as of this date” is an answer, and a
valuable one — it is the record that says the check ran. It is an HTTP 200,
and it is billed. The 4xx range is reserved for requests the service cannot
answer: a missing name, or one outside 2–200 characters.
A negative answer is only worth storing if it states its own scope, so
lists_screened and the snapshot date come back on every verdict, no_hit
included:
{
"query": { "name": "Melli Bank Investment Holding",
"normalized": "melli bank investment holding" },
"verdict": "weak_hit",
"verdict_basis": ["partial_tokens"],
"total_matches": 2,
"truncated": false,
"lists_screened": [
{ "list": "EU-FSF", "entities": 6234 },
{ "list": "OFAC-CONS", "entities": 481 },
{ "list": "OFAC-SDN", "entities": 19199 },
{ "list": "UN", "entities": 1011 }
]
}
Those counts are not decoration — they move. The same fields captured for the
endpoint documentation a few weeks earlier read 6017
and 19157: the EU list gained over two hundred entries and OFAC’s SDN list more
than forty in the interval. A screening verdict without a date and a list
inventory attached is an assertion about a world that has since changed. The
provenance block carries freshness.kind: "snapshot" and the as_of date that
determined the verdict, and it is the field to persist next to the answer.
Two related honesty rules travel with the response. The verdict always covers
all matches, never just the ones returned: hits are capped at 50 per answer, and
when the cap applies, total_matches reports the true number and truncated says
so — truncation never softens a verdict. And no cross-list reconciliation is
performed: an institution designated by two authorities comes back as two hits
with two programme sets and two designation dates, because merging them into one
entity is a judgement, not data.
Nothing about your counterparty leaves the service
Because the lists are ingested into a local snapshot, the lookup is purely local: no third-party call, response in milliseconds, and no data about the name you screened leaving the service. For an agent screening customer or supplier names on your behalf, that is a property worth checking before you wire in any provider — a screening query is itself sensitive, and most of the market answers it by forwarding your counterparty’s name to someone else.
Screening a book of names in one settlement
Onboarding a supplier file, clearing a payout list, or re-screening a customer
base after a lists update is the same call at a different shape:
POST /screen/entity/batch takes up to 200
names and settles them as one x402 payment, with one sourced verdict per
name plus a summary of the counts. lists_screened, limits and provenance
are stated once for the whole batch — every item was screened against the same
snapshot in the same call, which is exactly what makes the batch auditable as a
single event.
A malformed name is flagged at its position with its own error code and does
not fail the batch: a body with three good names and one one-character entry is a
200 carrying three verdicts and one INVALID_INPUT at index 3. include_weak
is a batch-level flag by design — it states what you count as a signal, which is
a property of your policy rather than of any one name.
Where it fits in the agent’s flow
- Before the money exists. For a transfer, screening the beneficiary name is
one of four checks that belong together;
GET /preflight/paymentruns this endpoint alongside IBAN validity, bank identification and bank/jurisdiction screening, and returns one verdict from all of them in a single settlement. - Before the relationship exists. For onboarding,
GET /preflight/supplierattaches the same name screening to company identity, insolvency events and VAT status. - For a
payTorather than a party.GET /screen/addressscreens a crypto address against the same lists — the relevant check when the counterparty is a wallet, including the one an x402 challenge asks you to pay.
The payment side is the ordinary discover → 402 → pay → replay cycle; the
Quickstart walks it with runnable snippets and
For agents covers the discovery surfaces. No price appears
in this article: the gateway’s /catalog is
the single source of truth for every amount and every accepted rail, the batch
route included.
What it will not do
- A
no_hitis not a clearance certificate. It is a dated statement about four named lists, and it never replaces your own AML obligations. - No ownership analysis. Names are screened as published. An entity that is not itself listed does not become a hit because a designated party owns it — OFAC’s 50 Percent Rule is an analysis over ownership data, and this endpoint does not perform it.
- No PEP screening and no adverse media. Neither is a designation list.
- No transaction analysis and no risk score. There is deliberately no number to threshold; there are named match types and a verdict you can recompute from the hits.
- Lookup by name only. There is no search by registration number, and no approximate or phonetic search — matching is deterministic on purpose.
That scope statement travels with every response in data.limits, so the agent
and its auditor read the same sentence. For the full parameter contract, the
field-by-field reference, the match-type semantics and the error codes, see the
GET /screen/entity documentation.