> ## Documentation Index
> Fetch the complete documentation index at: https://docs.khaime.com/llms.txt
> Use this file to discover all available pages before exploring further.

# Submit Merchant KYC

> Submit a KYC application on behalf of a sub-merchant.

# Submit Merchant KYC

Submits a Know Your Customer (KYC) application for a sub-merchant in your marketplace. This is required before a merchant can receive payouts.

<Note>
  The merchant must already exist in your marketplace. Create or link them first via [Create Merchant](/api-reference/marketplace/create-merchant) before submitting KYC.
</Note>

## How KYC Works

Khaime uses a **unified KYC system** that routes to the appropriate provider based on the merchant's country:

| Country              | KYC Provider       | Verification                  | Data Collection                         |
| -------------------- | ------------------ | ----------------------------- | --------------------------------------- |
| NG, GH, ZA, KE       | **Khaime KYC**     | Manual review within 24 hours | You submit documents via API            |
| US, GB, CA, EU, etc. | **Stripe Connect** | Automated via Stripe          | Merchant completes Stripe's hosted flow |

For **African markets (NG, GH, ZA, KE)**: You submit identity documents, business info, and bank details directly. Khaime reviews and approves.

For **other markets**: The merchant completes Stripe's hosted onboarding flow. You receive a URL to redirect them — Stripe collects all identity and business information directly.

## Path Parameters

<ParamField path="merchantId" type="number" required>
  The ID of the sub-merchant.
</ParamField>

***

## Request Body

### For African Countries (Khaime KYC)

You can submit KYC data in two formats:

1. **Structured format** (recommended) — Uses `owner`, `business`, and `bank_account` objects
2. **Flat format** (legacy) — Individual fields at the root level

<Tabs>
  <Tab title="Structured Format (Recommended)">
    #### Core Fields

    <ParamField body="id_country" type="string" required>
      ISO 3166-1 alpha-2 country code. Must be one of: `NG`, `GH`, `ZA`, `KE`.
    </ParamField>

    <ParamField body="account_type" type="string" required>
      Type of account. One of: `individual`, `registered_business`.
    </ParamField>

    #### Owner Object (Required)

    The `owner` object contains information about the business owner or individual.

    <ParamField body="owner" type="object" required>
      Owner/individual information.

      | Field             | Type   | Required | Description                                                 |
      | ----------------- | ------ | -------- | ----------------------------------------------------------- |
      | `first_name`      | string | Yes      | Owner's first name                                          |
      | `last_name`       | string | Yes      | Owner's last name                                           |
      | `date_of_birth`   | string | No       | Date of birth in `YYYY-MM-DD` format                        |
      | `phone_number`    | string | No       | Contact phone number                                        |
      | `email`           | string | No       | Contact email address                                       |
      | `id_type`         | string | Yes      | Document type: `passport`, `national_id`, `drivers_license` |
      | `id_number`       | string | Yes      | ID number (BVN, NIN, or passport number)                    |
      | `id_document_url` | string | Yes      | URL to uploaded identity document image                     |
      | `selfie_url`      | string | No       | URL to selfie photo for liveness verification               |
      | `address`         | object | Yes      | Owner's residential address (see Address Object)            |
    </ParamField>

    #### Business Object (Required for registered\_business)

    <ParamField body="business" type="object">
      Required when `account_type` is `registered_business`.

      | Field                       | Type   | Required | Description                                                                        |
      | --------------------------- | ------ | -------- | ---------------------------------------------------------------------------------- |
      | `legal_name`                | string | Yes      | Registered business name                                                           |
      | `trading_name`              | string | No       | Trading/DBA name if different                                                      |
      | `registration_number`       | string | Yes      | Business registration number (e.g., CAC number)                                    |
      | `tax_id`                    | string | No       | Tax identification number                                                          |
      | `business_type`             | string | No       | One of: `sole_proprietorship`, `partnership`, `llc`, `corporation`, `ngo`, `other` |
      | `website`                   | string | No       | Business website URL                                                               |
      | `phone_number`              | string | No       | Business phone number                                                              |
      | `registration_document_url` | string | Yes      | URL to certificate of incorporation                                                |
      | `additional_document_url`   | string | No       | URL to additional supporting document                                              |
      | `address`                   | object | Yes      | Business address (see Address Object)                                              |
    </ParamField>

    #### Bank Account Object (Optional)

    Bank details can be submitted with KYC or added later via [Add Bank Account](/api-reference/marketplace/add-bank-account).

    <ParamField body="bank_account" type="object">
      Payout bank account details.

      | Field            | Type   | Required | Description                                                                       |
      | ---------------- | ------ | -------- | --------------------------------------------------------------------------------- |
      | `country`        | string | Yes      | Bank country code (e.g., `NG`, `GH`)                                              |
      | `bank_name`      | string | Yes\*    | Bank name from [Get Supported Banks](/api-reference/marketplace/get-payout-banks) |
      | `bank_id`        | string | Yes\*    | Bank UUID from [Get Supported Banks](/api-reference/marketplace/get-payout-banks) |
      | `account_number` | string | Yes      | Bank account number                                                               |
      | `account_name`   | string | Yes      | Name on the bank account                                                          |
      | `bank_code`      | string | No       | Bank code (if applicable)                                                         |
      | `sort_code`      | string | No       | Sort code (required for UK accounts)                                              |
      | `routing_number` | string | No       | Routing number (for US accounts)                                                  |

      \*Either `bank_name` or `bank_id` is required.
    </ParamField>

    #### Address Object

    Used in both `owner.address` and `business.address`.

    | Field         | Type   | Required | Description                     |
    | ------------- | ------ | -------- | ------------------------------- |
    | `street`      | string | Yes      | Street address                  |
    | `city`        | string | Yes      | City or town                    |
    | `state`       | string | Yes      | State, province, or region      |
    | `postal_code` | string | No       | Postal or ZIP code              |
    | `country`     | string | Yes      | ISO 3166-1 alpha-2 country code |
  </Tab>

  <Tab title="Flat Format (Legacy)">
    <ParamField body="id_country" type="string" required>
      ISO 3166-1 alpha-2 country code for the identity document (e.g. `NG`, `GH`, `ZA`, `KE`).
    </ParamField>

    <ParamField body="business_type" type="string" required>
      The type of business. One of: `individual`, `registered_business`.
    </ParamField>

    <ParamField body="legal_name" type="string" required>
      Full legal name of the individual or registered business.
    </ParamField>

    <ParamField body="id_document_type" type="string" required>
      Type of identity document. One of: `passport`, `national_id`, `drivers_license`.
    </ParamField>

    <ParamField body="id_document_url" type="string" required>
      Publicly accessible URL to the uploaded identity document image.
    </ParamField>

    <ParamField body="selfie_url" type="string">
      URL to a selfie photo for liveness verification. Recommended for `individual` business types.
    </ParamField>

    <ParamField body="registration_number" type="string">
      Business registration number. Required when `business_type` is `registered_business`.
    </ParamField>

    <ParamField body="responsible_person_name" type="string">
      Name of the responsible person for the business.
    </ParamField>

    <ParamField body="business_address" type="object">
      Physical address of the business or individual.

      | Field         | Type   | Required | Description                                    |
      | ------------- | ------ | -------- | ---------------------------------------------- |
      | `line1`       | string | Yes      | Street address line 1                          |
      | `line2`       | string | No       | Street address line 2 (apartment, suite, etc.) |
      | `city`        | string | Yes      | City or town                                   |
      | `state`       | string | No       | State, province, or region                     |
      | `postal_code` | string | No       | Postal or ZIP code                             |
      | `country`     | string | Yes      | ISO 3166-1 alpha-2 country code                |
    </ParamField>

    <ParamField body="incorporation_cert_url" type="string">
      URL to the certificate of incorporation. Required when `business_type` is `registered_business`.
    </ParamField>

    #### Bank Details (Legacy Format)

    <ParamField body="bank_country" type="string">
      ISO 3166-1 alpha-2 country code for the merchant's bank. Defaults to `id_country` if omitted.
    </ParamField>

    <ParamField body="bank_name" type="string">
      Name of the merchant's bank. Must match a name from [Get Supported Banks](/api-reference/marketplace/get-payout-banks).
    </ParamField>

    <ParamField body="bank_account_number" type="string">
      The merchant's bank account number.
    </ParamField>

    <ParamField body="bank_account_name" type="string">
      The registered name on the bank account.
    </ParamField>

    <ParamField body="bank_sort_code" type="string">
      Bank sort code (required for UK accounts).
    </ParamField>
  </Tab>
</Tabs>

***

### For Other Countries (Stripe Connect)

For non-African countries, Khaime uses **Stripe Connect** for identity verification. You only need to provide minimal information — Stripe collects everything else directly from the merchant through their secure hosted onboarding flow.

<Info>
  **What Stripe Collects**: Personal information, government ID, business details, bank account for payouts, and tax information. All data is collected securely by Stripe — it never passes through your servers.
</Info>

<ParamField body="country" type="string" required>
  ISO 3166-1 alpha-2 country code (e.g. `US`, `GB`, `CA`, `DE`, `FR`, `AU`).
</ParamField>

<ParamField body="business_type" type="string">
  The type of business. One of: `individual`, `registered_business`. Defaults to `individual`.
</ParamField>

<ParamField body="preferred_currency" type="string">
  Settlement currency for payouts. **Automatically derived from country** — you typically don't need to specify this.

  | Country      | Default Currency |
  | ------------ | ---------------- |
  | US           | USD              |
  | GB           | GBP              |
  | CA           | CAD              |
  | EU countries | EUR              |
  | AU           | AUD              |
</ParamField>

<ParamField body="return_url" type="string" required>
  URL to redirect the merchant after they complete Stripe onboarding. This should be a page on your platform that handles the post-onboarding flow (e.g., shows a success message or redirects to their dashboard).
</ParamField>

<ParamField body="refresh_url" type="string" required>
  URL to redirect the merchant if the Stripe onboarding link expires or they need to restart. Typically the same page that initiates KYC.
</ParamField>

<Warning>
  **Redirect URLs are required** for Stripe Connect. When merchants complete Stripe's onboarding flow, they need to be redirected back to your platform — not Khaime's dashboard. This ensures a seamless white-label experience.
</Warning>

#### Stripe Onboarding Flow

```
1. You call POST /kyc with country + redirect URLs
2. API returns onboarding_url and client_secret
3. Redirect merchant to onboarding_url (or use embedded components with client_secret)
4. Merchant completes identity verification on Stripe
5. Stripe redirects to your return_url
6. Use GET /kyc/status to check verification result
7. Webhooks notify you when status changes
```

***

## Response

### African Countries (Khaime KYC)

```json theme={null}
{
  "success": true,
  "message": "KYC submitted for review. We will notify you within 24 hours.",
  "data": {
    "provider": "khaime",
    "id": 42,
    "status": "pending_review",
    "business_type": "individual",
    "legal_name": "Amara Osei",
    "id_country": "NG",
    "bank_name": "Access Bank",
    "bank_account_number": "0123456789",
    "bank_account_name": "Amara Osei",
    "settlement_currency": "NGN",
    "country_mismatch": false,
    "submitted_at": "2026-04-10T12:00:00.000Z",
    "reviewed_at": null,
    "rejection_reason": null
  }
}
```

### Other Countries (Stripe Connect)

```json theme={null}
{
  "success": true,
  "message": "Stripe Connect onboarding initiated. Complete verification on Stripe.",
  "data": {
    "provider": "stripe",
    "submission_id": 43,
    "stripe_account_id": "acct_1234567890",
    "onboarding_url": "https://connect.stripe.com/setup/s/abc123",
    "client_secret": "accs_1234567890_secret_xyz",
    "settlement_currency": "USD",
    "stripe_region": "US"
  }
}
```

| Field               | Description                                                                                                                |
| ------------------- | -------------------------------------------------------------------------------------------------------------------------- |
| `onboarding_url`    | Redirect the merchant here to complete Stripe's hosted onboarding                                                          |
| `client_secret`     | Use with [Stripe Connect Embedded Components](https://stripe.com/docs/connect/onboarding/quickstart) for in-app onboarding |
| `stripe_account_id` | The Stripe Connect account ID for this merchant                                                                            |
| `stripe_region`     | Which Stripe region handles this account (`US` or `EU`)                                                                    |

<Tip>
  **Embedded vs Redirect**: Use `onboarding_url` for a simple redirect flow. Use `client_secret` with Stripe.js for embedded onboarding that keeps users on your site.
</Tip>

***

## Response Fields

### KycSubmission Object (Source of Truth)

All KYC and bank data is stored in the **KycSubmissions** table. This is the single source of truth.

| Field                 | Type           | Description                                                                                      |
| --------------------- | -------------- | ------------------------------------------------------------------------------------------------ |
| `id`                  | number         | KYC submission ID                                                                                |
| `status`              | string         | Current status: `pending_review`, `approved`, `rejected`, `additional_info_requested`, `revoked` |
| `business_type`       | string         | `individual` or `registered_business`                                                            |
| `legal_name`          | string         | Legal name provided                                                                              |
| `id_country`          | string         | Country of identity document                                                                     |
| `bank_name`           | string \| null | Bank name                                                                                        |
| `bank_account_number` | string \| null | Account number                                                                                   |
| `bank_account_name`   | string \| null | Account holder name                                                                              |
| `bank_sort_code`      | string \| null | Sort code if applicable                                                                          |
| `settlement_currency` | string         | Currency locked for payouts (derived from `bank_country`)                                        |
| `country_mismatch`    | boolean        | `true` if `id_country` and `bank_country` differ — flags for manual review                       |
| `submitted_at`        | string         | ISO 8601 timestamp of submission                                                                 |
| `reviewed_at`         | string \| null | ISO 8601 timestamp of review, or `null` if pending                                               |
| `rejection_reason`    | string \| null | Reason for rejection if `status` is `rejected`                                                   |

***

## KYC Status Flow

```
not_started → pending_review → approved
                            ↘ rejected → (resubmit) → pending_review
                            ↘ additional_info_requested → (resubmit) → pending_review
approved → revoked (admin action)
```

**Auto-approval**: For African markets with valid Nigerian bank details and no country mismatch, KYC may be auto-approved immediately (status `approved` in the response).

***

## Error Codes

| Status | Error                                                                   | Fix                                                                    |
| ------ | ----------------------------------------------------------------------- | ---------------------------------------------------------------------- |
| `400`  | `country or id_country is required`                                     | Include the country field                                              |
| `400`  | `account_type is required`                                              | Include `account_type` for African markets                             |
| `400`  | `owner object is required for African markets`                          | Include the `owner` object with required fields                        |
| `400`  | `business object is required for registered businesses`                 | Include `business` object when `account_type` is `registered_business` |
| `400`  | `return_url and refresh_url are required for Stripe Connect onboarding` | Include both redirect URLs for non-African countries                   |
| `401`  | `Unauthorized`                                                          | Include a valid `X-API-Key` header                                     |
| `403`  | `This endpoint is restricted to marketplace operators`                  | Your API key must belong to a marketplace operator account             |
| `404`  | `Active merchant relationship not found`                                | The merchant is not linked to your marketplace                         |

***

<RequestExample>
  ```bash cURL (Nigeria - Structured Format) theme={null}
  curl -X POST "https://api.khaime.com/api/v1/partner/marketplace/merchants/123/kyc" \
    -H "X-API-Key: pk_sandbox_your_key" \
    -H "Content-Type: application/json" \
    -d '{
      "id_country": "NG",
      "account_type": "individual",
      "owner": {
        "first_name": "Amara",
        "last_name": "Osei",
        "date_of_birth": "1990-05-15",
        "phone_number": "+2348012345678",
        "email": "amara@example.com",
        "id_type": "national_id",
        "id_number": "12345678901",
        "id_document_url": "https://cdn.example.com/docs/amara-id.jpg",
        "selfie_url": "https://cdn.example.com/docs/amara-selfie.jpg",
        "address": {
          "street": "12 Victoria Island",
          "city": "Lagos",
          "state": "Lagos",
          "postal_code": "101001",
          "country": "NG"
        }
      },
      "bank_account": {
        "country": "NG",
        "bank_name": "Access Bank",
        "account_number": "0123456789",
        "account_name": "Amara Osei"
      }
    }'
  ```

  ```bash cURL (Nigeria - Registered Business) theme={null}
  curl -X POST "https://api.khaime.com/api/v1/partner/marketplace/merchants/123/kyc" \
    -H "X-API-Key: pk_sandbox_your_key" \
    -H "Content-Type: application/json" \
    -d '{
      "id_country": "NG",
      "account_type": "registered_business",
      "owner": {
        "first_name": "Chidi",
        "last_name": "Okoro",
        "id_type": "passport",
        "id_number": "A12345678",
        "id_document_url": "https://cdn.example.com/docs/chidi-passport.jpg",
        "address": {
          "street": "45 Broad Street",
          "city": "Lagos",
          "state": "Lagos",
          "country": "NG"
        }
      },
      "business": {
        "legal_name": "Okoro Enterprises Ltd",
        "trading_name": "Okoro Store",
        "registration_number": "RC123456",
        "tax_id": "TIN12345678",
        "business_type": "llc",
        "registration_document_url": "https://cdn.example.com/docs/cac-cert.pdf",
        "address": {
          "street": "45 Broad Street",
          "city": "Lagos",
          "state": "Lagos",
          "country": "NG"
        }
      },
      "bank_account": {
        "country": "NG",
        "bank_name": "GTBank",
        "account_number": "0234567890",
        "account_name": "Okoro Enterprises Ltd"
      }
    }'
  ```

  ```bash cURL (United States - Stripe Connect) theme={null}
  curl -X POST "https://api.khaime.com/api/v1/partner/marketplace/merchants/456/kyc" \
    -H "X-API-Key: pk_sandbox_your_key" \
    -H "Content-Type: application/json" \
    -d '{
      "country": "US",
      "business_type": "individual",
      "return_url": "https://yourplatform.com/merchants/456/kyc-complete",
      "refresh_url": "https://yourplatform.com/merchants/456/kyc"
    }'
  ```

  ```bash cURL (United Kingdom - Stripe Connect) theme={null}
  curl -X POST "https://api.khaime.com/api/v1/partner/marketplace/merchants/789/kyc" \
    -H "X-API-Key: pk_sandbox_your_key" \
    -H "Content-Type: application/json" \
    -d '{
      "country": "GB",
      "business_type": "registered_business",
      "return_url": "https://yourplatform.com/merchants/789/kyc-complete",
      "refresh_url": "https://yourplatform.com/merchants/789/kyc"
    }'
  ```

  ```bash cURL (Nigeria - Legacy Flat Format) theme={null}
  curl -X POST "https://api.khaime.com/api/v1/partner/marketplace/merchants/123/kyc" \
    -H "X-API-Key: pk_sandbox_your_key" \
    -H "Content-Type: application/json" \
    -d '{
      "id_country": "NG",
      "business_type": "individual",
      "legal_name": "Amara Osei",
      "id_document_type": "national_id",
      "id_document_url": "https://cdn.example.com/docs/amara-id.jpg",
      "business_address": {
        "line1": "12 Victoria Island",
        "city": "Lagos",
        "state": "Lagos",
        "postal_code": "101001",
        "country": "NG"
      },
      "bank_country": "NG",
      "bank_name": "Access Bank",
      "bank_account_number": "0123456789",
      "bank_account_name": "Amara Osei"
    }'
  ```
</RequestExample>

***

## Next Steps

* Check the submission outcome with [Get KYC Status](/api-reference/marketplace/get-kyc-status)
* If rejected, use [Resubmit KYC](/api-reference/marketplace/resubmit-kyc) with corrected documents
* Add bank details later with [Add Bank Account](/api-reference/marketplace/add-bank-account) if not provided at submission
