Supported Payment Flows
| Flow | Use Case | Trigger |
|---|---|---|
| STK Push | On-demand payment prompts | Subscriber clicks “Pay Now” in portal |
| C2B (Paybill) | Subscriber-initiated paybill payments | Subscriber pays via M-Pesa menu |
| Bill Manager | Automated invoices with SMS reminders | Invoice created by billing cycle |
Environment Endpoints
- Sandbox
- Production
Base URL:
https://sandbox.safaricom.co.ke| Endpoint | Path |
|---|---|
| OAuth Token | /oauth/v1/generate |
| STK Push | /mpesa/stkpush/v1/processrequest |
| STK Query | /mpesa/stkpushquery/v1/query |
| C2B Register | /mpesa/c2b/v2/registerurl |
| Transaction Status | /mpesa/transactionstatus/v1/query |
| Bill Manager | /v1/billmanager-invoice/... |
Authentication: OAuth Token Flow
All Daraja API calls require a Bearer token obtained via OAuth 2.0 client credentials.Obtain credentials from Daraja portal
Register your app at developer.safaricom.co.ke and get your Consumer Key and Consumer Secret.
Request an access token
FyberPay sends a GET request with Basic auth (base64-encoded
ConsumerKey:ConsumerSecret):STK Push (Lipa Na M-Pesa Online)
STK Push sends a payment prompt directly to the subscriber’s phone. The subscriber enters their M-Pesa PIN to authorize the payment.Request Format
The Password field is computed as
Base64(BusinessShortCode + Passkey + Timestamp). The Timestamp format is YYYYMMDDHHmmss in East Africa Time (UTC+3). FyberPay computes this automatically.M-Pesa requires whole number amounts. FyberPay applies
Math.ceil() to round up fractional amounts before sending.Phone Number Normalization
FyberPay normalizes Kenyan phone numbers to the254XXXXXXXXX format (no plus sign). The following inputs are all accepted:
| Input | Normalized |
|---|---|
+254712345678 | 254712345678 |
0712345678 | 254712345678 |
254712345678 | 254712345678 |
STK Push Response
CheckoutRequestID to correlate with the callback.
STK Push Callback
Safaricom sends the result to yourCallBackURL:
- Successful Payment
- Failed/Cancelled
MpesaReceiptNumber, Amount, and PhoneNumber from the CallbackMetadata.Item array.
STK Query (Status Check)
If no callback arrives, FyberPay can poll the transaction status:ResultCode to internal payment statuses:
| ResultCode | FyberPay Status | Meaning |
|---|---|---|
0 | SUCCESS | Payment completed |
1032 | CANCELLED | User cancelled the request |
1019 | PENDING | Transaction in progress |
1025 | PENDING | Transaction timed out, may still complete |
1037 | PENDING | Timeout waiting for user input |
| Other | FAILED | Transaction failed |
C2B (Customer to Business)
C2B handles payments where the subscriber initiates the transaction from their M-Pesa menu by sending money to the ISP’s paybill number.URL Registration
FyberPay registers validation and confirmation URLs with Safaricom:| URL Type | Endpoint | Purpose |
|---|---|---|
| Validation | /webhooks/mpesa/c2b/validation | FyberPay validates the payment before Safaricom processes it |
| Confirmation | /webhooks/mpesa/c2b/confirmation | Safaricom confirms the completed payment |
C2B Callback Payload
TransID as the receipt number, TransAmount as the payment amount, MSISDN as the phone number, and BillRefNumber as the account/invoice reference.
Bill Manager API
Bill Manager handles automated invoice delivery, SMS reminders, and payment reconciliation. It operates at the platform level (not per-org) using dedicated credentials.One-Time Setup: Opt-In
Register your paybill with Safaricom Bill Manager:app_key that confirms successful registration.
Sending Invoices
- Single Invoice
- Bulk Invoices
Endpoint:
POST /v1/billmanager-invoice/single-invoicingSends an invoice to a single subscriber. The subscriber receives an SMS with the amount, due date, and payment instructions.Cancelling Invoices
200 for successful cancellation or 409 if the invoice was already cancelled (both treated as success by FyberPay).
Payment Reconciliation
After processing a Bill Manager payment, FyberPay sends an acknowledgment back to Safaricom. This triggers an e-receipt SMS to the subscriber:Webhook Security
FyberPay validates incoming M-Pesa callbacks using IP allowlisting. Configure theDARAJA_ALLOWED_IPS environment variable with Safaricom’s callback IPs (comma-separated). If no allowlist is configured, all IPs are accepted (suitable for sandbox testing only).
Error Codes Reference
Common M-Pesa STK Push error codes:| Code | Description |
|---|---|
0 | Success |
1 | Insufficient funds |
1019 | Transaction in progress |
1025 | Timeout waiting for response |
1032 | Request cancelled by user |
1037 | Timeout waiting for user input |
2001 | Wrong PIN entered |
1001 | Unable to lock subscriber (subscriber busy) |
1 | Balance insufficient |
17 | Internal failure |
Retry Behavior and Circuit Breaker
All Daraja API calls are wrapped in a circuit breaker (daraja circuit). If Safaricom’s API is consistently failing, the circuit opens and FyberPay stops sending requests for a cooldown period. This prevents cascade failures and protects against Safaricom downtime.
For STK callbacks that fail to arrive:
- FyberPay queries the transaction status using the STK Query endpoint
- If the query also fails, the payment remains in
PENDINGstatus - A background job retries pending payment status checks periodically
Per-Org vs Platform Credentials
FyberPay supports two credential models:| Model | Use Case | Configuration |
|---|---|---|
| Platform credentials | Single paybill for all ISPs | Set via DARAJA_CONSUMER_KEY, DARAJA_CONSUMER_SECRET, DARAJA_SHORTCODE env vars |
| Per-org credentials | Each ISP has their own paybill | Configured in Settings > Payment Gateways per organization |