> For the complete documentation index, see [llms.txt](https://docs.voveid.com/docs/llms.txt). Markdown versions of documentation pages are available by appending `.md` to page URLs; this page is available as [Markdown](https://docs.voveid.com/docs/watchlist-screening/aml-screening.md).

# AML API reference

Create and review AML screening cases with an existing flow.

The AML API creates persistent screening cases with a status and audit trail.

AML routes use the unversioned API origin. Sandbox requests start with `https://api.voveid.net/aml`; Production requests start with `https://api.voveid.com/aml`. Send your private API key in the `x-api-key` header from your backend.

> A screening result is evidence, not a final compliance decision. Review possible matches according to your organization's policy.

## Configure AML flows

AML flows define which watchlists to search, whether the subject is an individual or entity, and the matching sensitivity. Create and manage flows in the VOVE ID dashboard under **AML Screening → Screening Flows**.

Use clear names such as “Standard individual screening” or “High-risk entity screening.” Before using a flow in Production, test it with approved sample data and confirm that its sources and matching settings meet your compliance requirements.

## Create an AML case

`POST /aml/case`

Creates a persistent AML case and runs the screening with an existing active flow. Use this workflow when you need to review matches, track the case status, or receive status webhooks.

### Request body

| Field                  | Type   | Required | Description                                        |
| ---------------------- | ------ | -------- | -------------------------------------------------- |
| `flowId`               | string | Yes      | ID of the active AML flow used for screening.      |
| `screeningData`        | object | Yes      | Person or entity data to screen.                   |
| `screeningData.name`   | string | Yes      | Full name of the person or entity.                 |
| `screeningData.dob`    | string | No       | Date of birth in `DD.MM.YYYY` format.              |
| `screeningData.gender` | enum   | No       | `male` or `female`.                                |
| `refId`                | string | Yes      | Your internal reference ID for tracking this case. |

```typescript
type AmlGender = 'male' | 'female';
type AmlCaseStatus = 'NO_MATCH' | 'IN_REVIEW' | 'CLEARED' | 'REJECTED';

interface CreateAmlCaseRequest {
  flowId: string;
  screeningData: {
    name: string;
    dob?: string;
    gender?: AmlGender;
  };
  refId: string;
}

interface AmlCase {
  id: string;
  flowId: string;
  screeningData: CreateAmlCaseRequest['screeningData'];
  status: AmlCaseStatus;
  refId: string;
  createdAt: string;
  updatedAt: string;
}
```

### Example request

```bash
curl https://api.voveid.net/aml/case \
  --request POST \
  --header "Content-Type: application/json" \
  --header "x-api-key: $VOVE_API_KEY" \
  --data '{
    "flowId": "507f1f77bcf86cd799439011",
    "screeningData": {
      "name": "John Doe",
      "dob": "15.03.1985",
      "gender": "male"
    },
    "refId": "customer-12345"
  }'
```

### Example response

```json
{
  "id": "507f1f77bcf86cd799439014",
  "flowId": "507f1f77bcf86cd799439011",
  "screeningData": {
    "name": "John Doe",
    "dob": "15.03.1985",
    "gender": "male"
  },
  "status": "IN_REVIEW",
  "refId": "customer-12345",
  "createdAt": "2024-01-15T10:30:00.000Z",
  "updatedAt": "2024-01-15T10:30:00.000Z"
}
```

The initial status is:

* `NO_MATCH` when the configured screening returns no matches.
* `IN_REVIEW` when a possible match requires manual review.

The response does not include sensitive hit details. Review possible matches in the dashboard.

## List AML cases

`GET /aml/case`

Returns a paginated list of your organization's AML cases. Filter by status or creation date to support review queues and reconciliation jobs.

### Query parameters

| Parameter   | Type            | Required | Default | Description                                        |
| ----------- | --------------- | -------- | ------- | -------------------------------------------------- |
| `page`      | number          | No       | `1`     | One-indexed page number.                           |
| `limit`     | number          | No       | `10`    | Number of cases per page.                          |
| `status`    | enum            | No       | —       | `NO_MATCH`, `IN_REVIEW`, `CLEARED`, or `REJECTED`. |
| `startDate` | ISO 8601 string | No       | —       | Include cases created at or after this time.       |
| `endDate`   | ISO 8601 string | No       | —       | Include cases created at or before this time.      |

### Example request

```bash
curl "https://api.voveid.net/aml/case?page=1&limit=20&status=IN_REVIEW" \
  --header "x-api-key: $VOVE_API_KEY"
```

### Example response

```json
{
  "data": [
    {
      "id": "507f1f77bcf86cd799439014",
      "flowId": "507f1f77bcf86cd799439011",
      "screeningData": {
        "name": "John Doe",
        "dob": "15.03.1985",
        "gender": "male"
      },
      "status": "IN_REVIEW",
      "refId": "customer-12345",
      "createdAt": "2024-01-15T10:30:00.000Z",
      "updatedAt": "2024-01-15T10:30:00.000Z"
    }
  ],
  "total": 42,
  "page": 1,
  "limit": 20
}
```

```typescript
interface AmlCaseListResponse {
  data: AmlCase[];
  total: number;
  page: number;
  limit: number;
}
```

To filter by date range:

```bash
curl "https://api.voveid.net/aml/case?startDate=2024-01-01T00:00:00.000Z&endDate=2024-01-31T23:59:59.999Z" \
  --header "x-api-key: $VOVE_API_KEY"
```

## Get an AML case by reference ID

`GET /aml/case/{refId}`

Retrieves one case using the `refId` you supplied when creating it.

| Path parameter | Type   | Required | Description                   |
| -------------- | ------ | -------- | ----------------------------- |
| `refId`        | string | Yes      | Your internal case reference. |

```bash
curl https://api.voveid.net/aml/case/customer-12345 \
  --header "x-api-key: $VOVE_API_KEY"
```

The response uses the `AmlCase` shape shown above. A `404 Not Found` response means the reference does not exist or does not belong to your organization.

## Webhook events

VOVE ID sends AML webhooks when a case is created or its status changes. Webhooks are sent only when the case has a `refId`.

| Event                | Status      |
| -------------------- | ----------- |
| `user.aml.no_match`  | `NO_MATCH`  |
| `user.aml.in_review` | `IN_REVIEW` |
| `user.aml.cleared`   | `CLEARED`   |
| `user.aml.rejected`  | `REJECTED`  |

```json
{
  "refId": "customer-12345",
  "status": "IN_REVIEW"
}
```

Case creation with `POST /aml/case` can trigger a webhook when the case has a `refId`.

Verify the Svix signature, deduplicate events using `svix-id`, and retrieve the current case before applying a consequential decision. See [Webhooks](/docs/kyc-api/webhooks.md).

## Errors

| HTTP status | Meaning                                   | Recommended action                                                |
| ----------- | ----------------------------------------- | ----------------------------------------------------------------- |
| `400`       | Invalid request data or an inactive flow. | Correct the request before trying again.                          |
| `401`       | Missing or invalid API key.               | Check the environment and private key.                            |
| `404`       | Flow or case not found.                   | Check the identifier and environment.                             |
| `429`       | Rate limit exceeded.                      | Retry with bounded backoff.                                       |
| `500`       | Unexpected server error.                  | Retry safely with backoff and reconcile before repeating a write. |

```json
{
  "statusCode": 400,
  "message": "Date of birth must be in DD.MM.YYYY format",
  "error": "Bad Request"
}
```

## Integration guidance

* Keep the private API key on your backend.
* Use a stable, non-sensitive `refId` for each subject.
* Use AML cases when you need review history or webhooks.
* Review names, aliases, dates, citizenship, positions, and source details. Do not decide from a score alone.
* Treat unknown statuses as pending review.
* Do not log full screening payloads or watchlist records.

Continue with the [AML operations guide](/docs/watchlist-screening/aml-operations.md) for the analyst and reviewer workflow.
