Skip to content

🌟 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 documents
  • BACK - Back side of identity documents
  • SELFIE - Selfie photos for biometric verification

Business Document Categories

  • PASSPORT - Passport documents
  • DRIVER_LICENSE - Driver's license
  • NATIONAL_ID - National ID card
  • RESIDENCE_PERMIT - Residence permit
  • BANK_STATEMENT - Bank statements
  • TAX_RETURN - Tax return documents
  • FINANCIAL_STATEMENT - Financial statements
  • PAY_STUB - Pay stubs
  • BUSINESS_LICENSE - Business operating licenses
  • ARTICLES_OF_INCORPORATION - Articles of incorporation
  • BYLAWS - Company bylaws
  • OPERATING_AGREEMENT - Operating agreements
  • UTILITY_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
Hold "Alt" / "Option" to enable pan & zoom

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"
}
| Field | Type | Description | |--------------|--------|---------------------------------------------| | id | UUID | Unique identifier for the KYC profile | | tenantId | UUID | Tenant identifier | | userId | UUID | User identifier | | status | String | Current KYC status | | ssnLastFour | String | Last four digits of SSN | | dateOfBirth | String | Date of birth (YYYY-MM-DD) | | addressId | UUID | Reference to the address entity | | amlRiskScore | String | AML risk score | | amlProviderReference | String | Reference from the AML provider | | pepFlag | Bool | Politically Exposed Person flag | | sanctionsFlag| Bool | Sanctions flag | | adverseMediaFlag | Bool | Adverse media flag | | createdBy | String | Who created the record | | updatedBy | String | Who last updated the record | | address | Object | Address details (see Address fields below) | | created | String | Creation timestamp (ISO 8601) | | updated | String | Last update timestamp (ISO 8601) |

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"
  }
}
| Field | Type | Description | |-------------|--------|----------------------------| | ssnLastFour | String | Last four digits of SSN | | dateOfBirth | String | Date of birth (YYYY-MM-DD) | | addressDto | Object | Address details |

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"
}
| Field | Type | Description | |--------------|--------|---------------------------------------------| | id | UUID | Unique identifier for the KYC profile | | tenantId | UUID | Tenant identifier | | userId | UUID | User identifier | | status | String | Current KYC status | | ssnLastFour | String | Last four digits of SSN | | dateOfBirth | String | Date of birth (YYYY-MM-DD) | | addressId | UUID | Reference to the address entity | | amlRiskScore | String | AML risk score | | amlProviderReference | String | Reference from the AML provider | | pepFlag | Bool | Politically Exposed Person flag | | sanctionsFlag| Bool | Sanctions flag | | adverseMediaFlag | Bool | Adverse media flag | | createdBy | String | Who created the record | | updatedBy | String | Who last updated the record | | address | Object | Address details (see Address fields below) | | created | String | Creation timestamp (ISO 8601) | | updated | String | Last update timestamp (ISO 8601) |

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>"
}
| Field | Type | Description | |-----------------|---------|---------------------------------------------| | idType | String | Type of ID document (e.g., PASSPORT) | | idNumber | String | ID document number | | issuingCountry | String | Country that issued the ID | | expiryDate | String | Expiry date of the ID (YYYY-MM-DD) | | frontImage | Binary | Front image of the ID document | | backImage | Binary | Back image of the ID document (optional) | | selfieImage | Binary | Selfie image of the user |

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"
}
| Field | Type | Description | |-------------------|---------|---------------------------------------------| | id | UUID | Unique identifier for the verification | | userId | UUID | User identifier | | tenantId | UUID | Tenant identifier | | kycProfileId | UUID | Reference to the KYC profile | | idType | String | Type of ID document | | idNumber | String | ID document number | | issuingCountry | String | Country that issued the ID | | expiryDate | String | Expiry date of the ID | | status | String | Verification status (e.g., PENDING) | | provider | String | Verification provider | | providerReference | String | Reference from the provider | | created | String | Creation timestamp | | updated | String | Last update timestamp |

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"
  }
}
Response: Returns 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
}
Workflow States: 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
}
POST /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
email 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
email 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"
}
| Field | Type | Description | |--------------|--------|---------------------------------------------| | id | UUID | Unique identifier for the KYC profile | | tenantId | UUID | Tenant identifier | | userId | UUID | User identifier | | status | String | Current KYC status | | ssnLastFour | String | Last four digits of SSN | | dateOfBirth | String | Date of birth (YYYY-MM-DD) | | addressId | UUID | Reference to the address entity | | amlRiskScore | String | AML risk score | | amlProviderReference | String | Reference from the AML provider | | pepFlag | Bool | Politically Exposed Person flag | | sanctionsFlag| Bool | Sanctions flag | | adverseMediaFlag | Bool | Adverse media flag | | createdBy | String | Who created the record | | updatedBy | String | Who last updated the record | | address | Object | Address details (see Address fields below) | | created | String | Creation timestamp (ISO 8601) | | updated | String | Last update timestamp (ISO 8601) |

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"
  }
}
| Field | Type | Description | |-------------|--------|----------------------------| | ssnLastFour | String | Last four digits of SSN | | dateOfBirth | String | Date of birth (YYYY-MM-DD) | | addressDto | Object | Address details |

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"
}
| Field | Type | Description | |--------------|--------|---------------------------------------------| | id | UUID | Unique identifier for the KYC profile | | tenantId | UUID | Tenant identifier | | userId | UUID | User identifier | | status | String | Current KYC status | | ssnLastFour | String | Last four digits of SSN | | dateOfBirth | String | Date of birth (YYYY-MM-DD) | | addressId | UUID | Reference to the address entity | | amlRiskScore | String | AML risk score | | amlProviderReference | String | Reference from the AML provider | | pepFlag | Bool | Politically Exposed Person flag | | sanctionsFlag| Bool | Sanctions flag | | adverseMediaFlag | Bool | Adverse media flag | | createdBy | String | Who created the record | | updatedBy | String | Who last updated the record | | address | Object | Address details (see Address fields below) | | created | String | Creation timestamp (ISO 8601) | | updated | String | Last update timestamp (ISO 8601) |

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>"
}
| Field | Type | Description | |-----------------|---------|---------------------------------------------| | idType | String | Type of ID document (e.g., PASSPORT) | | idNumber | String | ID document number | | issuingCountry | String | Country that issued the ID | | expiryDate | String | Expiry date of the ID (YYYY-MM-DD) | | frontImage | Binary | Front image of the ID document | | backImage | Binary | Back image of the ID document (optional) | | selfieImage | Binary | Selfie image of the user |

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"
}
| Field | Type | Description | |-------------------|---------|---------------------------------------------| | id | UUID | Unique identifier for the verification | | userId | UUID | User identifier | | tenantId | UUID | Tenant identifier | | kycProfileId | UUID | Reference to the KYC profile | | idType | String | Type of ID document | | idNumber | String | ID document number | | issuingCountry | String | Country that issued the ID | | expiryDate | String | Expiry date of the ID | | status | String | Verification status (e.g., PENDING) | | provider | String | Verification provider | | providerReference | String | Reference from the provider | | created | String | Creation timestamp | | updated | String | Last update timestamp |

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"
}
| Field | Type | Description | |---------------|---------|---------------------------------------------| | accountNumber | String | Bank account number | | routingNumber | String | Bank routing number | | accountType | String | Type of bank account (e.g., SAVINGS) | | bankName | String | Name of the bank |

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"
}
| Field | Type | Description | |-------------------|---------|---------------------------------------------| | id | UUID | Unique identifier for the verification | | userId | UUID | User identifier | | tenantId | UUID | Tenant identifier | | kycProfileId | UUID | Reference to the KYC profile | | accountNumber | String | Bank account number (masked in response) | | accountType | String | Type of bank account | | bankName | String | Name of the bank | | status | String | Verification status (e.g., PENDING) | | provider | String | Verification provider | | providerReference | String | Reference from the provider | | created | String | Creation timestamp | | updated | String | Last update timestamp |

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" }
]
| Field | Type | Description | |-------------|--------|-----------------------------------| | questionId | UUID | Suitability question identifier | | optionId | UUID | Selected option identifier |

Response:

{
  "success": true,
  "message": "Suitability responses submitted successfully."
}
| Field | Type | Description | |----------|---------|------------------------------------| | success | Boolean | Indicates if the operation succeeded| | message | String | Status or info message |

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"
}
| Field | Type | Description | |-------------|--------|------------------------------------| | userId | UUID | User identifier | | tenantId | UUID | Tenant identifier | | status | String | Current KYC status | | lastUpdated | String | Timestamp of last status update |

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
}
| Field | Type | Description | |--------------- |---------|---------------------------------------------| | referenceId | String | Provider reference for the verification | | success | Boolean | Whether the verification was successful | | livenessScore | Number | Liveness score from provider | | matchScore | Number | Match score from provider | | comment| String | Reason for rejection (if any) |

Response:

{
  "success": true,
  "message": "ID verification result processed."
}
| Field | Type | Description | |----------|---------|------------------------------------| | success | Boolean | Indicates if the operation succeeded| | message | String | Status or info message |

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
}
| Field | Type | Description | |--------------- |---------|---------------------------------------------| | referenceId | String | Provider reference for the verification | | success | Boolean | Whether the verification was successful | | bankName | String | Name of the bank | | comment| String | Reason for rejection (if any) |

Response:

{
  "success": true,
  "message": "Bank verification result processed."
}
| Field | Type | Description | |----------|---------|------------------------------------| | success | Boolean | Indicates if the operation succeeded| | message | String | Status or info message |

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"
}
| Field | Type | Description | |--------------------|-----------|------------------------------------| | employerName | String | Name of the employer | | employerAddress | String | Address of the employer | | employerPhoneNumber| String | Employer phone number | | employerEmail | String | Employer email address | | employmentStartDate| String | Employment start date (YYYY-MM-DD) | | employmentEndDate | String | Employment end date (YYYY-MM-DD) | | currentEmployer | Boolean | Is this the current employer? | | jobTitle | String | Job title | | salary | String | Salary | | employmentStatus | String | Employment status (e.g., 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"
}
| Field | Type | Description | |--------------------|-----------|------------------------------------| | userId | UUID | User identifier | | tenantId | UUID | Tenant identifier | | employerName | String | Name of the employer | | employerAddress | String | Address of the employer | | employerPhoneNumber| String | Employer phone number | | employerEmail | String | Employer email address | | employmentStartDate| String | Employment start date (YYYY-MM-DD) | | employmentEndDate | String | Employment end date (YYYY-MM-DD) | | currentEmployer | Boolean | Is this the current employer? | | jobTitle | String | Job title | | salary | String | Salary | | employmentStatus | String | Employment status (e.g., 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."
}
| Field | Type | Description | |----------|---------|------------------------------------| | success | Boolean | Indicates if the operation succeeded| | message | String | Status or info message |

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"
}
| Field | Type | Description | |---------|--------|------------------------------------| | taxId | String | Tax ID number | | type | String | Type of tax ID (see supported list)|

Response:

{
  "taxId": "A12345678",
  "type": "USA_SSN",
  "status": "VERIFIED"
}
| Field | Type | Description | |---------|--------|------------------------------------| | taxId | String | Tax ID number | | type | String | Type of tax ID | | status | String | Verification status |

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" },
  ...
]
| Field | Type | Description | |--------------|--------|------------------------------------| | name | String | Enum value for the tax ID type | | description | String | Human-readable description |


πŸ†• 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 Invalid and 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
Hold "Alt" / "Option" to enable pan & zoom

πŸ“‹ 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

MIT


Made with ❀️ by Olara Tech