Initiate a payout
Payment Collection
Initiate Payout
Send money from your company’s pay-out wallet to a mobile-money account. Calculates and applies fees, deducts atomically, and auto-refunds on failure.
POST
Initiate a payout
Overview
POST /payment/payout initiates a pay-out: it sends money from your company’s pay-out wallet to a mobile-money account. Cartevo:
- Calculates the total cost (
amount+ payout fee). - Verifies the pay-out wallet has sufficient balance.
- Reserves the funds atomically.
- Submits the disbursement to the operator.
- If the disbursement fails permanently, automatically refunds the reserved funds back to your wallet.
status: PENDING; the final outcome reaches you via webhook (or via notify_url).
When to use it
- Disburse salaries, payouts, refunds, or commissions to end users.
- Power any “send money” feature in your product.
POST /payment/collect.
Prerequisites
- Your company has a wallet for the requested
(country, currency)pair. - The wallet’s
payout_balanceis at leastamount + fee. (UsePOST /wallets/calculate-transfer-fees— currently undocumented — or estimate from your fee schedule.) - The combination of
country,currency, andoperatoris supported — see Payment guidelines.
Request
Headers
| Name | Required | Description |
|---|---|---|
Authorization | Yes | Bearer <access_token> |
Content-Type | Yes | application/json |
Body
| Field | Type | Required | Constraints / format |
|---|---|---|---|
operator | string | Yes | One of the supported operators — same enum as collection. Lowercase. |
country | string | Yes | ISO 3166-1 alpha-2, uppercase (e.g. CM). |
phone_number | string | Yes | Country code + local number, no + (e.g. 237670000000). Recipient phone number. |
amount | number | Yes | Minimum 1. Major currency units. Excludes fees (the fee is added on top and deducted from your wallet). |
currency | string | Yes | ISO 4217. Must match a wallet you own. |
external_id | string | No | Idempotency key. Up to 255 chars. Duplicates rejected with 400. Auto-generated if omitted. |
notify_url | string | No | HTTPS URL to receive the final status webhook. |
reference_id | string | No | Free-form reference shown in the dashboard. |
lang | string | No | Two-letter language code. |
purpose | string | No | Free-form description (e.g. "Salary May 2026"). |
Response
200 — Payout initiated
| Field | Description |
|---|---|
transaction_id | Cartevo transaction ID (UUID). |
external_id | Echoes your idempotency key (or auto-generated). |
status | One of PENDING, PROCESSING, SUCCESS, FAILED. |
error_message | Always null on initiation. Populated on failure (poll the status endpoint or wait for the webhook). |
Lifecycle and atomic behavior
- On
PENDING/PROCESSING: the funds are reserved in your wallet but not yet visible as deducted. - On
SUCCESS: the reserved funds are released to the operator. The recipient is credited. - On
FAILED: the reserved funds are returned to your wallet automatically. No manual reconciliation needed.
Error responses
| Status | message example | Trigger |
|---|---|---|
400 | "Insufficient balance (including fees)" | Pay-out wallet has less than amount + fee. |
400 | "Duplicate external_id" | An earlier call used the same external_id. |
400 | "No wallet for this country and currency" | You don’t own a wallet for the (country, currency) pair. |
400 | "Operator not available for this country/currency" | See Payment guidelines. |
401 | "Unauthorized" | Missing or expired token. |
Webhooks fired
- A status-update webhook is sent on each transition (
PENDING→PROCESSING→SUCCESS/FAILED). - If you supplied
notify_url, it receives the same updates.
Code examples
cURL
Node.js (axios)
Related
POST /payment/collect— the reverse direction.GET /payment/transactions/{id}/status— poll for the outcome.GET /payment/balance— check your pay-out wallet balance before calling.
Authorizations
Bearer authentication header of the form Bearer <token>, where <token> is your auth token.
Body
application/json
Available options:
mtn, orange, moov, airtel, mpesa, afrimoney, vodacom, wave, wligdicash, expresso, free, tmoney, celtiis, coris Example:
"mtn"
Pattern:
^[A-Z]{2}$Example:
"CM"
Example:
"237670000000"
Required range:
x >= 1Example:
1000
Example:
"XAF"
Example:
"https://example.com/webhook/payout"
Idempotency key (up to 255 chars). Duplicate values are rejected with 400 after the first call. Auto-generated if omitted.
Free-form reference shown in the dashboard (up to 255 chars).
Two-letter language code for operator-side prompts (e.g. en, fr).
Free-form description of the payout's purpose.