Overview
Platform admin endpoints for managing KYC profiles across all tenants. These endpoints allow reviewing, approving, and rejecting KYC submissions for both customers and businesses.
KYC Profile Types
| Type | Description | Typical Documents |
|---|---|---|
| Customer | Individual person KYC verification | Government ID, Proof of Address, Selfie |
| Business | Business/Company KYC verification | Certificate of Incorporation, Director IDs, Business Address Proof |
KYC Statuses
| Status | Description |
|---|---|
| pending | Awaiting review by admin |
| under_review | Currently being reviewed |
| approved | KYC verification approved |
| rejected | KYC verification rejected |
| expired | KYC documents have expired |
Business Submission Recovery
A business profile id on its own is not evidence that the submission completed. If admin details show business_details as null or directors are missing, the tenant integration should upload the required documents and resubmit against the existing profile before manual review continues.
List Customer KYC
Retrieve customer KYC profiles across all tenants.
Endpoint
/api/v1/admin/kyc/customersList all customer KYC profiles with filtering and pagination. Returns profiles across all tenants.
Headers
| Parameter | Type | Required | Description |
|---|---|---|---|
Authorization | string | Yes | Bearer {admin_access_token} |
Query Parameters
| Parameter | Type | Required | Description |
|---|---|---|---|
tenant_id | string | No | Filter by tenant UUID |
status | string | No | Filter by KYC statusValues: pending, under_review, approved, rejected, expired |
search | string | No | Search by name, email, or phone number |
submitted_from | string | No | Filter by submission date start (ISO 8601) |
submitted_to | string | No | Filter by submission date end (ISO 8601) |
limit | integer | No (default: 20) | Page size (max 100) |
offset | integer | No (default: 0) | Page offset |
Response- Paginated list of customer KYC profiles
{
"customers": [
{
"profile_id": "kyc_550e8400-e29b-41d4-a716-446655440000",
"customer_id": "cust_660e8400-e29b-41d4-a716-446655440001",
"tenant_id": "tenant_770e8400-e29b-41d4-a716-446655440002",
"tenant_name": "Acme Corp",
"full_name": "John Doe",
"email": "john.doe@example.com",
"phone": "+2348012345678",
"status": "pending",
"tier": "tier_1",
"submitted_at": "2025-01-14T10:00:00Z",
"reviewed_at": null,
"created_at": "2025-01-10T08:00:00Z"
}
],
"total": 1250,
"limit": 20,
"offset": 0
}Error Responses
| Status | Code | Description |
|---|---|---|
| 401 | unauthorized | Missing or invalid admin JWT |
| 403 | forbidden | Admin role required |
List Business KYC
Retrieve business KYC profiles across all tenants.
Endpoint
/api/v1/admin/kyc/businessesList all business KYC profiles with filtering and pagination. Returns profiles across all tenants.
Headers
| Parameter | Type | Required | Description |
|---|---|---|---|
Authorization | string | Yes | Bearer {admin_access_token} |
Query Parameters
| Parameter | Type | Required | Description |
|---|---|---|---|
tenant_id | string | No | Filter by tenant UUID |
status | string | No | Filter by KYC statusValues: pending, under_review, approved, rejected, expired |
business_type | string | No | Filter by business typeValues: sole_proprietorship, partnership, limited_company, ngo |
search | string | No | Search by business name or registration number |
limit | integer | No (default: 20) | Page size (max 100) |
offset | integer | No (default: 0) | Page offset |
Response- Paginated list of business KYC profiles
{
"businesses": [
{
"profile_id": "kyc_880e8400-e29b-41d4-a716-446655440003",
"business_id": "biz_990e8400-e29b-41d4-a716-446655440004",
"tenant_id": "tenant_770e8400-e29b-41d4-a716-446655440002",
"tenant_name": "Acme Corp",
"business_name": "Tech Solutions Ltd",
"registration_number": "RC123456",
"business_type": "limited_company",
"status": "under_review",
"tier": "tier_2",
"submitted_at": "2025-01-13T14:30:00Z",
"reviewed_at": null,
"created_at": "2025-01-12T09:00:00Z"
}
],
"total": 450,
"limit": 20,
"offset": 0
}Error Responses
| Status | Code | Description |
|---|---|---|
| 401 | unauthorized | Missing or invalid admin JWT |
| 403 | forbidden | Admin role required |
List KYC Requests
Retrieve all pending KYC requests awaiting review.
Endpoint
/api/v1/admin/kyc/requestsList KYC requests that require admin attention. Useful for review queues and dashboards.
Headers
| Parameter | Type | Required | Description |
|---|---|---|---|
Authorization | string | Yes | Bearer {admin_access_token} |
Query Parameters
| Parameter | Type | Required | Description |
|---|---|---|---|
tenant_id | string | No | Filter by tenant UUID |
type | string | No | Filter by profile typeValues: customer, business |
status | string | No | Filter by request statusValues: pending, under_review |
priority | string | No | Filter by priority levelValues: low, normal, high, urgent |
sort | string | No (default: submitted_at) | Sort fieldValues: submitted_at, priority, tenant_name |
order | string | No (default: asc) | Sort orderValues: asc, desc |
limit | integer | No (default: 20) | Page size |
offset | integer | No (default: 0) | Page offset |
Response- Paginated list of KYC requests
{
"requests": [
{
"request_id": "req_110e8400-e29b-41d4-a716-446655440005",
"profile_id": "kyc_550e8400-e29b-41d4-a716-446655440000",
"type": "customer",
"name": "John Doe",
"tenant_id": "tenant_770e8400-e29b-41d4-a716-446655440002",
"tenant_name": "Acme Corp",
"status": "pending",
"priority": "normal",
"tier_requested": "tier_2",
"documents_count": 3,
"submitted_at": "2025-01-14T10:00:00Z",
"sla_deadline": "2025-01-16T10:00:00Z"
}
],
"total": 85,
"limit": 20,
"offset": 0
}Error Responses
| Status | Code | Description |
|---|---|---|
| 401 | unauthorized | Missing or invalid admin JWT |
| 403 | forbidden | Admin role required |
Customer KYC Metrics
Platform-wide customer KYC verification metrics.
Endpoint
/api/v1/admin/kyc/customers/metricsGet aggregated metrics for customer KYC verifications across all tenants.
Headers
| Parameter | Type | Required | Description |
|---|---|---|---|
Authorization | string | Yes | Bearer {admin_access_token} |
Query Parameters
| Parameter | Type | Required | Description |
|---|---|---|---|
tenant_id | string | No | Filter metrics by tenant UUID |
start_date | string | No | Start date for metrics period (ISO 8601) |
end_date | string | No | End date for metrics period (ISO 8601) |
granularity | string | No (default: day) | Time granularityValues: hour, day, week, month |
Response- Customer KYC metrics summary
{
"summary": {
"total_profiles": 125000,
"pending": 2500,
"under_review": 450,
"approved": 118000,
"rejected": 3200,
"expired": 850
},
"by_tier": {
"tier_1": 75000,
"tier_2": 35000,
"tier_3": 15000
},
"approval_rate": 0.94,
"avg_review_time_hours": 4.2,
"trend": [
{
"date": "2025-01-13",
"submitted": 450,
"approved": 420,
"rejected": 25
},
{
"date": "2025-01-14",
"submitted": 520,
"approved": 480,
"rejected": 30
}
]
}Error Responses
| Status | Code | Description |
|---|---|---|
| 401 | unauthorized | Missing or invalid admin JWT |
| 403 | forbidden | Admin role required |
Business KYC Metrics
Platform-wide business KYC verification metrics.
Endpoint
/api/v1/admin/kyc/businesses/metricsGet aggregated metrics for business KYC verifications across all tenants.
Headers
| Parameter | Type | Required | Description |
|---|---|---|---|
Authorization | string | Yes | Bearer {admin_access_token} |
Query Parameters
| Parameter | Type | Required | Description |
|---|---|---|---|
tenant_id | string | No | Filter metrics by tenant UUID |
start_date | string | No | Start date for metrics period (ISO 8601) |
end_date | string | No | End date for metrics period (ISO 8601) |
Response- Business KYC metrics summary
{
"summary": {
"total_profiles": 45000,
"pending": 800,
"under_review": 150,
"approved": 42000,
"rejected": 1800,
"expired": 250
},
"by_type": {
"sole_proprietorship": 18000,
"partnership": 8000,
"limited_company": 17000,
"ngo": 2000
},
"approval_rate": 0.91,
"avg_review_time_hours": 8.5,
"trend": [
{
"date": "2025-01-13",
"submitted": 120,
"approved": 105,
"rejected": 12
}
]
}Error Responses
| Status | Code | Description |
|---|---|---|
| 401 | unauthorized | Missing or invalid admin JWT |
| 403 | forbidden | Admin role required |
Tenant KYC Summary
Get KYC summary for a specific tenant.
Endpoint
/api/v1/admin/tenants/{tenantID}/kyc/summaryGet a comprehensive KYC summary for a specific tenant including counts by status and type.
Headers
| Parameter | Type | Required | Description |
|---|---|---|---|
Authorization | string | Yes | Bearer {admin_access_token} |
Path Parameters
| Parameter | Type | Required | Description |
|---|---|---|---|
tenantID | string | Yes | UUID of the tenant |
Response- Tenant KYC summary
{
"tenant_id": "tenant_770e8400-e29b-41d4-a716-446655440002",
"tenant_name": "Acme Corp",
"customers": {
"total": 15000,
"pending": 250,
"under_review": 45,
"approved": 14200,
"rejected": 400,
"expired": 105
},
"businesses": {
"total": 2500,
"pending": 80,
"under_review": 15,
"approved": 2300,
"rejected": 85,
"expired": 20
},
"compliance_score": 0.96,
"last_updated": "2025-01-14T15:30:00Z"
}Error Responses
| Status | Code | Description |
|---|---|---|
| 401 | unauthorized | Missing or invalid admin JWT |
| 403 | forbidden | Admin role required |
| 404 | tenant_not_found | Tenant does not exist |
KYC Profile Overview
Get a high-level overview of a KYC profile.
Endpoint
/api/v1/admin/kyc/{profileID}/overviewGet a summary overview of a KYC profile including status, tier, and key information.
Headers
| Parameter | Type | Required | Description |
|---|---|---|---|
Authorization | string | Yes | Bearer {admin_access_token} |
Path Parameters
| Parameter | Type | Required | Description |
|---|---|---|---|
profileID | string | Yes | UUID of the KYC profile |
Response- KYC profile overview
{
"profile_id": "kyc_550e8400-e29b-41d4-a716-446655440000",
"type": "customer",
"status": "pending",
"current_tier": "tier_1",
"requested_tier": "tier_2",
"tenant_id": "tenant_770e8400-e29b-41d4-a716-446655440002",
"tenant_name": "Acme Corp",
"entity": {
"id": "cust_660e8400-e29b-41d4-a716-446655440001",
"name": "John Doe",
"email": "john.doe@example.com",
"phone": "+2348012345678"
},
"documents_summary": {
"total": 3,
"verified": 1,
"pending": 2,
"rejected": 0
},
"submitted_at": "2025-01-14T10:00:00Z",
"sla_deadline": "2025-01-16T10:00:00Z",
"days_pending": 0
}Error Responses
| Status | Code | Description |
|---|---|---|
| 401 | unauthorized | Missing or invalid admin JWT |
| 404 | profile_not_found | KYC profile not found |
KYC Profile Details
Get complete details of a KYC profile including all documents.
Endpoint
/api/v1/admin/kyc/{profileID}/detailsGet full details of a KYC profile including all submitted documents, verification results, and metadata.
Headers
| Parameter | Type | Required | Description |
|---|---|---|---|
Authorization | string | Yes | Bearer {admin_access_token} |
Path Parameters
| Parameter | Type | Required | Description |
|---|---|---|---|
profileID | string | Yes | UUID of the KYC profile |
Response- Complete KYC profile details
{
"profile_id": "kyc_550e8400-e29b-41d4-a716-446655440000",
"type": "customer",
"status": "pending",
"current_tier": "tier_1",
"requested_tier": "tier_2",
"tenant_id": "tenant_770e8400-e29b-41d4-a716-446655440002",
"entity": {
"id": "cust_660e8400-e29b-41d4-a716-446655440001",
"full_name": "John Doe",
"email": "john.doe@example.com",
"phone": "+2348012345678",
"date_of_birth": "1990-05-15",
"nationality": "NG",
"address": {
"line1": "123 Main Street",
"city": "Lagos",
"state": "Lagos",
"country": "NG",
"postal_code": "100001"
}
},
"documents": [
{
"document_id": "doc_220e8400-e29b-41d4-a716-446655440006",
"type": "national_id",
"status": "verified",
"file_url": "https://storage.example.com/docs/...",
"extracted_data": {
"id_number": "A12345678",
"expiry_date": "2028-05-15"
},
"verified_at": "2025-01-14T11:00:00Z",
"uploaded_at": "2025-01-14T10:00:00Z"
},
{
"document_id": "doc_330e8400-e29b-41d4-a716-446655440007",
"type": "proof_of_address",
"status": "pending",
"file_url": "https://storage.example.com/docs/...",
"uploaded_at": "2025-01-14T10:05:00Z"
},
{
"document_id": "doc_440e8400-e29b-41d4-a716-446655440008",
"type": "selfie",
"status": "pending",
"file_url": "https://storage.example.com/docs/...",
"liveness_score": 0.98,
"face_match_score": 0.95,
"uploaded_at": "2025-01-14T10:10:00Z"
}
],
"verification_checks": [
{
"check_type": "identity_verification",
"status": "passed",
"provider": "smile_id",
"completed_at": "2025-01-14T11:00:00Z"
},
{
"check_type": "address_verification",
"status": "pending",
"provider": "internal"
}
],
"submitted_at": "2025-01-14T10:00:00Z",
"created_at": "2025-01-10T08:00:00Z",
"updated_at": "2025-01-14T11:00:00Z"
}Error Responses
| Status | Code | Description |
|---|---|---|
| 401 | unauthorized | Missing or invalid admin JWT |
| 404 | profile_not_found | KYC profile not found |
KYC Profile History
Get the audit history of a KYC profile.
Endpoint
/api/v1/admin/kyc/{profileID}/historyGet the complete audit trail for a KYC profile including all status changes, document uploads, and admin actions.
Headers
| Parameter | Type | Required | Description |
|---|---|---|---|
Authorization | string | Yes | Bearer {admin_access_token} |
Path Parameters
| Parameter | Type | Required | Description |
|---|---|---|---|
profileID | string | Yes | UUID of the KYC profile |
Query Parameters
| Parameter | Type | Required | Description |
|---|---|---|---|
limit | integer | No (default: 50) | Number of history entries to return |
offset | integer | No (default: 0) | Offset for pagination |
Response- KYC profile audit history
{
"profile_id": "kyc_550e8400-e29b-41d4-a716-446655440000",
"history": [
{
"event_id": "evt_550e8400-e29b-41d4-a716-446655440009",
"event_type": "document_uploaded",
"description": "Selfie document uploaded",
"actor": {
"type": "customer",
"id": "cust_660e8400-e29b-41d4-a716-446655440001"
},
"metadata": {
"document_type": "selfie"
},
"timestamp": "2025-01-14T10:10:00Z"
},
{
"event_id": "evt_660e8400-e29b-41d4-a716-446655440010",
"event_type": "verification_completed",
"description": "Identity verification passed",
"actor": {
"type": "system",
"id": "smile_id"
},
"metadata": {
"check_type": "identity_verification",
"result": "passed"
},
"timestamp": "2025-01-14T11:00:00Z"
},
{
"event_id": "evt_770e8400-e29b-41d4-a716-446655440011",
"event_type": "status_changed",
"description": "Status changed from draft to pending",
"actor": {
"type": "customer",
"id": "cust_660e8400-e29b-41d4-a716-446655440001"
},
"metadata": {
"from_status": "draft",
"to_status": "pending"
},
"timestamp": "2025-01-14T10:15:00Z"
}
],
"total": 3,
"limit": 50,
"offset": 0
}Error Responses
| Status | Code | Description |
|---|---|---|
| 401 | unauthorized | Missing or invalid admin JWT |
| 404 | profile_not_found | KYC profile not found |
Approve KYC
Approve a KYC profile and upgrade the entity's verification tier.
Endpoint
/api/v1/admin/kyc/{profileID}/approveApprove a KYC profile. This will update the entity's verification tier and mark the profile as approved.
Headers
| Parameter | Type | Required | Description |
|---|---|---|---|
Authorization | string | Yes | Bearer {admin_access_token} |
Content-Type | string | Yes | application/json |
Path Parameters
| Parameter | Type | Required | Description |
|---|---|---|---|
profileID | string | Yes | UUID of the KYC profile to approve |
Request Body- Approval details
{
"tier": "tier_2",
"notes": "All documents verified successfully",
"notify_entity": true
}Response- KYC profile approved
{
"profile_id": "kyc_550e8400-e29b-41d4-a716-446655440000",
"status": "approved",
"tier": "tier_2",
"approved_at": "2025-01-14T16:00:00Z",
"approved_by": "admin_880e8400-e29b-41d4-a716-446655440012",
"entity_id": "cust_660e8400-e29b-41d4-a716-446655440001",
"notification_sent": true
}Error Responses
| Status | Code | Description |
|---|---|---|
| 400 | invalid_status | Profile is not in a reviewable status |
| 400 | documents_incomplete | Not all required documents are verified |
| 401 | unauthorized | Missing or invalid admin JWT |
| 404 | profile_not_found | KYC profile not found |
Request Body Parameters
| Field | Type | Required | Description |
|---|---|---|---|
| tier | string | No | Tier to assign (defaults to requested tier) |
| notes | string | No | Internal approval notes |
| notify_entity | boolean | No | Send notification to customer/business (default: true) |
Reject KYC
Reject a KYC profile with a reason.
Endpoint
/api/v1/admin/kyc/{profileID}/rejectReject a KYC profile. A rejection reason is required and will be communicated to the entity if notification is enabled.
Headers
| Parameter | Type | Required | Description |
|---|---|---|---|
Authorization | string | Yes | Bearer {admin_access_token} |
Content-Type | string | Yes | application/json |
Path Parameters
| Parameter | Type | Required | Description |
|---|---|---|---|
profileID | string | Yes | UUID of the KYC profile to reject |
Request Body- Rejection details
{
"reason": "document_mismatch",
"reason_details": "The name on the ID does not match the account name",
"documents_to_resubmit": [
"national_id"
],
"internal_notes": "Possible fraud attempt - flagged for review",
"notify_entity": true,
"allow_resubmission": true
}Response- KYC profile rejected
{
"profile_id": "kyc_550e8400-e29b-41d4-a716-446655440000",
"status": "rejected",
"rejected_at": "2025-01-14T16:30:00Z",
"rejected_by": "admin_880e8400-e29b-41d4-a716-446655440012",
"reason": "document_mismatch",
"can_resubmit": true,
"notification_sent": true
}Error Responses
| Status | Code | Description |
|---|---|---|
| 400 | invalid_status | Profile is not in a reviewable status |
| 400 | reason_required | Rejection reason is required |
| 401 | unauthorized | Missing or invalid admin JWT |
| 404 | profile_not_found | KYC profile not found |
Request Body Parameters
| Field | Type | Required | Description |
|---|---|---|---|
| reason | string | Yes | Rejection reason code (document_mismatch, document_expired, document_unreadable, suspicious_activity, incomplete_information) |
| reason_details | string | No | Human-readable explanation for the entity |
| documents_to_resubmit | array | No | List of document types that need to be resubmitted |
| internal_notes | string | No | Internal notes (not visible to entity) |
| notify_entity | boolean | No | Send notification to customer/business (default: true) |
| allow_resubmission | boolean | No | Allow the entity to resubmit (default: true) |
Rejection Reason Codes
| Code | Description |
|---|---|
| document_mismatch | Information on document doesn't match provided details |
| document_expired | Document has expired |
| document_unreadable | Document image is unclear or unreadable |
| suspicious_activity | Potential fraud or suspicious activity detected |
| incomplete_information | Required information is missing |