Skip to main content
To send money, you initiate a disbursement request with one or more recipient transactions. Kulmi Pay validates your request, creates a payment file, and either waits for your approval or processes the payment immediately — depending on how you configure requires_approval.
1

Initiate the disbursement

Call POST /api/v1/send-money/initiation/ with your currency, provider, and a list of transactions. Kulmi Pay creates a payment file and returns a file_id and tracking_id.
2

Review and approve

If requires_approval is "YES" (the default), call POST /api/v1/send-money/approve/ with the file_id to release the payment. If requires_approval is "NO", Kulmi Pay approves and queues the payment automatically — no second call needed.
3

Monitor status

Call POST /api/v1/send-money/status/ with your tracking_id to check the payment file status and see the result for each individual transaction.

Initiate a disbursement

M-Pesa B2C

Use provider MPESA-B2C to send money directly to an M-Pesa mobile wallet. The account field must be the recipient’s phone number in international format (e.g., 254712345678).
curl -X POST https://app.kulmipay.com/api/v1/send-money/initiation/ \
  -H "Authorization: Bearer <token>" \
  -H "Content-Type: application/json" \
  -d '{
    "currency": "KES",
    "provider": "MPESA-B2C",
    "requires_approval": "YES",
    "callback_url": "https://your-app.com/webhooks/disbursements",
    "transactions": [
      {
        "account": "254712345678",
        "amount": "500",
        "name": "Jane Doe",
        "narrative": "Salary payment"
      }
    ]
  }'
Response
{
  "file_id": "f1a2b3c4-0000-0000-0000-000000000001",
  "tracking_id": "550e8400-e29b-41d4-a716-446655440000",
  "status": "PREVIEW-AND-APPROVE",
  "status_code": null,
  "batch_reference": null,
  "transactions_count": 1,
  "total_amount": "500.00",
  "charge_estimate": "10.00",
  "total_amount_estimate": "510.00",
  "wallet": {
    "currency": "KES",
    "wallet_type": "SETTLEMENT"
  },
  "transactions": [
    {
      "transaction_id": "t9z8y7x6-0000-0000-0000-000000000001",
      "status": "PENDING",
      "account": "254712345678",
      "name": "Jane Doe",
      "amount": "500",
      "narrative": "Salary payment"
    }
  ],
  "created_at": "2024-01-15T10:30:00Z",
  "updated_at": "2024-01-15T10:30:00Z"
}
The minimum transaction amount for M-Pesa B2C is KES 10. For PesaLink bank transfers, the minimum is KES 100. Requests below these thresholds will be rejected.

Use provider PESALINK to transfer to a Kenyan bank account. You must include bank_code for each transaction. Find valid codes in the bank codes reference.
curl -X POST https://app.kulmipay.com/api/v1/send-money/initiation/ \
  -H "Authorization: Bearer <token>" \
  -H "Content-Type: application/json" \
  -d '{
    "currency": "KES",
    "provider": "PESALINK",
    "requires_approval": "YES",
    "transactions": [
      {
        "account": "1234567890",
        "amount": "5000",
        "name": "John Kamau",
        "narrative": "Vendor payment",
        "bank_code": "68"
      }
    ]
  }'

M-Pesa B2B

Use provider MPESA-B2B to pay a PayBill or Till number. Set account_type to "PayBill" or "Till". When paying a PayBill, you must also include account_reference (the customer account number associated with the bill).
curl -X POST https://app.kulmipay.com/api/v1/send-money/initiation/ \
  -H "Authorization: Bearer <token>" \
  -H "Content-Type: application/json" \
  -d '{
    "currency": "KES",
    "provider": "MPESA-B2B",
    "requires_approval": "YES",
    "transactions": [
      {
        "account": "400200",
        "amount": "10000",
        "name": "Electricity Bill",
        "narrative": "January invoice",
        "account_type": "PayBill",
        "account_reference": "ACC-00123"
      }
    ]
  }'

Request parameters

Top-level fields

FieldTypeRequiredDescription
currencystringYesMust be "KES"
providerstringYesPayment provider. See supported providers.
transactionsarrayYesList of recipient transactions (see below)
requires_approvalstringNo"YES" (default) or "NO". Set to "NO" to skip the manual approval step.
wallet_idstringNoID of a specific wallet to debit. Defaults to your KES settlement wallet.
batch_referencestringNoYour own reference label for the batch
callback_urlstringNoURL to receive webhook notifications when transactions complete

Transaction fields

FieldTypeRequiredDescription
accountstringYesRecipient identifier — phone number, bank account, or paybill/till number
amountstringYesAmount to send in KES
namestringYesRecipient’s full name
narrativestringYesPayment description shown to the recipient
account_typestringConditionalRequired for M-Pesa B2B: "PayBill" or "Till"
account_referencestringConditionalRequired when account_type is "PayBill"
bank_codestringConditionalRequired for PesaLink transfers. See bank codes.
id_numberstringNoRecipient’s national ID number
idempotency_keystringNoUnique key to prevent duplicate transactions. If a transaction with the same key already exists, the request is rejected.

Idempotency

To protect against duplicate payments (for example, if a network timeout causes you to retry a request), include a unique idempotency_key per transaction. If Kulmi Pay receives a second request with the same key for your business, it will reject it with an error rather than processing the payment twice.
{
  "account": "254712345678",
  "amount": "500",
  "name": "Jane Doe",
  "narrative": "Salary payment",
  "idempotency_key": "payroll-jan-2024-jane-doe-001"
}