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

# Setup Merchant Payout

> Configure payout settings for a sub-merchant so they can receive funds.

# Setup Merchant Payout

Configure payout for a sub-merchant. The country determines which payment infrastructure is used and what information is required. Once configured, the merchant's `baseline_currency` is automatically set based on their country.

<Note>
  This is a required step before a sub-merchant can receive charges. Until payout is configured, any charge attempt with `sub_merchant_id` will be blocked. Check `payout.charge_eligible` on [Get Merchant Details](/api-reference/marketplace/get-merchant) to confirm readiness.
</Note>

<Note>
  For NGN (`NG`) merchants, the `settlement_bank` must be a bank name from [Get Supported Payout Banks](/api-reference/marketplace/get-payout-banks). Retrieve the list first to ensure a valid name is used.
</Note>

## Data Storage

All bank details are stored in the **KycSubmissions** table, which is the single source of truth for both KYC status and payout information. This endpoint creates or updates the KycSubmissions record for the merchant.

## Path Parameters

<ParamField path="merchantId" type="string" required>
  The ID of the sub-merchant to configure payout for.
</ParamField>

## Request Body

<ParamField body="country" type="string" required>
  2-letter ISO country code (e.g., `US`, `NG`, `GB`). This determines the payout infrastructure and `baseline_currency`.
</ParamField>

### For African Countries (NG, GH, ZA, KE)

These countries use local bank transfers. Include bank account details:

<ParamField body="settlement_bank" type="string">
  Bank name for the settlement bank. Required for `NG`, `GH`, `ZA`, `KE`. For NGN merchants, this must exactly match a `name` from [Get Supported Payout Banks](/api-reference/marketplace/get-payout-banks).
</ParamField>

<ParamField body="account_number" type="string">
  Bank account number. Required for `NG`, `GH`, `ZA`, `KE`.
</ParamField>

<ParamField body="account_name" type="string">
  Account holder name. Required for `NG`, `GH`, `ZA`, `KE`.
</ParamField>

### For Other Countries (US, GB, CA, EU, etc.)

These countries use Stripe Connect. The merchant must complete an onboarding flow:

<ParamField body="email" type="string">
  Merchant's email address. Required for non-African countries.
</ParamField>

<ParamField body="callback_url" type="string" required>
  The URL where the merchant will be redirected after completing (or exiting) Stripe's onboarding flow. **Required for non-African countries.** This should be a page on your platform that handles the return from Stripe onboarding.
</ParamField>

<Warning>
  The `callback_url` is required for non-African countries. Without it, the merchant has no way to return to your platform after completing Stripe onboarding. Stripe uses this URL for both successful completion and when the merchant exits the flow early.
</Warning>

## Response

### African Countries (Immediate Setup)

When `country` is `NG`, `GH`, `ZA`, or `KE`, payout is configured immediately and bank details are stored in KycSubmissions:

```json theme={null}
{
  "success": true,
  "message": "Payout setup completed successfully",
  "data": {
    "merchant_id": 1676,
    "payout_ready": true,
    "baseline_currency": "NGN",
    "country": "NG",
    "date_connected": "2026-03-28T14:30:00.000Z"
  }
}
```

### Other Countries (Onboarding Required)

For international countries, the merchant must complete Stripe Connect onboarding:

```json theme={null}
{
  "success": true,
  "message": "Payout account created. Complete onboarding to activate.",
  "data": {
    "merchant_id": 1676,
    "payout_ready": false,
    "baseline_currency": "USD",
    "country": "US",
    "client_secret": "accs_1234567890",
    "onboarding_url": "https://connect.stripe.com/setup/..."
  }
}
```

<Warning>
  When `payout_ready` is `false`, the merchant must complete Stripe onboarding using the provided `client_secret` or `onboarding_url`. Until they do, `charge_eligible` on [Get Merchant Details](/api-reference/marketplace/get-merchant) will remain `false` and any charge with their `sub_merchant_id` will be blocked.
</Warning>

## Where Data is Stored

| Data                | Storage Location                     |
| ------------------- | ------------------------------------ |
| Bank name           | `KycSubmissions.bank_name`           |
| Account number      | `KycSubmissions.bank_account_number` |
| Account name        | `KycSubmissions.bank_account_name`   |
| Sort code           | `KycSubmissions.bank_sort_code`      |
| Stripe account ID   | `KycSubmissions.stripe_account_id`   |
| KYC status          | `KycSubmissions.status`              |
| Settlement currency | `KycSubmissions.settlement_currency` |
| Date connected      | `Educatorportfolio.date_connected`   |

<Info>
  **Important**: The `KycSubmissions` table is the single source of truth for all KYC and bank details. Legacy fields in `Educatorportfolio` (like `educator_bank_name`) are deprecated and no longer used.
</Info>

## Country to Currency Mapping

| Country      | Currency | Payout Type         |
| ------------ | -------- | ------------------- |
| `NG`         | NGN      | Immediate           |
| `GH`         | GHS      | Immediate           |
| `ZA`         | ZAR      | Immediate           |
| `KE`         | KES      | Immediate           |
| `US`         | USD      | Onboarding Required |
| `GB`         | GBP      | Onboarding Required |
| `CA`         | CAD      | Onboarding Required |
| EU countries | EUR      | Onboarding Required |

## Error Codes

| Status | Error                                                            | Fix                                                                                                        |
| ------ | ---------------------------------------------------------------- | ---------------------------------------------------------------------------------------------------------- |
| `400`  | `country is required`                                            | Include the `country` field                                                                                |
| `400`  | `settlement_bank, account_number, and account_name are required` | For African countries, include all bank details                                                            |
| `400`  | `email is required`                                              | For non-African countries, include the email                                                               |
| `400`  | `callback_url is required for non-African countries`             | Include a `callback_url` for Stripe onboarding redirect                                                    |
| `400`  | `Payout is already set up for this merchant`                     | Payout has already been configured — use [Update Payout](/api-reference/marketplace/update-payout) instead |
| `403`  | `This endpoint is restricted to marketplace operators`           | Your account must have marketplace mode enabled                                                            |
| `404`  | `Active merchant relationship not found`                         | The merchant is not linked to your marketplace                                                             |

<RequestExample>
  ```bash cURL (Nigeria) theme={null}
  curl -X POST https://api.khaime.com/api/v1/partner/marketplace/merchants/1676/payout \
    -H "X-API-Key: pk_sandbox_your_key" \
    -H "Content-Type: application/json" \
    -d '{
      "country": "NG",
      "settlement_bank": "Access Bank",
      "account_number": "0123456789",
      "account_name": "John Doe"
    }'
  ```

  ```bash cURL (United States) theme={null}
  curl -X POST https://api.khaime.com/api/v1/partner/marketplace/merchants/1676/payout \
    -H "X-API-Key: pk_sandbox_your_key" \
    -H "Content-Type: application/json" \
    -d '{
      "country": "US",
      "email": "merchant@example.com",
      "callback_url": "https://yourplatform.com/merchants/1676/payout-complete"
    }'
  ```
</RequestExample>

## How funds are split at charge time

Once payout is configured, funds are automatically split every time a charge is made with this merchant's `sub_merchant_id`:

| Recipient            | Amount                                                                                                     |
| -------------------- | ---------------------------------------------------------------------------------------------------------- |
| Sub-merchant         | Charge amount minus commission minus platform fee — transferred automatically to their bank/Stripe account |
| Marketplace operator | Commission — stays in the operator's account                                                               |
| Khaime               | Platform fee — taken upfront as part of the charge                                                         |

No manual disbursement step is needed. The split happens in real time when the payment clears.

## Checking readiness before charging

After calling this endpoint, poll [Get Merchant Details](/api-reference/marketplace/get-merchant) and check `payout.charge_eligible`:

```json theme={null}
{
  "payout": {
    "status": "active",
    "payout_ready": true,
    "charge_eligible": true
  }
}
```

| `charge_eligible` | Meaning                                                                |
| ----------------- | ---------------------------------------------------------------------- |
| `true`            | Ready — you can charge this merchant via `sub_merchant_id`             |
| `false`           | Not ready — payout setup is incomplete or Stripe onboarding is pending |

## Next Steps

After confirming `charge_eligible: true`:

* **For NGN/African merchants**: `charge_eligible` is `true` immediately after this endpoint returns `payout_ready: true`. No further action needed.
* **For international merchants**: `charge_eligible` becomes `true` only after the merchant completes Stripe onboarding via the `onboarding_url` returned in the response. Poll [Get Merchant Details](/api-reference/marketplace/get-merchant) until `charge_eligible` flips to `true`.

Once ready:

* Process charges on behalf of the merchant using the [Create Charge](/api-reference/payments/create-charge) endpoint with `sub_merchant_id`
* View the merchant's products using [List Merchant Products](/api-reference/marketplace/products)
