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 |
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 |