Documentation Index

Fetch the complete documentation index at: https://devdocs.veriff.com/llms.txt

Use this file to discover all available pages before exploring further.

AML Screening (legacy)

Prev Next

Available via API

Available via SDK

Needs configuration on Veriff's side

Needs a separate integration

Needs a solution-specific webhook

This article covers the legacy  AML Screening solution for existing customers.

If you are looking to sign up for the PEP & Sanctions solution, see the AML Screening (enhanced) article. Compared to the legacy solution, the enhanced AML Screening offers more customization options regarding which lists to screen against, how strictly names are matched and how results are filtered.

To upgrade to the enhanced solution, contact your Solutions Engineer.

These solutions can be used to meet and comply with Know-Your-Customer (KYC) and Anti-Money Laundering (AML) requirements.

It is available via API, web flow, and native SDKs.

Endpoints and webhooks used in this solution

You call:

Veriff sends:


Prerequisites

  • You have an integration set up with Veriff

  • You have the PEP & Sanctions checks configured by your Solutions Engineer

  • You have webhook(s) configured to get responses from Veriff (see the Webhooks section for info)

  • You can also opt in to use optional adverse media checks and ongoing monitoring solution


End-user data sources

The “end-user data sources” refer to different origins from which the end-user’s information can be collected for database verification. There are two data sources: initData and document data.

InitData

This is data that you provide when creating a verification session, i.e. the parameters you specify in the POST /sessions request.

Parameters that can be sent via initData are:

  • first name (required) in verification.person.firstName

  • last name (required) in verification.person.lastName

  • date of birth (optional) in verification.person.dateOfBirth

Date of birth info is used as part of screening data sent to do person search.

Document data

This is data that is extracted from the end-user’s document. Includes information like names, date of birth, etc.


Flow overview

The flow is a bit different, depending on whether you are using an IDV or non-IDV integration for the checks.

Using an IDV integration

This means that it is possible to run the identity verification checks related to document or document+selfie and the the PEP and Sanctions, Adverse Media and Ongoing Monitoring checks.

End-user’s data can be sent via both Veriff end-user flow and the API endpoints.

  1. Once the IDV integration is set up, generate a verification session using the regular POST /sessions endpoint

  2. After the end-user’s data has been passed and the session has been verified:

    1. The identity verification results are sent via decision webhook,

    2. The AML result will be sent in the Watchlist-screening webhook

      1. Veriff will send a new webhook if the ongoing monitoring reveals that the status of a verified person has changed

  3. You can:

    1. Query the results of AML checks from GET /sessions/{sessionId}/watchlist-screening endpoint. If you query it before screening completes, expect a 202 response.

    2. Query the results of IDV checks from GET /sessions/{sessionId}/decision endpoint

      1. This endpoint always returns 200. While the decision is still processing, verification is null; check for that instead of a status code

    3. Or view them in the Veriff Customer Portal

Using a non-IDV integration

This means that it is possible to run only the PEP and Sanctions, Adverse Media and Ongoing Monitoring checks. End-user’s data can be sent only via the API endpoints.

  1. Create a new session using the API keys and the baseURL of the integration you are using for the AML solution (see the API Documentation and reference how to find these). Include the following fields in the request:

    1. first name (required) in verification.person.firstName

    2. last name (required) in verification.person.lastName

    3. date of birth (optional) in verification.person.dateOfBirth

Click to see the minimum request payload sample needed to start a session

1.1 Include the API URL and mandatory headers

POST {baseURL}/v1/sessions
Type: object
Headers:
       X-AUTH-CLIENT: string (required) = API key
       Content-Type: application/json

1.2 Add the following data into the minimum payload

  • verification: object Verification object

    • person: object

      • firstName: string*

      • lastName: string*

      • dateOfBirth: string

*Required parameter

Request payload sample

curl -X POST \
  --url '/v1/sessions/' \
  -H 'Content-Type: application/json' \
  -H 'X-AUTH-CLIENT: API-KEY' \
  -d '{
    "verification": {
        "person": {
            "firstName": "Eva",
            "lastName": "Nováková",
            "dateOfBirth": "1980-02-21"
        }
    }
}'

  1. Change the status of the session to submitted using the PATCH /sessions/{sessionId} endpoint

  2. Receive the results from Veriff via Watchlist-screening webhook, query the results from GET /sessions/{sessionId}/watchlist-screening endpoint, or view them in the Veriff Customer Portal

    1. If you have set up the decision webhook, it will return session info, for example decision time, attempt id, and session status; but as no IDV checks were made, most of the fields will be null

    2. If you query the GET /sessions/{sessionId}/watchlist-screening endpoint right after submission, expect a 202 response while screening is still in progress.


Understanding the screening result

Here is the general shape of the screening result as returned by the GET /sessions/{sessionId}/watchlist-screening endpoint:

{
  "data": {
    "reviewStatus": "no_match | potential_match | reviewed",
    "totalHits": 0,
    "hasUnacknowledgedChanges": false,
    "hits": [ /* ... */ ]
  }
}

The reviewStatus field

The reviewStatus field is the primary outcome indicator of the AML/PEP screening. It directly answers the compliance question "Is this person flagged on any watchlist, and has that flag been resolved?"

Note that in the GET /sessions/{sessionId}/watchlist-screening endpoint's response, this field is nested inside a data object (data.reviewStatus); in the watchlist-screening webhook payload, it appears at the top level, without the wrapper.

The field has three possible values:

  • no_match: the person was not found in any of the configured lists/databases. The hits array is empty.

  • potential_match: the person was found in one or more listings/databases, and at least one hit has not been reviewed yet. The hits array is populated with data about the person.

  • reviewed: the person was found, and every hit has a review decision recorded. This is not permanent: if ongoing monitoring later detects a change, reviewStatus reverts to potential_match until you acknowledge the change and review any new hits (see Managing screening results below).

Deprecated: the matchStatus field (possible_match / no_match) is deprecated. Use reviewStatus instead.

totalHits shows the total number of hits returned by the check.

Each entry in hits also includes:

  • id: unique identifier of the hit. Use it to submit a review decision via the PATCH endpoint, see Managing screening results below.

  • matchStatus: the review decision for that specific hit, one of false_positive, potential_match (default until reviewed), true_match, inconclusive.

  • riskLevel: risk assessment for the hit, one of low, high. Present only when the hit's matchStatus is true_match.

hasUnacknowledgedChanges indicates whether ongoing monitoring has produced changes you have not yet acknowledged, see Managing screening results below.

This is independent from the session decision (approved/declined), which is driven by IDV checks.

The confidence in the screening result is higher when combined with IDV, because the screening data was extracted from a verified document. In standalone mode, the accuracy of the screening depends on the quality of the data you input.

If you require more data, you can use the relevant sessionId and query the GET /sessions/{sessionId}/person endpoint to find more detailed info about the match. Look for data in the person.pepSanctionMatches array. Its structure is different from the hits array documented above, see the GET /sessions/{sessionId}/person reference for the field list.

Possible session outcomes

The examples below show the API response format, where fields are wrapped inside a data object. The watchlist-screening webhook payload contains the same fields at the top level, without the data wrapper, see the webhook's sample payloads for the full webhook format.

Session approved + reviewStatus: no_match

This is the ideal outcome. The end-user's identity was verified successfully and they were not found on any PEP/Sanctions/Adverse Media lists. You can proceed with onboarding, no further AML action needed.

Click to open an API response excerpt

{
  "data": {
    "reviewStatus": "no_match",
    "totalHits": 0,
    "hasUnacknowledgedChanges": false,
    "hits": []
  }
}

Session approved + reviewStatus: potential_match

The end-user's identity is verified (the document and selfie are genuine), but they were found on one or more watchlists, and at least one hit has not been reviewed yet. Veriff only flags potential matches, you retain decisioning responsibility. Therefore, you need to perform manual review:

  • Review the hits array to examine the matched listings (source names, URLs, match types, etc.), including each hit's id.

  • Determine whether each hit is a true match or a false positive (e.g., common name coincidence).

  • Submit your review decision for each hit via the PATCH endpoint, see Managing screening results below.

Click to open an API response sample, showing the full hit shape

{
  "data": {
    "attemptId": "54233318-f81c-4ec4-8e4c-413168a3f5e6",
    "sessionId": "f04bdb47-d3be-4b28-b028-a652feb060b5",
    "vendorData": "12345678",
    "endUserId": "a1b2c35d-e8f7-6d5e-3cd2-a1b2c35db3d4",
    "checkType": "initial_result",
    "matchStatus": "possible_match",
    "reviewStatus": "potential_match",
    "hasUnacknowledgedChanges": false,
    "monitorStatus": "enabled",
    "searchTerm": {
      "name": "Mirko Kokki",
      "year": "1960",
      "lists": [
        "SANCTIONS",
        "PEP_CLASS_1",
        "PEP_CLASS_2"
      ],
      "countries": [
        "GB",
        "US",
        "FR"
      ],
      "exactMatch": false,
      "matchThreshold": 80,
      "excludeDeceased": true
    },
    "totalHits": 5,
    "createdAt": "2021-06-02T11:04:00.287Z",
    "hits": [
      {
        "id": "4KJL9THDX9ZNV4W",
        "matchStatus": "potential_match",
        "matchedName": "Miro kokkino",
        "countries": [
          "Australia",
          "Brazil"
        ],
        "dateOfBirth": "1960",
        "dateOfDeath": null,
        "matchTypes": [
          "aka_exact"
        ],
        "aka": [
          "Kokki Mirko",
          "Mirko Kokki"
        ],
        "associates": [
          "Desmon Lamela",
          "Fred Austin"
        ],
        "listingsRelatedToMatch": {
          "warnings": [
            {
              "sourceName": "FBI Most Wanted",
              "sourceUrl": "http://www.exampleUrl.com",
              "date": null
            }
          ],
          "sanctions": [
            {
              "sourceName": "Example Source",
              "sourceUrl": "https://www.exampleURL2.com",
              "date": null
            },
            {
              "sourceName": "Example Source 2",
              "sourceUrl": "https://www.exampleURL3.com",
              "date": null
            }
          ],
          "fitnessProbity": [
            {
              "sourceName": "Example Source 3",
              "sourceUrl": "https://www.exampleURL4.com"
            }
          ],
          "pep": [
            {
              "sourceName": "Example Source 4",
              "sourceUrl": "https://www.exampleURL5.com"
            }
          ],
          "adverseMedia": [
            {
              "date": "2020-09-23T00:00:00Z",
              "sourceName": "Example Source 5",
              "snippet": "Sang Tan Judges in the High Court in London have ruled that Saleh Ibrahim Mabrouk, a former aide of Libyan leader Colonel Muammar Gaddafi, was partly to blame for the murder of PC Yvonne Fletcher. The gunman",
              "sourceUrl": "https://www.exampleURL6.com"
            }
          ]
        }
      }
    ]
  }
}

Session approved + reviewStatus: reviewed

This state only tells you that every hit already has a review decision. It does not tell you what that decision was. Unlike no_match, a reviewed session is not automatically "clean": always check the per-hit outcome before proceeding.

Check the per-hit matchStatus (and riskLevel, where present) in the hits array to see the actual outcome of each review:

  • If every hit was reviewed as false_positive, no further AML action is needed.

  • If any hit was reviewed as true_match, apply your own risk-based decision depending on your regulation and requirements (decline the end-user, apply enhanced due diligence, or escalate), informed by that hit's riskLevel.

  • If a hit was reviewed as inconclusive, make a risk-based decision in line with your own policy and regulatory obligations about what additional verification is needed to determine whether this is a true match.

  • If the hit it still shows potential_match after review, then the hit has not yet received a conclusive review. Treat it as unresolved until it moves to one of the statuses above.

reviewed is also not a permanent state. If ongoing monitoring later detects a change, hasUnacknowledgedChanges becomes true and reviewStatus reverts to potential_match, even if every hit had already been reviewed. See Managing screening results below.

Click to open an API response excerpt

Same hit as above, now reviewed (fields unrelated to the review decision are omitted here; see the full example above).

{
  "data": {
    "reviewStatus": "reviewed",
    "hits": [
      {
        "id": "4KJL9THDX9ZNV4W",
        "matchStatus": "true_match",
        "riskLevel": "high"
      }
    ]
  }
}


You can get the data from three sources:

Webhook payload

  1. Check the decision webhook for the identity verification results

  2. Check the watchlist-screening webhook for AML checks results

  1. Check the watchlist-screening webhook for AML checks results

  2. If you have set up the decision webhook, you can check it for session info (note that as no IDV checks were made, most of the fields will be null)

API call response payload

You can use the GET /sessions/{sessionId}/watchlist-screening endpoint, which contains the same data as the watchlist-screening webhook, wrapped inside a data object (see The reviewStatus field above).

Screening can take a few seconds to minutes to complete after session submission, so the endpoint can return:

  • 200: screening results are ready, either matches were found or not

  • 202: screening is still in progress. Wait a few seconds and retry the request

  • 402: PEP & Sanctions screening is not enabled for your integration. Contact your Solutions Engineer

Veriff Customer Portal

You can find the verification session related info, including the decision, in the Veriff Customer Portal, under the Verifications tab.

See Review verification in Veriff Customer Portal about how to view the session info in the Veriff Customer portal


Status and reason codes

For an approved session, see the verification.code and verification.status parameters.

If the session was declined or resubmission_requested, you can find additional information by checking the verification.status, verification.code, verification.reason and verification.reasonCode data objects.

For more info about the codes you are seeing, refer to:


Managing screening results

Use the PATCH /sessions/{sessionId}/watchlist-screening endpoint to record a review decision on a hit, acknowledge monitoring changes, or disable ongoing monitoring for a specific end-user, identified by sessionId.

These three operations are mutually exclusive per request. Each request must contain exactly one of hit, hasUnacknowledgedChanges, or monitorStatus. To perform more than one, send separate requests. Sending more than one field in the same request results in a 400 error.

Review a hit

Submit your review decision for a specific hit in the hits array:

{
  "hit": {
    "id": "4KJL9THDX9ZNV4W",
    "matchStatus": "true_match",
    "riskLevel": "high"
  }
}
  • hit.id: the hit's id, from the GET /sessions/{sessionId}/watchlist-screening response.

  • hit.matchStatus: your review decision, one of false_positive, potential_match (default until reviewed), true_match, inconclusive.

  • optional hit.riskLevel: only accepted when matchStatus is true_match, one of low, high. Must not be sent for any other matchStatus value.

A hit's matchStatus can be changed at any time; there is no restriction on which transitions are allowed, for example from true_match back to false_positive if you need to revise an earlier decision.

Once every hit in the hits array has a review decision, reviewStatus changes to reviewed, and Veriff sends an updated watchlist-screening webhook to reflect this.

If ongoing monitoring later detects a change, hasUnacknowledgedChanges becomes true again and reviewStatus reverts to potential_match, even if every hit was previously reviewed. Acknowledge the change and review any new hits to return to reviewed.

Acknowledge monitoring changes

If ongoing monitoring detects a change, hasUnacknowledgedChanges becomes true. Acknowledge it with:

{
  "hasUnacknowledgedChanges": false
}

Only the value false is accepted.

Disable monitoring

  1. If unsure whether monitoring is enabled, check the monitorStatus parameter in the GET sessionId/watchlist-screening response payload.

  2. If monitorStatus is enabled or empty, set it to disabled using the PATCH /sessions/{sessionId}/watchlist-screening endpoint:

    {
      "monitorStatus": "disabled"
    }
    

    If monitoring is already disabled, the endpoint returns a 400 error:

    {
      "status": "fail",
      "message": "Watchlist screening is already disabled"
    }
    

  3. If you wish to re-enable ongoing monitoring for an end-user, contact your Solutions Engineer.

All three operations require endpoint-level HMAC signature authentication.


FAQ

Can I review hits in the Veriff Customer Portal?

No. Hit review, acknowledging monitoring changes, and disabling monitoring are currently only available via the API endpoints described above.

Can I submit review decisions for multiple hits in a single request?

No. Submit one PATCH request per hit.

Can I change a hit's review decision after submitting it?

Yes. A hit's matchStatus can move to any other value, for example from true_match back to false_positive, if you need to revise an earlier decision.

Does reviewing all hits mean the session stays reviewed permanently?

No. If ongoing monitoring detects a new change, hasUnacknowledgedChanges becomes true again and reviewStatus reverts to potential_match, even if every hit had already been reviewed. Acknowledge the change, and review any new hits, to return to reviewed.

If I already use the PATCH endpoint to disable monitoring, do I need to change anything?

No. It is the same endpoint, extended with additional optional fields. Existing integrations that only send monitorStatus continue to work unchanged.


Additional info

→ Log in to your Veriff account to see the PEP, Sanctions, Watchlists, and Adverse Media & Information checks[↗] article in Veriff Knowledge Base for more information about the Anti-Money Laundering solutions

Log in to your Veriff account to see What is PEP?[↗] article in Veriff Knowledge Base for more detailed insight into Politically Exposed Persons


Changelog

Date

Description

Jul 8, 2026

  • reviewStatus added as the primary screening outcome field, replacing deprecated matchStatus.

  • "About matchStatus field" renamed to "Understanding screening results”.

  • Per-hit id, matchStatus, and riskLevel added to the hits array.

  • hasUnacknowledgedChanges and totalHits added.

  • "Disabling ongoing monitoring for a specific end-user" expanded and renamed to "Managing screening results," covering hit review, acknowledging monitoring changes, and disabling monitoring.

  • Added "Endpoints and webhooks used in this solution" section, replacing the earlier two-webhook mention with a combined list of the endpoints called and webhooks sent for this solution.

  • Added a FAQ section.

May 19, 2026

Legacy solution note added

Jan 9, 2026

Added Disabling ongoing monitoring for a specific end-user section

Jun 6, 2025

Heading “Article versioning” changed to “Changelog”

March 20, 2025

“Using a non-IDV section” and “Webhooks payload” section updated with info about  the decision webhook in sessions done with non-IDV integration

March 12, 2025

Documentation published