# Meet Waldo AI

Stop fraud and monetize your bad actor data. Introducing a real-time & bidirectional fraud detection and compliance network.

## Welcome to Waldo AI API

Welcome to Waldo AI API! Here you'll find all the documentation you need to get up and running with the Waldo AI API.

## Want to jump right in?

Feeling like an eager beaver? Jump in to the quick start docs and get making your first request:

{% content-ref url="/pages/BP6O6Hk7mVhSsfXlP0zz" %}
[Quick Start](/quick-start)
{% endcontent-ref %}

## Want to deep dive?

Dive a little deeper and start exploring our API reference to get an idea of everything that's possible with the API:

{% content-ref url="/pages/ca8vN9B1uxPMo726OOVz" %}
[Authentication](/api-reference/authentication)
{% endcontent-ref %}


# Quick Start

This short tutorial should help you integrate Waldo AI into your system.

## Get your API keys

Your API requests are authenticated using API keys. Any request that doesn't include an API key will return an error.

You can generate an API key from your Dashboard at any time.

## Authenticate

The authentication is made by making a `POST` request to \`<https://api.waldo.ai/authenticate\\`> and passing your client API key and client API secret.

## Authenticate your account

<mark style="color:green;">`POST`</mark> `https://api.waldo.ai/authenticate`

#### Request Body

| Name                                           | Type   | Description |
| ---------------------------------------------- | ------ | ----------- |
| apiKey<mark style="color:red;">\*</mark>       |        |             |
| clientSecret<mark style="color:red;">\*</mark> | String |             |

{% tabs %}
{% tab title="401: Unauthorized Invalid API key or invalid client secret" %}

```json
{
  "code": "INVALID_API_KEY",
  "message": "Invalid API key"
}
```

{% endtab %}

{% tab title="400: Bad Request Missing parameters" %}

```json
{
  "code": "MISSING_PARAMETERS",
  "message": "Missing parameters"
}
```

{% endtab %}

{% tab title="403: Forbidden API key has been revoked" %}

```json
{
  "code": "API_KEY_REVOKED",
  "message": "This API key has been revoked. Please visit the Waldo AI dashboard to review your API key."
}
```

{% endtab %}

{% tab title="200: OK Token generated" %}

```json
{
  "token": "eyJh...."
}
```

{% endtab %}
{% endtabs %}

Authentication requests should look like below. A successful request will receive a JWT token in response. Please note that the token has an expiry date of 1 hour from the authentication request. The following API requests will receive a fresh token in response, so it's advised to verify the expiry date before making an API request. Take a look at the [authentication guide](/guides/authentication-process) for how to implement the token refresh smoothly.

{% tabs %}
{% tab title="CURL" %}
{% code overflow="wrap" fullWidth="false" %}

```
curl --location 'https://api.waldo.ai/authenticate' \
--data '{"apiKey": "YOUR_API_KEY","clientSecret": "CLIENT_SECRET"}'
```

{% endcode %}
{% endtab %}

{% tab title="NODE.JS" %}

```javascript
import axios from "axios";
const data = JSON.stringify({
  "apiKey": "YOUR_API_KEY",
  "clientSecret": "CLIENT_SECRET"
});

const config = {
  method: 'post',
  maxBodyLength: Infinity,
  url: 'https://api.waldo.ai/authenticate',
  headers: {
    'Content-Type': 'application/json'
  },
  data : data
};
axios.request(config)
.then((response) => {
  console.log(JSON.stringify(response.data));
})
.catch((error) => {
  console.log(error);
});
```

{% endtab %}

{% tab title="PYTHON" %}

```python
import requests
import json

url = "https://api.waldo.ai/authenticate"

payload = json.dumps({
  "apiKey": "YOUR_API_KEY",
  "clientSecret": "CLIENT_SECRET"
})
headers = {
  'Content-Type': 'application/json'
}
response = requests.request("POST", url, headers=headers, data=payload)

print(response.text)
```

{% endtab %}

{% tab title="PHP" %}

```php
<?php
$client = new Client();
$headers = [
  'Content-Type' => 'application/json'
];
$body = '{
  "apiKey": "YOUR_API_KEY",
  "clientSecret": "CLIENT_SECRET"
}';
$request = new Request('POST', 'https://api.waldo.ai/authenticate', $headers, $body);
$res = $client->sendAsync($request)->wait();
echo $res->getBody();
```

{% endtab %}

{% tab title="C#" %}

```csharp
var client = new HttpClient();
var request = new HttpRequestMessage(HttpMethod.Post, "https://api.waldo.ai/authenticate");
var content = new StringContent("{\"apiKey\": \"YOUR_API_KEY\",\"clientSecret\": \"CLIENT_SECRET\"}", null, "application/json");
request.Content = content;
var response = await client.SendAsync(request);
response.EnsureSuccessStatusCode();
Console.WriteLine(await response.Content.ReadAsStringAsync());
```

{% endtab %}
{% endtabs %}

## Make your first request

To make your first request, send an authenticated request to the onboarding endpoint. This will perform an initial evaluation of a `customer`.

## Onboard a customer

<mark style="color:green;">`POST`</mark> `https://api.waldo.ai/onboard`

#### Headers

| Name                                            | Type | Description                                                                       |
| ----------------------------------------------- | ---- | --------------------------------------------------------------------------------- |
| Authorization<mark style="color:red;">\*</mark> |      | The token obtained in the authentication request in the format `Bearer eyJhbG...` |
| Content-Type<mark style="color:red;">\*</mark>  |      | Expected type `application/json`                                                  |

#### Request Body

| Name                                         | Type   | Description                    |
| -------------------------------------------- | ------ | ------------------------------ |
| firstName<mark style="color:red;">\*</mark>  |        | Customer's first name          |
| lastName<mark style="color:red;">\*</mark>   |        | Customer's last name           |
| officialId<mark style="color:red;">\*</mark> | Object | Customer ID                    |
| dob<mark style="color:red;">\*</mark>        | String | Birthdate in format yyyy-MM-dd |
| address<mark style="color:red;">\*</mark>    | String | Customer's address             |
| email<mark style="color:red;">\*</mark>      | String | Customer's e-mail address      |
| zipCode<mark style="color:red;">\*</mark>    | String | Customer's postal code         |
| state<mark style="color:red;">\*</mark>      | String | Customer's state abbreviated   |
| phone<mark style="color:red;">\*</mark>      | String | Customer's phone number        |
| entityId                                     | String | Customer ID in your database   |
| city<mark style="color:red;">\*</mark>       | String | Customer's city                |

{% tabs %}
{% tab title="200 Onboarding successfully performed" %}

```json
{
    "event": "onboard",
    "evaluation": {
        "type": "kyc",
        "status": "initiated"
    },
    "validation": {
        "status": "REVIEW",
        "kyc": "PENDING",
        "fraudScore": 0,
        "fraudFlag": false
    },
    "externalId": "abcd-123-456-efgh",
    "customerId": "<customer-id>",
    "uri": "https://waldo.ai/customers/<customer-id>"
}
```

{% endtab %}

{% tab title="401 Invalid token" %}

```json
{
  "code": "INVALID_TOKEN", 
  "message": "Invalid token."
}
```

{% endtab %}

{% tab title="403: Forbidden Authorization header missing" %}

```json
{ 
  "code": "NOT_AUTHORIZED",
  "message": "Not authorized."
}
```

{% endtab %}

{% tab title="403: Forbidden Service or user not authorized" %}

```json
{ 
  "code": "NOT_AUTHORIZED",
  "message": "You are not authorized to perform this action. Please contact support for assistance."
}
```

{% endtab %}

{% tab title="403: Forbidden Inactive API key" %}

```json
{ 
  "code": "API_KEY_REVOKED",
  "message": "This API key has been revoked. Please visit the Waldo AI dashboard to review your API key."
}
```

{% endtab %}

{% tab title="400: Bad Request Missing customer data" %}

```json
{ 
  "code": "MISSING_DATA",
  "message": "Missing customer data."
}
```

{% endtab %}

{% tab title="400: Bad Request Invalid data format (birthdate, email, state)" %}

```json
{ 
  "code": "INVALID_DATA",
  "message": "Invalid <field name>"
}
```

{% endtab %}
{% endtabs %}

Take a look at how you might call this method:

{% tabs %}
{% tab title="CURL" %}

```
curl --location 'https://api.waldo.ai/onboard' \
--header 'Authorization: Bearer eyJhbGc...' \
--header 'Content-Type: application/json' \
--data-raw '{
  "firstName": "Paul",
  "lastName": "Atreides",
  "officialId": {
    "docType": "SSN",
    "value": "123-45-6789",
    "country": "US"
  },
  "dob": "1959-03-14",
  "address": "123 Fremen City",
  "email": "paul.atreides@yahoo.com",
  "zipCode": "01234",
  "state": "NV",
  "phone": "+1 123-456-7890",
  "externalId": "abcd-123-456-efgh",
  "city": "Arrakis",
  "options": {"includeFraudCheck": true}
}'
```

{% endtab %}

{% tab title="NODE.JS" %}

```javascript
import axios from "axios";
const data = JSON.stringify({
  "firstName": "Paul",
  "lastName": "Atreides",
  "officialId": {
    "docType": "SSN",
    "value": "123-45-6789",
    "country": "US"
  },
  "dob": "1959-03-14",
  "address": "123 Fremen City",
  "email": "paul.atreides@yahoo.com",
  "zipCode": "01234",
  "state": "NV",
  "phone": "+1 123-456-7890",
  "externalId": "abcd-123-456-efgh",
  "city": "Arrakis",
  "options": {"includeFraudCheck": true}
});

const config = {
  method: 'post',
  maxBodyLength: Infinity,
  url: 'https://api.waldo.ai/onboard',
  headers: { 
    'Authorization: Bearer eyJhbGc...', 
    'Content-Type': 'application/json'
  },
  data : data
};

axios.request(config)
.then((response) => {
  console.log(JSON.stringify(response.data));
})
.catch((error) => {
  console.log(error);
});
```

{% endtab %}

{% tab title="PYTHON" %}

```python
import requests
import json

url = "https://api.waldo.ai/onboard"

payload = json.dumps({
  "firstName": "Paul",
  "lastName": "Atreides",
  "officialId": {
    "docType": "SSN",
    "value": "123-45-6789",
    "country": "US"
  },
  "dob": "1959-03-14",
  "address": "123 Fremen City",
  "email": "paul.atreides@yahoo.com",
  "zipCode": "01234",
  "state": "NV",
  "phone": "+1 123-456-7890",
  "externalId": "abcd-123-456-efgh",
  "city": "Arrakis",
  "options": {"includeFraudCheck": true}
})
headers = {
  'Authorization: Bearer eyJhbGc...',
  'Content-Type': 'application/json'
}

response = requests.request("POST", url, headers=headers, data=payload)

print(response.text)
```

{% endtab %}

{% tab title="PHP" %}

```php
<?php
$client = new Client();
$headers = [
  'Authorization' => 'Bearer eyJhbGc...',
  'Content-Type' => 'application/json'
];
$body = '{
  "firstName": "Paul",
  "lastName": "Atreides",
  "officialId": {
    "docType": "SSN",
    "value": "123-45-6789",
    "country": "US"
  },
  "dob": "1959-03-14",
  "address": "123 Fremen City",
  "email": "paul.atreides@yahoo.com",
  "zipCode": "01234",
  "state": "NV",
  "phone": "+1 123-456-7890",
  "externalId": "abcd-123-456-efgh",
  "city": "Arrakis",
  "options": {"includeFraudCheck": true}
}';
$request = new Request('POST', 'https://api.waldo.ai/onboard', $headers, $body);
$res = $client->sendAsync($request)->wait();
echo $res->getBody();
```

{% endtab %}

{% tab title="C#" %}

```csharp
var client = new HttpClient();
var request = new HttpRequestMessage(HttpMethod.Post, "https://api.waldo.ai/onboard");
request.Headers.Add("Authorization", "Bearer eyJhbGc...");
var content = new StringContent("{\r\n  \"firstName\": \"Paul\",\r\n  \"lastName\": \"Atreides\",\r\n  \"officialId\": {\r\n    \"docType\": \"SSN\",\r\n    \"value\": \"123-45-6789\",\r\n    \"country\": \"US\"\r\n  },\r\n  \"dob\": \"1959-03-14\",\r\n  \"address\": \"123 Fremen City\",\r\n  \"email\": \"paul.atreides@yahoo.com\",\r\n  \"zipCode\": \"01234\",\r\n  \"state\": \"NV\",\r\n  \"phone\": \"+1 123-456-7890\",\r\n  \"externalId\": \"abcd-123-456-efgh\",\r\n  \"city\": \"Arrakis\"\r\n  \"options\": {\r\n  \"includeFraudCheck\": true}}", null, "application/json");
request.Content = content;
var response = await client.SendAsync(request);
response.EnsureSuccessStatusCode();
Console.WriteLine(await response.Content.ReadAsStringAsync());
```

{% endtab %}
{% endtabs %}


# Getting Started

In this tutorial you will find everything needed to start using Waldo AI

## Step 1: Create an account <a href="#create-an-account" id="create-an-account"></a>

Head over to <https://app.waldo.ai> and sign up.

## Step 2: Authorize the service <a href="#authorize-the-service" id="authorize-the-service"></a>

The service authorization is a legal agreement between you and Waldo AI in order to use the KYC/AML service.

## Step 3: Get acquainted with the features

Please visit the [features](/features/overview) section to understand the process better.


# Guides

Welcome to the Waldo AI Guides

Thank you for choosing our API! This section of our documentation is designed to provide you with in-depth guides, tutorials, and resources to help you make the most out of our services.

Here's what you can expect in this section:

1. **Step-by-Step Tutorials:** Dive into our comprehensive tutorials that walk you through common use cases, from setting up your API credentials to implementing advanced features.
2. **Best Practices:** Learn from our experts about recommended practices, tips, and tricks to optimize your integration and enhance your application's performance.
3. **Real-World Examples:** Explore real-world scenarios and see how our API can be leveraged to solve specific problems.
4. **Frequently Asked Questions:** Get quick answers to common queries and troubleshooting tips.

Let's get started! Choose a guide from the menu on the left to begin your API integration journey.


# Authentication process

This guide will help you manage the authentication process and token refresh

#### Step 1: Obtaining an API Token

To access our API services, users must first obtain an API token by making a POST request to `api.waldo.ai/authentication`. The request should include two parameters in the request body:

`apiKey`: Your unique API key.

`clientSecret`: Your client secret.

## Authenticate your account

<mark style="color:green;">`POST`</mark> `https://api.waldo.ai/authenticate`

#### Request Body

| Name                                           | Type   | Description |
| ---------------------------------------------- | ------ | ----------- |
| apiKey<mark style="color:red;">\*</mark>       | String |             |
| clientSecret<mark style="color:red;">\*</mark> | String |             |

A successful request will return a JSON Web Token (JWT) in the response. This JWT token will be used to authorize your subsequent API requests.

{% hint style="info" %}
View the authentication request in detail in the API Reference [section](/api-reference/authentication).
{% endhint %}

#### Step 2: Authenticating API Requests

Once you have obtained your JWT token, you should include it in the `Authorization` header of every API request you make. Set the header value as follows:

```
Authorization: Bearer your-jwt-token
```

This header informs our API that you are an authorized user, allowing you to access the requested resources.

### Token Refresh Process

To ensure uninterrupted access to our API services, you should be aware of token expiration and refresh your token as needed.

#### Token Expiry

Tokens issued by our API have a one-hour expiry period. After this period, the token becomes invalid, and you will need to obtain a new one to continue accessing our services.

#### Automatic Token Refresh

After each successful API request, our API will include a new JWT token in the response headers. More precisely, you will find the new token in the `Authorization` header.&#x20;

This token is generated automatically by our system and is used to refresh your current token.

To make use of this feature, it is recommended that you verify the expiration date of your token with each API request. If your token is about to expire, simply use the new token provided in the response header to replace the old one in your subsequent requests.

#### Example

Here's an example of how you can handle token refresh:

1. Make an API request with your current token.
2. Check the response headers for a new token (`Authorization: Bearer new-jwt-token`).
3. Replace your old token with the new one in subsequent requests.

Here's an example in Node.js using ESM (ECMAScript Modules) to demonstrate how to refresh the token after each API request.

First, make sure you have Node.js installed with support for ESM. You can create a JavaScript file (e.g., `api.js`) with the following code:

{% tabs %}
{% tab title="Node.js" %}

```javascript
// Import the necessary modules - axios and form-data may need to be installed, or you can use your own HTTP client
import axios from 'axios';
import FormData from 'form-data';
import jwt from 'jsonwebtoken';

// Initialize your API key, client secret, and initial token
const apiKey = 'YOUR-API-KEY';
const clientSecret = 'CLIENT-SECRET';
const apiRoot = 'https://api.waldo.ai';
let currentToken = null;

// Function to refresh your token
const refreshToken = async () => {
    try{
        // Make a request to the API to refresh your token
        const data = JSON.stringify({
            apiKey: apiKey,
            clientSecret: clientSecret
        });

        const response = await axios.request({
            method: 'post',
            url: `${apiRoot}/authenticate`,
            headers: {
                'Content-Type': 'application/json'
            },
            data: data
        });
        // Update the current token
        currentToken = response.data.token;
    }catch(error){
        console.log(error);
    }
};

const testToken = async () => {
    try {
        // Verify the token with the secret key
        const decodedToken = jwt.verify(currentToken, clientSecret);

        // Check the 'exp' claim in the decoded token
        const { exp } = decodedToken;

        // Get the current timestamp in seconds
        const currentTimestamp = Math.floor(Date.now() / 1000);

        // Compare the expiration timestamp with the current timestamp
        return exp && exp > currentTimestamp;
    } catch (error) {
        // Token is invalid or has expired
        return false;
    }
};

// Function to make an authenticated API request
const makeAuthenticatedRequest  = async () => {
    try {
        // Check if we have a valid token or obtain a new one
        if (!await testToken()) {
            await refreshToken();
        }

        const response = await axios.request({
            method: 'GET',
            url: `${apiRoot}/some-endpoint`,
            headers: {
                'Authorization': `Bearer ${currentToken}`,
                'Content-Type': 'application/json',
            },
        });

        if (response) {
            // Handle the successful response here
            const responseData = response.data;
        } else if (response.status === 401) {
            // Token expired, obtain a new one and update currentToken
            await refreshToken();
            return makeAuthenticatedRequest(); // Retry the original request
        } else {
            throw new Error('API request failed');
        }

        // Check if there is a new token in the response headers
        const newToken = response.headers.get('Authorization');
        if (newToken) {
            currentToken = newToken; // Update currentToken
        }
    } catch (error) {
        throw 'Error making an API request: ' + error.message;
    }
};

await makeAuthenticatedRequest();

```

{% endtab %}
{% endtabs %}

{% hint style="info" %}
**Note**: replace in the code above `/some-endpoint` with the appropriate endpoint.
{% endhint %}


# Customer Evaluation Lifecycle

The following flow should help you to understand the customer evaluation lifecycle. Please note that the steps are ordered sequentially, as they happen in the process. You can also view this guide in a [diagram format](https://waldostatic.s3.us-east-1.amazonaws.com/customer_evaluation_lifecycle.html).

{% hint style="info" %}
Please note that this documentation is only for the Public API. The customers managed via Waldo Dashboard have different evaluation lifecycles.
{% endhint %}

1. Trigger an evaluation.
2. Choose the evaluation type.
3. Understand the validation characteristics.
4. Understand the validation result.

#### Trigger an evaluation

There are two methods to trigger an evaluation:

1. Customer onboarding
   * this includes implicitly a KYC evaluation
2. Manually triggered
   * this is available after the customer onboarding, on demand

#### Choose the right evaluation

1. KYC (required)
   * this includes two analysis: identity verification and watchlist verification
2. ExpressKYC (optional)
   * this includes the same analysis as the KYC, but the process is different. Read `Understand the validation result` section to find the differences.
3. Fraud (optional)
   * this is a customer risk score determined from the provided customer information and existing information

#### Understand the validation characteristics

The validation result has three characteristics and are correlated with the evaluation type you choose.

1. KYC outcome - available in all evaluations, this is the result of identity check + watchlist check.
2. ExpressKYC outcome - available when include it in the evaluation options, this is the result of identity check only. The ExpressKYC is a best effort result, meaning that if the evaluation can be done fast, it will return the outcome, otherwise it will have the `success` property set to `false` and you should wait for the webhooks notifications to receive the full evaluation result.
3. Fraud score - executed if you have selected to include it in the evaluation. Will return a value of `0` if you don't request it.
4. Status - this can be determined in three different ways:
   * manually: you manually approve/reject the customer
   * KYC outcome: will always be "review" if you don't include the fraud score in the evaluation request
   * fraud score: can set the status to approved, rejected, or review, depending on the fraud score

The end goal of the customer status is to handle the customer access to your services. If the status is set to "approved", then your system is expected to allow the customer to access your services. If the status is set to "rejected", then the effect should be the opposite of approved. If the status is set to "review", then you should review the customer and decide how to proceed.

#### Understand the validation result

The validation result depends on the evaluation type you choose and the evaluation result. Let's breakdown the possible validation results, including the webhook responses.

A. Customer onboarding method

1. You choose KYC only.
   * request stage:
     * kyc outcome: `pending`
     * fraud score: 0
     * status: pending
     * expressKYC outcome: n/a
   * webhooks stage:
     * kyc outcome: `passed` or `review`
     * fraud score: 0
     * status: `review`
     * expressKYC outcome: n/a
2. You include ExpressKYC in the onboarding options, but not the fraud score.
   * request stage:
     * kyc outcome: `passed`, `review,` pending\`
     * fraud score: 0
     * status: pending
     * expressKYC outcome: `passed`, `review`. It can be missing if the ExpressKYC is not executed in a short amount of time - in which case, the expressKYC `success` is set to false.
   * webhooks stage:
     * kyc outcome: `passed` or `review`
     * fraud score: 0
     * status: `review`
     * expressKYC outcome: n/a
3. You include both the ExpressKYC and the fraud score in the onboarding options.
   * request stage:
     * kyc outcome: `passed`, `review,` pending\`
     * fraud score: 0
     * status: pending
     * expressKYC: `passed`, `review`. It can be missing if the ExpressKYC is not executed in a short amount of time - in which case, the expressKYC `success` is set to false.
   * webhooks stage:
     * kyc outome: `passed` or `review`
     * fraud score: 0.82
     * status: `approved`, `rejected`, or `review` - the status is consolidated by combining the KYC + fraud score
     * expressKYC: n/a
4. You include only the fraud score in the onboarding options.
   * request stage:
     * kyc outcome: `pending`
     * fraud score: 0
     * status: pending
     * expressKYC: n/a
   * webhooks stage:
     * kyc outcome: `passed` or `review`
     * fraud score: 0.82
     * status: `approved`, `rejected`, or `review` - the status is consolidated by combining the KYC + fraud score
     * expressKYC: n/a

B. Manually triggered evaluation method - kyc outome: `passed` or `review` -> previously obtained - fraud score: 0.92 -> new score - status: `approved`, `rejected`, or `review` -> previously obtained - expressKYC: n/a


# Sandbox Testing Scenarios

In our Public API sandbox environment, you can simulate different outcomes by including a specific `externalId` value in your request payload. Each value corresponds to a predefined response for various evaluation types.

{% hint style="warning" %}
Please note that the testing scenarios are for customer onboarding and evaluation requests. For other types of API requests, please check the [API Reference](/api-reference/authentication)
{% endhint %}

### How It Works

1. **Initial Request**: Send an API request to the sandbox endpoint, including one of the supported `externalId` values.
2. **Request Stage Response**: The sandbox returns an immediate HTTP response (the *request stage*) with initial metadata.
3. **Webhook Events**: If you have configured webhooks, the sandbox will dispatch up to three events in this order:
   * `initiated`
   * `in_progress`
   * `completed`

### Available Request Types & externalId Options

| Request Type      | Description                               | externalId values                                                                                   |
| ----------------- | ----------------------------------------- | --------------------------------------------------------------------------------------------------- |
| `kyc`             | Onboarding (KYC)                          | `kyc-pass`, `kyc-review`                                                                            |
| `fraud`           | Onboarding with fraud check               | `fraud-pass`, `fraud-review`, `fraud-reject`                                                        |
| `expressKYC`      | Onboarding with Express KYC               | `expressKYC-pass`, `expressKYC-review`, `expressKYC-delay`                                          |
| `expressKYCFraud` | Onboarding with Express KYC + fraud check | `expressKYCFraud-pass`, `expressKYCFraud-review`, `expressKYCFraud-reject`, `expressKYCFraud-delay` |
| `fraudCheck`      | Standalone fraud evaluation               | `fraudCheck-pass`, `fraudCheck-review`, `fraudCheck-reject`                                         |
| `documentUpload`  | Standalone document evaluation            | `documentUpload-pass`, `documentUpload-warn`                                                        |

### Common Request Payload

All sandbox endpoints share a similar request structure. Below is a generic example for the `kyc` endpoint. Replace `externalId` with one of the supported values above, and adjust the `options` object as needed for other request types.

{% hint style="info" %}
The request type is not a parameter, but an onboarding method. Include `useExpressKYC` or `includeFraudCheck` in the payload options to apply the desired request type. Check the [API Reference](/api-reference/authentication) to learn more.
{% endhint %}

```json
POST https://api.waldo.ai/onboard
Content-Type: application/json

{
  "firstName": "Cassian",
  "lastName": "Andor",
  "officialId": {
    "docType": "SSN",
    "value": "439-46-5491",
    "format": "XXX-XX-XXXX",
    "country": "US"
  },
  "dob": "1982-03-14",
  "address": "10436 Donnelly Green",
  "city": "Coruscant",
  "email": "trycia.effertz80@hotmail.com",
  "phone": "+12044372083",
  "zipCode": "81304",
  "state": "VA",
  "country": "US",
  "externalId": "kyc-pass",       // choose from the table above
  "options": {}                    // optional parameters vary by request type
}
```

### Response Stages

#### 1. Request Stage

An immediate HTTP response containing basic metadata about the evaluation.

**Example: `kyc-pass`**

```json
{
  "requestId": "f4XChEEXbz",
  "event": "onboard",
  "evaluation": {
    "type": "kyc",
    "status": "initiated"
  },
  "externalId": "kyc-pass",
  "customerId": "688ca69a34a12dc2f648163c",
  "uri": "https://app.waldo.ai/customers/688ca69a34a12dc2f648163c",
  "errors": []
}
```

#### 2. Webhook Events

If webhooks are configured, the sandbox will send three notifications to your endpoint in sequence.

**a. Initiated**

```json
{
  "requestId": "f4XChEEXbz",
  "event": "onboard",
  "evaluation": {"type": "kyc","status": "initiated"},
  "externalId": "kyc-pass",
  "customerId": "688ca69a34a12dc2f648163c",
  "uri": "https://app.waldo.ai/customers/688ca69a34a12dc2f648163c",
  "errors": []
}
```

**b. In Progress**

```json
{
  "requestId": "f4XChEEXbz",
  "event": "onboard",
  "evaluation": {"type": "kyc","status": "in_progress"},
  "externalId": "kyc-pass",
  "customerId": "688ca69a34a12dc2f648163c",
  "uri": "https://app.waldo.ai/customers/688ca69a34a12dc2f648163c",
  "errors": []
}
```

**c. Completed**

```json
{
  "requestId": "f4XChEEXbz",
  "event": "onboard",
  "evaluation": {"type": "kyc","status": "completed"},
  "validation": {
    "status": "REVIEW",
    "kyc": "PASSED",
    "fraudScore": 0,
    "fraudFlag": false,
    "warnings": 0,
    "warningTags": {
      "ssn": {"tag": "ssn","label": "SSN Integrity","passed": true},
      "date_of_birth": {"tag": "date_of_birth","label": "Date of Birth Integrity","passed": true},
      "address": {"tag": "address","label": "Address Integrity","passed": true},
      "legal_and_regulatory_warnings": {"tag": "legal_and_regulatory_warnings","label": "Legal and Regulatory Warnings","passed": true},
      "politically_exposed_person": {"tag": "politically_exposed_person","label": "Politically Exposed Person","passed": true},
      "sanction": {"tag": "sanction","label": "Sanctions List","passed": true},
      "fraud_reports": {"tag": "fraud_reports","label": "Network Fraud Detection","passed": true},
      "watchlists_validation": {"tag": "watchlists_validation","label": "Watchlists Validation","passed": true},
      "phone_number_validation": {"tag": "phone_number_validation","label": "Phone Number Validation","passed": true},
      "email_address_validation": {"tag": "email_address_validation","label": "Email Address Validation","passed": true}
    },
    "kycBreakdown": {"identityBreakdown": {},"watchlistBreakdown": {},"documentBreakdown": {}}
  },
  "externalId": "kyc-pass",
  "customerId": "688ca69a34a12dc2f648163c",
  "uri": "https://app.waldo.ai/customers/688ca69a34a12dc2f648163c",
  "errors": []
}
```

> **Tip**: The structure above is representative. To explore other scenarios (e.g., express kyc, fraud checks, document uploads), replace the `externalId` and examine the corresponding JSON in the `sandbox_event_triggers.txt` file below.

### Additional Scenarios

All other request types (`fraud`, `expressKYC`, `expressKYCFraud`, `fraudCheck`, `documentUpload`) follow the same pattern:

1. Send a request with one of the supported `externalId` values.
2. Receive an immediate `requestStage` HTTP response.
3. Optionally handle the three webhook events (`initiated`, `in_progress`, `completed`).

Refer to the `sandbox_event_triggers.txt` file below for full sample payloads and responses for each scenario.

{% file src="/files/UBBuoh07JMn3A03ZGJWX" %}


# Overview

On this page you can find the workflow of the Waldo AI customer onboarding and evaluations.

Waldo AI offers 4 methods of customer evaluation, each for different purposes.

In addition, Waldo's API offers methods to automate customer evaluation and synchronization with your system.

### Types of customer evaluation

**Onboarding**

The onboarding is the most basic type of customer evaluation.

This consists of a KYC/AML evaluation and for every customer added, Waldo AI will return a status of either passed, rejected, or review.

**Fraud Check**

The fraud check is a risk assessment of a customer. This evaluation includes information to help you take the right decision to accept or reject a customer.

To automate the decision, the fraud evaluation returns a customer risk score. Your organization can set its own customer risk thresholds.

**Document Check**

The document check is a supplemental KYC verification. Document verification is a critical process used to authenticate the identity of individuals by verifying the validity and authenticity of their submitted documents.

**Deep Background Check**

This will scan even more data sources across the entire web and generate a detailed report, using criminal records, work history, and AI facial recognition for this customer. A report will be emailed to you within one business day.

### Synchronizing with your system

Waldo AI includes the webhooks as a way to update your system (server/application, etc.) directly from our dashboard, and asynchronously from the API.

Since a part of the evaluations may not be completed in real time, we **highly recommend** setting up the webhooks.

Read more about [webhooks](https://docs.waldo.ai/features/webhooks).


# Onboarding

### Workflow

The customer onboarding is performed by providing a customer's information and a few additional fields.

All evaluation requests are asynchronous. Onboarding a customer includes a `kyc` or `fraud` evaluation.\
Therefore, the response to the onboarding request will not be completed in real time.\
If you have set up the webhooks, your system will receive notifications automatically.\
Otherwise, your system can poll Waldo's API until the evaluation is completed.

When the onboarding process is completed, the customer summary will contain:

* approval status
* KYC/AML status
* fraud score (optional)

### Mechanisms

The fraud score is returned only if the request had the property `includeFraudCheck` set to true.

The approval status will be always "review" if the fraud check was not requested. In this case it is possible to run a fraud check later via the API or dashboard, but the approval status will have to be set manually.

The approval status will be set by your organization's customer risk thresholds when in your onboarding request the property `includeFraudCheck` is set to true.


# Fraud Evaluation

### Workflow

The fraud evaluation can be performed independently from the onboarding process, but only if the onboarding process has been completed before.

This evaluation can be made multiple times, as needed.

For flexibility, the fraud evaluation can be included in the onboarding request.

### Fraud evaluation result

All evaluation requests are asynchronous. \
Therefore, the response to the fraud check request will not be completed in real time.\
If you have set up the webhooks, your system will receive notifications automatically.\
Otherwise, your system can poll Waldo's API until the evaluation is completed.

The final evaluation result includes:

* customer fraud health score
* detailed data validation

The customer fraud health score may vary between 0 and 1, where 1 is totally safe.

Detailed data validation provides information about the phone number, email address, watchlists and Waldo AI network reports.


# Express KYC

## Use Cases for Express KYC

\
This document outlines specific scenarios where a workflow involving delayed watchlist verification with limited user functionality is applicable. This approach balances the need for rapid initial user onboarding with the critical requirement of watchlist screening for regulatory compliance.  It is crucial to understand that this approach is contingent on restricting potentially risky user activities until watchlist verification is complete.<br>

**Core Principle:** Users are granted limited access initially, allowing them to explore the platform and complete preliminary steps, but are prevented from engaging in transactions or other high-risk actions until watchlist verification is successful.

**Use Cases:**

**1. Platforms with Low-Risk Initial Interactions:**  Suitable for platforms where initial user engagement doesn't involve immediate financial transactions or sensitive data exchange.

**2. Businesses with a Multi-Stage Onboarding Process:** Applicable when user onboarding involves several steps, and watchlist verification can be integrated seamlessly into the process.  Examples include:

**3. Situations Where Initial Speed is Paramount:** Relevant when a fast initial onboarding experience is crucial for attracting users, but full functionality requires verification.  This must be balanced with the risk of allowing unverified users any access.

**Key Considerations and Limitations:**

* **Risk Assessment:**  A thorough risk assessment is essential to determine which user activities must be restricted.  Any action that could facilitate financial crime or violate regulations must be blocked.
* **User Experience:** Transparency with users is crucial. You may want to explain why their functionality is limited and when they can expect full access.
* **Legal and Regulatory Compliance:** Ensure that you comply with and fulfill your local regulations and obligations. This documentation is **not** a substitute for legal advice.
* **Ongoing Monitoring:** Implement ongoing monitoring to identify any suspicious activity, even from users with limited access.

\
**Disclaimer:** This documentation provides general guidance and should not be considered legal advice.  It is essential to consult with legal counsel to ensure your specific implementation complies with all applicable laws and regulations.  The suitability of this workflow depends heavily on the specific business model, risk profile, and regulatory environment.

***

## Overview

The KYC Evaluation is performed asynchronously. However, in certain circumstances, a preliminary customer evaluation is enough to determine if the customer onboarding should continue or not.

The Express KYC is meant for such cases. Include `useExpressKYC` in the customer onboarding options request, and Waldo's Public API will make the best effort in a short time-frame to provide you a part of the KYC evaluation.

### **Workflow**

* **Onboarding request**: include the Express KYC option in the customer onboarding
* **Onboarding result**: the preliminary evaluation is returned synchronously, if it can be obtained quickly
* **Complete evaluation result:** webhook notifications are sent asynchronously

#### Preliminary KYC results

When the Express KYC option is included in the customer onboarding process, Waldo's Public API will attempt to obtain the **customer identity verification** in a decent amount of time. A fully qualified KYC evaluation should include the **customer watchlist verification,** therefore the final decision on the customer eligibility for the services you provide should be considered - meaning that the information provided in the webhook notifications will have the last word.


# Document Upload

### Workflow

The document upload is part of the KYC/AML evaluation. It is not a mandatory step, but it is enhancing the KYC/AML evaluation with additional verifications.

It is mandatory, however, to complete the onboarding process first.

All evaluation requests are asynchronous. \
Therefore, the response to the document check request will not be completed in real time.\
If you have set up the webhooks, your system will receive notifications automatically.\
Otherwise, your system can poll Waldo's API until the evaluation is completed.

### Document evaluation result

A complete document evaluation will include the following key information:

* the updated KYC outcome, when it's the case
* the list of KYC evaluation properties will be populated with the additional document evaluation properties
* the updated breakdown of KYC warnings, in detail


# Deep Background Check

This scan will provide even more data sources across the entire web and generate a detailed report, using criminal records, work history, and AI facial recognition for a customer.

This customer evaluation type is currently available only though Waldo AI dashboard.

A report will be emailed to you within one business day and your account will be charged as per the fee schedule.


# Webhooks

Webhooks are a way for your application to get real-time data from our API. They are a form of reverse API that gives you the ability to collect information as it happens, rather than making API calls

#### Setting up Webhooks

To set up a webhook, you need to provide a URL in your application where our API can send HTTP POST requests. This URL is known as your webhook endpoint.

The Webhooks configuration can be found on the [`API Integration`](https://app.waldo.ai/api-integration) page.&#x20;

#### Webhooks Events

Our application will send a POST request to your webhook endpoint every time an event happens in your account. The body of this POST request contains all the relevant information about the event.&#x20;

All events that include the `evaluation` property will contain the following information:

* `type` - can be `kyc`, `fraud`, or `document`
* `status` - can be `initiated`, `in_progress`, `completed`, or `failed`

Currently, we support the following webhook events:

* `onboard`: This event is triggered when a customer is approved or rejected on Waldo dashboard.

{% hint style="info" %}
Data sample for the `onboard` event received by your server

```json
{
  "event": "onboard",
  "validation": {
    "status": "APPROVED",
    "kyc": "PASSED",
    "fraudScore": 0,
    "fraudFlag": false,
    "warnings": 0,
    "warningTags": {...}
  },
  "customerId": "687e2821b16b30dd51e02c13",
  "uri": "https://app.waldo.ai/customers/687e2821b16b30dd51e02c13"
}
```

{% endhint %}

* `flag`: This event is triggered when a customer is flagged or unflagged as fraud risk on Waldo dashboard.

{% hint style="info" %}
Data sample for the `flag` event received by your server&#x20;

```json
{
    "event": "flag", 
    "flag": true,
    "externalId": "abcd-123-456-efgh",
    "customerId": "<customer-id>",
    "uri": "https://app.waldo.ai/customers/<customer-id>"
}
```

{% endhint %}

* `evaluation`: This event is triggered when an evaluation is requested via either the dashboard, or the API.

{% hint style="info" %}
Data sample for the `evaluation` event received by your server&#x20;

```json
{
  "requestId": "ayclpQyi6p",
  "event": "evaluation",
  "evaluation": {
    "type": "fraud",
    "status": "initiated"
  },
  "externalId": "abcd-123-456-efgh",
  "customerId": "650c3ebe44aa0043cc846755",
  "uri": "https://app.waldo.ai/customers/650c3ebe44aa0043cc846755"
}
```

{% endhint %}

#### Testing your Webhooks

When setting up the webhooks on Waldo dashboard, you will find a tool to test the integration.

#### Preventing webhook loops

Waldo's service can be used from the dashboard, and the API as well. To handle properly the incoming data in the webhooks, please track the property `requestId`.

When an operation is executed from the dashboard, the webhooks will receive a notification. This notification will not contain the `requestId`, therefore your system should process, if useful, this information.

When an operation is requested via the API, the response from Waldo will contain the `requestId` property. All subsequent notifications related to this request will include the `requestId` previously sent back. From this point, use the `requestId` to update your system, if needed.

#### Webhooks Security Configuration

To ensure the security of webhook notifications, we use HMAC (Hash-based Message Authentication Code) to sign the payloads. This allows webhook consumers to verify the authenticity of the requests.

For this you will need the webhooks secret you have used in the [webhooks configuration page](https://app.waldo.ai/api-integration).

Verifying the Webhook Signature

When your endpoint receives a webhook notification from Waldo, it will include a custom header `X-Waldo-Signature`. This header contains the HMAC signature of the payload. You should use this signature to verify the request.

Here is a step-by-step guide to verify the webhook signature:

1. **Extract the Signature**: Retrieve the `X-Waldo-Signature` header from the request
2. **Compute the HMAC**: Use the same secret key that was used to sign the payload to compute the HMAC of the received payload.
3. **Compare Signatures**: Compare the computed HMAC with the X-Waldo-Signature header. If they match, the request is verified.

Below is an example for the webhook signature verification:

{% tabs %}
{% tab title="JavaScript (Node.js)" %}

```javascript
import crypto from 'crypto';

/**
 * Verifies if the provided HMAC signature matches the calculated signature for the given payload.
 * 
 * @param {Object} payload - The payload to be signed.
 * @param {string} secret - The secret key provided in the webhooks configuration.
 * @param {string} signature - The HMAC signature (X-Waldo-Signature header) to verify.
 * @returns {boolean} - Returns true if the signatures match, otherwise false.
 */
 
const isAuthorized = (payload, secret, signature) => {
    const hmac = crypto.createHmac('sha256', secret);
    hmac.update(JSON.stringify(payload));
    const calculatedSignature = hmac.digest('hex');
    return calculatedSignature === signature;
};

```

{% endtab %}

{% tab title="Python" %}

```python
import hmac
import hashlib
import json


def is_authorized(payload, secret, signature):
    """
    Verify if the provided signature matches the HMAC-SHA256 of the payload using the secret.
   
    Args:
        payload: The data that was signed
        secret: The secret key used for signing
        signature: The signature to verify against
       
    Returns:
        bool: True if the calculated signature matches the provided signature
    """
    # Convert secret to bytes if it's a string
    if isinstance(secret, str):
        secret = secret.encode('utf-8')
       
    # Convert payload to JSON string and then to bytes
    payload_str = json.dumps(payload, separators=(',', ':'))
    payload_bytes = payload_str.encode('utf-8')
   
    # Calculate HMAC
    calculated_signature = hmac.new(
        secret,
        payload_bytes,
        hashlib.sha256
    ).hexdigest()
   
    # Compare signatures
    return calculated_signature == signature
```

{% endtab %}
{% endtabs %}


# Sandbox

Waldo AI currently offers sandbox access to support the API integration.\
Read the notes below to know what to expect.

#### How to use the Waldo sandbox

{% hint style="info" %}
The sandbox is currently available only for API requests. Meaning that any activity in the sandbox mode is not visible on Waldo dashboard (e.g. customers).
{% endhint %}

First, you should have an organization created on Waldo dashboard, and also must be authorized by Waldo staff.

Once you meet these requirements, you can create your organization's API keys on [Waldo dashboard](https://app.waldo.ai/api-integration).

<figure><img src="/files/KPlRibMX6zwFJz5QaVmW" alt=""><figcaption><p>API Integration - Waldo AI dashboard</p></figcaption></figure>

The API keys section will be filled with two sets:

* production mode API keys
* sandbox mode API keys

The API keys have a bit of semantic strings:

* `sandbox.` - these strings are particular to sandbox mode
* `wk.` - stands for *waldo key*
* `ws.` - stands for *waldo secret*

<figure><img src="/files/N2wQFPfuN6V46Pq65WfS" alt=""><figcaption></figcaption></figure>

{% hint style="warning" %}
In addition to the production webhooks, you can also set up the sandbox webhooks.
{% endhint %}

Note that you have the option to change or activate/deactivate production mode API keys, but not the sandbox API keys.

**Waldo API endpoint is the same for both production and sandbox:** [**https://api.waldo.ai**](https://api.waldo.ai)

#### Sandbox mode limitations

* The API requests made in sandbox mode follow the logical process just like in the production mode, but the responses are generic and the actual evaluations will differ in production mode.
* In addition to the API sandbox, you might want to test the webhooks during the development. Because we don't offer sandbox mode on the dashboard, we recommend you to validate your webhooks using the tool provided on the API Integration page from Waldo dashboard, as mentioned in this documentation, on the [webhooks section](https://docs.waldo.ai/features/webhooks).

<figure><img src="/files/VrmSgEXspQFCViQXXiDC" alt=""><figcaption></figcaption></figure>


# Authentication

Endpoint to authenticate your account. The API will return a token to authorize subsequent API requests.

## Authenticate your account

<mark style="color:green;">`POST`</mark> `https://api.waldo.ai/authenticate`

#### Request Body

| Name                                           | Type   | Description |
| ---------------------------------------------- | ------ | ----------- |
| apiKey<mark style="color:red;">\*</mark>       | String |             |
| clientSecret<mark style="color:red;">\*</mark> | String |             |

#### Response

{% tabs %}
{% tab title="200: OK Token generated" %}

```json
{
  "token": "eyJh...."
}
```

{% endtab %}

{% tab title="401: Unauthorized Invalid API key or invalid client secret" %}

```json
{
  "code": "INVALID_API_KEY",
  "message": "Invalid API key"
}
```

{% endtab %}

{% tab title="403: Forbidden API key has been revoked" %}

```json
{
  "code": "API_KEY_REVOKED",
  "message": "This API key has been revoked. Please visit the Waldo AI dashboard to review your API key."
}
```

{% endtab %}

{% tab title="400: Bad Request Missing parameters" %}

```json
{
    "code": 'MISSING_PARAMETERS',
    "message": 'Missing parameters'
}
```

{% endtab %}
{% endtabs %}

{% tabs %}
{% tab title="CURL" %}

```
curl --location 'https://api.waldo.ai/authenticate' \
--data '{"apiKey": "YOUR_API_KEY","clientSecret": "CLIENT_SECRET"}'
```

{% endtab %}

{% tab title="NODE.JS" %}

```javascript
import axios from "axios";
const data = JSON.stringify({
  "apiKey": "YOUR_API_KEY",
  "clientSecret": "CLIENT_SECRET"
});

const config = {
  method: 'post',
  url: 'https://api.waldo.ai/authenticate',
  headers: {
    'Content-Type': 'application/json'
  },
  data : data
};
axios.request(config)
.then((response) => {
  console.log(JSON.stringify(response.data));
})
.catch((error) => {
  console.log(error);
});
```

{% endtab %}

{% tab title="PYTHON" %}

```python
import requests
import json

url = "https://api.waldo.ai/authenticate"

payload = json.dumps({
  "apiKey": "YOUR_API_KEY",
  "clientSecret": "CLIENT_SECRET"
})
headers = {
  'Content-Type': 'application/json'
}

response = requests.post(url, headers=headers, data=payload)

print(response.text)
```

{% endtab %}

{% tab title="PHP" %}

```php
<?php
$client = new Client();
$headers = [
  'Content-Type' => 'application/json'
];
$body = '{
  "apiKey": "YOUR_API_KEY",
  "clientSecret": "CLIENT_SECRET"
}';
$request = new Request('POST', 'https://api.waldo.ai/authenticate', $headers, $body);
$res = $client->sendAsync($request)->wait();
echo $res->getBody();
```

{% endtab %}

{% tab title="C#" %}

```csharp
var client = new HttpClient();
var request = new HttpRequestMessage(HttpMethod.Post, "https://api.waldo.ai/authenticate");
var content = new StringContent("{\"apiKey\": \"YOUR_API_KEY\",\"clientSecret\": \"CLIENT_SECRET\"}", null, "application/json");
request.Content = content;
var response = await client.SendAsync(request);
response.EnsureSuccessStatusCode();
Console.WriteLine(await response.Content.ReadAsStringAsync());
```

{% endtab %}
{% endtabs %}

#### Authorization

Use the token from the authentication response to authorize subsequent API requests. The token should be added in the `Authorization` header:

```
Authorization: Bearer <token>
```


# Customer Onboarding

Endpoint to onboard a customer. The API responds with customer validation information.

## Onboard a customer

<mark style="color:green;">`POST`</mark> `https://api.waldo.ai/onboard`

{% hint style="info" %}
All evaluation requests are asynchronous. Onboarding a customer includes a `kyc` or `fraud` evaluation.\
Therefore, the response to the onboarding request will not be completed in real time.\
If you have set up the webhooks, your system will receive notifications automatically.\
Otherwise, your system can poll Waldo's API until the evaluation is completed.
{% endhint %}

#### Headers

| Name                                            | Type   | Description                                                                       |
| ----------------------------------------------- | ------ | --------------------------------------------------------------------------------- |
| Authorization<mark style="color:red;">\*</mark> | String | The token obtained in the authentication request in the format `Bearer eyJhbG...` |
| Content-Type<mark style="color:red;">\*</mark>  | String | Expected type is `application/json`                                               |

#### Request Body

| Name                                         | Type    | Description                                                                         |
| -------------------------------------------- | ------- | ----------------------------------------------------------------------------------- |
| firstName<mark style="color:red;">\*</mark>  | String  | Customer's first name                                                               |
| lastName<mark style="color:red;">\*</mark>   | String  | Customer's last name                                                                |
| officialId<mark style="color:red;">\*</mark> | Object  | Customer ID in format `{"docType": "SSN", "value": "123-45-6789", "country": "US"}` |
| email<mark style="color:red;">\*</mark>      | String  | Customer's e-mail address                                                           |
| phone<mark style="color:red;">\*</mark>      | String  | Customer's phone number                                                             |
| dob<mark style="color:red;">\*</mark>        | String  | Birthdate in format `yyyy-MM-dd`                                                    |
| address<mark style="color:red;">\*</mark>    | String  | Customer's address                                                                  |
| state<mark style="color:red;">\*</mark>      | String  | Customer's state (abbreviated) in format `NY`                                       |
| zipCode<mark style="color:red;">\*</mark>    | String  | Customer's postal code                                                              |
| entityId                                     | String  | Customer ID in your database                                                        |
| city<mark style="color:red;">\*</mark>       | String  | Customer's city                                                                     |
| country<mark style="color:red;">\*</mark>    | String  | Customer's country                                                                  |
| options                                      | Object  | Optional parameters.                                                                |
| ipAddress                                    | Boolean | Customer IP address                                                                 |

#### Options

| Name              | Type    | Description                                                                      |
| ----------------- | ------- | -------------------------------------------------------------------------------- |
| includeFraudCheck | Boolean | Set `includeFraudCheck` parameter to `true` to include the fraud check           |
| useExpressKYC     | Boolean | Set `useExpressKYC` parameter to `true` to obtain the preliminary KYC evaluation |

#### Sample Request Data

```json
{
  "firstName": "Paul",
  "lastName": "Atreides",
  "officialId": {
    "docType": "SSN",
    "value": "123-45-6789",
    "format": "XXX-XX-XXXX",
    "country": "US"
  },
  "dob": "1959-03-14",
  "address": "123 Fremen City",
  "city": "Arrakis",
  "email": "paul.atreides@yahoo.com",
  "phone": "+12044372083",
  "zipCode": "01234",
  "state": "NV",
  "country": "US",
  "externalId": "abcd-123-456-efgh",
  "options": {
    "includeFraudCheck": true,
    "useExpressKYC": false
  }
}
```

#### Response

{% tabs %}
{% tab title="200: OK Onboarding successfully performed" %}

```json
{
    "requestId": "ayclpQyi6p",
    "event": "onboard",
    "evaluation": {
        "type": "kyc",
        "status": "initiated"
    },
    "options": {
        "includeFraudCheck": true
    },
    "externalId": "abcd-123-456-efgh",
    "customerId": "<customer-id>",
    "uri": "https://app.waldo.ai/customers/<customer-id>"
}
```

{% endtab %}

{% tab title="400: Bad Request Missing customer data" %}

```json
{ 
  "code": "MISSING_DATA",
  "message": "Missing customer data."
}
```

{% endtab %}

{% tab title="400: Bad Request Invalid data format (birthdate, email, state)" %}

```json
{ 
  "code": "INVALID_DATA",
  "message": "Invalid <field name>"
}
```

{% endtab %}

{% tab title="401: Unauthorized Invalid token" %}

```json
{
  "code": "INVALID_TOKEN", 
  "message": "Invalid token."
}
```

{% endtab %}

{% tab title="403: Forbidden Authorization header missing" %}

```json
{ 
  "code": "NOT_AUTHORIZED",
  "message": "Not authorized."
}
```

{% endtab %}

{% tab title="403: Forbidden Service or user not authorized" %}

```json
{ 
  "code": "NOT_AUTHORIZED",
  "message": "You are not authorized to perform this action. Please contact support for assistance."
}
```

{% endtab %}

{% tab title="403: Forbidden Inactive API key" %}

```json
{ 
  "code": "API_KEY_REVOKED",
  "message": "This API key has been revoked. Please visit the Waldo AI dashboard to review your API key."
}
```

{% endtab %}
{% endtabs %}

#### Webhooks complete event notification

```json
{
  "requestId": "ayclpQyi6p",
  "event": "onboard",
  "evaluation": {
    "type": "fraud",
    "status": "completed"
  },
  "validation": {
    "status": "APPROVED",
    "kyc": "PASSED",
    "fraudScore": 0.9,
    "fraudFlag": false,
    "warnings": 3,
    "warningTags": {
      "ssn": {
        "tag": "ssn",
        "label": "SSN Integrity",
        "passed": true
      },
      "date_of_birth": {
        "tag": "date_of_birth",
        "label": "Date of Birth Integrity",
        "passed": true
      },
      "address": {
        "tag": "address",
        "label": "Address Integrity",
        "passed": true
      },
      "legal_and_regulatory_warnings": {
        "tag": "legal_and_regulatory_warnings",
        "label": "Legal and Regulatory Warnings",
        "passed": true
      },
      "politically_exposed_person": {
        "tag": "politically_exposed_person",
        "label": "Politically Exposed Person",
        "passed": true
      },
      "sanction": {
        "tag": "sanction",
        "label": "Sanctions List",
        "passed": true
      },
      "fraud_reports": {
        "tag": "fraud_reports",
        "label": "Network Fraud Detection",
        "passed": false
      },
      "watchlists_validation": {
        "tag": "watchlists_validation",
        "label": "Watchlists Validation",
        "passed": true
      },
      "phone_number_validation": {
        "tag": "phone_number_validation",
        "label": "Phone Number Validation",
        "passed": false
      },
      "email_address_validation": {
        "tag": "email_address_validation",
        "label": "Email Address Validation",
        "passed": false
      }
    },
    "kycBreakdown": {
      "identityBreakdown": {},
      "watchlistBreakdown": {},
      "documentBreakdown": {}
    }
  },
  "externalId": "abcd-123-456-efgh",
  "customerId": "<customer-id>",
  "uri": "https://app.waldo.ai/customers/<customer-id>",
  "errors": []
}
```

### Express KYC

{% hint style="info" %}
Please read the [feature documentation](/features/express-kyc) to understand when to use it.&#x20;
{% endhint %}

#### Include Express KYC in the onboarding options

```json
{
  "firstName": "Paul",
  "lastName": "Atreides",
  ....
  "options": {
    "useExpressKYC": true
  }
}
```

#### Sample response with Express KYC evaluation

```json
{
  "requestId": "cqsji7gyKE",
  "event": "onboard",
  "evaluation": {
    "type": "kyc",
    "status": "initiated"
  },
  "options": {
    "useExpressKYC": true
  },
  "expressKYCStatus": {
    "success": true,
    "outcome": "PASSED"
  },
  "customerId": "<customer-id>",
  "uri": "https://app.waldo.ai/customers/<customer-id>",
  "errors": []
}
```

#### Sample response without Express KYC evaluation

```json
{
  "requestId": "cqsji7gyKE",
  "customerId": "<customer-id>",
  "event": "onboard",
  "evaluation": {
    "status": "initiated",
    "type": "kyc"
  },
  "uri": "https://app.waldo.ai/customers/<customer-id>",
  "errors": []
}
```


# KYC History

Endpoint to read a customer's KYC/AML history

## Retrieve KYC/AML history

<mark style="color:blue;">`GET`</mark> `https://api.waldo.ai/history/kyc/:customerId`

#### Path Parameters

| Field                                        | Type   | Description          |
| -------------------------------------------- | ------ | -------------------- |
| customerId<mark style="color:red;">\*</mark> | String | Waldo AI customer id |

#### Headers

| Name                                            | Type   | Description                                |
| ----------------------------------------------- | ------ | ------------------------------------------ |
| Authorization<mark style="color:red;">\*</mark> | String | The token in the format `Bearer eyJhbG...` |
| Content-Type<mark style="color:red;">\*</mark>  | String | Expected type is `application/json`        |

#### Response

{% tabs %}
{% tab title="200: OK KYC History Available" %}

```json
{
    "active": {
        "date": 1724244780545,
        "outcome": "REVIEW",
        "documentType": "driving_licence",
        "issuingDate": "2018-08-16",
        "type": "document"
    },
    "history": [
        {
            "date": 1724144769269,
            "outcome": "PASSED",
            "type": "kyc"
        },
        {
            "date": 1724244780545,
            "outcome": "REVIEW",
            "documentType": "driving_licence",
            "issuingDate": "2018-08-16",
            "type": "document"
        }
    ]
}
```

{% endtab %}

{% tab title="403: Forbidden Missing authorization header" %}

```json
{
  "code": "NOT_AUTHORIZED",
  "message": "Not authorized."
}
```

{% endtab %}

{% tab title="401: Unauthorized Invalid token or expired" %}

```json
{
  "code": "INVALID_TOKEN",
  "message": "Invalid token."
}
```

{% endtab %}

{% tab title="403: Forbidden Service not authorized" %}

```json
{
  "code": "NOT_AUTHORIZED",
  "message": "You are not authorized to perform this action. Please contact support for assistance."
}
```

{% endtab %}

{% tab title="403: Forbidden Inactive API key" %}

```json
{
  "code": "API_KEY_REVOKED",
  "message": "This API key has been revoked. Please visit the Waldo AI dashboard to review your API key."
}
```

{% endtab %}

{% tab title="400: Bad Request Missing query parameters" %}
The query should include the following parameters:  `customerId`

```json
{
  "code": "INVALID_DATA",
  "message": "Invalid customer ID."
}
```

{% endtab %}

{% tab title="404: Customer not found" %}
Customer was not found, or has not been evaluated yet.

```json
{
  "code": "NOT_FOUND",
  "message": "KYC history not found."
}
```

{% endtab %}
{% endtabs %}


# Get Customer

Endpoint to read a customer

## Retrieve a customer

<mark style="color:blue;">`GET`</mark> `https://api.waldo.ai/customer?email=`<raych@example.com>

#### Query Parameters

| Name               | Type   | Description                                                                                                                                                |
| ------------------ | ------ | ---------------------------------------------------------------------------------------------------------------------------------------------------------- |
| \<customer\_field> | String | <p><code>\<customer\_field></code> should be one or more of the following: </p><p><code>customerId, email, officialId, zipCode, dob, externalId</code></p> |

#### Headers

| Name                                            | Type   | Description                                |
| ----------------------------------------------- | ------ | ------------------------------------------ |
| Authorization<mark style="color:red;">\*</mark> | String | The token in the format `Bearer eyJhbG...` |
| Content-Type<mark style="color:red;">\*</mark>  | String | Expected type is `application/json`        |

#### Response

{% tabs %}
{% tab title="200: OK A list of customers found" %}

```json
{
  "customers": [
    {
      "createdAt": 1695892771782,
      "firstName": "Raych",
      "lastName": "Foss",
      "officialId": {
        "docType": "SSN",
        "value": "123-45-6789",
        "country": "US"
      },
      "dob": "1985-04-24",
      "address": "Trantor Blvd. 73",
      "email": "raych@example.com",
      "phone": "(123) 456-7890",
      "zipCode": "00001",
      "state": "IL",
      "ipAddress": {
        "valid": true,
        "value": "12.34.56.78"
      },
      "evaluation": {
        "type": "idle",
        "status": "idle"
      },
      "validation": {
        "status": "APPROVED",
        "kyc": "REJECTED",
        "fraudScore": 0.82,
        "fraudReport": false,
        "fraudCheck": false,
        "warningTags": {
          "ssn": {
            "label": "SSN Integrity",
            "passed": true
          },
          "date_of_birth": {
            "label": "Date of Birth Integrity",
            "passed": true
          },
          "address": {
            "label": "Address Integrity",
            "passed": true
          },
          "legal_and_regulatory_warnings": {
            "label": "Legal and Regulatory Warnings",
            "passed": false
          },
          "politically_exposed_person": {
            "label": "Politically Exposed Person",
            "passed": false
          },
          "sanction": {
            "label": "Sanctions List",
            "passed": true
          }
        },
        "kycBreakdown": {
          "identityBreakdown": {},
          "watchlistBreakdown": {
            "matches": [
              {
                "name": "Raych V. Foss",
                "entity": "United States Individuals Barred by FINRA",
                "entityUrl": "https://www.finra.org/rules-guidance/oversight-Oversight%20%26%20Enforcement/individuals-barred-finra",
                "type": "warning"
              },
              {
                "name": "Raych M. Foss",
                "entity": "United States Missouri House of Representatives",
                "entityUrl": "https://house.mo.gov/MemberRoster.aspx",
                "matchUrl": "https://house.mo.gov/MemberDetails.aspx?code=R&district=0&year=2024",
                "type": "pep"
              }
            ]
          }
        }
      },
      "externalId": "abcd-123-456-efgh",
      "customerId": "6515452382d40426aa45989a",
      "uri": "https://app.waldo.ai/customers/6515452382d40426aa45989a"
    }
  ]
}
```

{% endtab %}

{% tab title="403: Forbidden Missing authorization header" %}

```json
{
  "code": "NOT_AUTHORIZED",
  "message": "Not authorized."
}
```

{% endtab %}

{% tab title="401: Unauthorized Invalid token or expired" %}

```json
{
  "code": "INVALID_TOKEN",
  "message": "Invalid token."
}
```

{% endtab %}

{% tab title="403: Forbidden Service not authorized" %}

```json
{
  "code": "NOT_AUTHORIZED",
  "message": "You are not authorized to perform this action. Please contact support for assistance."
}
```

{% endtab %}

{% tab title="403: Forbidden Inactive API key" %}

```json
{
  "code": "API_KEY_REVOKED",
  "message": "This API key has been revoked. Please visit the Waldo AI dashboard to review your API key."
}
```

{% endtab %}
{% endtabs %}

{% hint style="info" %}
Make sure to verify the evaluation status.\
Look for the evaluation property. A completed evaluation should be:

```json
"evaluation": {
    "type": "idle",
    "status": "idle"
}
```

{% endhint %}


# Document Upload

Endpoint to upload a customer's document

{% hint style="info" %}
To differentiate the document evaluation items, the `warningTags` include the `isDoc` key.\
Example:

<pre class="language-json"><code class="lang-json">{ 
    "tag": "compromised_document", 
    "passed": true, 
    <a data-footnote-ref href="#user-content-fn-1">"isDoc": true,</a> 
    "label": "Compromised Document" 
}
</code></pre>

{% endhint %}

## Upload a document

<mark style="color:blue;">`POST`</mark> `https://api.waldo.ai/document`

{% hint style="info" %}
All evaluation requests are asynchronous. \
Therefore, the response to the document check request will not be completed in real time.\
If you have set up the webhooks, your system will receive notifications automatically.\
Otherwise, your system can poll Waldo's API until the evaluation is completed.
{% endhint %}

#### Headers

| Name                                            | Type   | Description                                |
| ----------------------------------------------- | ------ | ------------------------------------------ |
| Authorization<mark style="color:red;">\*</mark> | String | The token in the format `Bearer eyJhbG...` |
| Content-Type<mark style="color:red;">\*</mark>  | String | Expected type is `multipart/form-data`     |

#### Request fields

| Name           | Type        | Description                                                                                    | Location  |
| -------------- | ----------- | ---------------------------------------------------------------------------------------------- | --------- |
| document       | binary file | Dcoument scan (`.jpg`, `png`, or `.pdf)` Maximum 10Mb size                                     | Body      |
| side           | String      | `front`or `back`                                                                               | Form data |
| customerId     | String      | Customer ID                                                                                    | Form data |
| documentType   | String      | `driving_licence`(US only), or `passport`(worldwide)                                           | Form data |
| issuingCountry | String      | Country code ([ISO 3166-1 alpha-3](https://en.wikipedia.org/wiki/ISO_3166-1_alpha-3) standard) | Form data |

#### Response

{% tabs %}
{% tab title="200: OK Document Upload Evaluation" %}

```json
{
  "requestId": "ayclpQyi6p",
  "event": "evaluation",
  "evaluation": {
    "type": "document",
    "status": "initiated"
  },
  "customerId": "66b9fc5fcfd24a0bb512fdeb",
  "uri": "https://app.waldo.ai/customers/66b9fc5fcfd24a0bb512fdeb",
  "errors": []
}
```

{% endtab %}

{% tab title="400 Bad request" %}

```json
{
    "code": "MISSING_DATA",
    "message": "Missing data: {field name}"
}
```

{% endtab %}

{% tab title="403: Forbidden Missing authorization header" %}

```json
{
  "code": "NOT_AUTHORIZED",
  "message": "Not authorized."
}
```

{% endtab %}

{% tab title="401: Unauthorized Invalid token or expired" %}

```json
{
  "code": "INVALID_TOKEN",
  "message": "Invalid token."
}
```

{% endtab %}

{% tab title="403: Forbidden Service not authorized" %}

```json
{
  "code": "NOT_AUTHORIZED",
  "message": "You are not authorized to perform this action. Please contact support for assistance."
}
```

{% endtab %}

{% tab title="403: Forbidden Inactive API key" %}

```json
{
  "code": "API_KEY_REVOKED",
  "message": "This API key has been revoked. Please visit the Waldo AI dashboard to review your API key."
}
```

{% endtab %}
{% endtabs %}

#### Webhooks complete event notification

```json
{
  "requestId": "ayclpQyi6p",
  "event": "evaluation",
  "evaluation": {
    "type": "document",
    "status": "completed"
  },
  "validation": {
    "status": "APPROVED",
    "kyc": "PASSED",
    "fraudScore": 0.9,
    "fraudFlag": false,
    "warnings": 3,
    "warningTags": [
      {
        "tag": "ssn",
        "passed": true,
        "label": "SSN Integrity"
      },
      {
        "tag": "date_of_birth",
        "passed": true,
        "label": "Date of Birth Integrity"
      },
      {
        "tag": "legal_and_regulatory_warnings",
        "passed": true,
        "label": "Legal and Regulatory Warnings"
      },
      {
        "tag": "politically_exposed_person",
        "passed": true,
        "label": "Politically Exposed Person"
      },
      {
        "tag": "sanction",
        "passed": true,
        "label": "Sanctions List"
      },
      {
        "tag": "age_validation",
        "passed": false,
        "isDoc": true,
        "label": "Age Validation"
      },
      {
        "tag": "image_integrity",
        "passed": false,
        "isDoc": true,
        "label": "Image Integrity"
      },
      {
        "tag": "data_comparison",
        "passed": true,
        "isDoc": true,
        "label": "Data Comparison"
      },
      {
        "tag": "data_consistency",
        "passed": true,
        "isDoc": true,
        "label": "Data Consistency"
      },
      {
        "tag": "compromised_document",
        "passed": true,
        "isDoc": true,
        "label": "Compromised Document"
      },
      {
        "tag": "visual_authenticity",
        "passed": false,
        "isDoc": true,
        "label": "Visual Authenticity"
      },
      {
        "tag": "data_validation",
        "passed": true,
        "isDoc": true,
        "label": "Data Validation"
      }
    ],
    "kycBreakdown": {
      "identityBreakdown": {},
      "watchlistBreakdown": {},
      "documentBreakdown": {
        "age_validation": {
          "label": "Age Validation",
          "passed": false,
          "tags": {
            "minimum_accepted_age": {
              "label": "Minimum Accepted Age",
              "passed": false
            }
          }
        },
        "image_integrity": {
          "label": "Image Integrity",
          "passed": false,
          "tags": {
            "colour_picture": {
              "label": "Colour Picture",
              "passed": false
            },
            "image_quality": {
              "label": "Image Quality",
              "passed": false
            }
          }
        },
        "visual_authenticity": {
          "label": "Visual Authenticity",
          "passed": false,
          "tags": {
            "digital_tampering": {
              "label": "Digital Tampering",
              "passed": false
            },
            "picture_face_integrity": {
              "label": "Picture Face Integrity",
              "passed": false
            }
          }
        }
      }
    }
  },
  "customerId": "<customer-id>",
  "uri": "https://app.waldo.ai/customers/<customer-id>",
  "errors": []
}
```

[^1]: The field is specific to document features


# Check Fraud

Endpoint to execute a fraud evaluation for an existing customer

## Request a fraud evaluation

<mark style="color:green;">`POST`</mark> `https://api.waldo.ai/check-fraud`

{% hint style="info" %}
All evaluation requests are asynchronous. \
Therefore, the response to the fraud check request will not be completed in real time.\
If you have set up the webhooks, your system will receive notifications automatically.\
Otherwise, your system can poll Waldo's API until the evaluation is completed.
{% endhint %}

**Request body**

| Name                                         | Type   | Description |
| -------------------------------------------- | ------ | ----------- |
| customerId<mark style="color:red;">\*</mark> | string | Customer ID |

**Response**

{% hint style="warning" %}
When requesting a fraud check, always verify the `evaluation` property; if its status is `initiated,` the `fraudScore` value is the last known fraud score, not of the current evaluation.
{% endhint %}

{% tabs %}
{% tab title="200" %}

```json
{
  "requestId": "ayclpQyi6p",
  "event": "evaluation",
  "evaluation": {
    "type": "fraud",
    "status": "initiated"
  },
  "externalId": "abcd-123-456-efgh",
  "customerId": "<customer-id>",
  "uri": "https://app.waldo.ai/customers/<customer-id>",
  "errors": []
}
```

{% endtab %}

{% tab title="400: Bad Request Missing customer data" %}

```json
{ 
  "code": "INVALID_DATA",
  "message": "Invalid <field name>"
}
```

{% endtab %}

{% tab title="401: Unauthorized Invalid token" %}

```
{
  "code": "INVALID_TOKEN", 
  "message": "Invalid token."
}
```

{% endtab %}

{% tab title="403: Forbidden Authorization header missing" %}

```
{ 
  "code": "NOT_AUTHORIZED",
  "message": "Not authorized."
}
```

{% endtab %}

{% tab title="403: Forbidden Service or user not authorized" %}

```
{ 
  "code": "NOT_AUTHORIZED",
  "message": "You are not authorized to perform this action. Please contact support for assistance."
}
```

{% endtab %}
{% endtabs %}

#### Webhooks complete event notification

```json
{
  "event": "evaluation",
  "evaluation": {
    "type": "fraud",
    "status": "completed"
  },
  "validation": {
    "status": "APPROVED",
    "kyc": "PASSED",
    "fraudScore": 0.89,
    "fraudFlag": false,
    "warnings": 3,
    "warningTags": {
      "ssn": {
        "tag": "ssn",
        "label": "SSN Integrity",
        "passed": true
      },
      "date_of_birth": {
        "tag": "date_of_birth",
        "label": "Date of Birth Integrity",
        "passed": true
      },
      "address": {
        "tag": "address",
        "label": "Address Integrity",
        "passed": true
      },
      "legal_and_regulatory_warnings": {
        "tag": "legal_and_regulatory_warnings",
        "label": "Legal and Regulatory Warnings",
        "passed": true
      },
      "politically_exposed_person": {
        "tag": "politically_exposed_person",
        "label": "Politically Exposed Person",
        "passed": true
      },
      "sanction": {
        "tag": "sanction",
        "label": "Sanctions List",
        "passed": true
      },
      "fraud_reports": {
        "tag": "fraud_reports",
        "label": "Network Fraud Detection",
        "passed": false
      },
      "watchlists_validation": {
        "tag": "watchlists_validation",
        "label": "Watchlists Validation",
        "passed": true
      },
      "phone_number_validation": {
        "tag": "phone_number_validation",
        "label": "Phone Number Validation",
        "passed": false
      },
      "email_address_validation": {
        "tag": "email_address_validation",
        "label": "Email Address Validation",
        "passed": false
      }
    },
    "kycBreakdown": {
      "identityBreakdown": {},
      "watchlistBreakdown": {},
      "documentBreakdown": {}
    }
  },
  "customerId": "<customer-id>",
  "uri": "https://app.waldo.ai/customers//<customer-id>"
}
```


# Fraud History

Endpoint to read a customer's fraud history

## Retrieve fraud history

<mark style="color:blue;">`GET`</mark> `https://api.waldo.ai/history/fraud/:customerId`

#### Path Parameters

| Field                                        | Type   | Description          |
| -------------------------------------------- | ------ | -------------------- |
| customerId<mark style="color:red;">\*</mark> | String | Waldo AI customer id |

#### Headers

| Name                                            | Type   | Description                                |
| ----------------------------------------------- | ------ | ------------------------------------------ |
| Authorization<mark style="color:red;">\*</mark> | String | The token in the format `Bearer eyJhbG...` |
| Content-Type<mark style="color:red;">\*</mark>  | String | Expected type is `application/json`        |

#### Response

{% tabs %}
{% tab title="200: OK KYC History Available" %}

```json
{
  "active": {
    "date": 1724152019860,
    "score": 0.9
  },
  "history": [
    {
      "date": 1724152019860,
      "score": 0.9
    }
  ]
}
```

{% endtab %}

{% tab title="403: Forbidden Missing authorization header" %}

```json
{
  "code": "NOT_AUTHORIZED",
  "message": "Not authorized."
}
```

{% endtab %}

{% tab title="401: Unauthorized Invalid token or expired" %}

```json
{
  "code": "INVALID_TOKEN",
  "message": "Invalid token."
}
```

{% endtab %}

{% tab title="403: Forbidden Service not authorized" %}

```json
{
  "code": "NOT_AUTHORIZED",
  "message": "You are not authorized to perform this action. Please contact support for assistance."
}
```

{% endtab %}

{% tab title="403: Forbidden Inactive API key" %}

```json
{
  "code": "API_KEY_REVOKED",
  "message": "This API key has been revoked. Please visit the Waldo AI dashboard to review your API key."
}
```

{% endtab %}

{% tab title="400: Bad Request Missing query parameters" %}
The query should include the following parameters:  `customerId`

```json
{
  "code": "INVALID_DATA",
  "message": "Invalid customer ID."
}
```

{% endtab %}

{% tab title="404: Customer not found" %}
Customer was not found, or has not been evaluated yet.

```json
{
  "code": "NOT_FOUND",
  "message": "Fraud history not found."
}
```

{% endtab %}
{% endtabs %}


# Flag Customer

Endpoint to read a customer

## Flag or remove fraud risk for a customer

<mark style="color:blue;">`POST`</mark> `https://api.waldo.ai/flag`

#### Request Body

| Field                                        | Type    | Description                               |
| -------------------------------------------- | ------- | ----------------------------------------- |
| customerId<mark style="color:red;">\*</mark> | String  | Waldo AI customer id                      |
| flag<mark style="color:red;">\*</mark>       | Boolean | The new risk fraud status (true or false) |
| note                                         | String  | Only when `flag` is set to `true`         |

#### Headers

| Name                                            | Type   | Description                                |
| ----------------------------------------------- | ------ | ------------------------------------------ |
| Authorization<mark style="color:red;">\*</mark> | String | The token in the format `Bearer eyJhbG...` |
| Content-Type<mark style="color:red;">\*</mark>  | String | Expected type is `application/json`        |

#### Response

{% tabs %}
{% tab title="200: OK Customer Flagged" %}

```json
{
    "flagged": true,
    "status": "REJECTED",
    "externalId": "abcd-123-456-efgh",
    "customerId": "65f2ddf6cfcf6ee1fd726307",
    "uri": "https://app.waldo.ai/customers/65f2ddf6cfcf6ee1fd726307"
}
```

{% endtab %}

{% tab title="403: Forbidden Missing authorization header" %}

```json
{
  "code": "NOT_AUTHORIZED",
  "message": "Not authorized."
}
```

{% endtab %}

{% tab title="401: Unauthorized Invalid token or expired" %}

```json
{
  "code": "INVALID_TOKEN",
  "message": "Invalid token."
}
```

{% endtab %}

{% tab title="403: Forbidden Service not authorized" %}

```json
{
  "code": "NOT_AUTHORIZED",
  "message": "You are not authorized to perform this action. Please contact support for assistance."
}
```

{% endtab %}

{% tab title="403: Forbidden Inactive API key" %}

```json
{
  "code": "API_KEY_REVOKED",
  "message": "This API key has been revoked. Please visit the Waldo AI dashboard to review your API key."
}
```

{% endtab %}

{% tab title="400: Bad Request Missing query parameters" %}
The query should include at least one of the following parameters:  `customerId, flag`&#x20;

```json
{
  "code": "INVALID_QUERY",
  "message": "Invalid query."
}
```

{% endtab %}
{% endtabs %}

#### Webhooks event notification

```json
{
    "event": "flag", 
    "flag": true,
    "externalId": "abcd-123-456-efgh",
    "customerId": "<customer-id>",
    "uri": "https://app.waldo.ai/customers/<customer-id>"
}
```


# Data Sources

## US Watchlists Checked

* AK Medicaid Exclusions Provider List
* AL Medicaid Exclusion List
* America Most Wanted Fugitives
* AR Excluded Provider List
* Australia's Implementation of United Nations Security Council Financial Sanctions List
* AU Sex Offender Registry
* AZ Medicaid Exclusions Provider List
* Bank of England Consolidated List
* Board of Governors of the Federal Reserve System - Enforcement Actions
* Boy Scouts of America Exclusions List
* Bureau of Alcohol, Tobacco, and Firearms
* CA Department of Health Care Services (Medi-Cal) Suspended and Ineligible Provider List
* Canadian Counter Terrorism - Listed Terrorist Entities
* Canadian Sanctions List - Entities
* Canadian Sanctions List - Individuals
* CT Medicare Administrative Action List
* DC Excluded Party List
* DE Adult Abuse Registry
* Denied Persons List
* Department of State – Non Proliferation Sanctions
* Department of Treasury Debarred List
* Directorate of Defense Trade Controls - Lists of Parties Debarred for AECA Convictions
* DOJ List of Currently and Previously Disciplined Practitioners
* Drug Enforcement Agency - Diversion Control Administrative Actions Against Doctors
* Drug Enforcement Agency - Diversion Control Criminal Cases Against Doctors
* European Union Consolidated Financial Sanctions List
* Excluded Parties List System - (SAM) System for Award Management List
* FDA Clinical Investigators Compliance List
* FDA Clinical Investigators No Longer Restricted List
* FDA Clinical Investigators Notice of Initiation
* FDA Clinical Investigators Presiding Officer Report List
* FDA Clinical Investigators Restricted List
* FDA Debarment List
* Federal Bureau of Investigation Most Wanted Additional Violent Crimes
* Federal Bureau of Investigation Most Wanted Crime Alerts
* Federal Bureau of Investigation Most Wanted Crimes Against Children
* Federal Bureau of Investigation Most Wanted Criminal Enterprise Investigations
* Federal Bureau of Investigation Most Wanted Cyber Crimes
* Federal Bureau of Investigation Most Wanted Domestic Terrorists
* Federal Bureau of Investigation Most Wanted Seeking Information
* Federal Bureau of Investigation Most Wanted Terrorists
* Federal Bureau of Investigation Most Wanted Violent Crimes - Murders
* Federal Bureau of Investigation Most Wanted White Collar Crimes
* Federal Bureau of Investigation Top Ten Most Wanted
* Federal Deposit Insurance Corporation (FDIC) list of failed banks
* Federal Deposit Insurance Corporation Enforcement Actions
* Federal Financial Institutions Examination Council (FFIEC) Unauthorized Bank List
* FL Suspended Providers List
* Health Education Assistance Loans (HEAL Default Borrowers)
* HI Exclusion & Reinstatement List
* Hong Kong Monetary Authority List
* Hong Kong Securities and Futures Commission (SFC) Enforcement Actions
* IA Direct Care Worker Registry
* ID Medicare Excluded Providers
* IL Provider Sanction List
* Interpol (International Criminal Police Organization) Most Wanted
* Kansas Department for Aging and Disability Services - Abuse Registry
* KY Excluded Medicaid Providers
* MA Health and Human Services Disciplinary Actions
* MD Medicaid Program Sanctioned Providers
* ME Excluded Providers
* MI Department of Community Health List of Sanctioned Providers
* Ministry of Export Trade and Investment (METI) Japan
* Monetary Authority of Singapore Enforcement Actions
* Money Services Businesses Financial Crimes Enforcement Network List
* MS Excluded Providers
* NCUA Administrative Orders
* ND Nurse Aide Abuse Registry
* NE Medicaid Excluded
* NJ Debarment List
* NV Medicaid Exclusion List
* NV Reinstatement list
* NY State Office Medicaid Inspector General
* NY Stock Exchange American Stock Exchange Disciplinary Actions List
* NY Stock Exchange Archipelago Exchange Disciplinary Actions List
* NY Stock Exchange Disciplinary Actions List
* Office Of Inspector General - Most Wanted Health Care Fugitives
* Office of Research Integrity - Findings of Research Misconduct and Administrative Actions
* Office of the Comptroller of Currency - Bank Enforcement Actions
* Office of the Comptroller of Currency - Office of Thrift Supervision - Enforcement Actions
* Office of the Comptroller of Currency- Institution Affiliated Parties Enforcement Actions
* Office of the Comptroller of the Currency - (OCC) Enforcement Actions
* OH Medicaid Provider Exclusion and Suspension List
* OIG Health & Human Services - List of Excluded Individuals and Entities
* OIG Health & Human Services - Waivers for Excluded Individuals and Entities
* OK Nurse Aide Abuse and/or Conviction Registry
* Palestine Legislative Council List
* Pennsylvania Medicheck List
* Politically Exposed Persons List
* SC Excluded Providers
* Secret Service Most Wanted
* Securities and Exchange Commission Enforcement Actions - Federal Court Actions
* Office of Foreign Assets Control (OFAC) Specially Designated Nationals and Blocked Persons
* Terrorism Knowledge Base
* TN Department of Health Abuse Registry
* TN Terminated Providers List
* TRICARE Sanctions List
* TX Health and Human Services Commission Medicaid and Title XX Provider Exclusion List
* UK Disqualified Directors
* US Air Force Fugitives
* US Department of Commerce
* US Department of Housing and Urban Development Denial of Participation List
* US Department Of State Terrorist Exclusion List
* US Drug Enforcement Administration Most Wanted Fugitives - Atlanta Division
* US Drug Enforcement Administration Most Wanted Fugitives - Caribbean Division
* US Drug Enforcement Administration Most Wanted Fugitives - Chicago Division
* US Drug Enforcement Administration Most Wanted Fugitives - Dallas Division
* US Drug Enforcement Administration Most Wanted Fugitives - Denver Division
* US Drug Enforcement Administration Most Wanted Fugitives - Detroit Division
* US Drug Enforcement Administration Most Wanted Fugitives - El Paso Division
* US Drug Enforcement Administration Most Wanted Fugitives - Houston Division
* US Drug Enforcement Administration Most Wanted Fugitives - Los Angeles Division
* US Drug Enforcement Administration Most Wanted Fugitives - Miami Division
* US Drug Enforcement Administration Most Wanted Fugitives - New England Division
* US Drug Enforcement Administration Most Wanted Fugitives - New Jersey Division
* US Drug Enforcement Administration Most Wanted Fugitives - New Orleans Division
* US Drug Enforcement Administration Most Wanted Fugitives - New York City Division
* US Drug Enforcement Administration Most Wanted Fugitives - Philadelphia Division
* US Drug Enforcement Administration Most Wanted Fugitives - Phoenix Division
* US Drug Enforcement Administration Most Wanted Fugitives - San Diego Division
* US Drug Enforcement Administration Most Wanted Fugitives - San Francisco Division
* US Drug Enforcement Administration Most Wanted Fugitives - Seattle Division
* US Drug Enforcement Administration Most Wanted Fugitives - St. Louis Division
* US Drug Enforcement Administration Most Wanted Fugitives - Washington DC Division
* US Food and Drug Administration- Warning Letters
* US Immigration and Customs Enforcement Most Wanted Criminal Aliens
* US Immigration and Customs Enforcement Most Wanted Fugitives
* US Marshals Service Fugitive Investigations Most Wanted
* US Marshals Service Major Fugitive Cases
* US Naval Criminal Investigative Service
* US Postal Service Most Wanted
* UT Nurse Aide Abuse Registry
* VT Office of Professional Regulation Conduct Decisions
* WA Social and Health Services Facility Sanctions List
* WI Nurse Aide Registry
* World Bank Debarred List
* WV Excluded Providers
* WY Excluded Providers


