Skip to content

Kenya Collections (V1)

Kenya collections use the V1 endpoint POST /api/v2/payments. There are two distinct kinds of collection — the difference is where the money settles:

Payment Channel collections

Money settles directly into your own external channel (bank account, Till, or Paybill), straight from the payer. PayHero never holds the funds — it only facilitates the transaction. You route with channel_id.

Wallet-based collections

Money settles into your PayHero-managed wallet (your customer wallet within PayHero). You later withdraw it to your preferred channel — bank, phone, Paybill, or Till. You route with network_code.

Both use the same endpoint; the fields you send decide the type.

Use these when you want funds to land directly in your external channel (bank, Till, or Paybill). PayHero doesn’t custody the money — it moves from the payer straight to your channel, and PayHero simply facilitates the collection. Route the collection with a channel_id.

Each external channel you configure (bank, Till, Paybill, or wallet) has a numeric id. Call GET /api/v2/payment_channels to list them, then use the id of an active channel as the channel_id in your collection request.

Terminal window
curl "$PH_BASE_URL/api/v2/payment_channels" \
-u "$PH_API_USERNAME:$PH_API_PASSWORD"

The response lists your channels (newest activity first):

{
"payment_channels": [
{
"id": 8949,
"account_number": "1234567890",
"channel_type": "bank",
"is_active": true,
"short_code": "123456",
"description": "My Bank Account",
"created_at": "2026-01-15T10:00:00Z",
"updated_at": "2026-01-15T10:00:00Z"
},
{
"id": 9765,
"account_number": "0123456789",
"channel_type": "paybill",
"is_active": true,
"short_code": "654321",
"description": "My Paybill",
"created_at": "2026-01-15T10:00:00Z",
"updated_at": "2026-01-15T10:00:00Z"
},
{
"id": 1501,
"account_number": "0700111222",
"channel_type": "wallet",
"is_active": true,
"short_code": "100200",
"description": "My Wallet",
"created_at": "2026-01-15T10:00:00Z",
"updated_at": "2026-01-15T10:00:00Z"
},
{
"id": 1389,
"account_number": "445566",
"channel_type": "till",
"is_active": false,
"short_code": "445566",
"description": "My Till",
"created_at": "2026-01-10T08:00:00Z",
"updated_at": "2026-01-10T08:00:00Z"
}
],
"pagination": { "count": 4, "page": 1, "per": 20, "num_pages": 1, "next_page": null, "prev_page": null }
}
Field Description
id The channel ID — pass this as channel_id when creating a collection.
account_number Destination account (for bank / paybill channels).
channel_type bank, paybill, till, or wallet.
is_active Only active channels can be used in a collection.
short_code The Till / Paybill / bank paybill number.
description Human-friendly label for the channel.
created_at When the channel was created.
updated_at When the channel was last updated.
Terminal window
curl -X POST "$PH_BASE_URL/api/v2/payments" \
-u "$PH_API_USERNAME:$PH_API_PASSWORD" \
-H "Content-Type: application/json" \
-d '{
"amount": 10,
"phone_number": "0712345678",
"provider": "m-pesa",
"channel_id": 8949,
"account_id": 63,
"external_reference": "test_ext",
"callback_url": "https://your-system.com/webhooks/payhero"
}'

Use these when you want funds to land in your PayHero wallet. PayHero holds the balance for you, and you later withdraw it to your preferred channel (bank, phone, Paybill, or Till). Route the collection with a network_code.

Terminal window
curl -X POST "$PH_BASE_URL/api/v2/payments" \
-u "$PH_API_USERNAME:$PH_API_PASSWORD" \
-H "Content-Type: application/json" \
-d '{
"amount": 10,
"phone_number": "0712345678",
"provider": "sasapay",
"network_code": "63902",
"account_id": 63,
"external_reference": "test_ext",
"callback_url": "https://your-system.com/webhooks/payhero"
}'

For an offline wallet collection, add is_offline: true (and a merchant_fee). No STK push is sent — the customer completes payment manually via M-Pesa Paybill, using the CheckoutRequestID from the response as the account reference.

  1. Make the request with is_offline: true and read the CheckoutRequestID from the response (e.g. 29119).
  2. The customer pays on M-Pesa:
    • Paybill number: 756756
    • Account number: 553125#<CheckoutRequestID> — e.g. 553125#29119
  3. The final result is delivered to your callback URL.

A successful request returns 201 with a CheckoutRequestID:

{
"success": true,
"status": "QUEUED",
"reference": "UFD003217286.iI",
"CheckoutRequestID": "29119",
"external_reference": "test_ext"
}
Type Where money settles Key field
Payment Channel Your external bank / Till / Paybill channel_id
Wallet-based Your PayHero wallet (withdraw later) network_code