Test mode & test cards
Build and test your XPay integration end to end without moving real money.
Test mode is a fully isolated environment that mirrors live: same API surface, same webhook payloads, same dashboard UI, separate everything else. New accounts start in test mode and stay there until your business is approved for live payments.
Test mode is where you build, test, and break things. Nothing you do in test mode touches a real card, your live customers, or your live balance.
What's separate, what's the same
| In test mode | In live mode |
|---|---|
pk_test_... and sk_test_... API keys | pk_live_... and sk_live_... API keys |
| Test customers, transactions, payouts | Live customers, transactions, payouts |
| Test balance ledger, separate from live | Live balance ledger |
| Test webhook endpoints (set up separately) | Live webhook endpoints |
| Same API request and response shapes | Same |
| Same webhook events and the data they carry | Same |
| Same dashboard UI, with a banner and orange tint | Same UI, no banner |
When you graduate to live mode, you don't change your code. You just swap your test keys for live keys and set up live webhook endpoints.
What you can test
- Card payments with predictable success and failure outcomes (see the table below).
- 3D Secure flows, including success, failure, cancellation, and timeout (via the ACS emulator).
- Refunds, full or partial, from the dashboard or the API.
- Webhooks to a real or local endpoint, including retries and replay from the dashboard.
- The full hosted checkout, drop-in, and Elements UI end to end.
- Payouts, simulated on the test schedule.
Test cards
XPay accepts four test cards in test mode. The card number determines the issuer and the brand; the expiry date determines the payment outcome.
| Brand | Issuer | Card number | Currency |
|---|---|---|---|
| Mastercard | National Bank of Egypt | 5123 4500 0000 0008 | EGP |
| Visa | Banque Misr | 4508 7500 1574 1019 | EGP |
| Mastercard | Credit Agricole Egypt | 5111 1111 1111 1118 | EGP |
| Mastercard | International | 2223 0000 0000 0007 | USD |
Any other card number is rejected in test mode. The international card is the one to use when you want to test the international fee tier.
Payment outcome by expiry
In test mode the expiry date decides whether the payment succeeds or fails, and how it fails. The card number itself does not.
| Expiry | Outcome |
|---|---|
01/39 | APPROVED |
05/39 | DECLINED |
01/27 | INSUFFICIENT_FUNDS |
04/27 | EXPIRED_CARD |
08/28 | TIMED_OUT |
01/37 | ACQUIRER_SYSTEM_ERROR |
02/37 | UNSPECIFIED_FAILURE |
05/37 | UNKNOWN |
Use 01/39 for the happy path. Use the others to validate how your code handles real-world failures: the Payment Intent moves to payment_failed, the Charge gets a failure_code, and you receive the matching webhooks (payment_intent.payment_failed, charge.failed).
CVV outcome by CVV value
The CVV controls the CVV match result reported on the resulting Charge.
| CVV | Result |
|---|---|
100 | MATCH |
101 | NOT_PROCESSED |
102 | NO_MATCH |
Use 100 unless you're testing CVV-mismatch handling.
3D Secure in test mode
Every test payment runs the full 3D Secure 2 challenge flow through XPay's sandbox emulator. After you submit the card form, an ACS (Access Control Server) page pops up where you choose the authentication outcome:
- Success. Finishes the payment along the happy path.
- Rejected. The issuer denies the challenge. The payment fails with
authentication_requiredorcard_declineddepending on the bank's response. - Cancelled. The customer dismisses the challenge.
- Timeout. No response within the issuer's window.
This is how you test the 3DS-failure branches of your integration without finding a real failing card.
Where to next
Quickstart
Haven't run a test payment yet? Take one end to end in five minutes.
Choose your integration
Pick the integration pattern you'll build with for real.
Set up a webhook endpoint
Subscribe to test events and verify the signature before you deploy.
Local webhook development
Tunnel test webhooks to your laptop while you build.