Reference
Simulate every payment outcome without moving money.
Sandbox
Use a plk_test_… key (or Developers → Sandbox in the app, which runs real requests with your account).
Sandbox payments:
- never call the payment provider and never move funds,
- return
sandbox: trueandsimulation: true, - are listed in your dashboard under Transactions → Sandbox,
- fire real webhooks to your endpoint when you simulate a result.
Test phone numbers
The scenario is chosen by the last digit of a number ending in 00000000N and works with every active operator of the country. Any country code works.
| Number (example CM) | HTTP | Result |
|---|---|---|
+237000000001 | 200 | status: "success" — confirmed immediately |
+237000000002 | 202 | status: "pending" — stays pending until you simulate |
+237000000003 | 200 | status: "failed" |
+237000000004 | 400 | otp_required — retry with otp: "000000" → 202 pending |
+237000000005 | 200 | status: "cancelled" |
Other numbers return 202 pending.
| Country | Code | Prefix |
|---|---|---|
| Cameroon | CM | +237 |
| Chad | TD | +235 |
| Central African Rep. | CF | +236 |
| Congo | CG | +242 |
| Gabon | GA | +241 |
| Equatorial Guinea | GQ | +240 |
| Senegal | SN | +221 |
| Côte d'Ivoire | CI | +225 |
| Mali | ML | +223 |
| Burkina Faso | BF | +226 |
| Niger | NE | +227 |
| Togo | TG | +228 |
| Benin | BJ | +229 |
| Guinea-Bissau | GW | +245 |
| DR Congo | CD | +243 |
| Nigeria | NG | +234 |
| Ghana | GH | +233 |
| Kenya | KE | +254 |
OTP simulation
json
1{2 "error": "otp_required",3 "sandbox": true,4 "simulation": true,5 "reference": "PLK-SBX-…",6 "ussd_code": "#SANDBOX#",7 "message": "Demo OTP required. Use 000000 with the same request."8}Re-send with "reference": "<returned reference>" and "otp": "000000". Any other OTP returns invalid_otp.
Finishing pending payments
bash
1curl -X POST https://paylinky.vercel.app/api/v1/sandbox/simulate \2 -H "Authorization: Bearer $PAYLINKY_TEST_KEY" \3 -H "Content-Type: application/json" \4 -d '{ "transaction_id": "0b9c…", "status": "success" }'This updates the transaction and sends payment.completed (or payment.failed) to your webhook.
Crypto in the sandbox
/crypto/collect returns a clearly fake address and stays pending until you call /sandbox/simulate.
Test checklist
200on/countriesand/crypto/assets- one
pending, onesuccess, onefailed, onecancelled - the OTP round-trip
- webhook received, signature verified, duplicate delivery ignored
- timeout → status check instead of a second payment
- errors
400,401,403,429