Disburse Funds
The Disbursement API lets you send money from your RWF merchant wallet to a recipient's bank account or mobile money wallet. This is useful for paying out vendors, refunding customers, or distributing salaries.
The merchant's wallet is debited the full amount. A fee is then deducted from the recipient's end — the recipient receives amount − fee. Always verify the amount exceeds the applicable fee before initiating.
| Field | Type | Required | Description |
|---|---|---|---|
amount | number | Required | Gross amount in RWF to send from your wallet. |
destination_type | string | Required | bank or mobile_money. |
recipient | object | Required | Recipient details. Fields vary by destination type. |
narration | string | Optional | Short note shown on the recipient's statement. |
callback_url | string | Optional | Override the default webhook URL for this transfer only. |
Bank Recipient Fields
| Field | Required |
|---|---|
bank_key | Required |
account_number | Required |
name | Optional |
branch | Optional |
Mobile Money Recipient Fields
| Field | Required |
|---|---|
msisdn | Required |
network | Required |
country | Required |
name | Optional |
curl -X POST \ https://pay.digitalservicescenter.rw/generation/v2/disburse \ -H "X-DGS-API-Key: YOUR_API_KEY" \ -H "Content-Type: application/json" \ -d '{ "amount": 10000, "destination_type": "bank", "recipient": { "bank_key": "kcb_rw", "account_number": "1234567890", "name": "John Doe", "branch": "Kigali Main" }, "narration": "Vendor payment April 2026" }'
curl -X POST \ https://pay.digitalservicescenter.rw/generation/v2/disburse \ -H "X-DGS-API-Key: YOUR_API_KEY" \ -H "Content-Type: application/json" \ -d '{ "amount": 5000, "destination_type": "mobile_money", "recipient": { "msisdn": "+250788123456", "network": "MTN", "country": "RW", "name": "Jane Doe" } }'
0788123456) or international format (+250788123456), both are accepted.
Disbursement Webhook
The POST /disburse response only confirms the transfer is queued for processing. The actual outcome — success or failure — is delivered via a webhook after the provider processes the transfer. You must handle this webhook to reliably update your records.
| Event | Description |
|---|---|
disbursement.success | Transfer confirmed by provider. Recipient has been credited. |
disbursement.failed | Transfer could not be completed. Check fail_reason. |
{
"event": "disbursement.success",
"dgs_reference": "DGS123456789",
"flw_transfer_id": 987654,
"status": "success",
"amount": 10000,
"fee": 100,
"recipient_gets": 9900,
"currency": "RWF",
"destination_type": "bank",
"recipient": {
"account_number": "1234567890",
"bank_key": "kcb_rw",
"name": "John Doe"
},
"proof": "FLW-PROOF-123456"
}
{
"event": "disbursement.failed",
"dgs_reference": "DGS123456789",
"flw_transfer_id": 987654,
"status": "failed",
"amount": 10000,
"fee": 100,
"recipient_gets": 9900,
"currency": "RWF",
"destination_type": "mobile_money",
"fail_reason": "Invalid account details"
}
Idempotent Handler — Pseudocode
Because webhooks can be retried on network failure, your handler must be idempotent. Use dgs_reference as the unique key to detect duplicates.
function handleWebhook(payload) { const ref = payload.dgs_reference; if (alreadyProcessed(ref)) { return HTTP_200; // duplicate — acknowledge but skip } if (payload.event === "disbursement.success") { markTransferSuccess(ref, payload.proof); } else if (payload.event === "disbursement.failed") { markTransferFailed(ref, payload.fail_reason); } recordAsProcessed(ref); return HTTP_200; }
- Index
dgs_referencein your database for fast idempotency lookups. - Return HTTP 200 even for duplicates — anything else triggers retries.
- Log every incoming payload for auditing and debugging.
- Always investigate
fail_reasonbefore re-attempting a failed transfer.
List Banks & Providers
Retrieve the current list of supported banks and mobile money providers for a given country. Always use this endpoint dynamically rather than hard-coding bank keys — providers change over time.
curl -X GET \ https://pay.digitalservicescenter.rw/generation/v2/banks/RW \ -H "X-DGS-API-Key: YOUR_API_KEY"
{
"status": "success",
"country": "RW",
"data": [
{
"bank_key": "bk_rw",
"name": "Banque de Kigali",
"type": "bank",
"code": "40",
"currency": "RWF",
"branch_required": 0
},
{
"bank_key": "mtn_rw",
"name": "MTN Mobile Money",
"type": "mobile_money",
"network": "MTN",
"currency": "RWF",
"branch_required": 0
}
]
}
- Use the
bank_keyvalue as thebank_keyfield in your disbursement request. - When
branch_requiredis1, include abranchfield in the recipient object. - Check
typeto distinguish banks ("bank") from mobile money providers ("mobile_money").