Guides

AML screening

Verify any natural or legal person against global sanctions, politically-exposed-person (PEP) and watchlist data — whether or not they are a VirtuaBroker customer. Run an instant list check with just a name, run an identity-rich screening with a stored review lifecycle, and let continuous screening re-check your verified customers automatically as list data changes.

Audience server-side integrators API External API v1 One call to verify

You'll need workspace credentials and a bearer token — see the Authentication guide. AML endpoints are a workspace capability: a 403 (AllowanceError) means screening is not enabled for your workspace — contact your account manager.

Choosing the right tool

The API gives you three complementary ways to keep bad actors out, from a one-line check to fully automatic monitoring:

List check

POST /v1/aml-checks — instant, stateless: send a name (and optionally an identifier) and get the live list matches back, with scores and flags. Works for anyone — no account, no verification required. Every check is stored as history.

Screening

POST /v1/aml-screenings — identity-rich: send full identity details (date of birth, nationality, tax id) for a higher-precision outcome with a review lifecycle (CLEAR / POTENTIAL_MATCH / REVIEW_REQUIRED) and idempotent retries.

Continuous screening

Automatic — every customer who completes identity verification (KYC/KYB) is enrolled in ongoing re-screening. When list data changes, compliance reviews the match. No integration work needed.

Unknown is never clear. Across every AML endpoint, match is a tri-state: true = potential matches found, false = clear, null = the check did not run. Branch on match === false to grant a pass — never on "not true". A 503 outcome must be retried, not treated as a pass.

1 · Run a list check

POST /v1/aml-checks verifies a name against sanctions, PEP and watchlist data in a single call. The subject does not need to be a VirtuaBroker customer — this is verification-as-a-service for your own onboarding, your client portfolio, or any counterparty you need to vet.

POST /v1/aml-checks
curl https://api.virtuabroker.com/v1/aml-checks \
  -H "Authorization: Bearer $VB_TOKEN" \
  -H "Content-Type: application/json" \
  -d '{
    "id": "012345678A",
    "name": "El payaso Miliki",
    "reference": "client-check-456"
  }'
FieldNotes
nameREQUIREDFull name of the natural or legal person, 2–140 characters
idOPTIONALIdentifier for your records, 3–32 characters. A Spanish DNI/NIE/NIF/CIF is recognised and used to infer the subject type — a CIF searches companies, a DNI/NIE searches persons. Any other national identifier is accepted as-is.
entityTypeOPTIONALINDIVIDUAL · COMPANY — overrides the inference. When neither is known the check matches both kinds.
referenceOPTIONALYour correlation reference (≤64 chars), echoed back on the response

A clean subject comes back with match: false and an empty results array:

200 · clear
{
  "checkId": "3JyVix1grJsu1z64h047",
  "reference": "client-check-456",
  "status": "COMPLETED",
  "match": false,
  "matchCount": 0,
  "checkedAt": "2026-07-20T09:00:00.000Z",
  "results": []
}

A potential match returns the list entries, each with a similarity score and the reasons the entry is listed:

200 · potential match
{
  "checkId": "8kQpWv2xTzRb5cJd9eYf",
  "status": "COMPLETED",
  "match": true,
  "matchCount": 1,
  "checkedAt": "2026-07-20T09:01:00.000Z",
  "results": [
    {
      "matchId": "Q6070218",
      "name": "Pedro Sánchez",
      "type": "PERSON",
      "score": 1,
      "flags": ["PEP"],
      "title": "Prime Minister of Spain",
      "countries": ["ES"],
      "dateOfBirth": "1972-02-29"
    }
  ]
}
Result fieldMeaning
matchIdStable identifier of the matched list entry — de-duplicate repeat checks on it
typePERSON · COMPANY · OTHER (vessels and other listed assets)
scoreMatch strength 0–1 — name similarity against the list entry
flagsWhy the entry is listed: SANCTIONS · PEP · WATCHLIST · CRIME · OTHER
title, countries, dateOfBirthKnown role or position, associated countries (ISO 3166-1 alpha-2), and date of birth where the lists record them

results is capped at 20 entries, while matchCount always reports the true total. More than 20 hits on a name means the name is too generic — add more of it (full name rather than surname) and check again.

If the check cannot run, the response is a 503 with match: null, status: "FAILED" and a coded errors array (CHECK_NOT_COMPLETED). The failed check is stored too — retrieving it later returns the same honest FAILED view. Retry with a new check; never treat it as a pass.

2 · Retrieve a stored check

GET /v1/aml-checks/{checkId} returns a previously run check. Checks are visible only to the workspace that created them; repeat checks of the same subject each produce their own record, so your audit trail shows every verification with its timestamp.

GET /v1/aml-checks/{checkId}
curl https://api.virtuabroker.com/v1/aml-checks/3JyVix1grJsu1z64h047 \
  -H "Authorization: Bearer $VB_TOKEN"

Every check is evidence. Store the checkId next to the client record in your systems — when an auditor asks "was this person screened, and when?", the stored check answers with the exact timestamp and result.

3 · Run an identity-rich screening

When you hold more than a name, POST /v1/aml-screenings screens with the full identity — date of birth, nationality, tax identifiers — for a higher-precision outcome and a review lifecycle. Richer identity information produces higher-quality screening.

POST /v1/aml-screenings
curl https://api.virtuabroker.com/v1/aml-screenings \
  -H "Authorization: Bearer $VB_TOKEN" \
  -H "Content-Type: application/json" \
  -H "Idempotency-Key: onboarding-7f3a2b" \
  -d '{
    "entity": {
      "entityType": "INDIVIDUAL",
      "firstName": "John",
      "lastName": "Smith",
      "dateOfBirth": "1985-03-14",
      "nationality": "GB",
      "taxIdentificationNumber": "X1234567L",
      "taxIdentificationType": "NIE",
      "taxIdentificationCountry": "ES"
    },
    "reason": "ONBOARDING",
    "reference": "client-check-456"
  }'

Companies use entityType: "COMPANY" with companyName, companyRegistrationNumber and countryOfResidence. At least one name (or an identifier that resolves to a known account) is required.

200 · response
{
  "screeningId": "5mRtYu8wQaSd2fGh4jKl",
  "reference": "client-check-456",
  "status": "COMPLETED",
  "result": "CLEAR",
  "match": false,
  "potentialMatchCount": 0,
  "reviewRequired": false,
  "screenedAt": "2026-07-20T09:02:00.000Z"
}
statusresultMeaning
COMPLETEDCLEARScreening ran; no potential matches (match: false)
COMPLETEDPOTENTIAL_MATCHPotential matches require review (match: true, reviewRequired: true). A potential match is never a confirmed match.
COMPLETEDREVIEW_REQUIREDA match requires compliance review before proceeding (match: true)
NOT_COMPLETEDINSUFFICIENT_DATANot enough identity information to screen reliably (match: null) — see errors
— (HTTP 503)ERRORScreening could not be completed (match: null) — retry; never interpret as clear

Screenings summarise the outcome — result, match, counts. Raw match details are retained for compliance review and are not returned on this resource (the list check above is the endpoint that returns match details). Retrieve a screening later with GET /v1/aml-screenings/{screeningId}.

Idempotency. Send an Idempotency-Key header (≤128 chars) to make retries safe: replaying the same key returns the original screening; reusing a key with a different payload returns 409.

4 · Continuous screening — automatic

List data changes daily: people become PEPs, sanctions are added, watchlists grow. Continuous screening closes that gap with zero integration work:

Verification enrols

Every customer who completes identity verification (KYC or KYB — see the Identity guide) is automatically enrolled in ongoing re-screening.

Lists change, we re-check

Enrolled identities are re-screened continuously against updated sanctions, PEP and watchlist data — including a daily re-sync of recently changed profiles.

Matches go to review

A new potential match opens a compliance review. Confirmed risk is handled through your workspace's compliance process — you don't need to poll anything.

Continuous screening protects the customers you verify through the platform. For subjects you only ever check (no VirtuaBroker verification), re-run POST /v1/aml-checks on your own schedule — each call runs fresh against current list data and appends to history.

Error handling & best practices

Errors

HTTPCauseWhat to do
400Validation failed — name too short, unknown field, malformed bodyFix the field named in the response and retry; the request schema is strict
401Missing or expired tokenRe-authenticate and retry
403AllowanceError — AML screening is not enabled for this workspaceContact your account manager to enable the capability
404Unknown checkId / screeningId — or it belongs to another workspaceVerify the id; records are only visible to the workspace that created them
409Idempotency-Key reused with a different payload (screenings)Generate a fresh key per distinct request
503The check/screening could not be completed — match: nullRetry later. Never treat an incomplete check as a pass.

Best practices

Quick reference

EndpointPurpose
POST /v1/aml-checksInstant list check by name (+ optional id); returns match details; stores history
GET /v1/aml-checks/{checkId}Retrieve a stored check — your audit trail
POST /v1/aml-screeningsIdentity-rich screening with review lifecycle and idempotent retries
GET /v1/aml-screenings/{screeningId}Retrieve a screening summary
← Prev
Identity (KYC)