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 | Score 100, BLOCK |
DOCUMENT_UPLOADED | ID documents uploaded | Score 100, BLOCK |
NIN_VERIFIED | NIN check passed | Score 100, BLOCK (maps to IN_PROGRESS) |
BVN_VERIFIED | BVN check passed | Score 100, BLOCK (maps to IN_PROGRESS) |
LIVENESS_PASSED | Biometric liveness check passed | Score 0, APPROVE (maps to VERIFIED) |
APPROVED | Fully verified | Score 0, APPROVE |
REJECTED | Failed verification | Score 100, BLOCK |
EXPIRED | Verification expired | Score 100, BLOCK |
KYC Tiers (CBN-Compliant)
The platform supports CBN-mandated account tiers. Each tier requires a different level of identity verification:
| Tier | Requirements | Typical Limits (CBN) |
|---|
TIER_1 · Basic | BVN or NIN | ₦20,000 single txn |
TIER_2 · Standard | BVN + valid ID (passport / driver’s license / voter’s card) | ₦500,000 max balance |
TIER_3 · Premium | BVN/NIN + valid ID + proof of address + liveness check | Unlimited |
Key behaviors:
- Applications default to
TIER_1 if no tier is specified at creation
- Tier 1 requires either BVN or NIN verification
- Tier 2 requires a linked BVN plus a valid means of identification (Passport, Driver’s License, Voter’s Card, or National ID)
- Tier 3 adds proof of address and a liveness/biometric check
- Smart tier default: If both BVN and NIN are provided at creation, the application defaults to
TIER_2
- Auto-upgrade: As applicants upload documents or complete verifications, the system automatically upgrades their tier when requirements are met
TIER_1 → TIER_2: requires verified BVN + valid ID (NIN alone is insufficient for Tier 2)
TIER_2 → TIER_3: requires verified BVN/NIN + valid ID + proof of address + liveness
- The admin reviews documents uploaded by the applicant — never uploads on their behalf
- The
tier field is stored on the KYCApplication and flows into transaction screening for rule-based limit enforcement
Applicant “Comes Back” — Adding BVN/NIN Later
Not all applicants provide both BVN and NIN at creation. The system supports a resume workflow where an applicant (or officer on their behalf) can add missing identity numbers to an existing PENDING application.
Scenario:
- Applicant creates application with only name and phone → Status:
PENDING, Tier: TIER_1
- Later, applicant provides their NIN via mobile app or branch visit
- Officer uses
PATCH /api/v1/kyc/applications/:id to add the NIN
- Officer clicks “Verify NIN” → Status becomes
NIN_VERIFIED
- Applicant is now Tier 1 approved (or can proceed to Tier 2/3)
# Officer adds missing NIN to an existing application
PATCH /api/v1/kyc/applications/kyc_abc123
{
"nin": "12345678901"
}
# Then verify it
POST /api/v1/kyc/applications/kyc_abc123/verify-nin
{
"nin": "12345678901",
"firstName": "Chinedu",
"lastName": "Obi",
"dateOfBirth": "1990-03-15"
}
Editable fields: nin, bvn, email, phone, dateOfBirth
Allowed statuses: PENDING, DOCUMENT_UPLOADED, NIN_VERIFIED, BVN_VERIFIED
Validation: NIN and BVN must be exactly 11 digits; empty strings clear the field; invalid dates are rejected
Smart tier bump: If both BVN and NIN become present, tier auto-bumps to TIER_2. If documents/verifications already exist, auto-upgrade is also evaluated.
Status Preservation During Verification
The KYC status field tracks the highest verified milestone reached. Verifying an identity type never downgrades a higher status:
| Current Status | Verify NIN | Verify BVN | Result |
|---|
PENDING | NIN_VERIFIED | BVN_VERIFIED | Normal progression |
NIN_VERIFIED | NIN_VERIFIED | BVN_VERIFIED | Upgrades to BVN |
BVN_VERIFIED | stays BVN_VERIFIED | BVN_VERIFIED | NIN does not downgrade |
LIVENESS_PASSED | stays LIVENESS_PASSED | stays LIVENESS_PASSED | Preserves highest milestone |
This ensures a Tier 2 application at BVN_VERIFIED remains approvable even if NIN is later verified, and a Tier 3 application at LIVENESS_PASSED remains approvable if additional identity checks are run.
Tier Upgrade Flow
- Applicant is approved at Tier 1 (NIN verified only)
- Later, they provide BVN → Admin clicks “Upgrade to Tier 2”
- System resets status to
NIN_VERIFIED (preserving the verified NIN)
- Admin verifies the BVN → Status becomes
BVN_VERIFIED
- Admin approves → Application is now Tier 2 · Approved
BYOL Provider Tier Limits
If a tenant uses BYOL (Bring Your Own License), their provider may not support all verification types needed for higher tiers. Configure maxTier and supportedVerifications in the BYOL config:
{
"providerName": "SmileIdentity",
"maxTier": "TIER_1",
"supportedVerifications": ["nin", "bvn"]
// ... rest of config
}
If a tenant requests Tier 2/3 but their BYOL provider’s maxTier is lower:
- With
kycFallbackMode = WALLET_RESERVE: Platform automatically falls back to embedded providers for the missing verification types
- With
kycFallbackMode = NONE: The verification is blocked with a clear error message
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 |
PATCH | /api/v1/kyc/applications/:id | Update identity fields |
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 |
POST | /api/v1/kyc/applications/:id/documents | Upload document to MinIO |
GET | /api/v1/kyc/applications/:id/documents | List uploaded documents |
GET | /api/v1/kyc/applications/:id/documents/:docId/download | Get presigned download URL |
DELETE | /api/v1/kyc/applications/:id/documents/:docId | Delete document from MinIO |
PATCH | /api/v1/kyc/applications/:id/approve | Approve application |
PATCH | /api/v1/kyc/applications/:id/reject | Reject application |
POST | /api/v1/kyc/applications/:id/upgrade-tier | Upgrade to Tier 2 or 3 |
GET | /api/v1/kyc/applications/:id/tier-requirements | Check tier requirements |
KYB Statuses
| Status | Meaning | Risk Impact |
|---|
PENDING | Application submitted, awaiting CAC lookup | Score 100, BLOCK |
CAC_VERIFIED | CAC lookup successful | Score 100, BLOCK |
DIRECTORS_VERIFIED | Directors identity verified | Score 100, BLOCK |
BENEFICIAL_OWNERS_VERIFIED | Beneficial owners screened | Score 100, BLOCK |
DOCUMENT_UPLOADED | Supporting documents uploaded | Score 100, BLOCK |
SCREENING_PASSED | All compliance checks passed | Score 100, BLOCK |
APPROVED | Fully verified | Score 0, APPROVE |
REJECTED | Failed verification or sanctions hit | Score 100, BLOCK |
Note: KYB is a hard prerequisite for business transactions. Only APPROVED status allows transactions to proceed without risk flags. All intermediate statuses score 100 and result in 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 |
POST | /api/v1/kyc/applications/:id/documents | Upload document to MinIO |
GET | /api/v1/kyc/applications/:id/documents | List uploaded documents |
GET | /api/v1/kyc/applications/:id/documents/:docId/download | Get presigned download URL |
DELETE | /api/v1/kyc/applications/:id/documents/:docId | Delete document from MinIO |
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 |
POST | /api/v1/kyc/kyb/applications/:id/documents | Upload KYB document to MinIO |
GET | /api/v1/kyc/kyb/applications/:id/documents | List KYB uploaded documents |
GET | /api/v1/kyc/kyb/applications/:id/documents/:docId/download | Get presigned download URL |
DELETE | /api/v1/kyc/kyb/applications/:id/documents/:docId | Delete KYB document from MinIO |
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, kycProviderConfig, kycTrustMode, and byolFallbackMode |
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") |
tier | string | | TIER_1, TIER_2, or TIER_3. Defaults to TIER_1 |
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",
"providerSource": "EMBEDDED",
"newStatus": "BVN_VERIFIED"
}
}
Auto-upgrade behavior: If the applicant has already uploaded a valid ID document, successful BVN verification may auto-upgrade the application from Tier 1 to Tier 2.
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",
"providerSource": "EMBEDDED",
"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**
```json
{
"success": true,
"data": {
"isLive": true,
"confidence": 0.97,
"faceMatch": true,
"faceMatchConfidence": 0.92,
"provider": "PREMBLY",
"providerSource": "EMBEDDED",
"newStatus": "LIVENESS_PASSED"
}
}
Auto-upgrade behavior: If the applicant has already uploaded a valid ID and proof of address, successful liveness verification may auto-upgrade the application from Tier 2 to Tier 3.
Approve Application
Final approval of a KYC application.
Path Parameters
| Parameter | Type | Description |
|---|
id | string | Application UUID |
Example Request
curl -X PATCH /v1/kyc/applications/kyc_abc123/approve \
-H "Authorization: Bearer <access_token>"
Example Response — 200 OK
{
"success": true,
"data": {
"id": "kyc_abc123",
"status": "APPROVED",
"riskLevel": "LOW",
"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": "BENEFICIAL_OWNERS_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 Request
curl -X PATCH /v1/kyc/kyb/applications/kyb_abc123/approve \
-H "Authorization: Bearer <access_token>"
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"
}
}
KYC Document Upload
Upload, manage, and retrieve KYC application documents stored in MinIO (S3-compatible object storage).
Upload KYC Document
POST /api/v1/kyc/applications/:id/documents
Upload a file to MinIO and attach it to a KYC application.
Path Parameters
| Parameter | Type | Description |
|---|
id | string | KYC Application UUID |
Request Body (multipart/form-data)
| Field | Type | Required | Description |
|---|
file | file | ✅ | The file to upload (PDF, JPG, PNG, max 10MB) |
documentType | string | ✅ | PASSPORT, NATIONAL_ID, DRIVERS_LICENSE, VOTERS_CARD, UTILITY_BILL, BANK_STATEMENT, SELFIE, LIVENESS_VIDEO, SIGNATURE, OTHER |
Example Request
curl -X POST /v1/kyc/applications/kyc_abc123/documents \
-H "Authorization: Bearer <access_token>" \
-F "file=@/path/to/passport.pdf" \
-F "documentType=PASSPORT"
Example Response — 200 OK
{
"success": true,
"data": {
"id": "doc_001",
"documentType": "PASSPORT",
"fileName": "passport.pdf",
"fileSizeBytes": 204800,
"mimeType": "application/pdf",
"uploadedAt": "2026-05-16T08:30:00Z",
"presignedUrl": "documents/kyc/kyc_abc123/1715851200000-passport.pdf?X-Amz-Algorithm=AWS4-HMAC-SHA256..."
}
}
Auto-upgrade behavior: After a document is uploaded, the system automatically checks if the applicant now meets the requirements for a higher tier. For example, uploading a PASSPORT after BVN verification may auto-upgrade the application from Tier 1 to Tier 2.
List KYC Documents
GET /api/v1/kyc/applications/:id/documents
List all documents for a KYC application with presigned URLs.
Example Response — 200 OK
{
"success": true,
"data": [
{
"id": "doc_001",
"documentType": "PASSPORT",
"fileName": "passport.pdf",
"fileSizeBytes": 204800,
"mimeType": "application/pdf",
"uploadedAt": "2026-05-16T08:30:00Z",
"presignedUrl": "documents/kyc/kyc_abc123/1715851200000-passport.pdf?X-Amz-Algorithm=..."
}
]
}
Get KYC Document Download URL
GET /api/v1/kyc/applications/:id/documents/:docId/download
Get a time-limited presigned URL to download a document directly from MinIO.
Path Parameters
| Parameter | Type | Description |
|---|
id | string | KYC Application UUID |
docId | string | Document UUID |
Example Response — 200 OK
{
"success": true,
"data": {
"url": "documents/kyc/kyc_abc123/1715851200000-passport.pdf?X-Amz-Algorithm=AWS4-HMAC-SHA256...",
"expiresIn": 300
}
}
Delete KYC Document
DELETE /api/v1/kyc/applications/:id/documents/:docId
Delete a document from MinIO and the database. Requires BANK_ADMIN or COMPLIANCE_OFFICER role.
Example Response — 200 OK
{
"success": true,
"data": { "deleted": true }
}
KYB Document Upload
Upload, manage, and retrieve KYB application documents stored in MinIO.
Upload KYB Document
POST /api/v1/kyc/kyb/applications/:id/documents
Request Body (multipart/form-data)
| Field | Type | Required | Description |
|---|
file | file | ✅ | The file to upload (PDF, JPG, PNG, max 10MB) |
documentType | string | ✅ | CAC_CERTIFICATE, MEMART, TAX_CLEARANCE, BOARD_RESOLUTION, AUDITED_ACCOUNTS, UTILITY_BILL, DIRECTOR_ID, BENEFICIAL_OWNER_ID, OTHER |
Example Request
curl -X POST /v1/kyc/kyb/applications/kyb_abc123/documents \
-H "Authorization: Bearer <access_token>" \
-F "file=@/path/to/cac_certificate.pdf" \
-F "documentType=CAC_CERTIFICATE"
Example Response — 200 OK
{
"success": true,
"data": {
"id": "doc_kyb_001",
"documentType": "CAC_CERTIFICATE",
"fileName": "cac_certificate.pdf",
"fileSizeBytes": 512000,
"mimeType": "application/pdf",
"uploadedAt": "2026-05-16T09:00:00Z",
"presignedUrl": "documents/kyb/kyb_abc123/1715853000000-cac_certificate.pdf?X-Amz-Algorithm=..."
}
}
List KYB Documents
GET /api/v1/kyc/kyb/applications/:id/documents
List all documents for a KYB application with presigned URLs.
Example Response — 200 OK
{
"success": true,
"data": [
{
"id": "doc_kyb_001",
"documentType": "CAC_CERTIFICATE",
"fileName": "cac_certificate.pdf",
"fileSizeBytes": 512000,
"mimeType": "application/pdf",
"uploadedAt": "2026-05-16T09:00:00Z",
"presignedUrl": "documents/kyb/kyb_abc123/1715853000000-cac_certificate.pdf?X-Amz-Algorithm=..."
}
]
}
Get KYB Document Download URL
GET /api/v1/kyc/kyb/applications/:id/documents/:docId/download
Get a time-limited presigned URL to download a KYB document.
Example Response — 200 OK
{
"success": true,
"data": {
"url": "documents/kyb/kyb_abc123/1715853000000-cac_certificate.pdf?X-Amz-Algorithm=AWS4-HMAC-SHA256...",
"expiresIn": 300
}
}
Delete KYB Document
DELETE /api/v1/kyc/kyb/applications/:id/documents/:docId
Delete a KYB document from MinIO and the database. Requires BANK_ADMIN or COMPLIANCE_OFFICER role.
Example Response — 200 OK
{
"success": true,
"data": { "deleted": true }
}