How to Integrate the Paysasa API: Checkout Sessions and Webhooks
Developers
A developer walkthrough for accepting payments on your website or app: create an API key, open a checkout session, redirect to the hosted page and confirm payment with signed webhooks.
If you run an online store, marketplace or app, you will want payments built into your own flow. The Paysasa REST API makes this possible with checkout sessions and a hosted payment page, plus webhooks that tell your server when a payment succeeds.
This guide walks through a typical integration. Always check the Paysasa API docs for the latest details.
What you need
A verified business on Paysasa. Until the business is verified, creating or paying checkout sessions returns `403` with a code such as `business_unverified` or `owner_kyc_unverified`.
A server that can make HTTPS requests and receive webhooks.
Basic familiarity with JSON and REST APIs.
The checkout integration flow end to end
Step 1: Create an API key
Sign in to Paysasa and open Businesses → API Keys.
Generate a key. Keys use a composite format: `apk_live_xxx.secret` for live, or `apk_test_xxx.secret` for test.
Store it securely — for example, in an environment variable.
Never expose your API key in client-side code or public repositories. Use it only on your server. Keys can be revoked from the Businesses page at any time, and each key is scoped to a single business.
Step 2: Understand amounts and currencies
All money-moving APIs use minor units (integers). For KES and USD, 100 minor units = 1.00, so KES 150 is `15000`.
Only currencies enabled for your account are accepted.
M-Pesa checkout requires KES; PayPal settles USD.
Step 3: Create a checkout session
From your server, call the base URL `https://api.paysasa.com/api/v1` with your key in the `x-api-key` header:
`POST /checkout/sessions` with `amount`, `currency` and `business_id` (required), plus a `description` the customer will see.
Add `success_url` and `cancel_url` for redirects, and optionally `return_url` and `callback_url` for cross-domain apps.
Use `allow_methods` to choose methods, such as `wallet` and `m_pesa` for KES sessions, or `paypal` for USD sessions.
Attach your own `metadata`, such as an order ID. It is passed back in webhooks.
The response includes a session `id`, a `reference`, a `status` of `pending`, an `expires_at` time and a `hosted_url`.
Step 4: Redirect the customer
Send the customer to the `hosted_url`. They complete payment on Paysasa's hosted page — for example, approving an M-Pesa prompt — and are then redirected to your `success_url` or `cancel_url`.
Do not treat the redirect alone as proof of payment. Confirm through a webhook or by reading the session status from your server.
Step 5: Receive and verify webhooks
Configure a webhook URL in your business webhook settings.
Paysasa sends a `POST` to your endpoint for each event, such as `checkout.paid`, with the session ID, reference, amount, currency, payment method and your metadata.
Each webhook is signed with HMAC-SHA256 using your webhook secret. Compute the signature over the raw request body and compare it with the signature header using a constant-time comparison. Reject requests that do not match.
Return a `2xx` response quickly, then process the event.
Paysasa retries failed webhook deliveries three times with exponential back-off (after about 1, 5 and 30 minutes), so make your handler idempotent — processing the same event twice should not ship an order twice.
Checkout session lifecycle
Step 6: Handle the session lifecycle
`pending` → `processing` when payment starts → `completed` on success.
Sessions can also end as `failed`, `expired` or `cancelled`.
Only failed sessions are retryable. Expired or cancelled sessions need a new session.
Completed sessions are final — never auto-retry them.
Sessions expire after 30 minutes by default.
You can read a session with `GET /checkout/sessions/:id` and cancel an active one with `POST /checkout/sessions/:id/cancel`.
Step 7: Use idempotency keys
Send an `X-Idempotency-Key` header on money-moving requests. It is required for `/checkout/sessions/:id/pay` and `/p2p/transfers`, and recommended for payouts and conversions. If a request is replayed with the same key, Paysasa returns the original result instead of charging twice.
Step 8: Go live safely
Test end to end with a test key before switching to live.
Log session IDs, references and webhook events.
Respect rate limits — by default 120 read and 60 write requests per minute per IP or key; check the `X-RateLimit-*` headers.
Handle `403` verification errors as onboarding states, not crashes.
Optional extras
Split payouts: route portions of each payment to other wallets in the same business with `use_split`.
POS flows: `POST /checkout/requests` creates a session for a phone number and returns a QR URL.
Conclusion
With an API key, a checkout session, a hosted page and verified webhooks, you can accept Paysasa payments in your own product securely and reliably. Start in test mode, verify every webhook and let idempotency protect you from duplicates.