Skip to main content
An exposure can be screened against OFAC sanctions lists through one action endpoint: It submits the values you send to the sanctions provider, saves the normalized answer to the exposure, and returns it. It requires exposure.edit — running a screening writes to the exposure, and needs no separate authority.

Screening is advisory

A screening blocks nothing: not a save, a quote, a bind, an issue, or an import. What comes back is a list of potential matches — similarity hits against sanctions entries, for a person to review. A hit is never a determination that the party you screened is the party on the list.

The carrier turns screening on

Screening runs through a placed screening field, and placing that field is the only on-switch. The carrier’s configuration needs an exposure field of type Object: OfacScreening, single-cardinality, placed on a card with the OFAC Screening input modality. The fieldReferenceId you send names that field. A company with no such field has no screening: the endpoint returns 400 (ofac-screening-field-not-placed) and nothing is submitted to the provider. Read GET /entities/{entityType}/configuration to discover the field and the screening sub-fields the carrier has configured. The placement can also limit screening to some exposure types, by naming keys of the carrier’s Exposure Types option set in its exposureTypes argument; the configuration export shows it. An exposure of any other type is not screened at all: the endpoint returns 400 (ofac-screening-exposure-type-not-screened) and submits nothing, and writes to it never start a screening record or a screening. A screening it already holds is kept and still returned. A placement without the argument screens every type.

What you can and cannot send

The values to screen — name, subject type, date of birth, address, identity documents and the rest — are yours. This endpoint copies nothing from other exposure fields: it screens exactly what you send, or exactly what the exposure already holds when you omit requestValues. Writing an exposure is different: see Writes screen automatically. The sanctions lists, the match threshold and the provider are not yours to choose. They are fixed platform settings, recorded on every result so a reader knows what a saved screening covered. Sending sources or minScore is rejected with 400 rather than quietly ignored, so a caller can never believe it selected its own lists. requestValues replaces the stored request values rather than patching them: send the whole set you want screened, because the saved record has to say what was actually submitted. Omit it entirely to re-screen what the exposure already holds.

Reading a result

A result keeps three questions separate, because collapsing them into a single verdict loses information that matters: “The provider found nothing” and “a reviewer decided the hits were not this party” are different facts, so screeningOutcome and reviewOutcome never merge. A failed call is neither noMatches nor matches. A provider failure comes back as 200 with status: failed, not as an HTTP error. The failure is recorded on the exposure, where it stays visible; HTTP errors are reserved for requests that were refused. Review decisions are written through an ordinary entity update: set reviewDecision (and optionally reviewNote) on a match. The platform stamps reviewedBy and reviewedAt itself and recomputes reviewOutcome, so those are read-only. A screening or review made with an API key is attributed to External API in screenedBy / reviewedBy and in the app, not to the person who owns the key.

Staleness is a comparison, not a flag

Every result carries screenedRequest — a snapshot of the values actually submitted. A saved result describes those values, as of screenedAt, against the sanctions lists as they stood then. So there are two reasons a stored result may no longer be current, and you decide both:
  • The party changed. Compare the exposure’s current screening values against screenedRequest. If they differ, the result describes someone else.
  • The lists changed. Sanctions lists are updated frequently. A party cleared last month is not cleared today.

Retries and repeat calls

Every call is a fresh screening, and every call is billable. There is no idempotency key and no reuse of a recent result: a repeat request re-submits to the provider, and the new answer replaces the stored one — including any review decisions recorded against the previous run, which were about a different screening. This makes retrying safe. A call that timed out can simply be sent again, and because screening blocks nothing, nothing is stuck while you wait. It also means a retry loop costs a provider call every time it goes round, so retry a failed screening deliberately rather than automatically on a tight interval.

Writes screen automatically

For a company with screening placed, creating or updating an exposure, through the app, the entities API or an import, also screens it. The write fills a blank screening name with the exposure’s own name. If the exposure’s screening values have never been screened, or differ from the ones last screened, a screening then runs in the background, and its result is written to the exposure a few seconds after the write returns. The copy of an exposure embedded in a quote or submission is screened the same way, on its own values, unless the quote is bound. When an exposure and its copies hold the same values they share one answer, so only a run that calls the provider is billable. An exposure whose type the placement does not screen is never screened this way.