Docs

Kenya payments

Local Payments API

Use the Kenya merchant payment APIs for M-Pesa STK Push, B2C payouts, transaction queries, and wallet balance checks.

How local payments work

Local Payments use the Kenya merchant wallet and M-Pesa rails. These are separate from the Global custodial wallet.

Collect

Trigger STK Push using a customer phone number and amount.

Pay out

Send B2C payments for refunds, suppliers, or staff.

Track

Read wallet balances before payouts and reconcile using transaction references.

STK Push

Use STK Push (Lipa na M-Pesa Online) when the customer is present and can approve the prompt on their phone with their M-Pesa PIN.

POST/api/v1/merchants/payments/stk-push

Initiate STK Push

Trigger a Lipa na M-Pesa Online prompt to a customer phone number.

Request bodyjson
1{2  "phone": "254712345678",3  "amount": 1000,4  "reference": "ORDER-12345",5  "channelId": "PAYL-XJ7K2P",6  "description": "Checkout payment",7  "callbackUrl": "https://example.com/paylor-callback"8}
Responsejson
1{2  "transactionId": "665f4c1b9a8d2e001f2a1234",3  "status": "SENT"4}

Code examples

POST /api/v1/merchants/payments/stk-pushbash
1curl -X POST https://api.paylorke.com/api/v1/merchants/payments/stk-push \2  -H "Authorization: Bearer YOUR_API_KEY" \3  -H "Content-Type: application/json" \4  -d '{5  "phone": "254712345678",6  "amount": 1000,7  "reference": "ORDER-12345",8  "channelId": "PAYL-XJ7K2P",9  "description": "Checkout payment",10  "callbackUrl": "https://example.com/paylor-callback"11}'
Initiate STK Pushjavascript
1const axios = require('axios');2 3const response = await axios.post(4  'https://api.paylorke.com/api/v1/merchants/payments/stk-push',5  {6    phone: '254712345678',7    amount: 1000,8    reference: 'ORDER-123',9    channelId: 'PAYL-XXXXXX',10    description: 'Payment for Service'11  },12  {13    headers: {14      'Authorization': 'Bearer YOUR_API_KEY',15      'Content-Type': 'application/json'16    }17  }18);
phone, amount, and reference are required. channelId is optional — when omitted, Paylor routes through your default active channel. Provide a callbackUrl to receive instant payment notifications signed with your Webhook Secret — see the Webhooks section for verification. Idempotency-Key headers are supported on all payment creation endpoints.

B2C payouts

Send money to any M-Pesa registered number for refunds, suppliers, staff, or operational disbursements. Min 10, max 150,000 KES per transaction.

POST/api/v1/merchants/payments/b2c

Send B2C payout

Send money to a customer, supplier, staff member, or refund recipient.

Request bodyjson
1{2  "phone": "254712345678",3  "amount": 500,4  "reference": "REFUND-9821",5  "remarks": "Customer refund",6  "callbackUrl": "https://example.com/paylor-callback"7}
Responsejson
1{2  "transactionId": "665f4c1b9a8d2e001f2a5678",3  "originatorConversationId": "AG_20260701_...",4  "conversationId": "AG_20260701_...",5  "status": "QUEUED",6  "message": "Accept the service request successfully.",7  "pricingQuote": {8    "amount": 500,9    "fee": 10,10    "total": 51011  }12}

Code examples

POST /api/v1/merchants/payments/b2cbash
1curl -X POST https://api.paylorke.com/api/v1/merchants/payments/b2c \2  -H "Authorization: Bearer YOUR_API_KEY" \3  -H "Content-Type: application/json" \4  -d '{5  "phone": "254712345678",6  "amount": 500,7  "reference": "REFUND-9821",8  "remarks": "Customer refund",9  "callbackUrl": "https://example.com/paylor-callback"10}'
Optional fields: description (alias remarks), commandId (SalaryPayment, BusinessPayment, or PromotionPayment), and callbackUrl. The response includes a pricingQuote with the fee charged for the payout.

Query transactions

Check the status of a transaction at any time. This is the recommended reconciliation path when a webhook delivery is missed.

GET/api/v1/merchants/payments/transactions/:transactionId

Query transaction status

Check the status of any transaction. Useful for verifying payments if a webhook delivery is missed.

No request body

Use the Authorization header and query string parameters shown in the endpoint path.

Responsejson
1{2  "id": "665f4c1b9a8d2e001f2a1234",3  "reference": "ORDER-12345",4  "amount": 1000,5  "status": "COMPLETED",6  "provider": "MPESA",7  "providerRef": "ws_CO_...",8  "metadata": {9    "mpesaReceipt": "RFL8S2K9P0"10  }11}

Code examples

GET /api/v1/merchants/payments/transactions/:transactionIdbash
1curl -X GET https://api.paylorke.com/api/v1/merchants/payments/transactions/:transactionId \2  -H "Authorization: Bearer YOUR_API_KEY" \3  -H "Content-Type: application/json"
GET/api/v1/merchants/payments/transactions?limit=50&offset=0&flow=standard

List transactions

List transactions with limit/offset pagination. The flow query parameter accepts standard (default), b2c, or all.

No request body

Use the Authorization header and query string parameters shown in the endpoint path.

Responsejson
1{2  "transactions": [3    {4      "id": "665f4c1b9a8d2e001f2a1234",5      "reference": "ORDER-12345",6      "amount": 1000,7      "status": "COMPLETED"8    }9  ],10  "total": 12811}

Code examples

GET /api/v1/merchants/payments/transactionsbash
1curl -X GET https://api.paylorke.com/api/v1/merchants/payments/transactions?limit=50&offset=0&flow=standard \2  -H "Authorization: Bearer YOUR_API_KEY" \3  -H "Content-Type: application/json"

B2C performance metrics

Retrieve aggregated payout data, including total volume and transaction counts.

GET/api/v1/merchants/payments/stats/b2c

B2C performance metrics

Retrieve aggregated payout history data, including total volume and transaction counts.

No request body

Use the Authorization header and query string parameters shown in the endpoint path.

Responsejson
1{2  "success": true,3  "stats": {4    "totalVolume": 250000,5    "count": 1826  }7}

Code examples

GET /api/v1/merchants/payments/stats/b2cbash
1curl -X GET https://api.paylorke.com/api/v1/merchants/payments/stats/b2c \2  -H "Authorization: Bearer YOUR_API_KEY" \3  -H "Content-Type: application/json"

Wallet API

Monitor service credits and B2C float programmatically to avoid transaction failures.

Service credits

A prepaid KES float (balance) that Paylor transaction fees are drawn from. It is not the money your customers pay you.

B2C float

A separate balance (b2cBalance) funding outbound payouts. Pending payouts are ring-fenced in b2cHeldBalance.

Read-only over the API

An API key with wallet:read can check balances. Adding credits is a dashboard action — there is no top-up endpoint.

Credits are checked, then charged. STK Push is rejected with 402 PAYMENT_REQUIRED if balance is below the fee for that amount, and the fee is only deducted once the payment completes — failed and abandoned prompts cost nothing. Crypto payments are charged the same way on confirmation, converted to KES. For B2C, the payout and carrier cost come out of b2cBalance while the Paylor platform fee comes out of balance, so a payout needs both balances funded.
Poll this endpoint and alert on a low balance. A completed payment is never reversed for insufficient credit — the fee is still charged and balance can go negative, after which new payments are blocked until you top up.
GET/api/v1/merchants/payments/wallet

Check merchant wallet

Read service credit and payout balances before initiating a payment. Requires the wallet:read scope. balance is the service credit float that transaction fees are drawn from; b2cBalance is the separate payout float. transactions holds the 20 most recent raw wallet ledger entries (TOPUP, FEE, B2C_TOPUP, B2C_PAYOUT, B2C_FEE, B2C_HOLD), where debits are negative amounts. This endpoint is read-only — topping up is done from the dashboard.

No request body

Use the Authorization header and query string parameters shown in the endpoint path.

Responsejson
1{2  "success": true,3  "wallet": {4    "balance": 12000,5    "b2cBalance": 5000,6    "b2cHeldBalance": 1500,7    "b2cAvailableBalance": 3500,8    "b2cOutstandingBalance": 0,9    "b2cHolds": [10      {11        "id": "665f4c1b9a8d2e001f2a3333",12        "amount": 1500,13        "reason": "B2C payout hold",14        "holdType": "PAYOUT",15        "reference": "PAYOUT-12345",16        "createdAt": "2026-07-30T09:12:44.001Z"17      }18    ],19    "currency": "KES"20  },21  "b2cStats": {22    "totalVolume": 250000,23    "count": 18224  },25  "transactions": [26    {27      "_id": "665f4c1b9a8d2e001f2a4444",28      "type": "FEE",29      "amount": -12,30      "status": "COMPLETED",31      "reference": "ORDER-12345",32      "description": "Transaction Fee for ORDER-12345",33      "createdAt": "2026-07-30T09:10:02.114Z"34    }35  ]36}

Code examples

GET /api/v1/merchants/payments/walletbash
1curl -X GET https://api.paylorke.com/api/v1/merchants/payments/wallet \2  -H "Authorization: Bearer YOUR_API_KEY" \3  -H "Content-Type: application/json"