DGS-Pay API v2
Dashboard
Disbursements

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.

Fee Deducted From Recipient You pay the gross amount. The recipient receives the net. If you want the recipient to receive exactly 10,000 RWF and the fee is 100 RWF, you must send 10,100 RWF.
POST/disburse
FieldTypeRequiredDescription
amountnumberRequiredGross amount in RWF to send from your wallet.
destination_typestringRequiredbank or mobile_money.
recipientobjectRequiredRecipient details. Fields vary by destination type.
narrationstringOptionalShort note shown on the recipient's statement.
callback_urlstringOptionalOverride the default webhook URL for this transfer only.

Bank Recipient Fields

FieldRequired
bank_keyRequired
account_numberRequired
nameOptional
branchOptional

Mobile Money Recipient Fields

FieldRequired
msisdnRequired
networkRequired
countryRequired
nameOptional
cURL — Bank Disbursement
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 — Mobile Money Disbursement
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"
    }
  }'
Phone Normalization Phone numbers are automatically normalized — you can pass local format (0788123456) or international format (+250788123456), both are accepted.
Disbursements

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.

Webhook is the Source of Truth Do not mark a transfer as completed based on the API response alone. Only the webhook event confirms final status.
EventDescription
disbursement.successTransfer confirmed by provider. Recipient has been credited.
disbursement.failedTransfer could not be completed. Check fail_reason.
JSON — Webhook Payload
{
  "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"
}
JSON — Webhook Payload
{
  "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.

Pseudocode
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;
}
Best Practices
  • Index dgs_reference in 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_reason before re-attempting a failed transfer.
Reference

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.

GET/banks/{country}
cURL
curl -X GET \
  https://pay.digitalservicescenter.rw/generation/v2/banks/RW \
  -H "X-DGS-API-Key: YOUR_API_KEY"
JSON
{
  "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
    }
  ]
}
Using This Response
  • Use the bank_key value as the bank_key field in your disbursement request.
  • When branch_required is 1, include a branch field in the recipient object.
  • Check type to distinguish banks ("bank") from mobile money providers ("mobile_money").

Need Help?

Our technical team is ready to assist with integration questions, testing, and go-live checks.

Contact Support