Skip to content

B2C Payments

B2C stands for business-to-customer. This is the disbursement flow where your business sends money out from its shortcode to a customer phone number.

Typical use cases:

  • customer refunds
  • merchant or agent settlements
  • salary or stipend payouts
  • promotional or goodwill payments

If the customer is paying you, use C2B Register URLs and Simulation or STK Push and Query instead.

  • Use the shortcode that Safaricom has provisioned for B2C on your Daraja profile.
  • The SDK will send whichever shortCode you configure, but Daraja permissions decide whether the payout is allowed.
  • Do not assume every till or paybill can perform B2C. Product enablement matters more than the number format.
ValueWhy it is needed
consumerKey and consumerSecretOAuth access token generation
environmentSandbox vs production behavior
shortCodeThe sending organization shortcode
initiatorNameB2C operator name configured in Daraja
securityCredentialEncrypted initiator secret required by B2C APIs
resultUrlFinal async result callback
queueTimeOutUrlTimeout callback if Daraja cannot complete the workflow in time
await mpesa.b2c.send({
recipientPhone: "254712345678",
amount: 500,
resultUrl: "https://example.com/mpesa/b2c/result",
queueTimeOutUrl: "https://example.com/mpesa/b2c/timeout",
remarks: "Partner settlement",
occasion: "March payout",
});
commandIdTypical use
BusinessPaymentSends money to registered M-Pesa customers for general business disbursements
SalaryPaymentSends salary payouts and can be used for both registered and unregistered M-Pesa customers
PromotionPaymentSends promotional payouts to registered M-Pesa customers
  • commandId defaults to BusinessPayment.
  • Pick the value that matches the Daraja business purpose you are actually running.
  • Treat the synchronous API response as submission acknowledgment only. Final status arrives through the result URL.
  • Persist ConversationID and OriginatorConversationID so you can match the later callback payload.
  • resultUrl receives the final B2C result.
  • queueTimeOutUrl receives a timeout notification when the workflow does not finish in time.
  • A timeout does not always mean permanent failure. You may need follow-up reconciliation before retrying.

The callback payload for B2C is parsed with parseDarajaResult(), and you can flatten the returned parameters with getResultParametersMap().

sequenceDiagram
    autonumber
    actor Ops as Finance or operations
    participant App as Your payout service
    participant SDK as PesaKit SDK
    participant Daraja
    participant Result as resultUrl
    participant Timeout as queueTimeOutUrl

    Ops->>App: Approve payout
    App->>SDK: mpesa.b2c.send(...)
    SDK->>Daraja: Submit B2C request
    Daraja-->>App: Sync acknowledgement + conversation IDs
    App->>App: Persist submission state

    alt Daraja finishes the workflow
        Daraja->>Result: Final result callback
        Result->>App: Mark success or failure
    else Daraja times out
        Daraja->>Timeout: Timeout callback
        Timeout->>App: Mark timeout
        App->>App: Schedule reconciliation or follow-up
    end
  • Do not mark the payout as complete from the synchronous response alone.
  • Store the raw result callback for audit and support work.
  • Keep your remarks and occasion fields meaningful enough for finance and operations teams.
  • If you need to recover an ambiguous payout, use your stored conversation IDs together with your operational reconciliation process.