Skip to main content
Use this guide to build a reliable payout flow with Waftpay. Payouts are asynchronous: you receive an acceptance response first, then a final outcome via webhook.

Quick flow

Authenticate -> Sign -> Send payout -> Receive acceptance -> Receive webhook -> Reconcile (optional status check).

Prerequisites


Endpoint

POST /payments-api-service/v1/payouts Required headers
Authorization: Bearer <access_token>
Content-Type: application/json
X-Custom-Signature: <base64-signature>
Idempotency: reuse the same transaction.reference for retries of the same logical payout.

Request body (example)

{
  "transaction": {
    "reference": "{{payouts_transaction_ref}}",
    "amount": 100,
    "currency": "KES",
    "description": "Test description",
    "timestamp": "2025-09-15T12:45:30.123Z",
    "service_code": "{{payout-service-code}}"
  },
  "originator": {
    "msisdn": "254708374149",
    "channel": "USSD",
    "country": "KE",
    "name": "Ralph",
    "purpose": "Xmas Bonus"
  },
  "recipient": {
    "reference": "INVJMA02",
    "account": "254708374149"
  },
  "callback_url": "https://webhook.site/7f04cce3-0472-4152-b0b1-feb62421e8fd",
  "meta": {}
}
Notes
  • amount is in major units (e.g., 1000 = 1000 KES).
  • timestamp must be ISO 8601 UTC (ends with Z).
  • transaction.service_code is assigned by Waftpay; confirm entitlement before go-live.

Acceptance response (immediate)

{
  "code": "100",
  "status": "ACCEPTED",
  "description": "Accepted for processing",
  "data": {
    "amount": 100,
    "transaction_reference": "919938",
    "payment_uuid": "413283551143664292",
    "payment_reference": "351CSICLV0",
    "time_received": "2026-01-07T09:44:43.558023Z"
  }
}

Webhook (final outcome)

We POST to your callback_url when the payout completes. See Webhook payload.

Status checks (optional)

If a webhook is delayed or missing, query status using Check payout status or Status checks.

Common issues

  • Signature mismatch: ensure the string-to-sign matches the payload exactly. See Signature generation.
  • Wrong token: use a payout-scoped Bearer token.
  • Duplicate references: reuse transaction.reference only for safe retries.