Environments, testing and local development
16.1 Testing without risking money
Creating a payment charges nothing: it stays pending until someone pays it. To test safely
against production: a minimal amount (L 1.00) and a near-term expires_at, and do not pay it. The
link expires on its own. Triggering 401 / 404 / 422 errors is equally harmless.
16.2 Sandbox test cards
Sandbox only, with sk_test_ / pk_test_ keys. The card number selects the outcome, so this
short list is enough to exercise every path a connector has to handle:
| What you want to test | PAN | Password | What happens |
|---|---|---|---|
| Happy path, no challenge | 4012000000020071 |
— | Approved, auth status Y |
| A real 3-D Secure challenge | 4012000000020006 |
3ds2 |
Challenge screen, then approved |
| Authentication rejected | 5100270000000072 |
— | Auth status R, declined |
| Bank decline (do not honor) | 4666666666662222 |
— | Response code 05 |
| Authenticated, then issuer down | 4111111111110000 |
3ds2 |
Status Y, then response code 91 |
| A card with no 3-D Secure at all | 4333333333332222 |
— | Approved, no challenge |
Any future expiry date works; 3-digit CVV for Visa and Mastercard, 4 for Amex. The password on any
challenge screen is 3ds2.
Send the cardholder name and an email or phone, otherwise 3-D Secure will not run and you will silently get the frictionless path every time.
Approved without a challenge (frictionless): Visa 4012000000020071 (Y),
4012000000020089 (A), 4012010000020070 and 4012010000020088 (with device fingerprinting);
Mastercard 5100270000000023 (Y), 5100271000000120; Amex 341111000000009 (Y),
341111000000011 (A), 341112000008012.
Approved after a real challenge (password 3ds2): Visa 4012000000020006,
4012010000020005; Mastercard 5100270000000031; Amex 341112000000001, 341111000000037.
No 3-D Secure involved: Visa 4333333333332222, Mastercard 5333333333332222,
Amex 343333333333335, Discover 6011111111111111, JCB 3528111111111108.
Declines and failed authentication:
| PAN | Password | What comes back |
|---|---|---|
4012000000020121 |
— | Status N, code 12 |
5100270000000098 |
— | Status N, code 12 |
5100270000000056 |
— | Challenge appears, then status N, code 12 |
5100270000000072 |
— | Status R |
4666666666662222 |
— | Status A, code 05, CVV check fails |
5555666666662222 |
— | Status U, code 05 |
4111111111119999 |
— | Status A, code 98 |
5111111111113333 |
— | Status A, code 05 |
4111111111110000 |
3ds2 |
Challenge passes (Y), then code 91 |
5111111111110000 |
3ds2 |
Challenge passes (Y), then code 91 |
341111000000029 |
— | Status N, code 12 |
6011111111111152 |
— | Discover decline |
3528111111111157 |
— | JCB decline |
Status Y means fully authenticated and A means authentication was attempted; both can still end in an approval. N, U and R do not.
Two things there is no card for, confirmed by the API team on 2026-08-25:
- Insufficient funds (
51). The code exists in the live response set, but no sandbox card produces it. Test your insufficient-funds branch by treating05as its stand-in and reading §15 for which codes are worth retrying. - An invalid or malformed card number. There is no card for it because it should never reach the API: validate the number in your own form first.
Source: PowerTranz sandbox documentation, relayed by the ROKI API team on 2026-08-25. These are the processor's cards, so they behave the same anywhere PowerTranz is the processor.
16.3 If sandbox rejects every creation
An sk_test_ key can authenticate correctly and still fail to create payments with:
422 "El entorno sandbox no esta configurado para enlaces de pago.
Contacte a soporte ROKI o use su clave API live."
That is not the key's fault and not the code's, and regenerating the key does not fix it: the sandbox terminal is not provisioned for that merchant. Ask ROKI to enable sandbox for the account.
16.4 Receiving webhooks in local development
ROKI must reach a public HTTPS URL, so localhost will not work. Options:
- A tunnel (ngrok, Cloudflare Tunnel), registering the generated URL in the portal under the sandbox environment.
- To only inspect events without writing code, a temporary public receiver (webhook.site and similar), useful for seeing the real payload and headers.
Remember to register the final URL before going to production: tunnel URLs change.
