> ## Documentation Index
> Fetch the complete documentation index at: https://docs.go.aiinsurance.io/llms.txt
> Use this file to discover all available pages before exploring further.

# Overview

> Run OFAC sanctions screenings on exposures and read their results

An exposure can be screened against OFAC sanctions lists through one action
endpoint:

| Method | Path                                        |
| ------ | ------------------------------------------- |
| `POST` | `/api/v1/companies/{companyId}/ofac/screen` |

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.

## What you can and cannot send

The values to screen — name, subject type, date of birth, address, identity
documents and the rest — are yours. The server copies nothing from other
exposure fields: it screens exactly what you send, or exactly what the exposure
already holds when you omit `requestValues`.

The carrier's own users see one convenience this API does not have: an empty
name box on the screening card starts out holding the exposure's name, which
they can overwrite before running. That is a form affordance in their browser,
not a server rule — **this endpoint screens when you call it and at no other
time**, and nothing about your writes triggers a screening. An exposure you
create or update through the API is not screened until somebody asks.

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:

| Field              | Answers                                                                        |
| ------------------ | ------------------------------------------------------------------------------ |
| `status`           | Did the call happen? `completed` or `failed`.                                  |
| `screeningOutcome` | What did the provider return? `noMatches` or `matches`.                        |
| `reviewOutcome`    | What did a human conclude? `notRequired`, `pending`, `cleared` or `confirmed`. |

"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.

## Importing exposures does not screen

Creating or updating an exposure through the entities API stores screening
request values like any other field data and runs **no** screening — no provider
call, no result. Screening happens only through this endpoint and through the
application UI.

This is deliberate. Screening on import is a decision we have deferred rather
than ruled out; until then, screen imported exposures explicitly.
