# KYC Identity Verification API - Global AML and eIDV (`nabeelbaghoor/kyc-identity-verification-api`) Actor

Verify a person against more than 200 government, credit bureau, utility, telco and electoral datasources in over 100 countries. One row per datasource, showing exactly which identity fields matched, plus the country and field configuration your own account is entitled to call.

- **URL**: https://apify.com/nabeelbaghoor/kyc-identity-verification-api.md
- **Developed by:** [Nabeel Hassan](https://apify.com/nabeelbaghoor) (community)
- **Categories:** Business, Developer tools, Automation
- **Stats:** 2 total users, 1 monthly users, 100.0% runs succeeded, 0 bookmarks
- **User rating**: No ratings yet

## Pricing

$15.00 / 1,000 verification results

This Actor is paid per event. You are not charged for the Apify platform usage, but only a fixed price for specific events.

Learn more: https://docs.apify.com/actors/running/actors-in-store.md#pay-per-event

## What's an Apify Actor?

Actors are web data automations that power AI and operations. They run on the Apify platform to scrape websites, process data, connect APIs, and automate workflows.
In Batch mode, an Actor accepts a well-defined JSON input, performs an action which can take anything from a few seconds to a few hours,
and optionally produces a well-defined JSON output, datasets with results, or files in key-value store.
In Standby mode, an Actor provides a web server which can be used as a website, API, or an MCP server.
Actors are written with capital "A".

## How to integrate an Actor?

If asked about integration, you help developers integrate Actors into their projects.
You adapt to their stack and deliver integrations that are safe, well-documented, and production-ready.
The best way to integrate Actors is as follows.

- **AI agents and MCP clients** — the [Apify MCP server](https://docs.apify.com/integrations/mcp.md) at `https://mcp.apify.com` (remote, streamable HTTP, OAuth on first use).
- **Agentic workflows and local Actor development** — [Agent Skills](https://apify.com/.well-known/agent-skills/index.json) with the [Apify CLI](https://docs.apify.com/cli/docs.md): `npm install -g apify-cli`, then `apify login`.
- **JavaScript/TypeScript projects** — the official [JS/TS client](https://docs.apify.com/api/client/js/docs.md): `npm install apify-client`.
- **Python projects** — the official [Python client](https://docs.apify.com/api/client/python/docs.md): `pip install apify-client`.
- **Any other language** — the [REST API](https://docs.apify.com/api/v2.md).

For usage examples, see the [API](#api) section below.

For more details, see Apify documentation as [Markdown index](https://docs.apify.com/llms.txt) and [Markdown full-text](https://docs.apify.com/llms-full.txt).

# README

## KYC Identity Verification API - Global AML and eIDV

Verify a person against more than 200 government registries, credit bureaus, utility files, telco records and electoral rolls across 100 or more countries, and get back exactly which identity fields each source matched.

### What this actor does

- **Electronic identity verification (eIDV)** against authoritative datasources, returning a field-by-field match rather than a single score.
- **One row per datasource**, so you can see that the credit bureau matched the name and date of birth while the utility file matched the address.
- **Know your customer and anti-money laundering checks** for onboarding, with the evidence stored alongside the decision.
- **Address and national ID verification**, including the provider's cleansed version of an address where the country supports it.
- **Account configuration modes** that read which countries your contract covers, which fields a given country needs, and the test identities to use against a sandbox account. These are never charged for.
- **Regional hosting**, so a contract requiring data residency in the EU, Canada or Australia calls its own host.
- Both credential generations are supported: OAuth client credentials for the current platform, and username and password for the long standing normalised API.

### Input

Fill in the people list and choose a country. Plain field names are accepted and mapped into this provider's nested request document for you.

```json
{
  "mode": "verify",
  "countryCode": "US",
  "people": [
    {
      "firstName": "Jane",
      "lastName": "Doe",
      "dateOfBirth": "1975-11-23",
      "buildingNumber": "123",
      "streetName": "Main",
      "streetType": "St",
      "city": "Seattle",
      "state": "WA",
      "postalCode": "98101"
    }
  ],
  "authMode": "oauth",
  "clientId": "YOUR_CLIENT_ID",
  "clientSecret": "YOUR_CLIENT_SECRET",
  "maxResults": 100
}
```

### Example output

```json
{
  "datasourceName": "Australia Citizen File",
  "recordStatus": "match",
  "matchedFields": ["BuildingNumber", "StreetName", "StreetType", "Suburb", "FirstGivenName", "FirstSurName"],
  "unmatchedFields": ["MiddleName", "UnitNumber"],
  "fieldStatuses": { "BuildingNumber": "match", "MiddleName": "missing", "StreetName": "match", "UnitNumber": "missing", "Suburb": "match", "StreetType": "match" },
  "appendedFields": null,
  "datasourceErrors": null,
  "transactionId": "a1b2c3d4-0000-0000-0000-000000000000",
  "transactionRecordId": "0ac8ccee-ab7a-495e-8b88-a6da1bdcb6ae",
  "countryCode": "AU",
  "productName": "Identity Verification",
  "customerReferenceId": "batch-2026-08",
  "errors": null,
  "inputSummary": "Jane Doe | AU | Identity Verification",
  "found": true
}
```

### Frequently asked questions

#### What is an eIDV API?

Electronic identity verification, or eIDV, confirms that a person exists and that the details they gave you belong to them, by matching those details against independent authoritative sources rather than by inspecting a document. This actor returns the match status of every field against every datasource, which is the evidence anti-money laundering and know your customer rules require you to keep.

#### Which datasources does it check?

Whichever ones your account is configured for in that country. The provider draws on more than 200 sources worldwide, including citizen and resident files, credit bureaus, electoral rolls, government issued identifiers such as national insurance numbers, driver licences and passports, property files, utility and telephone files, national ID validation, and sanctions and watchlist data. Each one answers separately and gets its own row.

#### How do I find out which countries I can verify in?

Run the actor in country codes mode. Coverage is set by your contract rather than by the API, so the provider serves the list per account. The fields mode does the same thing one level down, returning the exact fields a given country needs and which of them are mandatory. Neither mode is charged for.

#### Which credential do I need?

Whichever your account was issued. Accounts on the current platform get an OAuth client id and client secret, which are exchanged for a bearer token. Long standing accounts on the normalised API get a username and password sent as HTTP Basic. Set the credential type to match what you hold, because the two generations authenticate at different endpoints and verify at different paths, so the wrong choice reads as a rejected credential.

#### Does a non-match cost anything?

No. This actor charges only for datasource results that matched at least one identity field. Records refused before they were sent, records the provider would not process, datasource results with no match at all, and configuration rows are stored but not charged for.

#### Can I test without spending live credits?

Yes, if your account has a sandbox. Sandbox accounts check against the provider's own test identities rather than live data, and the test entities mode returns those identities for the country you name so you have something valid to send.

#### What about consent and permissible purpose?

Some datasources may only be queried with the individual's explicit consent. Name those sources in the consent for data sources field, and hold the consent yourself. Which sources need it, and what you may lawfully use the results for, is set by your contract with the provider and by the law of the country you are verifying in.

#### Why is the date of birth split into three fields?

Because the provider takes the day, month and year as separate integers rather than as a date. You can give an ordinary YYYY-MM-DD date and the actor splits it for you; a date it cannot parse is reported on that row rather than being sent as something the provider would misread.

### Which routes this actor calls

Every route was confirmed live against the provider before release, using a deliberately invalid credential so no real data was touched. Each answers 401, while an invented path under the same prefix answers 404, which is what tells a real route from a wrong one:

- `POST /v3/verifications/verify` verifies a person on the current platform.
- `POST /verifications/v1/verify` verifies a person on the normalised API.
- `GET /configuration/v1/countrycodes/{package}` lists the countries the account may call.
- `GET /configuration/v1/fields/{package}/{country}` lists the fields a country needs.
- `GET /configuration/v1/testentities/{package}/{country}` lists sandbox test identities.
- `POST https://auth-api.trulioo.com/connect/token` exchanges OAuth credentials for a bearer token.

Worth knowing: the provider's newer documentation writes the configuration routes as `/v3/configuration/...`, and that spelling does not exist. It answers 404 exactly as an invented path does, while the `/configuration/v1/` spelling answers 401. This actor uses the spellings that answer.

### Keyword map

identity verification API, KYC API, eIDV API, AML compliance API, know your customer, anti money laundering, global identity verification, national ID verification, address verification API, age verification, watchlist screening, sanctions screening, PEP check, credit bureau verification, electoral roll check, customer onboarding API, identity data sources, document free verification, cross border KYC, regulated onboarding.

# Actor input Schema

## `mode` (type: `string`):

Verify checks people against the datasources. The other three read your own account: which countries it may call, which fields a given country needs, and the test identities to use against a sandbox account. Reading the configuration is never charged for.

## `people` (type: `array`):

One object per person. Plain names are accepted and mapped to this provider's nested request for you: firstName, middleName, lastName, fullName, gender, dateOfBirth (YYYY-MM-DD), buildingNumber, unitNumber, streetName, streetType, city, suburb, county, state, postalCode, address1, telephone, mobileNumber, email, nationalId. A person may also carry a raw dataFields object in the provider's own spelling, and its own countryCode.

## `countryCode` (type: `string`):

The two letter country code to verify against, for example US, GB, AU, CA, IN or SG. This provider is structured by country and your contract decides which ones are available, so run the country codes mode if you are not sure. Required for the fields and test entities modes.

## `authMode` (type: `string`):

Which credential your account was issued. The current platform uses an OAuth client id and secret. Long standing accounts on the normalised API use a username and password. The two authenticate against different endpoints, so choosing the wrong one reads as a rejected credential.

## `clientId` (type: `string`):

Your own OAuth client id for this provider. Half of the credential pair, and stored encrypted. Used when the credential type is OAuth.

## `clientSecret` (type: `string`):

Your own OAuth client secret for this provider. Used when the credential type is OAuth.

## `username` (type: `string`):

Your own account username. Used when the credential type is Basic.

## `password` (type: `string`):

Your own account password. Used when the credential type is Basic.

## `region` (type: `string`):

Which regional host to call. The global host routes to the fastest location; the regional hosts exist for contracts that require data residency in a particular place. Your credentials have to be issued for the region you pick.

## `configurationName` (type: `string`):

The package your account is contracted under. Identity Verification is the usual value and the default. Change it only if your account was set up with a different package name.

## `customerReferenceId` (type: `string`):

A string of your own that is sent with every verification and returned on every row, so a result can be tied back to the case or batch it came from.

## `consentForDataSources` (type: `array`):

The names of any datasources that require the individual's explicit consent before they may be queried. A source that needs consent is skipped unless it is named here, and it is your responsibility to hold that consent.

## `cleansedAddress` (type: `boolean`):

Ask the provider to return its standardised version of the address it matched, where the country supports it.

## `skipNotVerified` (type: `boolean`):

Leave datasource results that matched nothing out of the dataset entirely. Off by default, because a datasource that did not match is a real answer and is not charged for.

## `tokenUrl` (type: `string`):

Where to exchange the client id and secret for a bearer token. The default is the provider's published endpoint. Change it only if your credentials were issued on a dedicated authorisation server.

## `scope` (type: `string`):

The scope requested with the token. The default is the one this provider documents for verification calls.

## `baseUrl` (type: `string`):

Overrides the host outright. Leave empty unless your account was issued a dedicated hostname, in which case the region setting is ignored.

## `maxResults` (type: `integer`):

Stop after this many rows. Rows are charged individually, so this is the ceiling on what a run can cost.

## `requestsPerMinute` (type: `integer`):

How fast to call the provider. Lower this if your contract has a tighter rate ceiling than the default.

## Actor input object example

```json
{
  "mode": "verify",
  "people": [
    {
      "firstName": "Jane",
      "lastName": "Doe",
      "dateOfBirth": "1975-11-23",
      "streetName": "Main",
      "streetType": "St",
      "buildingNumber": "123",
      "city": "Seattle",
      "state": "WA",
      "postalCode": "98101"
    }
  ],
  "countryCode": "US",
  "authMode": "oauth",
  "region": "global",
  "configurationName": "Identity Verification",
  "consentForDataSources": [],
  "cleansedAddress": false,
  "skipNotVerified": false,
  "tokenUrl": "https://auth-api.trulioo.com/connect/token",
  "scope": "workflow.studio.api",
  "maxResults": 100,
  "requestsPerMinute": 60
}
```

# Actor output Schema

## `results` (type: `string`):

One row per datasource result, using the provider's own field names, alongside the transaction record id.

# API

You can run this Actor programmatically using our API. Below are code examples in JavaScript, Python, and CLI, as well as the OpenAPI specification and MCP server setup.

## JavaScript example

```javascript
import { ApifyClient } from 'apify-client';

// Initialize the ApifyClient with your Apify API token
// Replace the '<YOUR_API_TOKEN>' with your token
const client = new ApifyClient({
    token: '<YOUR_API_TOKEN>',
});

// Prepare Actor input
const input = {
    "people": [
        {
            "firstName": "Jane",
            "lastName": "Doe",
            "dateOfBirth": "1975-11-23",
            "streetName": "Main",
            "streetType": "St",
            "buildingNumber": "123",
            "city": "Seattle",
            "state": "WA",
            "postalCode": "98101"
        }
    ],
    "consentForDataSources": []
};

// Run the Actor and wait for it to finish
const run = await client.actor("nabeelbaghoor/kyc-identity-verification-api").call(input);

// Fetch and print Actor results from the run's dataset (if any)
console.log('Results from dataset');
console.log(`💾 Check your data here: https://console.apify.com/storage/datasets/${run.defaultDatasetId}`);
const { items } = await client.dataset(run.defaultDatasetId).listItems();
items.forEach((item) => {
    console.dir(item);
});

// 📚 Want to learn more 📖? Go to → https://docs.apify.com/api/client/js/docs

```

## Python example

```python
from apify_client import ApifyClient

# Initialize the ApifyClient with your Apify API token
# Replace '<YOUR_API_TOKEN>' with your token.
client = ApifyClient("<YOUR_API_TOKEN>")

# Prepare the Actor input
run_input = {
    "people": [{
            "firstName": "Jane",
            "lastName": "Doe",
            "dateOfBirth": "1975-11-23",
            "streetName": "Main",
            "streetType": "St",
            "buildingNumber": "123",
            "city": "Seattle",
            "state": "WA",
            "postalCode": "98101",
        }],
    "consentForDataSources": [],
}

# Run the Actor and wait for it to finish
run = client.actor("nabeelbaghoor/kyc-identity-verification-api").call(run_input=run_input)

# Fetch and print Actor results from the run's dataset (if there are any)
print(f"💾 Check your data here: https://console.apify.com/storage/datasets/{run.default_dataset_id}")
for item in client.dataset(run.default_dataset_id).iterate_items():
    print(item)

# 📚 Want to learn more 📖? Go to → https://docs.apify.com/api/client/python/docs/quick-start

```

## CLI example

```bash
echo '{
  "people": [
    {
      "firstName": "Jane",
      "lastName": "Doe",
      "dateOfBirth": "1975-11-23",
      "streetName": "Main",
      "streetType": "St",
      "buildingNumber": "123",
      "city": "Seattle",
      "state": "WA",
      "postalCode": "98101"
    }
  ],
  "consentForDataSources": []
}' |
apify call nabeelbaghoor/kyc-identity-verification-api --silent --output-dataset

```

## MCP server setup

```json
{
    "mcpServers": {
        "apify": {
            "type": "http",
            "url": "https://mcp.apify.com/?tools=fetch-actor-details,nabeelbaghoor/kyc-identity-verification-api"
        }
    }
}

```

The hosted server signs you in with OAuth on first connect, so no API token belongs in this config. Clients without OAuth support can send an `Authorization: Bearer <APIFY_API_TOKEN>` header instead, using a token from API & Integrations in Apify Console (https://console.apify.com/settings/integrations).

## OpenAPI specification

Download the OpenAPI definition: https://api.apify.com/v2/actors/ePt7fGmqH6yrlmPYZ/builds/eBCeyohlgg8abG8BN/openapi.json
