Skip to documentation
BPBitcrowd Pay
DocsAPI guide

Server-side M-PESA payments

The API contract for payments that wait well.

Build against stable request, status, webhook, error, and retry semantics. The examples below use placeholders only.

STK Push

Send the phone number and amount from your trusted server. The request is asynchronous and idempotent; HTTP 202 means initiation was accepted, not payment success.

curl -X POST https://api.example.test/api/v1/payments/stk \
  -H 'Authorization: Bearer bcp_test_REPLACE_ME' \
  -H 'Content-Type: application/json' \
  -H 'Idempotency-Key: order_123_attempt_1' \
  -d '{"phone_number":"2547XXXXXXX","amount":100,"external_reference":"order_123"}'

Use these placeholders on your server; never put a key in browser code.

Payment status

Poll the payment resource with the returned identifier. Terminal states are SUCCESS, FAILED, CANCELLED, and TIMED_OUT.

Signed webhooks

Read the raw request body before parsing JSON. Require the webhook ID, Unix-seconds timestamp, v1=<hex> signature, and secret version; reject timestamps outside 900 seconds. Compare v1=<hex(HMAC-SHA256(secret_for_version, timestamp + "." + raw_body))> in constant time, persist the event ID before fulfillment, and return 2xx only after durable acceptance.

Errors and rate limits

Use the documented error code as the machine decision and customerMessage as display copy. Respect 429 retry guidance and never replace an uncertain attempt with a new idempotency key.

Sandbox and Live

Keep Sandbox and Live credentials, destinations, callbacks, and acceptance checks distinct. Promotion is a separate owner release decision.

Public operation map

These are the public operations in the validated contract. Owner management and internal routes are intentionally excluded.

  • POST /api/v1/payments/stkInitiate an M-PESA STK Push
  • GET /api/v1/paymentsSearch payments
  • GET /api/v1/payments/{payment_id}Get a payment
  • GET /api/public/v1/payment-links/{slug}Resolve an active hosted payment link
  • POST /api/public/v1/payment-links/{slug}/payments/stkInitiate an STK Push from an active payment link
  • GET /api/public/v1/payment-links/{slug}/payments/{payment_id}Poll a payment created through a hosted link
  • POST /api/public/v1/waitlistSubmit a coming-soon waitlist request