π KYC Service Java
A robust, multi-tenant Know Your Customer (KYC) microservice built with Spring Boot, designed to handle advanced KYC workflows, provider integrations, and compliance checks. This service is production-ready, highly scalable, and observability-enabled.
π Features
- Multi-Tenant Support: All entities and APIs are tenant-aware.
- Comprehensive KYC Workflow: Individual and business KYC with initiation, basic info, ID verification, bank verification, suitability, and compliance checks.
- Business KYC: Full business onboarding with document uploads, ownership verification, risk assessment, compliance monitoring, and structured address management.
- Provider Integrations: Pluggable AML, KYC, and bank verification providers.
- Document Management: Centralized document service integration with validation for all uploads.
- Document Categorization: Structured document types with categories (identity, financial, business) and sides (front/back/selfie).
- Pagination Support: All list endpoints support pagination with standardized response format.
- OpenAPI/Swagger Documentation: Auto-generated API documentation with examples.
- Observability: Loki, Prometheus, and OpenTelemetry for logging, metrics, and tracing.
- Service Discovery: Eureka integration for microservice environments.
- Database Migrations: Managed with Flyway.
- Validation: Strong input validation using Jakarta Bean Validation.
- Error Handling: Centralized, consistent error responses.
- Dockerized: Ready for local and UAT deployments.
οΏ½ Document Management
The service integrates with a centralized Document Service for secure document handling:
- UUID-based References: All document uploads use UUIDs from the document service instead of direct URLs
- Validation: Documents are validated to exist before association with entities
- Security: Prevents arbitrary URL injection and ensures document ownership
- Standardization: Consistent document upload pattern across individual and business KYC
Document Upload Flow: 1. Upload document to Document Service β Receive UUID 2. Submit UUID in KYC request β Service validates document exists 3. Document associated with entity β Download URL provided in responses
π Document Types & Categories
The service supports structured document categorization for both individual and business KYC:
Document Types (Sides)
FRONT- Front side of identity documentsBACK- Back side of identity documentsSELFIE- Selfie photos for biometric verification
Business Document Categories
PASSPORT- Passport documentsDRIVER_LICENSE- Driver's licenseNATIONAL_ID- National ID cardRESIDENCE_PERMIT- Residence permitBANK_STATEMENT- Bank statementsTAX_RETURN- Tax return documentsFINANCIAL_STATEMENT- Financial statementsPAY_STUB- Pay stubsBUSINESS_LICENSE- Business operating licensesARTICLES_OF_INCORPORATION- Articles of incorporationBYLAWS- Company bylawsOPERATING_AGREEMENT- Operating agreementsUTILITY_BILL- Utility bills (proof of address)BANK_STATEMENT_ADDRESS- Bank statements (proof of address)LEASE_AGREEMENT- Lease agreements (proof of address)OTHER- Other document types
Proof of Address
Businesses can provide proof of address by uploading supporting documents using the standard document upload endpoints. The service supports multiple document types for address verification:
- Utility Bills: Electricity, water, gas, internet, or phone bills
- Bank Statements: Recent bank statements showing business address
- Lease Agreements: Commercial lease or rental agreements
Upload Proof of Address:
POST /api/v1/business/{businessId}/documents
{
"documentType": "FRONT",
"documentCategory": "UTILITY_BILL",
"fileName": "utility_bill.pdf",
"documentId": "uuid-from-document-service",
"description": "Recent utility bill for address verification"
}
All proof of address documents are subject to the same validation and security measures as other business documents.
οΏ½ποΈ Architecture
sequenceDiagram
participant User
participant Frontend
participant Backend
participant KYC_Provider(Jumio/Onfido)
participant AML_Provider(Socure/LexisNexis)
participant Bank_Provider(Plaid)
Note over User,Frontend: 1. Registration
User->>Frontend: Enters email/phone
Frontend->>Backend: Submit credentials
Backend-->>Frontend: Send OTP
User->>Frontend: Inputs OTP
Frontend->>Backend: Verify OTP
Backend-->>Frontend: "OTP valid"
Note over User,Frontend: 2. Profile Setup
User->>Frontend: Inputs name, DOB, address, SSN
Frontend->>Backend: Submit profile data
Backend->>AML_Provider: Validate SSN/address
AML_Provider-->>Backend: Risk score + fraud flags
alt SSN valid & low risk
Backend-->>Frontend: "Profile approved"
else SSN issue
Backend-->>Frontend: "Reject: SSN mismatch"
end
Note over User,Frontend: 3. ID Verification
User->>Frontend: Uploads ID + selfie
Frontend->>KYC_Provider: Send ID/selfie
KYC_Provider-->>Backend: Liveness result + ID match
alt ID valid
Backend-->>Frontend: "ID verified"
else ID rejected
Backend-->>Frontend: "Reject: ID expired"
end
Note over User,Frontend: 4. Suitability Quiz
User->>Frontend: Answers income/experience
Frontend->>Backend: Submit responses
Backend-->>Frontend: Set trading limits
Note over User,Frontend: 5. Bank Linking
User->>Frontend: Selects bank (Plaid/micro-deposits)
Frontend->>Bank_Provider: Initiate auth
Bank_Provider-->>Backend: Account ownership
alt Account valid
Backend-->>Frontend: "Bank linked"
else Name mismatch
Backend-->>Frontend: "Reject: bank account"
end
Note over Backend: 6. Final Approval
Backend->>AML_Provider: OFAC/PEP screening
alt Clean record
Backend-->>Frontend: "Account approved"
Backend->>User: Email confirmation
else High risk
Backend->>Backend: Manual review (24-72h)
end
Business KYC Flow: The service also supports comprehensive business KYC with similar workflow but includes: - Business registration and profile setup with structured address information - Beneficial owner and director verification - Document uploads (certificates, financials, licenses, proof of address) - Address verification through supporting documents (utility bills, bank statements, leases) - Risk scoring and compliance monitoring - Ongoing AML/media monitoring
π οΈ Getting Started
Prerequisites
- Java 17+
- Docker & Docker Compose
- PostgreSQL
Local Development
git clone https://github.com/olara-tech/kyc-service-java.git
cd kyc-service-java
docker-compose -f docker-compose-uat.yml up --build
Access Services: - KYC API: http://localhost:10010/api/v1/kyc - Swagger UI: http://localhost:10010/swagger-ui.html - Eureka Dashboard: http://localhost:8761 - Loki: http://localhost:3100
π API Endpoints & Payloads
User Endpoints
| Endpoint | Method | Description |
|---|---|---|
/api/v1/kyc/initiate |
POST | Initiate KYC process |
/api/v1/kyc/basic-info |
POST | Submit basic info |
/api/v1/kyc/status |
GET | Get KYC status |
/api/v1/kyc/callbacks/id-verification |
POST | ID verification callback |
/api/v1/kyc/callbacks/bank-verification |
POST | Bank verification callback |
/api/v1/verification/id-verification |
POST | Start ID verification |
/api/v1/verification/bank-verification |
POST | Start bank verification (deprecated) |
/api/v1/verification/employer-verification |
POST/GET/PUT/DELETE | Employer verification CRUD |
/api/v1/verification/tax-id-verification |
POST | Verify tax ID |
/api/v1/verification/tax-id-types |
GET | Get supported tax ID types |
/api/v1/suitability/responses |
POST | Submit suitability responses |
/api/v1/suitability/responses |
GET | Get all suitability responses (paginated) |
Admin Endpoints
| Endpoint | Method | Description |
|---|---|---|
/api/v1/admin/kyc/basic-info |
POST | Admin submit basic info for user |
/api/v1/admin/kyc/address-info |
POST | Admin update address for user |
/api/v1/admin/kyc/us-person-status |
POST | Admin submit US person status for user |
/api/v1/admin/kyc/update-verification-status |
POST | Admin update verification status for user |
/api/v1/admin/kyc/overall-status |
GET | Admin get overall KYC status for user |
/api/v1/admin/verification/bank-verification |
POST/GET | Admin bank verification for user (POST deprecated) |
/api/v1/admin/verification/employer-verification |
POST/GET/PUT | Admin employer verification for user |
/api/v1/admin/verification/id-verification |
POST | Admin initiate ID verification for user |
/api/v1/admin/verification/tax-id-verification |
POST | Admin submit tax ID verification for user |
/api/v1/admin/verification/ssn-verification |
POST | Admin submit SSN verification for user |
/api/v1/admin/suitability/responses/user/{userId} |
GET | Admin get all suitability responses for user (paginated) |
/api/v1/admin/suitability/responses/user/{userId} |
POST | Admin submit suitability responses for user |
Standard Error Response
All endpoints return errors in the following format: ```json { "timestamp": "2025-05-04T07:00:00Z", "status": 400, "error": "Bad Request", "message": "Validation failed: ...", "path": "/api/v1/kyc/..." }
Headers:
| Field | Type | Description |
|---|---|---|
| timestamp | String | Error timestamp (ISO 8601) |
| status | Number | HTTP status code |
| error | String | Error type |
| message | String | Error message |
| path | String | Request path |
1. Initiate KYC Process
POST /api/v1/kyc/initiate
β¨ Initiates a new KYC profile for a current user and tenant. Returns the created KYC profile object.
Response:
{
"id": "b1c2d3e4-5678-1234-9abc-def012345678",
"tenantId": "123e4567-e89b-12d3-a456-426614174001",
"userId": "123e4567-e89b-12d3-a456-426614174000",
"status": "NOT_STARTED",
"ssnLastFour": null,
"dateOfBirth": null,
"addressId": null,
"amlRiskScore": null,
"amlProviderReference": null,
"pepFlag": false,
"sanctionsFlag": false,
"adverseMediaFlag": false,
"createdBy": "system",
"updatedBy": "system",
"address": null,
"created": "2025-05-04T07:00:00Z",
"updated": "2025-05-04T07:00:00Z"
}
Error Response Example:
{
"timestamp": "2025-05-04T07:00:00Z",
"status": 400,
"error": "Bad Request",
"message": "Validation failed: userId is required",
"path": "/api/v1/kyc/initiate"
}
2. Submit Basic Information
POST /api/v1/kyc/basic-info
β¨ Submits the user's basic information and address for KYC. Performs an AML check and updates the KYC profile.
Headers:
| Header | Type | Description |
|---|---|---|
| userId | UUID | User identifier |
| corporate-tenantId | UUID | Tenant identifier |
Request:
{
"ssnLastFour": "1234",
"dateOfBirth": "1990-01-01",
"addressDto": {
"address": "123 Main St",
"city": "New York",
"state": "NY",
"zipCode": "10001",
"country": "USA"
}
}
Response:
{
"id": "b1c2d3e4-5678-1234-9abc-def012345678",
"tenantId": "123e4567-e89b-12d3-a456-426614174001",
"userId": "123e4567-e89b-12d3-a456-426614174000",
"status": "BASIC_INFO_SUBMITTED",
"ssnLastFour": "1234",
"dateOfBirth": "1990-01-01",
"addressId": "aabbccdd-1234-5678-9abc-def012345678",
"amlRiskScore": "LOW",
"amlProviderReference": "aml-123456",
"pepFlag": false,
"sanctionsFlag": false,
"adverseMediaFlag": false,
"createdBy": "system",
"updatedBy": "system",
"address": {
"address": "123 Main St",
"city": "New York",
"state": "NY",
"zipCode": "10001",
"country": "USA"
},
"created": "2025-05-04T07:00:00Z",
"updated": "2025-05-04T07:00:00Z"
}
Error Response Example:
{
"timestamp": "2025-05-04T07:00:00Z",
"status": 400,
"error": "Bad Request",
"message": "Validation failed: ssnLastFour is required",
"path": "/api/v1/kyc/basic-info"
}
3. Start ID Verification
POST /api/v1/verification/id-verification
β¨ Starts the ID verification process for a user. Accepts document and selfie images, and returns the verification record.
Headers:
| Header | Type | Description |
|---|---|---|
| userId | UUID | User identifier |
| corporate-tenantId | UUID | Tenant identifier |
Request:
{
"idType": "PASSPORT",
"idNumber": "A12345678",
"issuingCountry": "USA",
"expiryDate": "2030-01-01",
"frontImage": "<base64 or binary>",
"backImage": "<base64 or binary>",
"selfieImage": "<base64 or binary>"
}
Response:
{
"id": "idv-1234-5678-9abc-def012345678",
"userId": "123e4567-e89b-12d3-a456-426614174000",
"tenantId": "123e4567-e89b-12d3-a456-426614174001",
"kycProfileId": "b1c2d3e4-5678-1234-9abc-def012345678",
"idType": "PASSPORT",
"idNumber": "A12345678",
"issuingCountry": "USA",
"expiryDate": "2030-01-01",
"status": "PENDING",
"provider": "kyc-provider",
"providerReference": "kyc-123456",
"created": "2025-05-04T07:00:00Z",
"updated": "2025-05-04T07:00:00Z"
}
Error Response Example:
{
"timestamp": "2025-05-04T07:00:00Z",
"status": 422,
"error": "Unprocessable Entity",
"message": "Invalid ID document type",
"path": "/api/v1/verification/id-verification"
}
π οΈ Getting Started
Prerequisites
- Java 17+
- Docker & Docker Compose
- PostgreSQL
Local Development
git clone https://github.com/olara-tech/kyc-service-java.git
cd kyc-service-java
docker-compose -f docker-compose-uat.yml up --build
Access Services: - KYC API: http://localhost:10010/api/v1/kyc - Swagger UI: http://localhost:10010/swagger-ui.html - Eureka Dashboard: http://localhost:8761 - Loki: http://localhost:3100
π API Endpoints & Payloads
User Endpoints
| Endpoint | Method | Description |
|---|---|---|
/api/v1/kyc/initiate |
POST | Initiate KYC process |
/api/v1/kyc/basic-info |
POST | Submit basic information |
/api/v1/kyc/address-info |
POST | Update personal address information |
/api/v1/kyc/status |
GET | Get KYC status |
/api/v1/kyc/us-person-status |
POST | Submit US person status |
/api/v1/kyc/overall-status |
GET | Get overall KYC status |
/api/v1/verification/id-verification |
POST | Start ID verification |
/api/v1/verification/bank-verification |
GET | Get bank verification status |
/api/v1/verification/bank-verification |
POST | Start bank verification (deprecated) |
/api/v1/verification/employer-verification |
POST | Create employer verification |
/api/v1/verification/employer-verification |
PUT | Update employer verification |
/api/v1/verification/employer-verification |
GET | Get employer verification for current user |
/api/v1/verification/tax-id-verification |
POST | Verify tax ID |
/api/v1/verification/id-types |
GET | Get supported tax ID types |
/api/v1/verification/ssn-verification |
POST | Verify Social Security Number |
/api/v1/suitability/responses |
POST | Submit suitability responses |
/api/v1/suitability/questions |
GET | Get all suitability questions (paginated) |
/api/v1/suitability/questions/{id} |
GET | Get suitability question by ID |
/api/v1/suitability/responses |
GET | Get all suitability responses for current user |
Business Endpoints
| Endpoint | Method | Description |
|---|---|---|
/api/v1/business |
POST | Register a new business |
/api/v1/business/{id} |
GET | Get business details by ID |
/api/v1/business |
GET | Get businesses (paginated) |
/api/v1/business/{id} |
PUT | Update business information |
/api/v1/business/{id}/address |
PUT | Update business address |
/api/v1/business/{id}/owners |
POST | Add beneficial owner (>25%) |
/api/v1/business/{id}/owners |
GET | List UBOs linked to a business |
/api/v1/business/{id}/directors |
POST | Add directors/board members |
/api/v1/business/{id}/directors |
GET | List directors for a business |
/api/v1/business/{id}/documents |
POST | Upload business documents |
/api/v1/business/{id}/documents |
GET | Retrieve uploaded business documents (paginated) |
/api/v1/business/{id}/documents/{docId} |
DELETE | Delete business document |
/api/v1/business/{id}/financials |
POST | Upload financial documents |
/api/v1/business/{id}/financials |
GET | Retrieve financial records (paginated) |
/api/v1/business/{id}/licenses |
POST | Upload business licenses |
/api/v1/business/{id}/licenses |
GET | Get list of business licenses (paginated) |
Admin Business Endpoints
| Endpoint | Method | Description |
|---|---|---|
/api/v1/admin/business |
GET | Get businesses (paginated, admin view) |
/api/v1/admin/business/register |
POST | Admin register a new business |
/api/v1/admin/business/{id} |
GET | Admin get business details by ID |
/api/v1/admin/business/{id} |
PUT | Admin update business information |
/api/v1/admin/business/{id}/address |
PUT | Admin update business address |
/api/v1/admin/business/{id} |
DELETE | Admin archive/deactivate a business |
π’ Business Onboarding Workflow
Overview
Business onboarding involves multiple sequential phases: registration, ownership verification, document collection, compliance screening, risk assessment, and workflow management. The process supports both single business and bulk operations for tenants.
Phase 1: Business Registration
Step 1.1: Register Business Profile
Purpose: Create the core business entity with basic information and validate uniqueness
API: POST /api/v1/business (or POST /api/v1/admin/business/register for admin bulk)
Required Fields:
{
"legalName": "Acme Corporation",
"registrationNumber": "REG123456",
"businessStructure": "CORPORATION",
"address": {
"address": "123 Business St",
"city": "Business City",
"state": "State",
"country": "Country",
"zipCode": "12345",
"nearestLandmark": "Near Central Park"
}
}
BusinessDto with generated business ID and PENDING status
Step 1.2: Add Beneficial Owners (UBOs)
Purpose: Identify individuals with >25% ownership for KYC compliance and regulatory reporting
API: POST /api/v1/business/{businessId}/owners
Required Fields:
{
"firstName": "John",
"lastName": "Smith",
"email": "john.smith@acme.com",
"phoneNumber": "+1-555-0123",
"ownershipPercentage": 60.5
}
Step 1.3: Add Directors/Board Members
Purpose: Establish corporate governance structure and key decision-makers
API: POST /api/v1/business/{businessId}/directors
Required Fields:
{
"firstName": "Jane",
"lastName": "Doe",
"email": "jane.doe@acme.com",
"phoneNumber": "+1-555-0124",
"position": "CEO"
}
Phase 2: Document Collection
Step 2.1: Upload Business Documents
Purpose: Collect incorporation certificates, bylaws, and legal formation documents
API: POST /api/v1/business/{businessId}/documents
Required Fields:
{
"documentType": "CERTIFICATE_OF_INCORPORATION",
"documentCategory": "LEGAL",
"fileName": "incorporation_cert.pdf",
"documentId": "uuid-from-document-service",
"description": "Certificate of Incorporation"
}
Step 2.2: Upload Financial Documents
Purpose: Verify financial health, revenue, and regulatory compliance
API: POST /api/v1/business/{businessId}/financials
Required Fields:
{
"documentType": "FINANCIAL_STATEMENT",
"fileName": "financial_statement_2024.pdf",
"documentId": "uuid-from-document-service",
"annualRevenue": 5000000.00,
"fiscalYearEnd": "2024-12-31",
"description": "2024 Financial Statement"
}
Step 2.3: Upload Business Licenses
Purpose: Verify regulatory approvals, operating licenses, and industry certifications
API: POST /api/v1/business/{businessId}/licenses
Required Fields:
{
"licenseType": "BUSINESS_LICENSE",
"licenseNumber": "LIC123456",
"issuingAuthority": "State Business Bureau",
"issueDate": "2024-01-01",
"expiryDate": "2025-12-31",
"fileName": "business_license.pdf",
"documentId": "uuid-from-document-service",
"description": "State Business License"
}
Phase 3: Compliance & Risk Assessment
Step 3.1: Trigger AML/PEP Screening
Purpose: Screen business and owners against sanctions, PEP lists, and adverse media
API: POST /api/v1/admin/business/{businessId}/screening (Admin only)
Response: Initiates background screening process, returns screening status
Step 3.2: Calculate Risk Score
Purpose: Assess overall business risk based on screening results, transaction history, and compliance factors
API: POST /api/v1/admin/business/{businessId}/risk-score (Admin only)
Response: Returns comprehensive risk score (0.0-1.0) with breakdown by risk factors
Step 3.3: Enable Ongoing Monitoring
Purpose: Set up continuous AML/media monitoring for regulatory compliance
API: POST /api/v1/business/{businessId}/monitoring/start
Response: Enables continuous monitoring service with periodic re-verification
Phase 4: Workflow Management
Step 4.1: Start Onboarding Workflow
Purpose: Initialize the approval workflow process and create workflow tracking
API: POST /api/v1/business/{businessId}/workflow/start
Response: Creates workflow entity with initial INTAKE status
Step 4.2: Monitor Workflow Status
Purpose: Track current stage of the onboarding process and identify bottlenecks
API: GET /api/v1/business/{businessId}/workflow/status
Response: Returns current workflow stage and progress details
Step 4.3: Make Workflow Decision
Purpose: Approve, reject, or escalate the business application based on compliance review
API: POST /api/v1/business/{businessId}/decision
Request:
{
"decision": "APPROVE" // APPROVE, REJECT, or ESCALATE
}
INTAKE β SCREENING β MANUAL_REVIEW β APPROVED/REJECTED
Bulk Operations for Multiple Businesses
Admin Bulk Registration
Purpose: Efficiently onboard multiple businesses with owners and directors in a single operation
API: POST /api/v1/admin/business/register
Request:
{
"tenantId": "tenant-uuid",
"legalName": "Bulk Business Corp",
"registrationNumber": "BULK123",
"businessStructure": "CORPORATION",
"address": {
"address": "123 Main St",
"city": "Business City",
"state": "State",
"country": "Country",
"zipCode": "12345",
"nearestLandmark": "Near Downtown"
},
"owners": [
{
"firstName": "John",
"lastName": "Owner",
"email": "john@bulk.com",
"phoneNumber": "+1234567890",
"ownershipPercentage": 50.0
}
],
"directors": [
{
"firstName": "Jane",
"lastName": "Director",
"email": "jane@bulk.com",
"phoneNumber": "+1234567891",
"position": "CEO"
}
]
}
Monitoring & Audit
View Complete Audit Trail
Purpose: Track all onboarding activities, changes, and compliance actions
API: GET /api/v1/business/audit/{businessId}
Generate Compliance Reports
Purpose: Create regulatory compliance documentation and audit reports
API: GET /api/v1/business/reports/compliance
Monitor Ongoing Status
Purpose: Check monitoring alerts, screening updates, and system health
API: GET /api/v1/business/{businessId}/monitoring/logs
Key Features & Optimizations
- Parallel Processing: Owners/directors processed concurrently for bulk operations
- Async Operations: Screening, risk calculation, and audit logging run asynchronously
- Comprehensive Validation: All documents validated through centralized Document Service
- Audit Trail: Complete audit logging of all activities with timestamps and user tracking
- State Management: Robust workflow state transitions with validation
- Caching: High-performance caching for frequent lookups and status checks
This workflow ensures full KYC compliance, risk assessment, and regulatory reporting for business onboarding across single or multiple business scenarios.
Admin Endpoints
| Endpoint | Method | Description |
|---|---|---|
/api/v1/admin/kyc/basic-info |
POST | Admin submit basic info for user |
/api/v1/admin/kyc/address-info |
POST | Admin update address for user |
/api/v1/admin/kyc/us-person-status |
POST | Admin submit US person status for user |
/api/v1/admin/verification/id-verification |
POST | Admin initiate ID verification for user |
/api/v1/admin/verification/bank-verification |
POST | Admin bank verification for user (deprecated) |
/api/v1/admin/verification/employer-verification |
POST | Admin create employer verification for user |
/api/v1/admin/verification/employer-verification |
PUT | Admin update employer verification for user |
/api/v1/admin/verification/tax-id-verification |
POST | Admin submit tax ID verification for user |
/api/v1/admin/verification/ssn-verification |
POST | Admin submit SSN verification for user |
/api/v1/admin/suitability/responses/user/{userId} |
GET | Admin get suitability responses for user |
/api/v1/admin/suitability/responses/user/{userId} |
POST | Admin submit suitability responses for user |
Standard Error Response
All endpoints return errors in the following format:
{ "timestamp": "2025-09-19T12:00:00Z", "status": 400, "error": "Bad Request", "message": "Validation failed: ...", "path": "/api/v1/kyc/..." }
Headers:
| Field | Type | Description |
|---|---|---|
| timestamp | String | Error timestamp (ISO 8601) |
| status | Number | HTTP status code |
| error | String | Error type |
| message | String | Error message |
| path | String | Request path |
1. Initiate KYC Process
POST /api/v1/kyc/initiate
β¨ Initiates a new KYC profile for the current user and tenant.
Response:
{
"success": true,
"message": "KYC process initiated successfully",
"data": {
"id": "b1c2d3e4-5678-1234-9abc-def012345678",
"tenantId": "123e4567-e89b-12d3-a456-426614174001",
"userId": "123e4567-e89b-12d3-a456-426614174000",
"status": "NOT_STARTED",
"firstName": null,
"lastName": null,
"email": null,
"phoneNumber": null,
"dateOfBirth": null,
"countryOfResidence": null,
"gender": null,
"usResidence": false,
"countryOfResidence": null,
"pepFlag": false,
"sanctionsFlag": false,
"adverseMediaFlag": false,
"createdAt": "2025-09-19T12:00:00Z",
"updatedAt": "2025-09-19T12:00:00Z"
}
}
2. Submit Basic Information
POST /api/v1/kyc/basic-info
β¨ Submits the user's basic information for KYC verification.
Request:
{
"firstName": "John",
"lastName": "Doe",
"countryOfResidence": "USA",
"gender": "MALE",
"dateOfBirth": "1990-01-01",
"email": "john.doe@example.com"
}
Response:
{
"success": true,
"message": "Basic information submitted successfully",
"data": {
"id": "b1c2d3e4-5678-1234-9abc-def012345678",
"tenantId": "123e4567-e89b-12d3-a456-426614174001",
"userId": "123e4567-e89b-12d3-a456-426614174000",
"status": "BASIC_INFO_SUBMITTED",
"firstName": "John",
"lastName": "Doe",
"email": "john.doe@example.com",
"phoneNumber": null,
"dateOfBirth": "1990-01-01",
"countryOfResidence": "USA",
"gender": "MALE",
"usResidence": false,
"pepFlag": false,
"sanctionsFlag": false,
"adverseMediaFlag": false,
"createdAt": "2025-09-19T12:00:00Z",
"updatedAt": "2025-09-19T12:00:00Z"
}
}
3. Update Address Information
POST /api/v1/kyc/address-info
β¨ Updates the user's address information for KYC verification.
Request:
{
"address": "456 Elm St",
"city": "Los Angeles",
"state": "CA",
"country": "USA",
"zipCode": "90001",
"nearestLandmark": "Near Central Park"
}
Response:
{
"success": true,
"message": "Address information updated successfully",
"data": {
"id": "b1c2d3e4-5678-1234-9abc-def012345678",
"tenantId": "123e4567-e89b-12d3-a456-426614174001",
"userId": "123e4567-e89b-12d3-a456-426614174000",
"status": "ADDRESS_INFO_SUBMITTED",
"firstName": "John",
"lastName": "Doe",
"email": "john.doe@example.com",
"phoneNumber": null,
"dateOfBirth": "1990-01-01",
"countryOfResidence": "USA",
"gender": "MALE",
"usResidence": false,
"pepFlag": false,
"sanctionsFlag": false,
"adverseMediaFlag": false,
"createdAt": "2025-09-19T12:00:00Z",
"updatedAt": "2025-09-19T12:00:00Z"
}
}
4. Submit US Person Status
POST /api/v1/kyc/us-person-status
β¨ Submits the US person status for tax compliance.
Request:
{
"isUsPerson": true
}
Response:
{
"success": true,
"message": "US person status submitted successfully"
}
5. Get KYC Status
GET /api/v1/kyc/status
β¨ Retrieves the current KYC status for the authenticated user.
Response:
{
"success": true,
"message": "KYC status retrieved successfully",
"data": {
"id": "b1c2d3e4-5678-1234-9abc-def012345678",
"tenantId": "123e4567-e89b-12d3-a456-426614174001",
"userId": "123e4567-e89b-12d3-a456-426614174000",
"status": "BASIC_INFO_SUBMITTED",
"firstName": "John",
"lastName": "Doe",
"email": "john.doe@example.com",
"phoneNumber": null,
"dateOfBirth": "1990-01-01",
"countryOfResidence": "USA",
"gender": "MALE",
"usResidence": false,
"pepFlag": false,
"sanctionsFlag": false,
"adverseMediaFlag": false,
"createdAt": "2025-09-19T12:00:00Z",
"updatedAt": "2025-09-19T12:00:00Z"
}
}
6. Get Overall KYC Status
GET /api/v1/kyc/overall-status
β¨ Retrieves the overall KYC status including all verification steps.
Response:
{
"success": true,
"message": "Overall KYC status retrieved successfully",
"data": {
"kycProfile": {
"id": "b1c2d3e4-5678-1234-9abc-def012345678",
"status": "BASIC_INFO_SUBMITTED",
"firstName": "John",
"lastName": "Doe"
},
"idVerification": {
"status": "PENDING",
"provider": "JUMIO"
},
"bankVerification": {
"status": "NOT_STARTED"
},
"employerVerification": {
"status": "NOT_STARTED"
},
"suitabilityAssessment": {
"status": "NOT_STARTED",
"completedQuestions": 0,
"totalQuestions": 25
},
"overallStatus": "IN_PROGRESS"
}
}
7. Start ID Verification
POST /api/v1/verification/id-verification
β¨ Starts the ID verification process using document UUIDs from the document service.
Request:
{
"idType": "PASSPORT",
"idNumber": "A12345678",
"issuingCountry": "USA",
"expiryDate": "2030-01-01",
"frontImageId": "123e4567-e89b-12d3-a456-426614174000",
"backImageId": "123e4567-e89b-12d3-a456-426614174001",
"selfieImageId": "123e4567-e89b-12d3-a456-426614174002"
}
Response:
{
"success": true,
"message": "ID verification initiated successfully",
"data": {
"id": "idv-1234-5678-9abc-def012345678",
"userId": "123e4567-e89b-12d3-a456-426614174000",
"tenantId": "123e4567-e89b-12d3-a456-426614174001",
"kycProfileId": "b1c2d3e4-5678-1234-9abc-def012345678",
"idType": "PASSPORT",
"idNumber": "A12345678",
"issuingCountry": "USA",
"expiryDate": "2030-01-01",
"frontImageId": "123e4567-e89b-12d3-a456-426614174000",
"backImageId": "123e4567-e89b-12d3-a456-426614174001",
"selfieImageId": "123e4567-e89b-12d3-a456-426614174002",
"status": "PENDING",
"provider": "JUMIO",
"providerReference": "jumio-123456",
"livenessScore": null,
"matchScore": null,
"comment": null,
"createdAt": "2025-09-19T12:00:00Z",
"updatedAt": "2025-09-19T12:00:00Z"
}
}
8. Register Business
POST /api/v1/business
β¨ Registers a new business profile for KYC verification.
Request:
{
"tenantId": "123e4567-e89b-12d3-a456-426614174001",
"legalName": "Acme Corporation",
"registrationNumber": "REG123456",
"businessStructure": "CORPORATION",
"address": "123 Business St, Business City, BC 12345"
}
Response:
{
"success": true,
"message": "Business registered successfully",
"data": {
"id": "biz-1234-5678-9abc-def012345678",
"tenantId": "123e4567-e89b-12d3-a456-426614174001",
"legalName": "Acme Corporation",
"registrationNumber": "REG123456",
"businessStructure": "CORPORATION",
"address": "123 Business St, Business City, BC 12345",
"status": "PENDING",
"createdAt": "2025-09-19T12:00:00Z",
"updatedAt": "2025-09-19T12:00:00Z"
}
}
9. Add Business Owner
POST /api/v1/business/{id}/owners
β¨ Adds a beneficial owner to a business (owners with >25% ownership).
Request:
{
"firstName": "Jane",
"lastName": "Smith",
"email": "jane.smith@example.com",
"phoneNumber": "+1-555-0123",
"ownershipPercentage": 60.5
}
Response:
{
"success": true,
"message": "Business owner added successfully",
"data": {
"id": "own-1234-5678-9abc-def012345678",
"businessId": "biz-1234-5678-9abc-def012345678",
"firstName": "Jane",
"lastName": "Smith",
"email": "jane.smith@example.com",
"phoneNumber": "+1-555-0123",
"ownershipPercentage": 60.5,
"kycStatus": "NOT_STARTED",
"createdAt": "2025-09-19T12:00:00Z",
"updatedAt": "2025-09-19T12:00:00Z"
}
}
10. Submit Suitability Responses
POST /api/v1/suitability/responses
β¨ Submits suitability assessment responses for investment profiling.
Request:
[
{
"questionId": "1290300ce-ecdd-6b7a-816b-83a6ad09f11f",
"optionId": "b1a2c3d4-5678-1234-5678-abcdefabcdef"
},
{
"questionId": "178300e3-367e-634b-8940-1dbbec71d430",
"optionId": "c2b3a4d5-6789-2345-6789-bcdefabcdefa"
}
]
Response:
{
"success": true,
"message": "Suitability responses submitted successfully",
"data": {
"submittedResponses": 2,
"totalQuestions": 25,
"completionPercentage": 8.0,
"riskProfile": "MODERATE",
"nextQuestionId": "239400f4-478f-745c-9a50-2eccfd82e540"
}
}
11. Upload Business Document
POST /api/v1/business/{id}/documents
β¨ Uploads business documents using document service UUIDs with categorized document types.
Request:
{
"documentType": "FRONT",
"documentCategory": "BUSINESS_LICENSE",
"fileName": "business_license_2024.pdf",
"documentId": "123e4567-e89b-12d3-a456-426614174000",
"description": "2024 Business Operating License"
}
Response:
{
"success": true,
"message": "Business document uploaded successfully",
"data": {
"id": "doc-1234-5678-9abc-def012345678",
"businessId": "biz-1234-5678-9abc-def012345678",
"tenantId": "tenant-1234-5678-9abc-def012345678",
"documentType": "FRONT",
"documentCategory": "BUSINESS_LICENSE",
"fileName": "business_license_2024.pdf",
"downloadUrl": "https://document-service.com/download/123e4567-e89b-12d3-a456-426614174000",
"description": "2024 Business Operating License",
"isActive": true,
"created": "2025-09-21T12:00:00Z",
"updated": "2025-09-21T12:00:00Z",
"createdBy": "user-1234-5678-9abc-def012345678",
"updatedBy": "user-1234-5678-9abc-def012345678"
}
}
12. Get Business Documents (Paginated)
GET /api/v1/business/{id}/documents?page=0&size=20&sort=created,desc
β¨ Retrieves uploaded business documents with pagination support.
Response:
{
"content": [
{
"id": "doc-1234-5678-9abc-def012345678",
"businessId": "biz-1234-5678-9abc-def012345678",
"tenantId": "tenant-1234-5678-9abc-def012345678",
"documentType": "FRONT",
"documentCategory": "BUSINESS_LICENSE",
"fileName": "business_license_2024.pdf",
"downloadUrl": "https://document-service.com/download/123e4567-e89b-12d3-a456-426614174000",
"description": "2024 Business Operating License",
"isActive": true,
"created": "2025-09-21T12:00:00Z",
"updated": "2025-09-21T12:00:00Z",
"createdBy": "user-1234-5678-9abc-def012345678",
"updatedBy": "user-1234-5678-9abc-def012345678"
}
],
"pageNumber": 0,
"pageSize": 20,
"totalElements": 1,
"totalPages": 1,
"numberOfElements": 1,
"first": true,
"last": true,
"empty": false
}
13. Get Business Financials (Paginated)
GET /api/v1/business/{id}/financials?page=0&size=20&sort=created,desc
β¨ Retrieves financial records with pagination support.
Response:
{
"content": [
{
"id": "fin-1234-5678-9abc-def012345678",
"businessId": "biz-1234-5678-9abc-def012345678",
"tenantId": "tenant-1234-5678-9abc-def012345678",
"documentType": "FINANCIAL_STATEMENT",
"fileName": "annual_financial_2024.pdf",
"downloadUrl": "https://document-service.com/download/456e7890-e89b-12d3-a456-426614174001",
"annualRevenue": 2500000.00,
"fiscalYearEnd": "2024-12-31",
"description": "2024 Annual Financial Statement",
"created": "2025-09-21T12:00:00Z",
"updated": "2025-09-21T12:00:00Z",
"createdBy": "user-1234-5678-9abc-def012345678",
"updatedBy": "user-1234-5678-9abc-def012345678"
}
],
"pageNumber": 0,
"pageSize": 20,
"totalElements": 1,
"totalPages": 1,
"numberOfElements": 1,
"first": true,
"last": true,
"empty": false
}
14. Get Business Licenses (Paginated)
GET /api/v1/business/{id}/licenses?page=0&size=20&sort=created,desc
β¨ Retrieves business licenses with pagination support.
Response:
{
"content": [
{
"id": "lic-1234-5678-9abc-def012345678",
"businessId": "biz-1234-5678-9abc-def012345678",
"tenantId": "tenant-1234-5678-9abc-def012345678",
"licenseType": "Business License",
"licenseNumber": "BL2024001",
"issuingAuthority": "State Business Bureau",
"issueDate": "2024-01-01",
"expiryDate": "2024-12-31",
"fileName": "business_license_2024.pdf",
"downloadUrl": "https://document-service.com/download/789e0123-e89b-12d3-a456-426614174002",
"description": "2024 Business Operating License",
"created": "2025-09-21T12:00:00Z",
"updated": "2025-09-21T12:00:00Z",
"createdBy": "user-1234-5678-9abc-def012345678",
"updatedBy": "user-1234-5678-9abc-def012345678"
}
],
"pageNumber": 0,
"pageSize": 20,
"totalElements": 1,
"totalPages": 1,
"numberOfElements": 1,
"first": true,
"last": true,
"empty": false
}
/api/v1/admin/kyc/basic-info?userId={userId}
β¨ Allows administrators to submit basic information on behalf of a user.
Request:
{
"firstName": "John",
"lastName": "Doe",
"countryOfResidence": "USA",
"gender": "MALE",
"dateOfBirth": "1990-01-01",
"email": "john.doe@example.com"
}
Response:
{
"success": true,
"message": "Basic information submitted successfully for user",
"data": {
"id": "b1c2d3e4-5678-1234-9abc-def012345678",
"tenantId": "123e4567-e89b-12d3-a456-426614174001",
"userId": "123e4567-e89b-12d3-a456-426614174000",
"status": "BASIC_INFO_SUBMITTED",
"firstName": "John",
"lastName": "Doe",
"email": "john.doe@example.com",
"phoneNumber": null,
"dateOfBirth": "1990-01-01",
"countryOfResidence": "USA",
"gender": "MALE",
"usResidence": false,
"pepFlag": false,
"sanctionsFlag": false,
"adverseMediaFlag": false,
"createdAt": "2025-09-19T12:00:00Z",
"updatedAt": "2025-09-19T12:00:00Z"
}
}
/api/v1/business/{id}/directors | GET | List directors/board members |
| /api/v1/business/{id}/documents | POST | Upload business documents (certificates, tax filings, bank statements) |
| /api/v1/business/{id}/documents | GET | Retrieve uploaded business documents |
| /api/v1/business/{id}/documents/{docId} | DELETE | Delete business document |
| /api/v1/business/{id}/financials | POST | Upload financial documents (statements, tax clearance) |
| /api/v1/business/{id}/financials | GET | Retrieve financial records |
| /api/v1/business/{id}/licenses | POST | Upload licenses/regulatory approvals |
| /api/v1/business/{id}/licenses | GET | Retrieve licenses |
| /api/v1/business/{id}/screening | POST | Trigger AML/PEP/sanctions screening |
| /api/v1/business/{id}/screening/status | GET | Get screening status |
| /api/v1/business/{id}/risk-score | POST | Calculate risk score |
| /api/v1/business/{id}/risk-score | GET | Get current risk rating |
| /api/v1/business/{id}/monitoring/start | POST | Enable ongoing AML/media monitoring |
| /api/v1/business/{id}/monitoring/refresh | POST | Manually trigger re-verification |
| /api/v1/business/{id}/monitoring/logs | GET | Retrieve monitoring history |
| /api/v1/business/{id}/workflow/start | POST | Begin onboarding workflow |
| /api/v1/business/{id}/workflow/status | GET | Get current workflow stage |
| /api/v1/business/{id}/decision | POST | Approve, reject, or escalate |
| /api/v1/business/audit/{id} | GET | Get full audit log of business onboarding |
| /api/v1/business/reports/compliance | GET | Generate regulatory compliance report |
π οΈ Getting Started
Prerequisites
"createdAt": "2025-09-19T10:00:00Z", "updatedAt": "2025-09-19T10:00:00Z" }
#### 3. Add Business Owner
**POST** `/api/v1/business/{id}/owners`
β¨ Adds a beneficial owner (UBO) with >25% ownership to the business.
**Request:**
```json
{
"firstName": "John",
"lastName": "Smith",
"email": "john.smith@acme.com",
"phoneNumber": "+1-555-0123",
"ownershipPercentage": 60.5
}
Request Fields:
| Field | Type | Required | Description |
|---|---|---|---|
| firstName | String | Yes | Owner's first name |
| lastName | String | Yes | Owner's last name |
| String | No | Owner's email address | |
| phoneNumber | String | No | Owner's phone number |
| ownershipPercentage | BigDecimal | Yes | Ownership percentage (>25%) |
Response:
{
"id": "owner123e4567-e89b-12d3-a456-426614174000",
"businessId": "b1c2d3e4-5678-1234-9abc-def012345678",
"firstName": "John",
"lastName": "Smith",
"email": "john.smith@acme.com",
"phoneNumber": "+1-555-0123",
"ownershipPercentage": 60.5,
"createdAt": "2025-09-19T10:00:00Z",
"updatedAt": "2025-09-19T10:00:00Z"
}
4. Add Business Director
POST /api/v1/business/{id}/directors
β¨ Adds a director or board member to the business.
Request:
{
"firstName": "Jane",
"lastName": "Doe",
"email": "jane.doe@acme.com",
"phoneNumber": "+1-555-0456",
"position": "CEO"
}
Request Fields:
| Field | Type | Required | Description |
|---|---|---|---|
| firstName | String | Yes | Director's first name |
| lastName | String | Yes | Director's last name |
| String | No | Director's email address | |
| phoneNumber | String | No | Director's phone number |
| position | String | No | Director's position/title |
Response:
{
"id": "dir123e4567-e89b-12d3-a456-426614174000",
"businessId": "b1c2d3e4-5678-1234-9abc-def012345678",
"firstName": "Jane",
"lastName": "Doe",
"email": "jane.doe@acme.com",
"phoneNumber": "+1-555-0456",
"position": "CEO",
"createdAt": "2025-09-19T10:00:00Z",
"updatedAt": "2025-09-19T10:00:00Z"
}
5. Upload Financial Document
POST /api/v1/business/{id}/financials
β¨ Uploads financial documents with metadata.
Request:
{
"documentType": "Annual Financial Statement",
"fileName": "financial_statement_2024.pdf",
"documentId": "f1c2d3e4-5678-1234-9abc-def012345678",
"annualRevenue": 2500000.00,
"fiscalYearEnd": "2024-12-31",
"description": "2024 Annual Financial Statement"
}
Request Fields:
| Field | Type | Required | Description |
|---|---|---|---|
| documentType | String | Yes | Type of financial document |
| fileName | String | Yes | Original filename |
| documentId | UUID | Yes | UUID reference from Document Service |
| annualRevenue | BigDecimal | No | Annual revenue amount |
| fiscalYearEnd | String | No | Fiscal year end date (YYYY-MM-DD) |
| description | String | No | Optional description |
Response:
{
"id": "fin123e4567-e89b-12d3-a456-426614174000",
"businessId": "b1c2d3e4-5678-1234-9abc-def012345678",
"documentType": "Annual Financial Statement",
"fileName": "financial_statement_2024.pdf",
"downloadUrl": "https://document-service.com/download/f1c2d3e4-5678-1234-9abc-def012345678",
"annualRevenue": 2500000.00,
"fiscalYearEnd": "2024-12-31",
"description": "2024 Annual Financial Statement",
"createdAt": "2025-09-19T10:00:00Z",
"updatedAt": "2025-09-19T10:00:00Z"
}
6. Upload License Document
POST /api/v1/business/{id}/licenses
β¨ Uploads regulatory licenses and approvals.
Request:
{
"licenseType": "Business License",
"licenseNumber": "LIC123456789",
"issuingAuthority": "State Business Bureau",
"issueDate": "2024-01-15",
"expiryDate": "2025-01-14",
"fileName": "business_license_2024.pdf",
"documentId": "l1c2d3e4-5678-1234-9abc-def012345678",
"description": "2024 Business Operating License"
}
Request Fields:
| Field | Type | Required | Description |
|---|---|---|---|
| licenseType | String | Yes | Type of license |
| licenseNumber | String | No | License number |
| issuingAuthority | String | No | Issuing authority |
| issueDate | String | No | Issue date (YYYY-MM-DD) |
| expiryDate | String | No | Expiry date (YYYY-MM-DD) |
| fileName | String | Yes | Original filename |
| documentId | UUID | Yes | UUID reference from Document Service |
| description | String | No | Optional description |
Response:
{
"id": "lic123e4567-e89b-12d3-a456-426614174000",
"businessId": "b1c2d3e4-5678-1234-9abc-def012345678",
"licenseType": "Business License",
"licenseNumber": "LIC123456789",
"issuingAuthority": "State Business Bureau",
"issueDate": "2024-01-15",
"expiryDate": "2025-01-14",
"fileName": "business_license_2024.pdf",
"downloadUrl": "https://document-service.com/download/l1c2d3e4-5678-1234-9abc-def012345678",
"description": "2024 Business Operating License",
"createdAt": "2025-09-19T10:00:00Z",
"updatedAt": "2025-09-19T10:00:00Z"
}
7. Get Businesses (Paginated)
GET /api/v1/business?page=0&size=10&sort=created,desc&q=search_term
β¨ Retrieves businesses with pagination support and optional search.
Response:
{
"content": [
{
"id": "b1c2d3e4-5678-1234-9abc-def012345678",
"tenantId": "123e4567-e89b-12d3-a456-426614174001",
"legalName": "Acme Corporation Inc.",
"registrationNumber": "REG123456789",
"businessStructure": "CORPORATION",
"address": "123 Business St, Business City, BC 12345",
"status": "APPROVED",
"created": "2025-09-19T10:00:00Z",
"updated": "2025-09-19T10:00:00Z"
}
],
"pageNumber": 0,
"pageSize": 10,
"totalElements": 1,
"totalPages": 1,
"numberOfElements": 1,
"first": true,
"last": true,
"empty": false
}
8. Get Business Details
GET /api/v1/business/{id}
β¨ Retrieves complete business information including all associated data.
Response:
{
"id": "b1c2d3e4-5678-1234-9abc-def012345678",
"tenantId": "123e4567-e89b-12d3-a456-426614174001",
"legalName": "Acme Corporation Inc.",
"registrationNumber": "REG123456789",
"businessStructure": "CORPORATION",
"address": "123 Business St, Business City, BC 12345",
"status": "APPROVED",
"owners": [
{
"id": "owner123e4567-e89b-12d3-a456-426614174000",
"firstName": "John",
"lastName": "Smith",
"ownershipPercentage": 60.5
}
],
"directors": [
{
"id": "dir123e4567-e89b-12d3-a456-426614174000",
"firstName": "Jane",
"lastName": "Doe",
"position": "CEO"
}
],
"documents": [
{
"id": "doc123e4567-e89b-12d3-a456-426614174000",
"documentType": "FRONT",
"fileName": "certificate_of_incorporation.pdf",
"downloadUrl": "https://document-service.com/download/d1c2d3e4-5678-1234-9abc-def012345678"
}
],
"financials": [
{
"id": "fin123e4567-e89b-12d3-a456-426614174000",
"documentType": "Annual Financial Statement",
"annualRevenue": 2500000.00
}
],
"licenses": [
{
"id": "lic123e4567-e89b-12d3-a456-426614174000",
"licenseType": "Business License",
"licenseNumber": "LIC123456789"
}
],
"createdAt": "2025-09-19T10:00:00Z",
"updatedAt": "2025-09-19T10:00:00Z"
}
Standard Error Response
All endpoints return errors in the following format: ```json { "timestamp": "2025-05-04T07:00:00Z", "status": 400, "error": "Bad Request", "message": "Validation failed: ...", "path": "/api/v1/kyc/..." }
Headers:
| Field | Type | Description |
|---|---|---|
| timestamp | String | Error timestamp (ISO 8601) |
| status | Number | HTTP status code |
| error | String | Error type |
| message | String | Error message |
| path | String | Request path |
1. Initiate KYC Process
POST /api/v1/kyc/initiate
β¨ Initiates a new KYC profile for a current user and tenant. Returns the created KYC profile object.
Response:
{
"id": "b1c2d3e4-5678-1234-9abc-def012345678",
"tenantId": "123e4567-e89b-12d3-a456-426614174001",
"userId": "123e4567-e89b-12d3-a456-426614174000",
"status": "NOT_STARTED",
"ssnLastFour": null,
"dateOfBirth": null,
"addressId": null,
"amlRiskScore": null,
"amlProviderReference": null,
"pepFlag": false,
"sanctionsFlag": false,
"adverseMediaFlag": false,
"createdBy": "system",
"updatedBy": "system",
"address": null,
"created": "2025-05-04T07:00:00Z",
"updated": "2025-05-04T07:00:00Z"
}
Error Response Example:
{
"timestamp": "2025-05-04T07:00:00Z",
"status": 400,
"error": "Bad Request",
"message": "Validation failed: userId is required",
"path": "/api/v1/kyc/initiate"
}
2. Submit Basic Information
POST /api/v1/kyc/basic-info
β¨ Submits the user's basic information and address for KYC. Performs an AML check and updates the KYC profile.
Headers:
| Header | Type | Description |
|---|---|---|
| userId | UUID | User identifier |
| corporate-tenantId | UUID | Tenant identifier |
Request:
{
"ssnLastFour": "1234",
"dateOfBirth": "1990-01-01",
"addressDto": {
"address": "123 Main St",
"city": "New York",
"state": "NY",
"zipCode": "10001",
"country": "USA"
}
}
Response:
{
"id": "b1c2d3e4-5678-1234-9abc-def012345678",
"tenantId": "123e4567-e89b-12d3-a456-426614174001",
"userId": "123e4567-e89b-12d3-a456-426614174000",
"status": "BASIC_INFO_SUBMITTED",
"ssnLastFour": "1234",
"dateOfBirth": "1990-01-01",
"addressId": "aabbccdd-1234-5678-9abc-def012345678",
"amlRiskScore": "LOW",
"amlProviderReference": "aml-123456",
"pepFlag": false,
"sanctionsFlag": false,
"adverseMediaFlag": false,
"createdBy": "system",
"updatedBy": "system",
"address": {
"address": "123 Main St",
"city": "New York",
"state": "NY",
"zipCode": "10001",
"country": "USA"
},
"created": "2025-05-04T07:00:00Z",
"updated": "2025-05-04T07:00:00Z"
}
Error Response Example:
{
"timestamp": "2025-05-04T07:00:00Z",
"status": 400,
"error": "Bad Request",
"message": "Validation failed: ssnLastFour is required",
"path": "/api/v1/kyc/basic-info"
}
3. Start ID Verification
POST /api/v1/verification/id-verification
β¨ Starts the ID verification process for a user. Accepts document and selfie images, and returns the verification record.
Headers:
| Header | Type | Description |
|---|---|---|
| userId | UUID | User identifier |
| corporate-tenantId | UUID | Tenant identifier |
Request:
{
"idType": "PASSPORT",
"idNumber": "A12345678",
"issuingCountry": "USA",
"expiryDate": "2030-01-01",
"frontImage": "<base64 or binary>",
"backImage": "<base64 or binary>",
"selfieImage": "<base64 or binary>"
}
Response:
{
"id": "idv-1234-5678-9abc-def012345678",
"userId": "123e4567-e89b-12d3-a456-426614174000",
"tenantId": "123e4567-e89b-12d3-a456-426614174001",
"kycProfileId": "b1c2d3e4-5678-1234-9abc-def012345678",
"idType": "PASSPORT",
"idNumber": "A12345678",
"issuingCountry": "USA",
"expiryDate": "2030-01-01",
"status": "PENDING",
"provider": "kyc-provider",
"providerReference": "kyc-123456",
"created": "2025-05-04T07:00:00Z",
"updated": "2025-05-04T07:00:00Z"
}
Error Response Example:
{
"timestamp": "2025-05-04T07:00:00Z",
"status": 422,
"error": "Unprocessable Entity",
"message": "Invalid ID document type",
"path": "/api/v1/verification/id-verification"
}
4. Start Bank Verification (Deprecated)
POST /api/v1/verification/bank-verification
β¨ Starts the bank verification process for a user. This endpoint is deprecated and will be removed in a future release. Accepts bank account details and returns the verification record.
Headers:
| Header | Type | Description |
|---|---|---|
| userId | UUID | User identifier |
| corporate-tenantId | UUID | Tenant identifier |
Request:
{
"accountNumber": "123456789",
"routingNumber": "987654321",
"accountType": "SAVINGS",
"bankName": "Bank of America"
}
Response:
{
"id": "bankv-1234-5678-9abc-def012345678",
"userId": "123e4567-e89b-12d3-a456-426614174000",
"tenantId": "123e4567-e89b-12d3-a456-426614174001",
"kycProfileId": "b1c2d3e4-5678-1234-9abc-def012345678",
"accountNumber": "β’β’β’β’6789",
"accountType": "SAVINGS",
"bankName": "Bank of America",
"status": "PENDING",
"provider": "bank-provider",
"providerReference": "bank-123456",
"created": "2025-05-04T07:00:00Z",
"updated": "2025-05-04T07:00:00Z"
}
Error Response Example:
{
"timestamp": "2025-05-04T07:00:00Z",
"status": 400,
"error": "Bad Request",
"message": "Invalid bank account number",
"path": "/api/v1/verification/bank-verification"
}
5. Submit Suitability Responses
POST /api/v1/suitability/responses
β¨ Submits the user's answers to suitability questions for compliance and risk assessment.
Headers:
| Header | Type | Description |
|---|---|---|
| userId | UUID | User identifier |
| corporate-tenantId | UUID | Tenant identifier |
Request:
[
{ "questionId": "1290300ce-ecdd-6b7a-816b-83a6ad09f11f", "optionId": "b1a2c3d4-5678-1234-5678-abcdefabcdef" },
{ "questionId": "178300e3-367e-634b-8940-1dbbec71d430", "optionId": "c2b3a4d5-6789-2345-6789-bcdefabcdefa" }
]
Response:
{
"success": true,
"message": "Suitability responses submitted successfully."
}
Error Response Example:
{
"timestamp": "2025-05-04T07:00:00Z",
"status": 400,
"error": "Bad Request",
"message": "Missing suitability responses",
"path": "/api/v1/suitability/responses"
}
6. Get KYC Status
GET /api/v1/kyc/status
β¨ Retrieves the current KYC status for a user and tenant.
Headers:
| Header | Type | Description |
|---|---|---|
| userId | UUID | User identifier |
| corporate-tenantId | UUID | Tenant identifier |
Response:
{
"userId": "123e4567-e89b-12d3-a456-426614174000",
"tenantId": "123e4567-e89b-12d3-a456-426614174001",
"status": "ID_VERIFIED",
"lastUpdated": "2025-05-04T07:00:00Z"
}
Error Response Example:
{
"timestamp": "2025-05-04T07:00:00Z",
"status": 404,
"error": "Not Found",
"message": "KYC profile not found",
"path": "/api/v1/kyc/status"
}
7. ID Verification Callback (Provider)
POST /api/v1/kyc/callbacks/id-verification
β¨ Endpoint for providers to send ID verification results back to the KYC service.
Request:
{
"referenceId": "kyc-123456",
"success": true,
"livenessScore": 0.98,
"matchScore": 0.99,
"comment": null
}
Response:
{
"success": true,
"message": "ID verification result processed."
}
Error Response Example:
{
"timestamp": "2025-05-04T07:00:00Z",
"status": 404,
"error": "Not Found",
"message": "Verification reference not found",
"path": "/api/v1/kyc/callbacks/id-verification"
}
8. Bank Verification Callback (Provider)
POST /api/v1/kyc/callbacks/bank-verification
β¨ Endpoint for providers to send bank verification results back to the KYC service.
Request:
{
"referenceId": "bank-123456",
"success": true,
"bankName": "Bank of America",
"comment": null
}
Response:
{
"success": true,
"message": "Bank verification result processed."
}
Error Response Example:
{
"timestamp": "2025-05-04T07:00:00Z",
"status": 404,
"error": "Not Found",
"message": "Verification reference not found",
"path": "/api/v1/kyc/callbacks/bank-verification"
}
9. Employer Verification (Full CRUD)
Create Employer Verification
POST /api/v1/verification/employer-verification
β¨ Creates a new employer verification record for the current user.
Headers:
| Header | Type | Description |
|---|---|---|
| userId | UUID | User identifier |
| corporate-tenantId | UUID | Tenant identifier |
Request:
{
"employerName": "Acme Corp",
"employerAddress": "123 Main St",
"employerPhoneNumber": "555-1234",
"employerEmail": "hr@acme.com",
"employmentStartDate": "2020-01-01",
"employmentEndDate": "2022-01-01",
"currentEmployer": true,
"jobTitle": "Software Engineer",
"salary": "100000",
"employmentStatus": "FULL_TIME"
}
Response:
{
"userId": "123e4567-e89b-12d3-a456-426614174000",
"tenantId": "123e4567-e89b-12d3-a456-426614174011",
"employerName": "Acme Corp",
"employerAddress": "123 Main St",
"employerPhoneNumber": "555-1234",
"employerEmail": "hr@acme.com",
"employmentStartDate": "2020-01-01",
"employmentEndDate": "2022-01-01",
"currentEmployer": true,
"jobTitle": "Software Engineer",
"salary": "100000",
"employmentStatus": "FULL_TIME"
}
Error Response Example:
{
"timestamp": "2025-05-04T07:00:00Z",
"status": 400,
"error": "Bad Request",
"message": "Missing employerName",
"path": "/api/v1/verification/employer-verification"
}
Get Employer Verification
GET /api/v1/verification/employer-verification
β¨ Retrieves the employer verification record for the current user.
Headers:
| Header | Type | Description |
|---|---|---|
| userId | UUID | User identifier |
| corporate-tenantId | UUID | Tenant identifier |
Response:
{
"userId": "123e4567-e89b-12d3-a456-426614174000",
"tenantId": "123e4567-e89b-12d3-a456-426614174011",
"employerName": "Acme Corp",
"employerAddress": "123 Main St",
"employerPhoneNumber": "555-1234",
"employerEmail": "hr@acme.com",
"employmentStartDate": "2020-01-01",
"employmentEndDate": "2022-01-01",
"currentEmployer": true,
"jobTitle": "Software Engineer",
"salary": "100000",
"employmentStatus": "FULL_TIME"
}
Error Response Example:
{
"timestamp": "2025-05-04T07:00:00Z",
"status": 404,
"error": "Not Found",
"message": "Employer verification not found",
"path": "/api/v1/verification/employer-verification"
}
Update Employer Verification
PUT /api/v1/verification/employer-verification/{id}
β¨ Updates an existing employer verification record for the current user.
Headers:
| Header | Type | Description |
|---|---|---|
| userId | UUID | User identifier |
| corporate-tenantId | UUID | Tenant identifier |
Request:
{
"employerName": "Acme Corp",
"employerAddress": "456 Elm St",
"employerPhoneNumber": "555-5678",
"employerEmail": "hr@acme.com",
"employmentStartDate": "2020-01-01",
"employmentEndDate": "2022-01-01",
"currentEmployer": false,
"jobTitle": "Senior Engineer",
"salary": "120000",
"employmentStatus": "FULL_TIME"
}
Response:
{
"userId": "123e4567-e89b-12d3-a456-426614174000",
"tenantId": "123e4567-e89b-12d3-a456-426614174011",
"employerName": "Acme Corp",
"employerAddress": "456 Elm St",
"employerPhoneNumber": "555-5678",
"employerEmail": "hr@acme.com",
"employmentStartDate": "2020-01-01",
"employmentEndDate": "2022-01-01",
"currentEmployer": false,
"jobTitle": "Senior Engineer",
"salary": "120000",
"employmentStatus": "FULL_TIME"
}
Error Response Example:
{
"timestamp": "2025-05-04T07:00:00Z",
"status": 404,
"error": "Not Found",
"message": "Employer verification not found",
"path": "/api/v1/verification/employer-verification/{id}"
}
Delete Employer Verification
DELETE /api/v1/verification/employer-verification/{id}
β¨ Deletes the employer verification record for the current user.
Headers:
| Header | Type | Description |
|---|---|---|
| userId | UUID | User identifier |
| corporate-tenantId | UUID | Tenant identifier |
Response:
{
"success": true,
"message": "Employer verification deleted successfully."
}
Error Response Example:
{
"timestamp": "2025-05-04T07:00:00Z",
"status": 404,
"error": "Not Found",
"message": "Employer verification not found",
"path": "/api/v1/verification/employer-verification/{id}"
}
10. Verify Tax ID
POST /api/v1/verification/tax-id-verification
β¨ Verifies a tax ID for a given type. Returns a verification status.
Request:
{
"taxId": "A12345678",
"type": "USA_SSN"
}
Response:
{
"taxId": "A12345678",
"type": "USA_SSN",
"status": "VERIFIED"
}
Error Response Example:
{
"timestamp": "2025-05-04T07:00:00Z",
"status": 400,
"error": "Bad Request",
"message": "Invalid tax ID or type",
"path": "/api/v1/verification/tax-id-verification"
}
11. Get Supported Tax ID Types
GET /api/v1/verification/tax-id-types
β¨ Returns all supported tax ID types and their descriptions.
Response:
[
{ "name": "USA_SSN", "description": "USA Social Security Number" },
{ "name": "ARG_AR_CUIT", "description": "Argentina CUIT" },
{ "name": "AUS_TFN", "description": "Australian Tax File Number" },
...
]
π Supported Tax ID Types (Enum)
Below are all supported values for the type field in tax ID verification:
| Name | Description |
|---|---|
| USA_SSN | USA Social Security Number |
| ARG_AR_CUIT | Argentina CUIT |
| AUS_TFN | Australian Tax File Number |
| AUS_ABN | Australian Business Number |
| BOL_NIT | Bolivia NIT |
| BRA_CPF | Brazil CPF |
| CHL_RUT | Chile RUT |
| COL_NIT | Colombia NIT |
| CRI_NITE | Costa Rica NITE |
| DEU_TAX_ID | Germany Tax ID (Identifikationsnummer) |
| DOM_RNC | Dominican Republic RNC |
| ECU_RUC | Ecuador RUC |
| FRA_SPI | France SPI (Reference Tax Number) |
| GBR_UTR | UK UTR (Unique Taxpayer Reference) |
| GBR_NINO | UK NINO (National Insurance Number) |
| GTM_NIT | Guatemala NIT |
| HND_RTN | Honduras RTN |
| HUN_TIN | Hungary TIN Number |
| IDN_KTP | Indonesia KTP |
| IND_PAN | India PAN Number |
| ISR_TAX_ID | Israel Tax ID (Teudat Zehut) |
| ITA_TAX_ID | Italy Tax ID (Codice Fiscale) |
| JPN_TAX_ID | Japan Tax ID (Koijin Bango) |
| MEX_RFC | Mexico RFC |
| NIC_RUC | Nicaragua RUC |
| NLD_TIN | Netherlands TIN Number |
| PAN_RUC | Panama RUC |
| PER_RUC | Peru RUC |
| PRY_RUC | Paraguay RUC |
| SGP_NRIC | Singapore NRIC |
| SGP_FIN | Singapore FIN |
| SGP_ASGD | Singapore ASGD |
| SGP_ITR | Singapore ITR |
| SLV_NIT | El Salvador NIT |
| SWE_TAX_ID | Sweden Tax ID (Personnummer) |
| URY_RUT | Uruguay RUT |
| VEN_RIF | Venezuela RIF |
| NATIONAL_ID | National ID number, if a tax ID number is not available |
| PASSPORT | Passport number, if a tax ID number is not available |
| PERMANENT_RESIDENT | Permanent resident number, if a tax ID number is not available |
| DRIVER_LICENSE | Drivers license number, if a tax ID number is not available |
| OTHER_GOV_ID | Other government issued identifier, if a tax ID number is not available |
| NOT_SPECIFIED | Other Tax IDs |
| ID_CARD | Generic ID Card |
| DRIVERS_LICENSE | Generic Driver's License |
| RESIDENCE_PERMIT | Generic Residence Permit |
π·οΈ Environment Variables
| Variable | Description |
|---|---|
SPRING_PROFILES_ACTIVE |
Spring profile (e.g., uat) |
SPRING_DATASOURCE_URL |
JDBC URL for PostgreSQL |
LOGGING_LOKI_URL |
Loki push endpoint |
EUREKA_CLIENT_SERVICEURL_DEFAULTZONE |
Eureka server URL |
AML_PROVIDER_URL |
AML provider base URL |
KYC_PROVIDER_URL |
KYC provider base URL |
| ... | ... |
π¦ Observability & Operations
- Loki for log aggregation (
LOGGING_LOKI_URL). - Prometheus for metrics.
- OpenTelemetry for distributed tracing.
- Eureka for service discovery.
π§ͺ Testing
- JUnit 5 for unit and integration tests.
- To run tests:
./gradlew test
π€ Contributing
Pull requests are welcome! Please open issues for bugs or feature requests.
π KYC API Field Reference
Below is a table explaining the main fields used in the KYC API request and response payloads:
| Field | Type | Description |
|---|---|---|
id |
UUID | Unique identifier for the resource |
tenantId |
UUID | Tenant identifier for multi-tenancy |
userId |
UUID | User identifier |
status |
String | Current KYC status (e.g., NOT_STARTED, BASIC_INFO_SUBMITTED, etc.) |
ssnLastFour |
String | Last four digits of the user's SSN |
dateOfBirth |
String | User's date of birth (ISO format: YYYY-MM-DD) |
addressId |
UUID | Reference to the address entity |
amlRiskScore |
String | AML (Anti-Money Laundering) risk score |
amlProviderReference |
String | Reference from the AML provider |
pepFlag |
Boolean | Politically Exposed Person flag |
sanctionsFlag |
Boolean | Sanctions flag |
adverseMediaFlag |
Boolean | Adverse media flag |
createdBy |
String | User or system that created the record |
updatedBy |
String | User or system that last updated the record |
address |
Object | Address details (see below) |
created |
String | Timestamp when the record was created (ISO 8601) |
updated |
String | Timestamp when the record was last updated (ISO 8601) |
idType |
String | Type of ID document (e.g., PASSPORT, DRIVER_LICENSE) |
idNumber |
String | ID document number |
issuingCountry |
String | Country that issued the ID |
expiryDate |
String | Expiry date of the ID document (ISO format) |
accountNumber |
String | Bank account number (masked in responses) |
routingNumber |
String | Bank routing number |
accountType |
String | Type of bank account (e.g., SAVINGS, CHECKING) |
bankName |
String | Name of the bank |
bankId |
UUID | Reference to the bank entity |
provider |
String | Name of the verification provider |
providerReference |
String | Reference from the provider |
comment |
String | Reason for rejection (if any) |
livenessScore |
Number | Liveness score from ID verification |
matchScore |
Number | Match score from ID verification |
responses |
Array | List of suitability responses |
questionId |
String | Suitability question identifier |
response |
String | Suitability question response |
success |
Boolean | Indicates if the operation was successful |
message |
String | Additional message or status info |
lastUpdated |
String | Timestamp of last status update |
Address Object Fields:
| Field | Type | Description |
|---|---|---|
address |
String | Street address |
city |
String | City |
state |
String | State or province |
zipCode |
String | Postal/ZIP code |
country |
String | Country |
π KYC Document Expiry & Notification Workflow
KYC documents (e.g., passport, ID card) are monitored for expiry. The system automatically checks expiry dates and notifies users and updates account status as follows:
Expiry Handling Logic
- Expiring Soon (within 30 days):
- User receives a one-time "Expiring Soon" warning (Email/SMS/Push).
- Expired (expiry date < today):
- User receives a "Document Expired" reminder every 7 days until updated.
- Just Expired (expiry date == yesterday):
- KYC status is set to
Invalidand the account is locked. - User receives an "Account Locked" notification.
All notifications update the last_notified_date to avoid spamming.
Technical Workflow
sequenceDiagram
participant S as Daily Scheduler
participant D as Database
participant N as Notification Service
participant A as Auth/Account Service
Note over S: Scheduler Run (02:00 AM)
S->>D: For each user, fetch KYC docs & status
loop For Each Document
S->>D: Get document expiry_date, last_notified_date
alt Just Expired (expiry_date == yesterday)
S->>A: Set KYC status = 'Invalid'
A->>D: Update user status (Invalid)
S->>A: Lock account
A->>D: Update account (Locked)
S->>N: Send "Account Locked" notification
N->>D: Update last_notified_date = today
N-->>User: Send Email/SMS/Push
else Expired (expiry_date < today)
S->>D: Check if (today - last_notified_date) >= 7 days
alt Reminder is due
S->>N: Send "Document Expired" reminder
N->>D: Update last_notified_date = today
N-->>User: Send Email/SMS/Push
else Reminder not due
Note over S: Skip notification for now
end
else Expiring Soon (within 30 days)
S->>D: Check if last_notified_date is null
alt First Warning
S->>N: Send "Expiring Soon" warning
N->>D: Update last_notified_date = today
N-->>User: Send Email/SMS/Push
else Already Notified
Note over S: Skip notification (one-time only)
end
end
end
π Recent Updates
v2.2.0 - Business Document Categorization & Pagination (2025-09-21)
β¨ New Features:
- Document Categorization System: Added structured document categories (PASSPORT, BUSINESS_LICENSE, FINANCIAL_STATEMENT, etc.) alongside document types (FRONT/BACK/SELFIE)
- Pagination Support: All business document endpoints now support pagination with standardized PaginatedResponse format
- Enhanced Business Documents: Business documents now include both document type and category for better organization and compliance
π§ Improvements:
- API Enhancement: Business document, financial, and license endpoints now return paginated results with full metadata
- Data Structure: Updated BusinessDocument entity with documentCategory field for comprehensive document classification
- Response Standardization: All paginated endpoints use consistent response format with page metadata
π Documentation: - Updated Business API endpoints with pagination indicators - Added Document Types & Categories reference section - Updated request/response examples to include new document categorization fields - Added paginated endpoint examples with full payload structures
v2.1.0 - Business KYC & Document Standardization (2025-09-19)
β¨ New Features: - Business KYC Support: Complete business onboarding workflow with registration, ownership verification, document uploads, and compliance monitoring - Document Upload Standardization: All document uploads now use UUID-based references from the centralized Document Service for enhanced security and validation - Business Endpoints: Full API coverage for business operations including owners, directors, documents, financials, licenses, screening, and monitoring
π§ Improvements: - Security Enhancement: Document validation prevents arbitrary URL injection - API Consistency: Unified document upload pattern across individual and business KYC - Centralized Document Management: Integration with Document Service for secure file handling
π Documentation: - Added comprehensive Business API endpoints documentation - Updated architecture overview to include business KYC flows - Added Document Management section explaining the standardized upload process
π License
Made with β€οΈ by Olara Tech