Sanctions and PEP screening
Korala screens a person or a company against the official sanctions lists you choose, and a person against Korala’s list of politically exposed persons (PEPs) and their family members, and tells you which listed entries may be them, how likely, and why. Screening runs on its own through the API, or as a step of a verification session, where the person’s identity document supplies the name, date of birth, nationality and document number.
News about a subject is a separate search: see Adverse media.
Korala gives no default opinion on which lists apply to you. You name the lists your obligations require, and your risk policy decides what a possible match or a match does.
The lists
| Key | List | Publisher |
|---|---|---|
eu_fsf | EU Consolidated Financial Sanctions List | European Commission |
ofac_sdn | Specially Designated Nationals and Blocked Persons List | US Treasury, OFAC |
ofac_consolidated | Consolidated Sanctions List (non-SDN) | US Treasury, OFAC |
uk_sanctions | UK Sanctions List | UK FCDO |
idb_sanctions | Sanctioned Firms and Individuals | Inter-American Development Bank |
korala_pep | Korala PEP list (see PEP screening) | Korala, from Wikidata and official rosters |
GET /api/v1/screening/sources returns each list with its active version,
the publication date the file states, when Korala last confirmed it, and
whether it is stale or needs an operator’s attention. A result that used a
list must credit it with the attribution text the endpoint returns.
Screen a subject
POST /api/v1/screening/runs
Idempotency-Key: 6f1d7c1e-onboarding-4411{
"subject": {
"name": "Testa Fictionaria",
"datesOfBirth": ["1984-03-17"],
"nationalities": ["IT"],
"identifiers": [{ "kind": "passport", "value": "YA1234567", "country": "IT" }]
},
"sources": ["eu_fsf", "uk_sanctions", "ofac_sdn"],
"reviewScore": 70,
"matchScore": 90
}| Field | Notes |
|---|---|
subject.name | Required, up to 300 characters, in any script. |
subject.aliases | Up to five other names: the name in its own script, a former name. |
subject.entityType | person or entity. Unset, both can match. |
subject.country | The country of the document the name comes from; it decides how a name in another script is read. |
subject.datesOfBirth | Up to three, as YYYY-MM-DD, YYYY-MM or YYYY. |
subject.nationalities | Up to five ISO 3166-1 codes; for a company, its country of registration. |
subject.identifiers | Up to ten: passport, national_id, registration_number or wallet. |
sources | Required. The lists to screen against, each once. |
reviewScore, matchScore | Whole numbers from 1 to 100, defaults 70 and 90; reviewScore must be below matchScore (equal scores are refused, 400; so is a reviewScore of 90 or more without a matchScore). |
riskSubjectId | Optional: a risk subject in the same environment to record the outcome on. |
Idempotency-Key is required. Retry with the same key and the same body to
get the same run; a different body with a used key returns 409. A test
API key screens in the test environment and sees only test runs.
The response is the run:
{
"id": "0b8c1f4e-2d7a-4c35-9a51-3f0e6d2b9c10",
"status": "possible_match",
"incomplete": false,
"incompleteReasons": [],
"errorCode": null,
"trigger": "api",
"sources": [
{
"key": "eu_fsf",
"versionId": "5e2f0a91-7c43-4b8e-a1d6-0c9b3e7f2a58",
"publishedAt": "2026-10-08T00:00:00.000Z",
"missing": false,
"stale": false,
"staleReasons": [],
"attention": null
}
],
"policy": { "reviewScore": 70, "matchScore": 90, "scorerVersion": "screening-score-v2" },
"riskSource": "korala:screening:eu_fsf+ofac_sdn+uk_sanctions:r70:m90",
"candidateCount": 12,
"topScore": 78,
"matches": [
{
"id": "9a7d3c2b-1e4f-4a6b-8c5d-2f1e0b9a8c7d",
"source": "eu_fsf",
"sourceEntryId": "123456",
"listedName": "Testa Maria Fictionaria",
"matchedName": "Testa Maria Fictionaria",
"score": 78,
"factors": [
{ "code": "all_subject_tokens", "points": 72, "detail": "Testa Maria Fictionaria" },
{ "code": "dob_same_year", "points": 6, "detail": "1984" }
],
"decision": "pending"
}
]
}candidateCount is how many listed entries were scored, and topScore the
highest of their scores (null when none was). When more than 200 entries
share a word with the name, those whose kind, dates of birth or
nationalities keep them below reviewScore are set aside without a score:
neither number counts them.
status | Meaning |
|---|---|
match | An entry scored at or above matchScore, or a reviewer confirmed one. |
possible_match | An entry scored at or above reviewScore. A person should look. |
clear | Every requested list was searched completely and nothing reached reviewScore, or every hit was marked a false positive. |
incomplete | Nothing reached reviewScore, but the screening was not complete. Never treat it as clear. |
error | The subject was not screened: no name with anything to search by (missing_name), none of the lists is loaded (no_lists), or the service is not configured or failed. Never treat it as clear. |
incomplete: true says the screening was not complete, and
incompleteReasons says why:
| Reason | Meaning |
|---|---|
source_missing | A requested list was not searched: unknown, switched off or never loaded. |
source_stale | A list is stale (see its staleReasons). |
source_attention | A list needs an operator’s attention. |
source_dropped_entries | The list version dropped entries its parser could not read (droppedEntries). |
source_reindex_pending | The list’s index had not yet been rebuilt for names one letter off (reindexPending): those were not searched on it. |
candidates_capped | More sanctions list entries that could reach review share a word with the name than are scored (200). An entry whose kind, dates of birth or nationalities keep it below review is not scored and does not count. |
pep_candidates_capped | The same for the PEP list, which has a pool of its own (1,000), so PEP entries never take the place of sanctions entries. |
name_terms_capped | The subject had more names (six, counting spellings without spaces), more identifiers (ten) or more search terms than are searched, or an identifier too long to search by. |
name_without_tokens | No name had a word to search by, only initials or similar. |
A possible match or a match in an incomplete run keeps its status.
A name may have at most 12 words; a longer one is refused. A name in Chinese, Japanese or Korean script written with spaces between its characters is also screened as written without them, and Chinese characters with no country to read them by are read as mainland China, Taiwan and Hong Kong romanise them.
A name alone reaches possible_match at most. A match needs the same day of
birth, a matching wallet address, or a document number that matches with the
same country beside a listed name that agrees with the subject’s
exactly: the same name, or every word of one name in the other, with no
word one letter off (an alias the list marks as weak counts, and the
match names it).
Decide a match
POST /api/v1/screening/matches/9a7d3c2b-1e4f-4a6b-8c5d-2f1e0b9a8c7d/decision
Idempotency-Key: review-9a7d3c2b-1{ "decision": "false_positive", "reason": "Listed person was born in 1951; passport says 1984." }Decisions are made by an organization owner or admin signed in to the
dashboard; API keys and members are refused with 403.
decision is confirmed or false_positive; the reason is required. The
run’s status is derived again from all its matches, every decision is kept in
the run’s audit trail with who made it, and a later decision can change an
earlier one.
GET /api/v1/screening/runs/:id reads one run; GET /api/v1/screening/runs
lists them newest first (page, limit up to 100, and filters status,
sessionId, riskSubjectId).
In a verification session
Add a check step to a workflow that runs after the identity document:
{
"type": "check",
"config": {
"kind": "pep_sanctions",
"provider": "korala_screening",
"providerConfig": { "sources": ["eu_fsf", "uk_sanctions"], "reviewScore": 70, "matchScore": 90 }
}
}The step reads the person’s identity document from the same session: the
name in Latin letters and as printed, date of birth, nationality and the
passport or national id number. A workflow is refused at save when
sources is missing, a score is out of bounds, or reviewScore is not
below matchScore; a step saved earlier with equal scores ends in
error with review recommended, never clear. The session check’s
providerRef is screening-run:<id>, and its status is match,
review_required (a possible match, or an incomplete run) or error.
Risk evidence
When the screened session has a risk subject (or an API run names one),
Korala records the fact screening.sanctions with value clear,
possible_match or match under the run’s riskSource, such as
korala:screening:eu_fsf+uk_sanctions:r70:m90. A run that screened the
PEP list also records screening.pep under its own source, such as
korala:screening:korala_pep:r70:m90:l12 (the last part is the
look-back), with value none, possible_pep, pep, former_pep or
family_member. A definite match (confirmed, or at or above matchScore)
gives its standing, pep before family_member; an open possible match on
a PEP or a family member gives possible_pep, which comes before
former_pep. A possible match on a former PEP gives former_pep at most. The
run’s riskSources lists each fact with its source. A PEP is never
recorded as a sanctions hit, and a problem with one kind of list (stale,
capped) does not make the other kind’s evidence unavailable. When the PEP
screening was incomplete, only pep and possible_pep are recorded; any
other value is unavailable, since a current PEP may be among the entries
not searched. A policy condition on a screening fact may name only the
values above: a misspelt one is refused when the policy is published. Accept each source in a
policy input for its fact, screening.sanctions or screening.pep (type
string), and decide in the
policy what each value does. Changing the lists or the scores of the step
changes the source, so the policy must be bound again. A run that could not
screen, or an incomplete run that found nothing, records the fact as
unavailable, which your policy treats as missing evidence.
Webhooks
| Event | When |
|---|---|
screening.run.completed | A run was recorded: run id, status, incomplete, error code, trigger, session and risk subject ids, match count. |
screening.match.found | The run has matches at or above reviewScore: each match’s id, entry id, list, listKind, score and, for a PEP match, pepStanding. |
Payloads never carry a name, a date of birth or an identifier; read the run for the matches. Deliveries are at least once. Decisions do not send an event; read the run after a decision.
What a run keeps
A run keeps a keyed digest of what was screened, not the name, the date of birth or the numbers: those stay in the session or in your own system. Matches keep the listed entry and the factors about it.
PEP screening
Add korala_pep to sources to screen for politically exposed persons,
on its own or beside sanctions lists. Each list has a listKind
(sanctions or pep), and each match says which kind it came from.
The PEP list is built by Korala from Wikidata and official rosters (parliaments, governments, EU institutions): heads of state and government, ministers, members of parliament, top judges, central bank boards, ambassadors, heads of international organisations and of state-owned enterprises, regional leaders, and the family members Wikidata links to them. Close associates are not included: no free source records them. Coverage differs by country; Korala publishes it per country rather than claiming global coverage.
A PEP match carries pep:
standing:pep(in office, or out of office for less than the look-back),former_pep(out of office for longer, withlastHeldUntil),family_member(withrelatedPeps: the PEP’s entry id, name, the relation, such asspouseorchild, and the PEP’s positions), ornone: a relative whose related PEPs are no longer PEPs on the day. Anonematch is shown with its relation, andscreening.peprecords no family member for it.flags:position_dates_unknownwhen no position states when it was held. Such a person is a PEP until a reviewer finds otherwise.positions: each with its category, title, country, start and end dates, whether the source says it is current, and the roster that states it.
The standing is judged on the day of the screening from the dates the list
states. A family member is one while a PEP it is related to is a PEP by the
same look-back. Following the EU AML Regulation (Article 2(1)(35)),
spouses, children and parents count for every PEP (the Regulation also names
registered partners and children’s spouses, which the list does not hold
yet); a sibling counts only for heads of state and government, ministers and
deputy ministers. pepLookbackMonths sets how long after leaving office a person
still counts as a PEP: at least 12, the minimum the EU AML Regulation
sets, and the default. It is accepted only with korala_pep.
{
"subject": { "name": "Erika Lindqvist-Moreau", "datesOfBirth": ["1972-03-14"], "nationalities": ["SE"] },
"sources": ["eu_fsf", "ofac_sdn", "korala_pep"],
"pepLookbackMonths": 18
}A PEP match makes the run a possible_match or match like any other, and
screening.pep says what was found. A PEP calls for enhanced due
diligence, not a refusal, so a check step never blocks on one: a finding
on the PEP list alone makes the step review_required at most, whatever
its score, and only a sanctions match makes it a match. Decide in your
risk policy what each standing does.
How well it finds people
Measured on 2026-10-10 with the default scores against the five lists:
- False hits: about 2% of ordinary customers reached
possible_match, most of them without a date of birth to compare; none reachedmatch. - Listed names: every listed entry sampled (798) reached review on its
own listed name; with the listed full date of birth, all reached
match, under aliases, names in their original script and reordered names too. - Spelling variants the transliteration rules do not fold are found about four times in five.
- A name one letter off (a letter changed, added or dropped, or two
neighbouring letters swapped, in a word of five letters or more) is
found at review when a date of birth or nationality agrees: for persons
with a listed date of birth about nine times in ten (measured
2026-10-12; before, one time in ten). Such a name alone never reaches
review at the default scores, and it never reaches
match, whatever match score you set: with a date of birth, a nationality or a document number it reaches review at most (a wallet address stays decisive). The match carries afuzzy_tokenfactor naming the listed spelling, and each list on the run gives thetermBuilderVersionit was searched with (3 and later find names one letter off). Two letters off is still missed, so check names that were typed by hand.
PEPs, measured on 2026-10-11 against the build of 2026-10-10 (78,119 entries), with a labelled set drawn from the list: every listed name, name in another script and reordered name was found at review in the 20 countries with most entries and Korea; with spelling changes and typos included, 92% to 99.7% per country (81% to 99% before names one letter off were matched). Of the current heads of state and government on the US World Leaders list, 91% are found by an entry from another source.
Not yet
Close associates of PEPs, adverse media and ongoing re-screening when a list changes are not part of screening yet.