Documentation Index
Fetch the complete documentation index at: https://docs.verifow.com/llms.txt
Use this file to discover all available pages before exploring further.
Overview
The KYC module handles identity verification for your customers. Applications flow through statuses from submission to final approval, with BVN and NIN verification steps against national identity providers.
Common Workflows
New customer onboarding: Customer submits KYC application → System verifies BVN/NIN against provider APIs → Officer reviews and approves → Customer can transact without KYC-related risk flags.
Re-verification: A customer’s KYC expires → They submit updated documents → Officer verifies and approves → KYC status updates to APPROVED.
Business onboarding (KYB): Officer creates KYB application → CAC lookup fetches company details → Directors verified via NIN/BVN → Beneficial owners screened against sanctions → Officer approves → Business can transact without KYB risk flags.
Permissions
| Action | Who Can Do It |
|---|
| Submit, list, view applications | All authenticated users |
| Verify BVN/NIN | BANK_ADMIN, COMPLIANCE_OFFICER |
| Approve/reject KYC | BANK_ADMIN, COMPLIANCE_OFFICER |
| Create KYB application | BANK_ADMIN, COMPLIANCE_OFFICER |
| Run CAC lookup / verify directors / screen BOs | BANK_ADMIN, COMPLIANCE_OFFICER |
| Approve/reject KYB | BANK_ADMIN, COMPLIANCE_OFFICER |
KYC Statuses
| Status | Meaning | Risk Impact |
|---|
PENDING | Submitted, awaiting document upload | No KYC record found — score 40, REVIEW |
DOCUMENT_UPLOADED | ID documents uploaded | Awaiting verification |
NIN_VERIFIED | NIN check passed | Partially verified |
BVN_VERIFIED | BVN check passed | Partially verified |
LIVENESS_PASSED | Biometric liveness check passed | Partially verified |
APPROVED | Fully verified | Score 0, APPROVE |
REJECTED | Failed verification | Score 70, ESCALATE |
EXPIRED | Verification expired | Score 50, REVIEW |
KYB Statuses
| Status | Meaning | Risk Impact |
|---|
PENDING | Application submitted, awaiting CAC lookup | Score 40, REVIEW |
CAC_VERIFIED | CAC lookup successful | Score 40, REVIEW |
DIRECTORS_VERIFIED | Directors identity verified | Score 40, REVIEW |
BOS_VERIFIED | Beneficial owners screened | Score 10, APPROVE |
APPROVED | Fully verified | Score 0, APPROVE |
REJECTED | Failed verification or sanctions hit | Score 85, BLOCK |
Per-Tenant KYC Provider Configuration
Each tenant can independently configure how identity verification is performed.
Provider Modes
| Mode | Description |
|---|
EMBEDDED | Uses platform-managed providers. Default for all new tenants. |
BYOL | Uses the tenant’s own KYC provider API, configured via JSON. |
Switching Provider Mode
BANK_ADMIN users can switch modes from Dashboard → Settings → KYC Provider:
- Select Embedded or BYOL from the dropdown.
- If BYOL, fill in the configuration form:
- Provider Name
- Base URL
- API Key / App ID
- Endpoint paths for NIN, BVN, and Liveness
- Request/response field mappings
- Match confidence threshold
- Save — the change takes effect immediately for all new verifications.
The configuration is stored as JSON in Tenant.kycProviderConfig:
{
"providerName": "SmileIdentity",
"baseUrl": "https://api.smileidentity.com/v1",
"headers": { "Authorization": "Bearer sk_xxx" },
"endpoints": {
"nin": "/id_verification",
"bvn": "/id_verification",
"liveness": "/biometric"
},
"methods": { "nin": "POST", "bvn": "POST" },
"requestMapping": {
"nin": { "id_number": "nin", "id_type": "'NIN'" },
"bvn": { "id_number": "bvn", "id_type": "'BVN'" }
},
"responseMapping": {
"firstNamePath": "result.first_name",
"lastNamePath": "result.last_name"
},
"matchConfidence": 92
}
KYC Endpoints
| Method | Endpoint | Description |
|---|
POST | /api/v1/kyc/applications | Submit a KYC application |
GET | /api/v1/kyc/applications | List applications |
GET | /api/v1/kyc/applications/:id | Retrieve application details |
POST | /api/v1/kyc/applications/:id/verify-bvn | Verify applicant BVN |
POST | /api/v1/kyc/applications/:id/verify-nin | Verify applicant NIN |
POST | /api/v1/kyc/applications/:id/liveness-check | Run biometric liveness check |
PATCH | /api/v1/kyc/applications/:id/approve | Approve application |
PATCH | /api/v1/kyc/applications/:id/reject | Reject application |
KYB Endpoints
| Method | Endpoint | Description |
|---|
POST | /api/v1/kyc/kyb/applications | Create a KYB application |
GET | /api/v1/kyc/kyb/applications | List KYB applications |
GET | /api/v1/kyc/kyb/applications/:id | Get KYB application details |
POST | /api/v1/kyc/kyb/applications/:id/verify-cac | Run CAC lookup by RC number |
POST | /api/v1/kyc/kyb/applications/:id/verify-directors | Verify all directors via KYC |
POST | /api/v1/kyc/kyb/applications/:id/screen-beneficial-owners | Screen BOs against sanctions |
PATCH | /api/v1/kyc/kyb/applications/:id/approve | Approve KYB application |
PATCH | /api/v1/kyc/kyb/applications/:id/reject | Reject KYB application |
Tenant Configuration Endpoints
| Method | Endpoint | Description |
|---|
PATCH | /api/v1/tenants/me | Update tenant config including kycProviderMode and kycProviderConfig |
Submit KYC Application
Create a new KYC application for a customer.
Request Body
| Field | Type | Required | Description |
|---|
entityType | string | ✅ | INDIVIDUAL or BUSINESS |
firstName | string | ✅ | Applicant first name |
lastName | string | ✅ | Applicant last name |
bvn | string | | Bank Verification Number |
nin | string | | National Identity Number |
phone | string | | Mobile number with country code |
email | string | | Email address |
dateOfBirth | string | | ISO 8601 date (e.g. "1990-03-15") |
Example Request
curl -X POST /v1/kyc/applications \
-H "Authorization: Bearer <access_token>" \
-H "Content-Type: application/json" \
-d '{
"entityType": "INDIVIDUAL",
"firstName": "Chinedu",
"lastName": "Obi",
"bvn": "22012345678",
"nin": "12345678901",
"phone": "+2348012345678",
"email": "chinedu.obi@email.com",
"dateOfBirth": "1990-03-15"
}'
Example Response — 201 Created
{
"success": true,
"data": {
"id": "kyc_abc123",
"tenantId": "660e8400-e29b-41d4-a716-446655440001",
"entityType": "INDIVIDUAL",
"firstName": "Chinedu",
"lastName": "Obi",
"bvn": "22012345678",
"nin": "12345678901",
"phone": "+2348012345678",
"email": "chinedu.obi@email.com",
"dateOfBirth": "1990-03-15T00:00:00Z",
"status": "PENDING",
"riskLevel": null,
"assignedTo": null,
"notes": null,
"createdAt": "2026-05-16T08:00:00Z",
"updatedAt": "2026-05-16T08:00:00Z"
}
}
Create KYB Application
Create a new KYB application for a corporate entity.
Request Body
| Field | Type | Required | Description |
|---|
companyName | string | ✅ | Registered company name |
rcNumber | string | | CAC registration number |
tin | string | | Tax Identification Number |
address | string | | Registered business address |
incorporationDate | string | | ISO 8601 date |
directors | array | | Array of director objects |
directors[].name | string | ✅ | Director full name |
directors[].bvn | string | | Director BVN |
directors[].nin | string | | Director NIN |
directors[].email | string | | Director email |
directors[].phone | string | | Director phone |
directors[].nationality | string | | Director nationality |
beneficialOwners | array | | Array of beneficial owner objects |
beneficialOwners[].name | string | ✅ | Owner full name |
beneficialOwners[].percentage | number | ✅ | Ownership percentage |
beneficialOwners[].bvn | string | | Owner BVN |
beneficialOwners[].nin | string | | Owner NIN |
Example Request
curl -X POST /v1/kyc/kyb/applications \
-H "Authorization: Bearer <access_token>" \
-H "Content-Type: application/json" \
-d '{
"companyName": "Acme Nigeria Ltd",
"rcNumber": "RC123456",
"tin": "12345678-0001",
"address": "15 Broad Street, Lagos",
"incorporationDate": "2015-06-12",
"directors": [
{ "name": "John Doe", "bvn": "22012345678", "email": "john@acme.ng" }
],
"beneficialOwners": [
{ "name": "Jane Smith", "percentage": 75, "bvn": "22087654321" }
]
}'
Verify CAC
Run a CAC lookup for a KYB application.
Path Parameters
| Parameter | Type | Description |
|---|
id | string | KYB Application UUID |
Request Body
| Field | Type | Required | Description |
|---|
rcNumber | string | ✅ | CAC registration number to look up |
Example Request
curl -X POST /v1/kyc/kyb/applications/kyb_abc123/verify-cac \
-H "Authorization: Bearer <access_token>" \
-H "Content-Type: application/json" \
-d '{
"rcNumber": "RC123456"
}'
Example Response — 200 OK
{
"success": true,
"data": {
"id": "kyb_abc123",
"status": "CAC_VERIFIED",
"companyName": "Acme Nigeria Ltd",
"rcNumber": "RC123456",
"directors": [{ "name": "John Doe", "role": "Director" }],
"beneficialOwners": [{ "name": "Jane Smith", "percentage": 75 }],
"updatedAt": "2026-05-16T09:00:00Z"
}
}
List KYC Applications
Query Parameters
| Parameter | Type | Default | Description |
|---|
status | string | — | Filter by status |
page | integer | 1 | Page number |
limit | integer | 20 | Items per page |
Example Request
curl -X GET "/v1/kyc/applications?status=PENDING&page=1&limit=10" \
-H "Authorization: Bearer <access_token>"
Example Response — 200 OK
{
"success": true,
"data": {
"items": [
{
"id": "kyc_abc123",
"entityType": "INDIVIDUAL",
"firstName": "Chinedu",
"lastName": "Obi",
"status": "PENDING",
"riskLevel": null,
"createdAt": "2026-05-16T08:00:00Z",
"updatedAt": "2026-05-16T08:00:00Z"
}
],
"total": 5,
"page": 1,
"limit": 10,
"totalPages": 1
}
}
Get KYC Application
Retrieve a KYC application with full verification results and uploaded documents.
Example Request
curl -X GET /v1/kyc/applications/kyc_abc123 \
-H "Authorization: Bearer <access_token>"
Example Response — 200 OK
{
"success": true,
"data": {
"id": "kyc_abc123",
"tenantId": "660e8400-e29b-41d4-a716-446655440001",
"entityType": "INDIVIDUAL",
"status": "BVN_VERIFIED",
"firstName": "Chinedu",
"lastName": "Obi",
"bvn": "22012345678",
"nin": "12345678901",
"phone": "+2348012345678",
"email": "chinedu.obi@email.com",
"dateOfBirth": "1990-03-15T00:00:00Z",
"riskLevel": null,
"assignedTo": null,
"notes": null,
"createdAt": "2026-05-16T08:00:00Z",
"updatedAt": "2026-05-16T09:00:00Z",
"verificationResults": [
{
"id": "vr_001",
"applicationId": "kyc_abc123",
"identityType": "BVN",
"provider": "PREMBLY",
"isMatch": true,
"confidence": 0.95,
"rawResponse": null,
"errorMessage": null,
"verifiedAt": "2026-05-16T09:00:00Z"
}
],
"documents": [
{
"id": "doc_001",
"applicationId": "kyc_abc123",
"documentType": "PASSPORT",
"fileName": "passport.pdf",
"fileUrl": "kyc-documents/passport-123.pdf",
"fileSizeBytes": 204800,
"mimeType": "application/pdf",
"uploadedAt": "2026-05-16T08:30:00Z"
}
]
}
}
Verify BVN
Trigger BVN verification against the identity provider.
Path Parameters
| Parameter | Type | Description |
|---|
id | string | Application UUID |
Request Body
| Field | Type | Required | Description |
|---|
bvn | string | ✅ | BVN to verify (11 digits) |
firstName | string | ✅ | First name for cross-match |
lastName | string | ✅ | Last name for cross-match |
dateOfBirth | string | ✅ | Date of birth for cross-match |
Example Request
curl -X POST /v1/kyc/applications/kyc_abc123/verify-bvn \
-H "Authorization: Bearer <access_token>" \
-H "Content-Type: application/json" \
-d '{
"bvn": "22012345678",
"firstName": "Chinedu",
"lastName": "Obi",
"dateOfBirth": "1990-03-15"
}'
Example Response — 200 OK
{
"success": true,
"data": {
"isMatch": true,
"confidence": 0.95,
"provider": "PREMBLY",
"newStatus": "BVN_VERIFIED"
}
}
Verify NIN
Trigger NIN verification.
Path Parameters
| Parameter | Type | Description |
|---|
id | string | Application UUID |
Request Body
| Field | Type | Required | Description |
|---|
nin | string | ✅ | NIN to verify (11 digits) |
firstName | string | ✅ | First name for cross-match |
lastName | string | ✅ | Last name for cross-match |
dateOfBirth | string | ✅ | Date of birth for cross-match |
Example Request
curl -X POST /v1/kyc/applications/kyc_abc123/verify-nin \
-H "Authorization: Bearer <access_token>" \
-H "Content-Type: application/json" \
-d '{
"nin": "12345678901",
"firstName": "Chinedu",
"lastName": "Obi",
"dateOfBirth": "1990-03-15"
}'
Example Response — 200 OK
{
"success": true,
"data": {
"isMatch": true,
"confidence": 0.94,
"provider": "PREMBLY",
"newStatus": "NIN_VERIFIED"
}
}
Liveness Check
Run a biometric liveness and face-match check.
Path Parameters
| Parameter | Type | Description |
|---|
id | string | Application UUID |
Request Body
| Field | Type | Required | Description |
|---|
selfieImageBase64 | string | ✅ | Base64-encoded selfie image (JPEG/PNG) |
documentImageBase64 | string | | Base64-encoded ID document for face-match |
Example Request
curl -X POST /v1/kyc/applications/kyc_abc123/liveness-check \
-H "Authorization: Bearer <access_token>" \
-H "Content-Type: application/json" \
-d '{
"selfieImageBase64": "/9j/4AAQSkZJRgABAQEASABIAAD...",
"documentImageBase64": "/9j/4AAQSkZJRgABAQEASABIAAD..."
}'
Example Response — 200 OK
{
"success": true,
"data": {
"isLive": true,
"confidence": 0.97,
"faceMatch": true,
"faceMatchConfidence": 0.92,
"provider": "PREMBLY",
"newStatus": "LIVENESS_PASSED"
}
}
Approve Application
Final approval of a KYC application.
Path Parameters
| Parameter | Type | Description |
|---|
id | string | Application UUID |
Request Body
| Field | Type | Required | Description |
|---|
notes | string | | Officer notes |
Example Request
curl -X PATCH /v1/kyc/applications/kyc_abc123/approve \
-H "Authorization: Bearer <access_token>" \
-H "Content-Type: application/json" \
-d '{
"notes": "All documents verified. BVN and NIN match."
}'
Example Response — 200 OK
{
"success": true,
"data": {
"id": "kyc_abc123",
"status": "APPROVED",
"riskLevel": "LOW",
"notes": "All documents verified. BVN and NIN match.",
"updatedAt": "2026-05-16T10:00:00Z"
}
}
Approving a KYC application updates the customer’s risk profile. Future
transactions from this customer will reflect the APPROVED status.
Reject Application
Reject a KYC application that fails verification.
Path Parameters
| Parameter | Type | Description |
|---|
id | string | Application UUID |
Request Body
| Field | Type | Required | Description |
|---|
reason | string | ✅ | Reason for rejection |
Example Request
curl -X PATCH /v1/kyc/applications/kyc_abc123/reject \
-H "Authorization: Bearer <access_token>" \
-H "Content-Type: application/json" \
-d '{
"reason": "BVN name mismatch. Uploaded document appears fraudulent."
}'
Example Response — 200 OK
{
"success": true,
"data": {
"id": "kyc_abc123",
"status": "REJECTED",
"riskLevel": "HIGH",
"notes": "BVN name mismatch. Uploaded document appears fraudulent.",
"updatedAt": "2026-05-16T10:00:00Z"
}
}
Verify Directors
Verify each director’s identity via BVN/NIN against identity providers.
Path Parameters
| Parameter | Type | Description |
|---|
id | string | KYB Application UUID |
Request Body
| Field | Type | Required | Description |
|---|
directors | array | ✅ | Array of director objects |
directors[].name | string | ✅ | Director full name |
directors[].nin | string | | Director NIN |
directors[].bvn | string | | Director BVN |
directors[].verified | boolean | | Pre-verified flag |
Example Request
curl -X POST /v1/kyc/kyb/applications/kyb_abc123/verify-directors \
-H "Authorization: Bearer <access_token>" \
-H "Content-Type: application/json" \
-d '{
"directors": [
{ "name": "John Doe", "nin": "12345678901", "bvn": "22012345678", "verified": true }
]
}'
Example Response — 200 OK
{
"success": true,
"data": {
"allVerified": true,
"directors": [
{
"name": "John Doe",
"nin": "12345678901",
"bvn": "22012345678",
"verified": true
}
],
"newStatus": "DIRECTORS_VERIFIED"
}
}
Screen Beneficial Owners
Screen beneficial owners against global sanctions and PEP watchlists.
Path Parameters
| Parameter | Type | Description |
|---|
id | string | KYB Application UUID |
Request Body
| Field | Type | Required | Description |
|---|
beneficialOwners | array | ✅ | Array of BO objects |
beneficialOwners[].name | string | ✅ | Owner full name |
beneficialOwners[].clean | boolean | ✅ | Pre-screened clean flag |
beneficialOwners[].hits | array | | Watchlist hits if not clean |
Example Request
curl -X POST /v1/kyc/kyb/applications/kyb_abc123/screen-beneficial-owners \
-H "Authorization: Bearer <access_token>" \
-H "Content-Type: application/json" \
-d '{
"beneficialOwners": [
{ "name": "Jane Smith", "clean": true, "hits": [] }
]
}'
Example Response — 200 OK
{
"success": true,
"data": {
"allClean": true,
"beneficialOwners": [{ "name": "Jane Smith", "clean": true, "hits": [] }],
"newStatus": "BOS_VERIFIED"
}
}
Approve KYB Application
Final approval of a KYB application. Requires BANK_ADMIN or COMPLIANCE_OFFICER role.
Path Parameters
| Parameter | Type | Description |
|---|
id | string | KYB Application UUID |
Example Response — 200 OK
{
"success": true,
"data": {
"id": "kyb_abc123",
"status": "APPROVED",
"riskLevel": "LOW",
"updatedAt": "2026-05-16T10:00:00Z"
}
}
Approving a KYB application updates the business entity’s risk profile. Future
transactions from this entity will reflect the APPROVED status (score 0, no
KYB-related risk).
Reject KYB Application
Reject a KYB application that fails verification. Requires BANK_ADMIN or COMPLIANCE_OFFICER role.
Path Parameters
| Parameter | Type | Description |
|---|
id | string | KYB Application UUID |
Request Body
| Field | Type | Required | Description |
|---|
reason | string | ✅ | Reason for rejection |
Example Request
curl -X PATCH /v1/kyc/kyb/applications/kyb_abc123/reject \
-H "Authorization: Bearer <access_token>" \
-H "Content-Type: application/json" \
-d '{
"reason": "Sanctions hit on beneficial owner Jane Smith."
}'
Example Response — 200 OK
{
"success": true,
"data": {
"id": "kyb_abc123",
"status": "REJECTED",
"riskLevel": "HIGH",
"notes": "Sanctions hit on beneficial owner Jane Smith.",
"updatedAt": "2026-05-16T10:00:00Z"
}
}