Testing
Pesapal runs a sandbox that mirrors production. Only the host differs:
| Environment | Base URL |
|---|---|
| Sandbox | https://cybqa.pesapal.com/pesapalv3/api |
| Production | https://pay.pesapal.com/v3/api |
Paths, request bodies and responses are identical, so pointing an integration at production is a one-line change.
Credentials
Section titled “Credentials”Pesapal publishes sandbox credentials openly at the demo keys page. You do not need an account to start.
Test cards
Section titled “Test cards”Use these on the hosted payment page. Any name, address and future expiry works alongside them.
Approve Immediately
Section titled “Approve Immediately”| Brand | Number | Expiry | CVV |
|---|---|---|---|
| Visa | 4761 7390 0101 0010 |
07/28 | 123 |
| MasterCard | 5200 0000 0000 0114 |
07/28 | 123 |
| Amex | 3400 0000 0003 961 |
07/28 | 1234 |
Trigger 3D Secure
Section titled “Trigger 3D Secure”| Brand | Number | Expiry | CVV |
|---|---|---|---|
| Visa | 4000 0000 0000 1091 |
07/28 | 123 |
| MasterCard | 5200 0000 0000 0007 |
07/28 | 123 |
Decline
Section titled “Decline”| Brand | Number | Expiry | CVV |
|---|---|---|---|
| Visa | 4000 0000 0000 1018 |
07/28 | 123 |
You can find these card details on the Test Payments page.
What the sandbox cannot simulate
Section titled “What the sandbox cannot simulate”That has a knock-on effect worth planning around: you cannot test your
failure-handling path end to end. status_code values other than 1 have
never been observed, so any branch you write for them is untested code.
Two ways to work around it:
- Unit test your handler against a hand-written failed response rather than a live one.
- Test the pending path instead, which is easy and is where most bugs live. Create an order and query it without paying. See an unpaid order comes back as an error.
Testing Notifications
Section titled “Testing Notifications”Pesapal only sends an IPN when a payment actually completes, so you need a publicly reachable URL before you can see one.
-
Open webhook.site and copy your unique URL. It gives you a public endpoint and logs the full request, including query parameters.
-
Register it with
RegisterIPNand keep theipn_id. -
Create an order with that
notification_id, open itsredirect_url, and pay with a test card. -
Refresh webhook.site. The notification arrives as a GET with three query parameters and no body.
When you move to testing against your own server, a tunnel such as
ngrok or cloudflared exposes localhost publicly.
Going to Production
Section titled “Going to Production”-
Swap the base URL to
https://pay.pesapal.com/v3/api. -
Swap your consumer key and secret for your own, from the Pesapal dashboard. Keep them out of source control.
-
Register your production IPN URL. Registrations do not carry across environments, and the
ipn_idwill be different. -
Verify your IPN endpoint is actually reachable from the public internet. Pesapal does not check this at registration, so a wrong URL fails silently.
-
Confirm your first real transaction end to end before taking live traffic.