# Bumxpress Business documentation for LLMs
This file is a consolidated plain-text copy of the Bumxpress Business developer documentation. Use it to answer implementation questions about authentication, customers, KYC, quotes, payins, payouts, transfers, webhooks, environments, errors, coverage, and the OpenAPI reference.
Canonical documentation: https://docs.bumxpress.com
Merchant dashboard: https://portal.bumxpress.com
Production API base URL: https://api.business.bumxpress.com
## Navigation
- Guides / Getting started / Welcome to Bumxpress Business: /index
- Guides / Getting started / What Bumxpress Business does: /guides/what-is-bumxpress-business
- Guides / Getting started / How payments work: /guides/how-payments-work
- Guides / Getting started / Quickstart: /quickstart
- Guides / Getting started / Environments: /guides/environments
- Guides / Getting started / Authentication: /guides/authentication
- Guides / Core concepts / Customers and KYC: /guides/customers-and-kyc
- Guides / Core concepts / Quotes: /guides/quotes
- Guides / Core concepts / Payins: /guides/payins
- Guides / Core concepts / Payouts: /guides/payouts
- Guides / Core concepts / Transfers: /guides/transfers
- Guides / Practical flows / Mobile money payin: /guides/mobile-money-payin
- Guides / Practical flows / Mobile money payout: /guides/mobile-money-payout
- Guides / Practical flows / Cross-border transfer: /guides/cross-border-transfer
- Guides / Supporting documentation / Coverage: /guides/coverage-map
- Guides / Supporting documentation / Idempotency: /guides/idempotency
- Guides / Supporting documentation / Errors: /guides/errors
- Guides / Supporting documentation / Webhooks: /guides/webhooks
- Guides / Operate / Go-live checklist: /guides/go-live-checklist
- Guides / Operate / Changelog: /guides/changelog
- API Reference / Customers / Create customer: /api-reference/customers/create-customer
- API Reference / Customers / Get customer: /api-reference/customers/get-customer
- API Reference / Customer KYC / Submit KYC documents: /api-reference/customer-kyc/submit-kyc-documents
- API Reference / Customer KYC / Get customer KYC status: /api-reference/customer-kyc/get-customer-kyc-status
- API Reference / Quotes / Create payin quote: /api-reference/quotes/create-payin-quote
- API Reference / Quotes / Create payout quote: /api-reference/quotes/create-payout-quote
- API Reference / Quotes / Create transfer quote: /api-reference/quotes/create-transfer-quote
- API Reference / Quotes / Get quote: /api-reference/quotes/get-quote
- API Reference / Payins / Create payin: /api-reference/payins/create-payin
- API Reference / Payins / Get payin: /api-reference/payins/get-payin
- API Reference / Payouts / Create payout: /api-reference/payouts/create-payout
- API Reference / Payouts / Get payout: /api-reference/payouts/get-payout
- API Reference / Transfers / Create transfer: /api-reference/transfers/create-transfer
- API Reference / Transfers / Get transfer: /api-reference/transfers/get-transfer
- API Reference / Transfers / Relaunch transfer payout: /api-reference/transfers/relaunch-transfer-payout
---
# Welcome to Bumxpress Business
Source: /index
Section: Guides / Getting started
---
title: "Welcome to Bumxpress Business"
description: "Integrate collections, payouts, transfers, customers, KYC, and webhooks with the Bumxpress Business merchant API."
---
Bumxpress Business lets merchants collect and disburse money through mobile money and other payment rails across supported African markets.
Use these docs to create customers, generate quotes, initiate payins and payouts, launch transfers, and receive asynchronous webhook updates.
Create your first authenticated merchant API request.
Learn how `X-Api-Key` and `X-Api-Secret` protect merchant endpoints.
Review supported countries, currencies, mobile money operators, and corridors.
Browse the OpenAPI-generated merchant API reference.
## Core concepts
- Quotes lock pricing for 15 minutes.
- Payins, payouts, and transfers are asynchronous.
- Write requests use `Idempotency-Key` for safe retries.
- Merchant resources are scoped to the API key that creates or accesses them.
- Final payment status should be read from webhooks or follow-up `GET` requests.
---
# What Bumxpress Business does
Source: /guides/what-is-bumxpress-business
Section: Guides / Getting started
---
title: "What Bumxpress Business does"
description: "Understand the merchant payment platform before integrating the API."
---
Bumxpress Business gives merchants API access to payment collection, disbursement, transfer, customer, KYC, and webhook workflows.
The merchant API is designed for server-side integrations. Your backend creates customers, requests quotes, initiates money movement, stores returned resource IDs, and reconciles final status through webhooks or follow-up `GET` requests.
## What you can build
Create quote-backed payins from supported customer payment rails.
Disburse funds to recipients through supported local rails.
Collect from a payer and disburse to a recipient in a two-leg flow.
Receive asynchronous events as payment resources change state.
## Main resources
| Resource | Purpose |
| --- | --- |
| Customer | The person or entity associated with a payment flow. |
| KYC | Customer identity and compliance information. |
| Quote | A short-lived pricing and routing lock for money movement. |
| Payin | A collection from a payer. |
| Payout | A disbursement to a recipient. |
| Transfer | A two-leg collect-and-disburse flow. |
| Webhook | An asynchronous event delivered to your integration. |
## Integration model
Create requests return resource identifiers. Store those IDs in your own system and use them for reconciliation, customer support, retries, and webhook handling.
---
# How payments work
Source: /guides/how-payments-work
Section: Guides / Getting started
---
title: "How payments work"
description: "Learn the quote-backed asynchronous payment model used by Bumxpress Business."
---
Bumxpress Business payment flows are quote-backed and asynchronous.
You first create a quote to lock pricing, routing, fees, FX, and amounts. Then you create the payment resource with that active quote. The create response usually returns a pending status, while the final status arrives later through webhooks or a `GET` endpoint.
## Single-leg payin or payout
```mermaid
sequenceDiagram
participant Merchant
participant BumxpressAPI
participant Provider
participant CustomerPhone
Merchant->>BumxpressAPI: POST /customers
Merchant->>BumxpressAPI: POST /quotes/payin or /quotes/payout
Merchant->>BumxpressAPI: POST /payins or /payouts
BumxpressAPI-->>Merchant: 201 pending
BumxpressAPI->>Provider: Async submission
Provider->>CustomerPhone: Prompt or rail action
Provider-->>BumxpressAPI: Status callback
BumxpressAPI-->>Merchant: Webhook event
```
## Two-leg transfer
Transfers collect from a payer first and then disburse to a recipient. Use transfer quotes for cross-border or local two-leg flows where both legs must be tracked together.
## Important behaviors
- Quotes are valid for 15 minutes.
- Payins, payouts, and transfers are asynchronous.
- Final status should be reconciled through webhooks or `GET` endpoints.
- Write requests require `Idempotency-Key` unless the endpoint documentation says otherwise.
- Operator and corridor availability depends on your merchant account routing.
---
# Quickstart
Source: /quickstart
Section: Guides / Getting started
---
title: "Quickstart"
description: "Make your first authenticated request to the Bumxpress Business merchant API."
---
## Base URL
```text
https://api.business.bumxpress.com
```
All merchant API requests and responses use JSON.
## Prerequisites
- A Bumxpress Business merchant account
- A merchant API key and secret from the dashboard
- A unique `Idempotency-Key` for each create request
Copy your API secret when it is created. The dashboard shows it once and cannot display it again later.
## Make a request
Open the merchant dashboard and create an API key.
You will use the public key as `X-Api-Key` and the secret as `X-Api-Secret`.
```bash
curl -X POST "https://api.business.bumxpress.com/customers" \
-H "Content-Type: application/json" \
-H "X-Api-Key: bmx_pk_xxx" \
-H "X-Api-Secret: bmx_sk_xxx" \
-H "Idempotency-Key: customer_001" \
-d '{
"first_name": "Amina",
"last_name": "Ndongo",
"phone": "+237670000000",
"country_code": "CM"
}'
```
Generate a payin, payout, or transfer quote before initiating money movement.
```bash
curl -X POST "https://api.business.bumxpress.com/quotes/payin" \
-H "Content-Type: application/json" \
-H "X-Api-Key: bmx_pk_xxx" \
-H "X-Api-Secret: bmx_sk_xxx" \
-H "Idempotency-Key: quote_payin_001" \
-d '{
"country_code": "CM",
"operator_code": "CM_MTN_MOMO",
"rail_type": "mobile_money",
"send_amount": "10000",
"send_currency": "XAF"
}'
```
Use the quote ID from the quote response when creating a payin, payout, or transfer.
## Next steps
Send the required merchant API headers.
Walk through a complete mobile money collection.
---
# Environments
Source: /guides/environments
Section: Guides / Getting started
---
title: "Environments"
description: "Use the correct Bumxpress Business API base URL and request conventions."
---
## Production
```text
https://api.business.bumxpress.com
```
## Conventions
| Convention | Value |
| --- | --- |
| Request body | JSON with `Content-Type: application/json` |
| Response body | JSON |
| Amounts | Decimal strings, for example `"10000"` or `"25.00"` |
| Country codes | ISO 3166-1 alpha-2, for example `CM`, `SN`, `CI` |
| Currency codes | ISO 4217, for example `XAF`, `XOF`, `USD`, `UGX` |
| Phone numbers | E.164 recommended, for example `+237670000000` |
| Rail type | `mobile_money` or `bank_transfer` |
Operator and corridor availability can vary by merchant account. The coverage map lists platform-supported values; your account may support a subset.
---
# Authentication
Source: /guides/authentication
Section: Guides / Getting started
---
title: "Authentication"
description: "Authenticate merchant API requests with your API key and secret."
---
All protected merchant endpoints require two headers:
```http
X-Api-Key: bmx_pk_xxx
X-Api-Secret: bmx_sk_xxx
```
| Header | Description |
| --- | --- |
| `X-Api-Key` | Public key that identifies the merchant API credential. |
| `X-Api-Secret` | Secret shown once when the key is created in the merchant dashboard. |
If authentication fails, the API returns `401 Unauthorized`.
## Credential handling
- Create API keys in the merchant dashboard.
- Store `X-Api-Secret` in a secret manager.
- Never expose API secrets in mobile apps, browsers, logs, or public repositories.
- Rotate or revoke credentials from the dashboard if a secret is exposed.
## Example
```http
GET /customers/22222222-2222-2222-2222-222222222222
X-Api-Key: bmx_pk_xxx
X-Api-Secret: bmx_sk_xxx
```
Merchant resources are scoped to the merchant attached to the API key. A key cannot access another merchant's customers, quotes, payments, transfers, or webhook configuration.
---
# Customers and KYC
Source: /guides/customers-and-kyc
Section: Guides / Core concepts
---
title: "Customers and KYC"
description: "Create customer records and submit identity documents when payment providers or corridors require KYC."
---
Customers represent the people or businesses that send or receive money through your integration.
Create customers before payment flows so each quote, payin, payout, transfer, and webhook can be reconciled back to your internal records. Use `external_ref` to store your own customer identifier.
## Customer types
| Type | Use case | Required identity fields |
| --- | --- | --- |
| `individual` | A person sending or receiving money. | `first_name`, `last_name` |
| `retail` | A person identified mainly by document number. | `first_name`, `last_name`, `id_number` |
| `business` | A business customer. | `business_name` |
## Recommended customer fields
Provider requirements vary by country, operator, and corridor. For payout and transfer flows, collect the fullest profile you can:
- Name or business name
- Phone number in E.164 format
- Email address
- Country and nationality codes
- Date of birth
- Address and city
- Occupation and source of funds
For Yellow Card-backed payouts, make sure the customer profile includes `address_line1`, `city`, `occupation`, and `source_of_funds`.
## KYC documents
Submit KYC documents through `POST /customers/{customer_id}/kyc`. Document files must be hosted at public HTTPS URLs that Bumxpress can fetch.
Supported document examples include `national_id` and `passport`. At least one file URL is required per document, such as `front_file_url`, `back_file_url`, or `selfie_file_url`.
## Status tracking
Read KYC state with `GET /customers/{customer_id}/kyc`. Store the returned `kyc_status` and document IDs in your system so support and compliance teams can reconcile provider requirements.
---
# Quotes
Source: /guides/quotes
Section: Guides / Core concepts
---
title: "Quotes"
description: "Create quotes before initiating payins, payouts, or transfers."
---
Quotes lock fees, FX, provider routing, and amounts for 15 minutes. Create a fresh quote before every payin, payout, or transfer.
## Quote types
| Endpoint | Use case |
| --- | --- |
| `POST /quotes/payin` | Collect money from a customer. |
| `POST /quotes/payout` | Send money to a recipient. |
| `POST /quotes/transfer` | Collect from a payer and disburse to a recipient. |
| `GET /quotes/{quote_id}` | Read an existing quote. |
## Payin quote example
```json
{
"country_code": "CM",
"operator_code": "CM_MTN_MOMO",
"rail_type": "mobile_money",
"send_amount": "10000",
"send_currency": "XAF"
}
```
## Statuses
| Status | Meaning |
| --- | --- |
| `active` | The quote can be used to create a payin, payout, or transfer. |
| `expired` | The quote is past `expires_at`; create a new quote. |
---
# Payins
Source: /guides/payins
Section: Guides / Core concepts
---
title: "Payins"
description: "Collect money from customers with a quote-backed payin."
---
Payins are asynchronous. `POST /payins` returns quickly with a pending resource. Poll `GET /payins/{payin_id}` or wait for a webhook to receive the final status.
## Flow
Create a customer before initiating the collection.
Use `POST /quotes/payin` with the country, operator, rail type, amount, and currency.
Use the active `quote_id` and source details such as phone and operator.
Receive the final status by webhook or `GET /payins/{payin_id}`.
## Mobile money source
```json
{
"quote_id": "33333333-3333-3333-3333-333333333333",
"customer_id": "22222222-2222-2222-2222-222222222222",
"source": {
"country_code": "CM",
"rail_type": "mobile_money",
"phone": "+237670000000",
"operator_code": "CM_MTN_MOMO"
}
}
```
---
# Payouts
Source: /guides/payouts
Section: Guides / Core concepts
---
title: "Payouts"
description: "Send money to recipients with quote-backed payouts."
---
Payouts are asynchronous. `POST /payouts` creates the payout and returns a pending resource. Poll `GET /payouts/{payout_id}` or wait for a webhook to receive the final status.
## Flow
Use `POST /quotes/payout` to lock pricing and routing.
Use the active `quote_id` and recipient details.
Store the payout ID and wait for the webhook or poll the payout endpoint.
## Mobile money recipient
```json
{
"quote_id": "33333333-3333-3333-3333-333333333333",
"customer_id": "22222222-2222-2222-2222-222222222222",
"payment_reason_text": "Merchant payout",
"recipient": {
"country_code": "CM",
"rail_type": "mobile_money",
"phone": "+237670000000",
"operator_code": "CM_MTN_MOMO"
}
}
```
---
# Transfers
Source: /guides/transfers
Section: Guides / Core concepts
---
title: "Transfers"
description: "Collect from a payer and disburse to a recipient in a two-leg transfer flow."
---
Transfers are two-legged. Bumxpress first collects from the payer, then disburses to the recipient.
## Flow
Use `POST /quotes/transfer` with the source and destination operators, amount, and currencies.
Submit payer and recipient details with the active transfer quote.
Read transfer status from webhooks or `GET /transfers/{transfer_id}`.
## Quote fields
| Field | Required | Description |
| --- | --- | --- |
| `payer_operator_code` | Yes | Source-side operator for collection. |
| `recipient_operator_code` | Yes | Destination-side operator for disbursement. |
| `payin_amount` | Yes, unless quoting fixed payout | Amount collected from payer. |
| `payin_currency` | Yes | Source-side currency. |
| `payout_currency` | Yes | Destination-side currency. |
| `payout_amount` | No | Optional fixed payout amount. |
Your merchant account must have an active transfer corridor configured before transfer quotes succeed.
---
# Mobile money payin
Source: /guides/mobile-money-payin
Section: Guides / Practical flows
---
title: "Mobile money payin"
description: "Collect a mobile money payment from a customer."
---
Use this recipe when a customer pays your business from a mobile money wallet.
```bash
curl -X POST "https://api.business.bumxpress.com/customers" \
-H "Content-Type: application/json" \
-H "X-Api-Key: bmx_pk_xxx" \
-H "X-Api-Secret: bmx_sk_xxx" \
-H "Idempotency-Key: customer_001" \
-d '{"first_name":"Amina","last_name":"Ndongo","phone":"+237670000000","country_code":"CM"}'
```
```bash
curl -X POST "https://api.business.bumxpress.com/quotes/payin" \
-H "Content-Type: application/json" \
-H "X-Api-Key: bmx_pk_xxx" \
-H "X-Api-Secret: bmx_sk_xxx" \
-H "Idempotency-Key: quote_payin_001" \
-d '{"country_code":"CM","operator_code":"CM_MTN_MOMO","rail_type":"mobile_money","send_amount":"10000","send_currency":"XAF"}'
```
```bash
curl -X POST "https://api.business.bumxpress.com/payins" \
-H "Content-Type: application/json" \
-H "X-Api-Key: bmx_pk_xxx" \
-H "X-Api-Secret: bmx_sk_xxx" \
-H "Idempotency-Key: payin_001" \
-d '{
"quote_id": "33333333-3333-3333-3333-333333333333",
"customer_id": "22222222-2222-2222-2222-222222222222",
"source": {
"country_code": "CM",
"rail_type": "mobile_money",
"phone": "+237670000000",
"operator_code": "CM_MTN_MOMO"
}
}'
```
---
# Mobile money payout
Source: /guides/mobile-money-payout
Section: Guides / Practical flows
---
title: "Mobile money payout"
description: "Send money to a recipient's mobile money wallet."
---
Use this recipe when your business pays out to a recipient through mobile money.
```bash
curl -X POST "https://api.business.bumxpress.com/quotes/payout" \
-H "Content-Type: application/json" \
-H "X-Api-Key: bmx_pk_xxx" \
-H "X-Api-Secret: bmx_sk_xxx" \
-H "Idempotency-Key: quote_payout_001" \
-d '{"country_code":"CM","operator_code":"CM_MTN_MOMO","rail_type":"mobile_money","send_amount":"25.00","send_currency":"USD"}'
```
```bash
curl -X POST "https://api.business.bumxpress.com/payouts" \
-H "Content-Type: application/json" \
-H "X-Api-Key: bmx_pk_xxx" \
-H "X-Api-Secret: bmx_sk_xxx" \
-H "Idempotency-Key: payout_001" \
-d '{
"quote_id": "33333333-3333-3333-3333-333333333333",
"customer_id": "22222222-2222-2222-2222-222222222222",
"payment_reason_text": "Merchant payout",
"recipient": {
"country_code": "CM",
"rail_type": "mobile_money",
"phone": "+237670000000",
"operator_code": "CM_MTN_MOMO"
}
}'
```
---
# Cross-border transfer
Source: /guides/cross-border-transfer
Section: Guides / Practical flows
---
title: "Cross-border transfer"
description: "Collect from a payer and disburse to a recipient in another supported market."
---
Use transfers for two-leg flows where Bumxpress collects from a payer and disburses to a recipient.
```bash
curl -X POST "https://api.business.bumxpress.com/quotes/transfer" \
-H "Content-Type: application/json" \
-H "X-Api-Key: bmx_pk_xxx" \
-H "X-Api-Secret: bmx_sk_xxx" \
-H "Idempotency-Key: quote_transfer_001" \
-d '{
"payer_operator_code": "CM_MTN_MOMO",
"recipient_operator_code": "CI_ORANGE_MOMO",
"payin_amount": "100000",
"payin_currency": "XAF",
"payout_currency": "XOF"
}'
```
Submit the active quote ID with payer and recipient details.
Store the transfer ID and listen for webhook updates.
---
# Coverage
Source: /guides/coverage-map
Section: Guides / Supporting documentation
---
title: "Coverage"
description: "Supported mobile money countries and operator codes for Bumxpress Business merchant integrations."
---
Use this page to choose the correct `country_code`, `currency`, `rail_type`, and `operator_code` when creating quotes, payins, payouts, and transfers.
Platform coverage can differ from the operators enabled on your merchant account. Confirm your account routing before going live.
## Supported countries
| Country | `country_code` | Region | Currency |
| --- | --- | --- | --- |
| Cameroon | `CM` | Central Africa | `XAF` |
| Senegal | `SN` | West Africa | `XOF` |
| Benin | `BJ` | West Africa | `XOF` |
| Togo | `TG` | West Africa | `XOF` |
| Cote d'Ivoire | `CI` | West Africa | `XOF` |
## Mobile money operators
All operators listed here use:
| Field | Value |
| --- | --- |
| `rail_type` | `mobile_money` |
| Amount format | Decimal string, for example `"10000"` |
| Country format | ISO 3166-1 alpha-2 |
| Currency format | ISO 4217 |
XAF mobile money operators.
XOF mobile money operators.
XOF mobile money operators.
XOF mobile money operators.
XOF mobile money operators.
### Cameroon
| Operator | Display name | `operator_code` | Currency |
| --- | --- | --- | --- |
| MTN Cameroon | MTN Mobile Money | `CM_MTN_MOMO` | `XAF` |
| Orange Cameroon | Orange Money | `CM_ORANGE_MOMO` | `XAF` |
### Senegal
| Operator | Display name | `operator_code` | Currency |
| --- | --- | --- | --- |
| Orange Senegal | Orange Money | `SN_ORANGE_MOMO` | `XOF` |
| Free Money Senegal | Free Money | `SN_FREE_MOMO` | `XOF` |
| Expresso Senegal | Expresso Money | `SN_EXPRESSO_MOMO` | `XOF` |
### Benin
| Operator | Display name | `operator_code` | Currency |
| --- | --- | --- | --- |
| MTN Benin | MTN Mobile Money | `BJ_MTN_MOMO` | `XOF` |
| Moov Benin | Moov Money | `BJ_MOOV_MOMO` | `XOF` |
### Togo
| Operator | Display name | `operator_code` | Currency |
| --- | --- | --- | --- |
| T Money Togo | T Money | `TG_T_MONEY_MOMO` | `XOF` |
### Cote d'Ivoire
| Operator | Display name | `operator_code` | Currency |
| --- | --- | --- | --- |
| MTN Cote d'Ivoire | MTN MoMo | `CI_MTN_MOMO` | `XOF` |
| Orange Cote d'Ivoire | Orange Money | `CI_ORANGE_MOMO` | `XOF` |
| Moov Cote d'Ivoire | Moov Money | `CI_MOOV_MOMO` | `XOF` |
| Wave Cote d'Ivoire | Wave Mobile Money | `CI_WAVE_MOMO` | `XOF` |
## Usage
Quote and payment requests must use matching country, currency, rail, and operator values.
```json
{
"country_code": "CM",
"operator_code": "CM_MTN_MOMO",
"rail_type": "mobile_money",
"send_amount": "10000",
"send_currency": "XAF"
}
```
For transfer quotes, use source and destination operator codes:
```json
{
"corridor_code": "CM-CI-XAF-XOF",
"payer_operator_code": "CM_MTN_MOMO",
"recipient_operator_code": "CI_ORANGE_MOMO",
"payin_amount": "100000",
"payin_currency": "XAF",
"payout_currency": "XOF"
}
```
---
# Idempotency
Source: /guides/idempotency
Section: Guides / Supporting documentation
---
title: "Idempotency"
description: "Retry create requests safely with Idempotency-Key."
---
Write endpoints that create customers, quotes, payins, payouts, transfers, or transfer relaunches require an `Idempotency-Key` header.
```http
Idempotency-Key: payin_2026_06_08_0001
```
## Required endpoints
| Endpoint | Purpose |
| --- | --- |
| `POST /customers` | Create customer |
| `POST /quotes/payin` | Create payin quote |
| `POST /quotes/payout` | Create payout quote |
| `POST /quotes/transfer` | Create transfer quote |
| `POST /payins` | Create payin |
| `POST /payouts` | Create payout |
| `POST /transfers` | Create transfer |
| `POST /transfers/{id}/relaunch-payout` | Relaunch failed transfer disbursement |
## Rules
- Use a unique key for each distinct business intent.
- Reuse the same key only when retrying the exact same request body after a timeout or network error.
- Use a new key when creating a new payment, quote, customer, or transfer.
When a request is replayed successfully, the API marks the response metadata:
```json
{
"_meta": {
"idempotency_key": "payin_2026_06_08_0001",
"idempotency_replayed": true
}
}
```
---
# Errors
Source: /guides/errors
Section: Guides / Supporting documentation
---
title: "Errors"
description: "Understand the standard merchant API error shape and common HTTP statuses."
---
Merchant API errors use a consistent JSON shape:
```json
{
"error": {
"code": "bad_request",
"message": "quote_id is required"
}
}
```
## HTTP statuses
| Status | Meaning |
| --- | --- |
| `400` | Invalid body, missing field, expired quote, quote mismatch, or insufficient balance. |
| `401` | Missing, invalid, expired, or inactive API credentials. |
| `404` | Resource not found for the authenticated merchant. |
| `409` | Idempotency conflict or a request with the same key is still processing. |
## Handling recommendations
- Show actionable validation errors to your operators or support team.
- Retry network failures with the same `Idempotency-Key` only when the business intent and request body are unchanged.
- Do not retry authentication errors until credentials have been fixed.
- Store error responses with your internal payment record for reconciliation and support.
---
# Webhooks
Source: /guides/webhooks
Section: Guides / Supporting documentation
---
title: "Webhooks"
description: "Receive signed event callbacks when payins, payouts, or transfers change status."
---
Webhooks let Bumxpress push status changes to your backend instead of relying only on polling `GET` endpoints. Use them to update your internal records when payins, payouts, or transfers complete or fail.
## Configure your webhook
In the merchant dashboard you configure:
- **URL**: HTTPS endpoint on your backend, for example `https://api.yourapp.com/webhooks/bumxpress`
- **Signing secret**: Shared secret used to verify signatures
All webhook requests use:
```http
POST /webhooks/bumxpress
Content-Type: application/json
X-Bumxpress-Signature: sha256=
X-Bumxpress-Timestamp: 1779705120
X-Bumxpress-Event: payout.completed
X-Bumxpress-Webhook-Id: 88888888-8888-8888-8888-888888888888
```
## Verify the signature
Signatures use an HMAC over the timestamp and raw request body:
```text
sha256=HMAC_SHA256(webhook_secret, timestamp + "." + raw_request_body)
```
Verify signatures **before** parsing JSON or applying side effects.
```ts
import crypto from "node:crypto";
export function verifyBumxpressWebhook({
secret,
timestamp,
rawBody,
signature,
}: {
secret: string;
timestamp: string;
rawBody: string;
signature: string;
}) {
const expected =
"sha256=" +
crypto
.createHmac("sha256", secret)
.update(`${timestamp}.${rawBody}`)
.digest("hex");
const expectedBuffer = Buffer.from(expected);
const signatureBuffer = Buffer.from(signature);
return (
expectedBuffer.length === signatureBuffer.length &&
crypto.timingSafeEqual(expectedBuffer, signatureBuffer)
);
}
```
Always verify `X-Bumxpress-Signature` using the raw request body. Reject requests when verification fails.
## Event types
Bumxpress emits a small set of payment events. Use the `event` and `data.type` fields to route handling logic.
```json
{
"id": "88888888-8888-8888-8888-888888888888",
"event": "payin.completed",
"created_at": "2026-06-08T10:40:00Z",
"data": {
"type": "payin",
"id": "44444444-4444-4444-4444-444444444444",
"object": { }
}
}
```
Supported events:
- **payin.completed** / **payin.failed** (`data.type: "payin"`)
- **payout.completed** / **payout.failed** (`data.type: "payout"`)
- **transfer.payin.completed** / **transfer.payin.failed** (`data.type: "transfer"`)
- **transfer.payout.completed** / **transfer.payout.failed** (`data.type: "transfer"`)
- **transfer.completed** / **transfer.failed** (`data.type: "transfer"`)
Transfer leg events are sent as each leg reaches a terminal state. Aggregate transfer events are still sent when the full transfer reaches a final state. The `data.object` field contains a snapshot of the resource at event time, including amounts, status, operator, wallet impact, and timestamps.
## Example payloads
**Payin webhook**
```json
{
"id": "88888888-8888-8888-8888-888888888888",
"event": "payin.completed",
"created_at": "2026-06-08T10:40:00Z",
"data": {
"type": "payin",
"id": "44444444-4444-4444-4444-444444444444",
"object": {
"id": "44444444-4444-4444-4444-444444444444",
"status": "completed",
"send_amount": "10000",
"send_currency": "XAF",
"receive_amount": "16",
"receive_currency": "USD",
"country_code": "CM",
"operator_code": "CM_MTN_MOMO",
"rail_type": "mobile_money",
"wallet_impact": {
"credit_amount": "16.00",
"currency": "USD"
},
"completed_at": "2026-06-08T10:39:30Z"
}
}
}
```
**Payout webhook**
```json
{
"id": "99999999-9999-9999-9999-999999999999",
"event": "payout.completed",
"created_at": "2026-06-08T10:42:00Z",
"data": {
"type": "payout",
"id": "66666666-6666-6666-6666-666666666666",
"object": {
"id": "66666666-6666-6666-6666-666666666666",
"status": "completed",
"send_amount": "25",
"send_currency": "USD",
"receive_amount": "15125",
"receive_currency": "XAF",
"operator_code": "CM_MTN_MOMO",
"wallet_impact": {
"debit_amount": "26.50",
"currency": "USD"
},
"completed_at": "2026-06-08T10:41:30Z"
}
}
}
```
**Transfer webhook**
```json
{
"id": "aaaaaaaa-aaaa-aaaa-aaaa-aaaaaaaaaaaa",
"event": "transfer.completed",
"created_at": "2026-06-08T11:30:00Z",
"data": {
"type": "transfer",
"id": "77777777-7777-7777-7777-777777777777",
"object": {
"id": "77777777-7777-7777-7777-777777777777",
"status": "completed",
"payin_status": "completed",
"payout_status": "completed",
"send_amount": "100000",
"send_currency": "XAF",
"receive_amount": "98500",
"receive_currency": "XOF",
"corridor_code": "CM-CI-XAF-XOF",
"payer_operator_code": "CM_MTN_MOMO",
"recipient_operator_code": "CI_ORANGE_MOMO",
"collection_completed_at": "2026-06-08T11:15:00Z",
"disbursement_completed_at": "2026-06-08T11:28:00Z"
}
}
}
```
**Transfer payin leg webhook**
```json
{
"id": "bbbbbbbb-bbbb-bbbb-bbbb-bbbbbbbbbbbb",
"event": "transfer.payin.completed",
"created_at": "2026-06-08T11:15:05Z",
"data": {
"type": "transfer",
"id": "77777777-7777-7777-7777-777777777777",
"object": {
"id": "77777777-7777-7777-7777-777777777777",
"status": "disbursing",
"payin_status": "completed",
"payout_status": "pending",
"payin_amount": "100000",
"payin_currency": "XAF",
"payout_amount": "98500",
"payout_currency": "XOF",
"payer_operator_code": "CM_MTN_MOMO",
"recipient_operator_code": "CI_ORANGE_MOMO",
"collection_reference": "TXN_COLLECTION_123",
"collection_completed_at": "2026-06-08T11:15:00Z"
}
}
}
```
**Transfer payout leg webhook**
```json
{
"id": "cccccccc-cccc-cccc-cccc-cccccccccccc",
"event": "transfer.payout.failed",
"created_at": "2026-06-08T11:28:05Z",
"data": {
"type": "transfer",
"id": "77777777-7777-7777-7777-777777777777",
"object": {
"id": "77777777-7777-7777-7777-777777777777",
"status": "failed",
"payin_status": "completed",
"payout_status": "failed",
"payin_amount": "100000",
"payin_currency": "XAF",
"payout_amount": "98500",
"payout_currency": "XOF",
"payer_operator_code": "CM_MTN_MOMO",
"recipient_operator_code": "CI_ORANGE_MOMO",
"disbursement_reference": "TXN_PAYOUT_123",
"disbursement_failed_at": "2026-06-08T11:28:00Z"
}
}
}
```
## Delivery and retries
Return any **2xx** status code to acknowledge receipt. If your endpoint returns a non-2xx or times out, Bumxpress retries with exponential backoff:
| Failed attempt | Next retry |
| -------------- | ----------- |
| 1 | 1 minute |
| 2 | 5 minutes |
| 3 | 15 minutes |
| 4 | 1 hour |
| 5 | 4 hours |
| 6 | 12 hours |
After the seventh failed attempt, delivery is marked failed.
## Recommended handler pattern
Implement your webhook handler with these rules:
1. **Verify** the HMAC signature.
2. **Deduplicate** using `X-Bumxpress-Webhook-Id` or event `id`.
3. **Update** your local record using `data.id` and `data.type`.
4. **Acknowledge** with `200 OK` only after the update succeeds.
5. **Fallback** to `GET /payins/{id}`, `GET /payouts/{id}`, or `GET /transfers/{id}` when you need to recover from missed events.
---
# Go-live checklist
Source: /guides/go-live-checklist
Section: Guides / Operate
---
title: "Go-live checklist"
description: "Prepare a Bumxpress Business merchant integration for production traffic."
---
Use this checklist before moving real payment volume through the merchant API.
## Credentials
- Create production API credentials in the merchant dashboard.
- Store `X-Api-Secret` in a secret manager.
- Confirm secrets are not exposed in browser, mobile, logs, analytics, or public repositories.
- Document the credential rotation process.
## Payment flows
- Store all resource IDs returned by create responses.
- Use a unique `Idempotency-Key` for every distinct create request.
- Confirm quote expiry handling creates a fresh quote.
- Confirm payin, payout, and transfer records can move from pending to final status.
- Confirm your merchant account has the required operators and corridors enabled.
## Webhooks
- Configure production webhook endpoints.
- Verify `X-Bumxpress-Signature` before processing events.
- Process duplicate webhook deliveries idempotently.
- Reconcile missed events with `GET` endpoints.
- Return `2xx` only after accepting an event.
## Operations
- Add internal dashboards or logs for customer, quote, payment, transfer, and webhook IDs.
- Define support procedures for pending, failed, and duplicate-looking payments.
- Monitor API error rates and webhook delivery failures.
---
# Changelog
Source: /guides/changelog
Section: Guides / Operate
---
title: "Changelog"
description: "Merchant API documentation updates."
---
## July 2026
- Created the Mintlify documentation project.
- Added starter guides, recipes, and API reference pages for the merchant API.
- Added coverage, authentication, idempotency, and webhook documentation.
---
# Create customer
Source: /api-reference/customers/create-customer
Section: API Reference / Customers
---
title: "Create customer"
description: "Create an individual, retail, or business customer."
openapi: "POST /customers"
---
Create a customer before starting payment flows so quotes, payments, transfers, and webhook events can be reconciled to your internal records.
---
# Get customer
Source: /api-reference/customers/get-customer
Section: API Reference / Customers
---
title: "Get customer"
description: "Retrieve a merchant-scoped customer by ID."
openapi: "GET /customers/{customer_id}"
---
The authenticated API key can only access customers that belong to its merchant.
---
# Submit KYC documents
Source: /api-reference/customer-kyc/submit-kyc-documents
Section: API Reference / Customer KYC
---
title: "Submit KYC documents"
description: "Submit identity documents for a customer."
openapi: "POST /customers/{customer_id}/kyc"
---
Document files must be available at public HTTP or HTTPS URLs so Bumxpress can fetch them.
---
# Get customer KYC status
Source: /api-reference/customer-kyc/get-customer-kyc-status
Section: API Reference / Customer KYC
---
title: "Get customer KYC status"
description: "Read the latest KYC status and submitted documents for a customer."
openapi: "GET /customers/{customer_id}/kyc"
---
Use this endpoint to reconcile customer KYC state before payout or transfer flows that require provider compliance checks.
---
# Create payin quote
Source: /api-reference/quotes/create-payin-quote
Section: API Reference / Quotes
---
title: "Create payin quote"
description: "Create a quote before initiating a payin."
openapi: "POST /quotes/payin"
---
Quotes lock fees, routing, FX, and amounts for 15 minutes.
---
# Create payout quote
Source: /api-reference/quotes/create-payout-quote
Section: API Reference / Quotes
---
title: "Create payout quote"
description: "Create a quote before initiating a payout."
openapi: "POST /quotes/payout"
---
Use payout quotes before sending funds from your USD merchant wallet to a recipient in local currency.
---
# Create transfer quote
Source: /api-reference/quotes/create-transfer-quote
Section: API Reference / Quotes
---
title: "Create transfer quote"
description: "Create a quote for a two-leg transfer flow."
openapi: "POST /quotes/transfer"
---
Use transfer quotes for flows that collect from a payer and disburse to a recipient.
---
# Get quote
Source: /api-reference/quotes/get-quote
Section: API Reference / Quotes
---
title: "Get quote"
description: "Retrieve a payin, payout, or transfer quote by ID."
openapi: "GET /quotes/{quote_id}"
---
Expired quotes cannot be used to create payment resources.
---
# Create payin
Source: /api-reference/payins/create-payin
Section: API Reference / Payins
---
title: "Create payin"
description: "Create a quote-backed payin."
openapi: "POST /payins"
---
The API returns a pending resource while provider processing continues asynchronously.
---
# Get payin
Source: /api-reference/payins/get-payin
Section: API Reference / Payins
---
title: "Get payin"
description: "Retrieve a payin by ID."
openapi: "GET /payins/{payin_id}"
---
Poll this endpoint or process webhooks to reconcile final status.
---
# Create payout
Source: /api-reference/payouts/create-payout
Section: API Reference / Payouts
---
title: "Create payout"
description: "Create a quote-backed payout."
openapi: "POST /payouts"
---
Payouts debit the merchant wallet and are processed asynchronously.
---
# Get payout
Source: /api-reference/payouts/get-payout
Section: API Reference / Payouts
---
title: "Get payout"
description: "Retrieve a payout by ID."
openapi: "GET /payouts/{payout_id}"
---
Store payout IDs from create responses or webhook payloads.
---
# Create transfer
Source: /api-reference/transfers/create-transfer
Section: API Reference / Transfers
---
title: "Create transfer"
description: "Create a quote-backed transfer."
openapi: "POST /transfers"
---
Bumxpress collects from the payer first, then disburses to the recipient.
---
# Get transfer
Source: /api-reference/transfers/get-transfer
Section: API Reference / Transfers
---
title: "Get transfer"
description: "Retrieve transfer status and leg execution details."
openapi: "GET /transfers/{transfer_id}"
---
Use this endpoint to read payin and payout leg status, execution metadata, and timestamps.
---
# Relaunch transfer payout
Source: /api-reference/transfers/relaunch-transfer-payout
Section: API Reference / Transfers
---
title: "Relaunch transfer payout"
description: "Retry a failed transfer disbursement leg."
openapi: "POST /transfers/{transfer_id}/relaunch-payout"
---
Retry a failed transfer disbursement leg without collecting from the payer again.
---
# OpenAPI specification
Source: /openapi.yaml
```yaml
---
openapi: 3.0.3
info:
title: Bumxpress Business Merchant API
version: 1.0.0
description: |
Merchant API for customers, KYC, quotes, payins, payouts, transfers, and webhooks.
All merchant resources are scoped to the merchant attached to the API key.
license:
name: Proprietary
url: https://business.bumxpress.com
servers:
- url: https://api.business.bumxpress.com
description: Production
security:
- ApiKeyAuth: []
ApiSecretAuth: []
tags:
- name: Customers
description: Create and retrieve merchant-scoped customer records.
- name: Customer KYC
description: Submit and retrieve customer identity document status.
- name: Quotes
description: Create and retrieve pricing and routing quotes.
- name: Payins
description: Create and retrieve payment collection resources.
- name: Payouts
description: Create and retrieve disbursement resources.
- name: Transfers
description: Create, retrieve, and relaunch two-leg transfer resources.
paths:
"/customers":
post:
tags:
- Customers
summary: Create customer
description: Create an individual, retail, or business customer.
operationId: createCustomer
parameters:
- "$ref": "#/components/parameters/IdempotencyKey"
requestBody:
required: true
content:
application/json:
schema:
"$ref": "#/components/schemas/CreateCustomerRequest"
examples:
individual:
value:
external_ref: your-internal-id-123
customer_type: individual
first_name: Awa
last_name: Ngu
id_number: ID123456
id_type: national_id
email: awa@example.com
phone: "+237670000000"
country_code: CM
nationality_code: CM
date_of_birth: '1990-05-15'
address_line1: 123 Main Street
city: Douala
occupation: Engineer
source_of_funds: salary
business:
value:
external_ref: biz-456
customer_type: business
business_name: Acme SARL
email: billing@acme.com
phone: "+237670000001"
country_code: CM
nationality_code: CM
address_line1: 45 Avenue Kennedy
city: Douala
responses:
'201':
description: Customer created.
content:
application/json:
schema:
"$ref": "#/components/schemas/Customer"
'400':
"$ref": "#/components/responses/BadRequest"
'401':
"$ref": "#/components/responses/Unauthorized"
'409':
"$ref": "#/components/responses/Conflict"
"/customers/{customer_id}":
get:
tags:
- Customers
summary: Get customer
operationId: getCustomer
parameters:
- "$ref": "#/components/parameters/CustomerId"
responses:
'200':
description: Customer object.
content:
application/json:
schema:
"$ref": "#/components/schemas/Customer"
'401':
"$ref": "#/components/responses/Unauthorized"
'404':
"$ref": "#/components/responses/NotFound"
"/customers/{customer_id}/kyc":
post:
tags:
- Customer KYC
summary: Submit KYC documents
description: Submit identity documents for a customer. Document file URLs must be public HTTP or HTTPS URLs that Bumxpress can fetch.
operationId: submitCustomerKyc
parameters:
- "$ref": "#/components/parameters/CustomerId"
requestBody:
required: true
content:
application/json:
schema:
"$ref": "#/components/schemas/SubmitKycRequest"
example:
documents:
- document_type: national_id
document_number: ID123456
issue_country_code: CM
issue_date: '2020-01-15'
expiry_date: '2030-01-15'
front_file_url: https://cdn.example.com/kyc/front.jpg
back_file_url: https://cdn.example.com/kyc/back.jpg
selfie_file_url: https://cdn.example.com/kyc/selfie.jpg
responses:
'201':
description: KYC documents accepted.
content:
application/json:
schema:
"$ref": "#/components/schemas/KycStatus"
'400':
"$ref": "#/components/responses/BadRequest"
'401':
"$ref": "#/components/responses/Unauthorized"
'404':
"$ref": "#/components/responses/NotFound"
get:
tags:
- Customer KYC
summary: Get customer KYC status
operationId: getCustomerKyc
parameters:
- "$ref": "#/components/parameters/CustomerId"
responses:
'200':
description: Customer KYC status and documents.
content:
application/json:
schema:
"$ref": "#/components/schemas/KycStatus"
'401':
"$ref": "#/components/responses/Unauthorized"
'404':
"$ref": "#/components/responses/NotFound"
"/quotes/payin":
post:
tags:
- Quotes
summary: Create payin quote
description: Create a quote to collect money from a customer into the merchant USD wallet.
operationId: createPayinQuote
parameters:
- "$ref": "#/components/parameters/IdempotencyKey"
requestBody:
required: true
content:
application/json:
schema:
"$ref": "#/components/schemas/CreatePayinQuoteRequest"
responses:
'201':
description: Payin quote created.
content:
application/json:
schema:
"$ref": "#/components/schemas/Quote"
'400':
"$ref": "#/components/responses/BadRequest"
'401':
"$ref": "#/components/responses/Unauthorized"
'409':
"$ref": "#/components/responses/Conflict"
"/quotes/payout":
post:
tags:
- Quotes
summary: Create payout quote
description: Create a quote to send money from the merchant USD wallet to a recipient in local currency.
operationId: createPayoutQuote
parameters:
- "$ref": "#/components/parameters/IdempotencyKey"
requestBody:
required: true
content:
application/json:
schema:
"$ref": "#/components/schemas/CreatePayoutQuoteRequest"
responses:
'201':
description: Payout quote created.
content:
application/json:
schema:
"$ref": "#/components/schemas/Quote"
'400':
"$ref": "#/components/responses/BadRequest"
'401':
"$ref": "#/components/responses/Unauthorized"
'409':
"$ref": "#/components/responses/Conflict"
"/quotes/transfer":
post:
tags:
- Quotes
summary: Create transfer quote
description: Create a quote for a two-leg flow that collects from a payer and disburses to a recipient.
operationId: createTransferQuote
parameters:
- "$ref": "#/components/parameters/IdempotencyKey"
requestBody:
required: true
content:
application/json:
schema:
"$ref": "#/components/schemas/CreateTransferQuoteRequest"
responses:
'201':
description: Transfer quote created.
content:
application/json:
schema:
"$ref": "#/components/schemas/Quote"
'400':
"$ref": "#/components/responses/BadRequest"
'401':
"$ref": "#/components/responses/Unauthorized"
'409':
"$ref": "#/components/responses/Conflict"
"/quotes/{quote_id}":
get:
tags:
- Quotes
summary: Get quote
operationId: getQuote
parameters:
- "$ref": "#/components/parameters/QuoteId"
responses:
'200':
description: Quote object.
content:
application/json:
schema:
"$ref": "#/components/schemas/Quote"
'401':
"$ref": "#/components/responses/Unauthorized"
'404':
"$ref": "#/components/responses/NotFound"
"/payins":
post:
tags:
- Payins
summary: Create payin
description: Create a quote-backed payin. The API returns pending and processes the provider submission asynchronously.
operationId: createPayin
parameters:
- "$ref": "#/components/parameters/IdempotencyKey"
requestBody:
required: true
content:
application/json:
schema:
"$ref": "#/components/schemas/CreatePayinRequest"
responses:
'201':
description: Payin created.
content:
application/json:
schema:
"$ref": "#/components/schemas/Payin"
'400':
"$ref": "#/components/responses/BadRequest"
'401':
"$ref": "#/components/responses/Unauthorized"
'409':
"$ref": "#/components/responses/Conflict"
"/payins/{payin_id}":
get:
tags:
- Payins
summary: Get payin
operationId: getPayin
parameters:
- "$ref": "#/components/parameters/PayinId"
responses:
'200':
description: Payin object.
content:
application/json:
schema:
"$ref": "#/components/schemas/Payin"
'401':
"$ref": "#/components/responses/Unauthorized"
'404':
"$ref": "#/components/responses/NotFound"
"/payouts":
post:
tags:
- Payouts
summary: Create payout
description: Create a quote-backed payout. Payout processing is asynchronous.
operationId: createPayout
parameters:
- "$ref": "#/components/parameters/IdempotencyKey"
requestBody:
required: true
content:
application/json:
schema:
"$ref": "#/components/schemas/CreatePayoutRequest"
responses:
'201':
description: Payout created.
content:
application/json:
schema:
"$ref": "#/components/schemas/Payout"
'400':
"$ref": "#/components/responses/BadRequest"
'401':
"$ref": "#/components/responses/Unauthorized"
'409':
"$ref": "#/components/responses/Conflict"
"/payouts/{payout_id}":
get:
tags:
- Payouts
summary: Get payout
operationId: getPayout
parameters:
- "$ref": "#/components/parameters/PayoutId"
responses:
'200':
description: Payout object.
content:
application/json:
schema:
"$ref": "#/components/schemas/Payout"
'401':
"$ref": "#/components/responses/Unauthorized"
'404':
"$ref": "#/components/responses/NotFound"
"/transfers":
post:
tags:
- Transfers
summary: Create transfer
description: Create a quote-backed transfer that collects from a payer and disburses to a recipient.
operationId: createTransfer
parameters:
- "$ref": "#/components/parameters/IdempotencyKey"
requestBody:
required: true
content:
application/json:
schema:
"$ref": "#/components/schemas/CreateTransferRequest"
responses:
'201':
description: Transfer created.
content:
application/json:
schema:
"$ref": "#/components/schemas/Transfer"
'400':
"$ref": "#/components/responses/BadRequest"
'401':
"$ref": "#/components/responses/Unauthorized"
'409':
"$ref": "#/components/responses/Conflict"
"/transfers/{transfer_id}":
get:
tags:
- Transfers
summary: Get transfer
operationId: getTransfer
parameters:
- "$ref": "#/components/parameters/TransferId"
responses:
'200':
description: Transfer object.
content:
application/json:
schema:
"$ref": "#/components/schemas/Transfer"
'401':
"$ref": "#/components/responses/Unauthorized"
'404':
"$ref": "#/components/responses/NotFound"
"/transfers/{transfer_id}/relaunch-payout":
post:
tags:
- Transfers
summary: Relaunch transfer payout
description: Retry a failed disbursement leg without re-collecting from the payer.
operationId: relaunchTransferPayout
parameters:
- "$ref": "#/components/parameters/TransferId"
- "$ref": "#/components/parameters/IdempotencyKey"
requestBody:
required: false
content:
application/json:
schema:
"$ref": "#/components/schemas/RelaunchPayoutRequest"
responses:
'202':
description: Payout leg relaunched.
content:
application/json:
schema:
"$ref": "#/components/schemas/Transfer"
'400':
"$ref": "#/components/responses/BadRequest"
'401':
"$ref": "#/components/responses/Unauthorized"
'404':
"$ref": "#/components/responses/NotFound"
'409':
"$ref": "#/components/responses/Conflict"
components:
securitySchemes:
ApiKeyAuth:
type: apiKey
in: header
name: X-Api-Key
description: Public API key from the merchant dashboard.
ApiSecretAuth:
type: apiKey
in: header
name: X-Api-Secret
description: Secret shown once when the API key is created.
parameters:
IdempotencyKey:
name: Idempotency-Key
in: header
required: true
description: Unique key for this business intent. Reuse only when retrying the same request body.
schema:
type: string
example: payin_2026_06_08_0001
CustomerId:
name: customer_id
in: path
required: true
schema:
type: string
format: uuid
QuoteId:
name: quote_id
in: path
required: true
schema:
type: string
format: uuid
PayinId:
name: payin_id
in: path
required: true
schema:
type: string
format: uuid
PayoutId:
name: payout_id
in: path
required: true
schema:
type: string
format: uuid
TransferId:
name: transfer_id
in: path
required: true
schema:
type: string
format: uuid
responses:
BadRequest:
description: Invalid body, missing field, expired quote, quote mismatch, or insufficient balance.
content:
application/json:
schema:
"$ref": "#/components/schemas/ErrorResponse"
Unauthorized:
description: Missing, invalid, expired, or inactive API credentials.
content:
application/json:
schema:
"$ref": "#/components/schemas/ErrorResponse"
NotFound:
description: Resource not found for the authenticated merchant.
content:
application/json:
schema:
"$ref": "#/components/schemas/ErrorResponse"
Conflict:
description: Idempotency conflict or request with same key still processing.
content:
application/json:
schema:
"$ref": "#/components/schemas/ErrorResponse"
schemas:
ErrorResponse:
type: object
required:
- error
properties:
error:
type: object
required:
- code
- message
properties:
code:
type: string
example: bad_request
message:
type: string
example: quote_id is required
CreateCustomerRequest:
type: object
properties:
external_ref:
type: string
description: Merchant reference, unique per merchant.
customer_type:
type: string
enum:
- individual
- retail
- business
default: individual
first_name:
type: string
last_name:
type: string
business_name:
type: string
id_number:
type: string
id_type:
type: string
enum:
- national_id
- passport
- driver_license
email:
type: string
format: email
phone:
type: string
example: "+237670000000"
country_code:
"$ref": "#/components/schemas/CountryCode"
nationality_code:
"$ref": "#/components/schemas/CountryCode"
date_of_birth:
type: string
format: date
address_line1:
type: string
city:
type: string
occupation:
type: string
source_of_funds:
type: string
Customer:
allOf:
- "$ref": "#/components/schemas/CreateCustomerRequest"
- type: object
required:
- id
- merchant_id
- customer_type
- kyc_status
- status
- created_at
- updated_at
properties:
id:
type: string
format: uuid
merchant_id:
type: string
format: uuid
kyc_status:
type: string
enum:
- not_started
- pending
- approved
- rejected
status:
type: string
example: active
created_at:
type: string
format: date-time
updated_at:
type: string
format: date-time
_meta:
"$ref": "#/components/schemas/IdempotencyMeta"
SubmitKycRequest:
type: object
required:
- documents
properties:
documents:
type: array
minItems: 1
items:
"$ref": "#/components/schemas/KycDocumentInput"
KycDocumentInput:
type: object
required:
- document_type
properties:
document_type:
type: string
example: national_id
document_number:
type: string
issue_country_code:
"$ref": "#/components/schemas/CountryCode"
issue_date:
type: string
format: date
expiry_date:
type: string
format: date
front_file_url:
type: string
format: uri
back_file_url:
type: string
format: uri
selfie_file_url:
type: string
format: uri
KycStatus:
type: object
required:
- customer_id
- kyc_status
- documents
properties:
customer_id:
type: string
format: uuid
kyc_status:
type: string
enum:
- not_started
- pending
- approved
- rejected
documents:
type: array
items:
allOf:
- "$ref": "#/components/schemas/KycDocumentInput"
- type: object
properties:
id:
type: string
format: uuid
status:
type: string
example: uploaded
created_at:
type: string
format: date-time
CreatePayinQuoteRequest:
type: object
required:
- country_code
- operator_code
- rail_type
- send_amount
- send_currency
properties:
customer_id:
type: string
format: uuid
country_code:
"$ref": "#/components/schemas/CountryCode"
operator_code:
type: string
example: CM_MTN_MOMO
rail_type:
"$ref": "#/components/schemas/RailType"
send_amount:
"$ref": "#/components/schemas/DecimalString"
send_currency:
"$ref": "#/components/schemas/CurrencyCode"
example:
customer_id: 22222222-2222-2222-2222-222222222222
country_code: CM
operator_code: CM_MTN_MOMO
rail_type: mobile_money
send_amount: '10000'
send_currency: XAF
CreatePayoutQuoteRequest:
allOf:
- "$ref": "#/components/schemas/CreatePayinQuoteRequest"
example:
customer_id: 22222222-2222-2222-2222-222222222222
country_code: CM
operator_code: CM_MTN_MOMO
rail_type: mobile_money
send_amount: '25.00'
send_currency: USD
CreateTransferQuoteRequest:
type: object
required:
- corridor_code
- payer_operator_code
- recipient_operator_code
- payout_currency
properties:
customer_id:
type: string
format: uuid
corridor_code:
type: string
example: CM-CI-XAF-XOF
payer_operator_code:
type: string
example: CM_MTN_MOMO
recipient_operator_code:
type: string
example: CI_ORANGE_MOMO
payin_amount:
"$ref": "#/components/schemas/DecimalString"
payin_currency:
"$ref": "#/components/schemas/CurrencyCode"
payout_amount:
"$ref": "#/components/schemas/DecimalString"
payout_currency:
"$ref": "#/components/schemas/CurrencyCode"
send_amount:
"$ref": "#/components/schemas/DecimalString"
send_currency:
"$ref": "#/components/schemas/CurrencyCode"
example:
customer_id: 22222222-2222-2222-2222-222222222222
corridor_code: CM-CI-XAF-XOF
payer_operator_code: CM_MTN_MOMO
recipient_operator_code: CI_ORANGE_MOMO
payin_amount: '100000'
payin_currency: XAF
payout_amount: '98500'
payout_currency: XOF
send_amount: '100000'
send_currency: XAF
Quote:
type: object
properties:
id:
type: string
format: uuid
customer_id:
type: string
format: uuid
flow_type:
type: string
enum:
- payin
- payout
- transfer
status:
type: string
enum:
- active
- expired
- consumed
expires_at:
type: string
format: date-time
send_amount:
"$ref": "#/components/schemas/DecimalString"
send_currency:
"$ref": "#/components/schemas/CurrencyCode"
receive_amount:
"$ref": "#/components/schemas/DecimalString"
receive_currency:
"$ref": "#/components/schemas/CurrencyCode"
country_code:
"$ref": "#/components/schemas/CountryCode"
operator_code:
type: string
rail_type:
"$ref": "#/components/schemas/RailType"
corridor_code:
type: string
corridor_type:
type: string
payer_operator_code:
type: string
recipient_operator_code:
type: string
total_fee:
"$ref": "#/components/schemas/DecimalString"
wallet_impact:
type: object
additionalProperties: true
created_at:
type: string
format: date-time
_meta:
"$ref": "#/components/schemas/IdempotencyMeta"
CreatePayinRequest:
type: object
required:
- quote_id
- customer_id
- source
properties:
quote_id:
type: string
format: uuid
customer_id:
type: string
format: uuid
source:
"$ref": "#/components/schemas/RailParty"
example:
quote_id: 33333333-3333-3333-3333-333333333333
customer_id: 22222222-2222-2222-2222-222222222222
source:
country_code: CM
rail_type: mobile_money
phone: "+237670000000"
operator_code: CM_MTN_MOMO
CreatePayoutRequest:
type: object
required:
- quote_id
- customer_id
- recipient
properties:
quote_id:
type: string
format: uuid
customer_id:
type: string
format: uuid
payment_reason_code:
type: string
example: OTHER
payment_reason_text:
type: string
example: Merchant payout
recipient:
"$ref": "#/components/schemas/Recipient"
example:
quote_id: 33333333-3333-3333-3333-333333333333
customer_id: 22222222-2222-2222-2222-222222222222
payment_reason_code: OTHER
payment_reason_text: Merchant payout
recipient:
recipient_type: individual
first_name: Awa
last_name: Ngu
country_code: CM
rail_type: mobile_money
phone: "+237670000000"
email: awa@example.com
recipient_nationality_code: CM
operator_code: CM_MTN_MOMO
address_line1: 123 Main Street
city: Douala
CreateTransferRequest:
type: object
required:
- quote_id
- customer_id
- payer
- recipient
properties:
quote_id:
type: string
format: uuid
customer_id:
type: string
format: uuid
payment_reason_code:
type: string
example: OTHER
sender_source_of_funds:
type: string
example: salary
sender_occupation:
type: string
example: Engineer
payer:
"$ref": "#/components/schemas/RailParty"
recipient:
"$ref": "#/components/schemas/Recipient"
example:
quote_id: 33333333-3333-3333-3333-333333333333
customer_id: 22222222-2222-2222-2222-222222222222
payment_reason_code: OTHER
sender_source_of_funds: salary
sender_occupation: Engineer
payer:
country_code: CM
rail_type: mobile_money
phone: "+237670000000"
operator_code: CM_MTN_MOMO
recipient:
recipient_type: individual
first_name: Mariam
last_name: Traore
country_code: CI
rail_type: mobile_money
phone: "+2250700112233"
operator_code: CI_ORANGE_MOMO
email: mariam.traore@example.com
recipient_nationality_code: CI
address_line1: Rue du Commerce
city: Abidjan
RelaunchPayoutRequest:
type: object
properties:
payout_amount:
"$ref": "#/components/schemas/DecimalString"
recipient:
"$ref": "#/components/schemas/Recipient"
example:
payout_amount: '98500'
recipient:
recipient_type: individual
first_name: Mariam
last_name: Traore
country_code: CI
rail_type: mobile_money
phone: "+2250700112233"
operator_code: CI_ORANGE_MOMO
email: mariam.traore@example.com
recipient_nationality_code: CI
address_line1: Rue du Commerce
city: Abidjan
Payin:
allOf:
- "$ref": "#/components/schemas/PaymentBase"
- type: object
properties:
status:
type: string
enum:
- created
- pending
- completed
- failed
source:
"$ref": "#/components/schemas/RailParty"
Payout:
allOf:
- "$ref": "#/components/schemas/PaymentBase"
- type: object
properties:
status:
type: string
enum:
- created
- pending
- completed
- failed
recipient:
"$ref": "#/components/schemas/Recipient"
Transfer:
type: object
properties:
id:
type: string
format: uuid
merchant_id:
type: string
format: uuid
customer_id:
type: string
format: uuid
quote_id:
type: string
format: uuid
status:
type: string
enum:
- pending
- collecting
- disbursing
- completed
- failed
payin_status:
type: string
payout_status:
type: string
send_amount:
"$ref": "#/components/schemas/DecimalString"
send_currency:
"$ref": "#/components/schemas/CurrencyCode"
receive_amount:
"$ref": "#/components/schemas/DecimalString"
receive_currency:
"$ref": "#/components/schemas/CurrencyCode"
payin_amount:
"$ref": "#/components/schemas/DecimalString"
payin_currency:
"$ref": "#/components/schemas/CurrencyCode"
payout_amount:
"$ref": "#/components/schemas/DecimalString"
payout_currency:
"$ref": "#/components/schemas/CurrencyCode"
corridor_code:
type: string
corridor_type:
type: string
execution:
type: object
additionalProperties: true
payer:
"$ref": "#/components/schemas/RailParty"
recipient:
"$ref": "#/components/schemas/Recipient"
pricing:
type: object
additionalProperties: true
history:
type: array
items:
"$ref": "#/components/schemas/StatusHistory"
created_at:
type: string
format: date-time
updated_at:
type: string
format: date-time
PaymentBase:
type: object
properties:
id:
type: string
format: uuid
merchant_id:
type: string
format: uuid
customer_id:
type: string
format: uuid
quote_id:
type: string
format: uuid
send_amount:
"$ref": "#/components/schemas/DecimalString"
send_currency:
"$ref": "#/components/schemas/CurrencyCode"
receive_amount:
"$ref": "#/components/schemas/DecimalString"
receive_currency:
"$ref": "#/components/schemas/CurrencyCode"
country_code:
"$ref": "#/components/schemas/CountryCode"
rail_type:
"$ref": "#/components/schemas/RailType"
operator_code:
type: string
provider_reference:
type: string
nullable: true
wallet_impact:
type: object
additionalProperties: true
pricing:
type: object
additionalProperties: true
history:
type: array
items:
"$ref": "#/components/schemas/StatusHistory"
created_at:
type: string
format: date-time
updated_at:
type: string
format: date-time
RailParty:
type: object
required:
- country_code
- rail_type
properties:
country_code:
"$ref": "#/components/schemas/CountryCode"
rail_type:
"$ref": "#/components/schemas/RailType"
phone:
type: string
example: "+237670000000"
operator_code:
type: string
example: CM_MTN_MOMO
bank_name:
type: string
bank_code:
type: string
account_name:
type: string
account_number:
type: string
Recipient:
allOf:
- "$ref": "#/components/schemas/RailParty"
- type: object
required:
- recipient_type
properties:
recipient_type:
type: string
enum:
- individual
- business
first_name:
type: string
last_name:
type: string
business_name:
type: string
email:
type: string
format: email
recipient_nationality_code:
"$ref": "#/components/schemas/CountryCode"
address_line1:
type: string
city:
type: string
StatusHistory:
type: object
properties:
status:
type: string
reason:
type: string
nullable: true
created_at:
type: string
format: date-time
IdempotencyMeta:
type: object
properties:
idempotency_key:
type: string
idempotency_replayed:
type: boolean
CountryCode:
type: string
minLength: 2
maxLength: 2
example: CM
CurrencyCode:
type: string
minLength: 3
maxLength: 3
example: XAF
DecimalString:
type: string
pattern: "^[0-9]+(\\.[0-9]+)?$"
example: '10000'
RailType:
type: string
enum:
- mobile_money
- bank_transfer
```