Skip to main content

Identity Verification (IDV) API

The Identity Verification API provides a single endpoint for submitting KYC (Know Your Customer) identity verification data. The API runs sanctions screening first, then verifies users through document verification and selfie matching.

Base URL

{{baseUrl}}/v2/idv/verify

Authentication

This API uses Basic Authentication. Include your merchant credentials in the Authorization header:

  • Username: {{merchantApiKey}}
  • Password: {{merchantSecret}}

Processing Flow

  1. Validation — field formats, empty values, required fields (merchant-configured)
  2. Sanctions Screening — checks applicant against OpenSanctions database (threshold: 0.8)
    • If unreachable → request blocked (fail closed)
    • If matches found → request blocked, KYC skipped
    • If no matches → proceed to KYC
  3. KYC Verification — document verification, face match, MRZ extraction, OCR comparison
  4. Logging — request, response, and uploaded files stored in database
  5. Webhook — summary POST sent to configured URL (if set)

Endpoint

POST /v2/idv/verify

Submit identity verification data with user information and identity documents.

Content-Type

multipart/form-data

Empty Fields

Any field present in the request must have a non-empty value. Sending a field with an empty string will return a 400 error.

Request Parameters

FieldTypeRequiredDescription
firstNamestringYesUser's first name (English characters only)
lastNamestringYesUser's last name (English characters only)
externalUserIdstringYesUnique identifier for the user in your system
ocrMatchstringNoEnable OCR name matching ("true" or "false"). Compares names on ID document against submitted names.
middleNamestringNoUser's middle name (English characters only)
dobstringNoDate of birth in YYYY-MM-DD format
phonestringNoPhone number in international format (e.g., +16045551234)
emailstringNoEmail address
streetstringNoStreet address line 1 (English characters only)
street2stringNoStreet address line 2 (English characters only)
citystringNoCity (English characters only)
statestringNoState or province code (e.g., BC, ON) (English characters only)
postcodestringNoPostal or ZIP code
countrystringNoCountry code (ISO 3166-1 alpha-3, e.g., CAN, USA)
nationalitystringNoNationality code (ISO 3166-1 alpha-3)
documentTypesstringNoComma-separated list: PASSPORT, DRIVERS, ID_CARD
documentCountrystringConditionalCountry code for issued documents (ISO 3166-1 alpha-3). Required when documentTypes is provided.
ssnstringConditionalSocial Security Number. Required when country is USA.
Merchant-Configured Required Fields

Merchants can configure which optional fields are required via the portal's API Configuration page. When configured, the API enforces those fields as required and returns specific error messages listing which fields are missing.

File Upload Fields

All files: max 10 MB, formats JPEG, PNG, WEBP, BMP, PDF.

FieldTypeRequired WhenDescription
passportFrontfiledocumentTypes includes PASSPORTFront side of passport
driversFrontfiledocumentTypes includes DRIVERSFront side of driver's license
driversBackfiledocumentTypes includes DRIVERSBack side of driver's license
idCardFrontfiledocumentTypes includes ID_CARDFront side of ID card
idCardBackfiledocumentTypes includes ID_CARDBack side of ID card
selfiefileAny documentTypes providedUser selfie for face matching
Document Requirements
  • Passport: Front side only — passports never require a back side
  • Driver's License: Front + back required for most countries
  • ID Card: Front + back required for most countries
  • Selfie: Required when any document is provided, cannot be submitted alone
  • Empty files: File fields must contain actual file data — empty file fields are rejected

Usage Examples

Example 1: Passport with OCR Match

curl -X POST '{{baseUrl}}/v2/idv/verify' \
-u '{{merchantApiKey}}:{{merchantSecret}}' \
-F 'firstName=Sophie' \
-F 'lastName=Gagnon' \
-F 'dob=1985-11-22' \
-F 'phone=+15145551234' \
-F 'email=sophie.gagnon@example.com' \
-F 'street=200 Rue Sainte-Catherine Ouest' \
-F 'city=Montreal' \
-F 'state=QC' \
-F 'postcode=H2X 1L1' \
-F 'country=CAN' \
-F 'nationality=CAN' \
-F 'documentTypes=PASSPORT' \
-F 'documentCountry=CAN' \
-F 'externalUserId=user-67890' \
-F 'ocrMatch=true' \
-F 'passportFront=@/path/to/passport.jpg' \
-F 'selfie=@/path/to/selfie.jpg'

Example 2: Driver's License (Canada)

curl -X POST '{{baseUrl}}/v2/idv/verify' \
-u '{{merchantApiKey}}:{{merchantSecret}}' \
-F 'firstName=Jordan' \
-F 'middleName=Robert' \
-F 'lastName=Tremblay' \
-F 'dob=1992-08-14' \
-F 'phone=+16045551234' \
-F 'email=jordan.tremblay@example.com' \
-F 'street=450 Granville Street' \
-F 'street2=Suite 200' \
-F 'city=Vancouver' \
-F 'state=BC' \
-F 'postcode=V6C 1V4' \
-F 'country=CAN' \
-F 'nationality=CAN' \
-F 'documentTypes=DRIVERS' \
-F 'documentCountry=CAN' \
-F 'externalUserId=user-12345' \
-F 'ocrMatch=true' \
-F 'driversFront=@/path/to/drivers_front.jpg' \
-F 'driversBack=@/path/to/drivers_back.jpg' \
-F 'selfie=@/path/to/selfie.jpg'

Example 3: Multiple Documents (Passport + Driver's License)

curl -X POST '{{baseUrl}}/v2/idv/verify' \
-u '{{merchantApiKey}}:{{merchantSecret}}' \
-F 'firstName=Luc' \
-F 'lastName=Pelletier' \
-F 'dob=1990-02-18' \
-F 'country=CAN' \
-F 'documentTypes=DRIVERS,PASSPORT' \
-F 'documentCountry=CAN' \
-F 'externalUserId=user-33333' \
-F 'ocrMatch=true' \
-F 'driversFront=@/path/to/drivers_front.jpg' \
-F 'driversBack=@/path/to/drivers_back.jpg' \
-F 'passportFront=@/path/to/passport.jpg' \
-F 'selfie=@/path/to/selfie.jpg'

Example 4: Minimal Required Fields

curl -X POST '{{baseUrl}}/v2/idv/verify' \
-u '{{merchantApiKey}}:{{merchantSecret}}' \
-F 'firstName=Akira' \
-F 'lastName=Tanaka' \
-F 'externalUserId=user-22222'

Response Format

All verification responses return HTTP 200. The success field in the response body indicates the outcome.

Success Response — Verification Passed

{
"success": true,
"metadata": {
"externalUserId": "user-67890",
"info": {
"firstName": "Sophie",
"lastName": "Gagnon",
"dob": "1985-11-22",
"country": "CAN"
},
"ocrMatch": true,
"documents": [
{ "idDocType": "PASSPORT", "country": "CAN" }
]
},
"documents_processed": 1,
"facemap_id": "69dd249e...",
"document_results": [
{
"document_type": "PASSPORT",
"face_match": true,
"similarity_score": 0.682,
"message": "Faces match"
}
],
"mrz_data": {
"mrz_data": {
"status": "SUCCESS",
"given_name": "SOPHIE",
"surname": "GAGNON",
"document_number": "AB1234567",
"issuer_code": "CAN",
"birth_date": "1985-11-22",
"expiry_date": "2034-11-23",
"sex": "F",
"mrz_type": "TD3"
},
"success": true
},
"ocr_comparison": {
"match": true,
"match_score": 100,
"field_results": {},
"mismatches": [],
"warnings": []
},
"kycResults": {
"status": 200,
"results": [],
"total": { "value": 0, "relation": "eq" }
}
}

Success Response — Sanctions Match Found (KYC Not Performed)

{
"success": false,
"message": "Sanctions screening failed — potential match found",
"kycResults": {
"status": 200,
"results": [
{
"id": "entity-id",
"caption": "Entity Name",
"schema": "Person",
"score": 0.85,
"match": true,
"datasets": ["us_ofac_sdn"]
}
],
"total": { "value": 1, "relation": "eq" }
}
}

Success Response — Sanctions Unavailable (KYC Not Performed)

{
"success": false,
"message": "Sanctions screening unavailable — unable to verify, please try again later",
"kycResults": { "error": "Sanctions check failed" }
}

Success Response — KYC Service Error

{
"success": false,
"message": "External verification service error",
"error": {
"code": "...",
"reason": "...",
"message": "..."
}
}

Error Responses

These errors return non-200 status codes and indicate the request was rejected before processing.

400 — Empty Field

{
"success": false,
"message": "Validation failed",
"errors": ["state cannot be empty"]
}

400 — Validation Error

{
"success": false,
"message": "Validation failed",
"errors": ["firstName - First name is required"]
}

400 — Missing Required Fields (Merchant Config)

{
"success": false,
"message": "Required fields missing",
"errors": [
"Date of Birth is required",
"Document Type is required: ID Card, Passport",
"ID Card Front is required",
"Passport Front is required",
"Selfie is required"
]
}

400 — File Validation Error

{
"success": false,
"message": "File validation failed",
"errors": ["selfie file is empty"]
}

400 — Missing SSN for US

{
"success": false,
"message": "Validation failed",
"errors": ["Social Security Number is mandatory for US citizens"]
}

401 — Invalid Credentials

{
"message": "Invalid Merchant or Secret Key"
}

403 — Restricted Jurisdiction

{
"success": false,
"message": "Restricted jurisdiction",
"errors": ["Country of residence 'RUS' is a restricted jurisdiction"]
}
Restricted Jurisdictions

The following countries are restricted and will return a 403 error:

  • Russia (RUS)
  • Additional restricted countries as configured by your compliance policy

Webhooks

Merchants can configure a webhook URL in the portal's API Configuration page. After each verification, a summary POST is sent to the configured URL.

Webhook Payload

{
"event": "idv.verification.completed",
"success": true,
"externalUserId": "user-67890",
"documentTypes": "PASSPORT",
"sanctionsMatch": 0,
"timestamp": "2026-04-16T12:00:00.000Z"
}
  • Fire-and-forget — does not delay the API response
  • Timeout: 10 seconds
  • Disable: Leave webhook URL empty in the portal

Environment Variables

When using the Postman collection, configure these variables:

VariableDescriptionExample Value
baseUrlAPI base URLhttp://localhost:3000
merchantApiKeyYour merchant API keyProvided in portal
merchantSecretYour merchant secretProvided in portal

Document Type Reference

Document TypeFront FieldBack FieldBack Required
PassportpassportFrontN/ANever
Driver's LicensedriversFrontdriversBackMost countries
ID CardidCardFrontidCardBackMost countries

Country Code Reference

Common country codes (ISO 3166-1 alpha-3):

CountryCode
CanadaCAN
United StatesUSA
United KingdomGBR
AustraliaAUS
GermanyDEU
FranceFRA