Skip to main content
Getting in, and what the setup wizard changes, is on Sandbox Environment & Access FAQ. The simulator walkthrough is on Sandbox simulator and Sandbox Testing FAQ. This page is the boundary map: which scenarios the sandbox can actually produce, which it cannot, and where the reserved amounts do and do not apply. Read it before you plan an acceptance run, so you do not spend a day trying to reproduce something that has no sandbox path.

What can and cannot be simulated? Give me the whole list.

Everything in the “No” rows is genuinely absent rather than undocumented, so plan around it: prove those code paths with unit tests against recorded payloads, and verify the live behaviour in production once you are live.

Which reserved amounts trigger which error, and on which endpoints?

The sandbox intercepts specific order amounts and returns the matching error instead of processing normally. The mapping: Read the “applies to” column carefully, because it is where the mistakes happen:
  • On create, the amount is taken from the request — the order amount on an order create, the amount on a subscription create.
  • On cancel, you do not pass an amount. The amount matched is the one stored on the order or subscription you are cancelling. So to test a cancel error you must create the order at 9.3 first, then cancel it.
  • These amounts are a sandbox-only rule. Nothing like this exists in production, where the same amounts are ordinary amounts.

Why do the reserved refund amounts not work?

Because the refund path does not use the refund-specific amounts. The 9.5 and 9.6 families listed for the refund API on the published Sandbox simulator page do not take effect — a refund of 995 is an ordinary refund. What the refund path does react to are the create families: a refundAmount equal to one of the 90 / 9.1 / 9.2 family values (the same amounts that trigger C0005, C0001 and E0001 on order create) makes the refund request fail at request time with an error of the matching class — a channel or system error for the 90 and 9.1 families, an unknown-status error for the 9.2 family. The refund order that was opened for the request finishes as REFUND_FAILED, and a refund notification reporting the failure is sent to your refund notify URL. That lets you prove your handling of a rejected refund request and of a failed refund record; what it cannot give you is a refund that first goes in progress and fails later, and there is no other way to force one in the sandbox. What you can still prove on the refund path: For a genuine refund failure, test your handler against a recorded payload rather than trying to provoke one.

My real prices land on the reserved amounts and my sandbox orders keep failing

This is a known situation and it has a fix that is not “change your prices”: a sandbox merchant ID can be exempted from amount simulation. Contact integration support with your sandbox merchant ID and ask for the exemption; once applied, reserved amounts behave as ordinary amounts for your sandbox. Until then, the workaround is to avoid the five families above. In practice that means avoiding amounts ending in 90, and the 9.x / x91–x96 patterns — adding a cent (for example 90.01 instead of 90) is enough, because the match is exact.

Does the sandbox really send webhooks?

Yes. Sandbox webhook delivery follows the same contract as production — the same signature, the same accepted response body, the same retry schedule. Everything in Webhook Delivery Contract FAQ applies unchanged. Two things that are not different but get blamed for looking different:
  • Your notifyUrl must be publicly reachable. The sandbox cannot reach localhost or a private address, and your TLS certificate must be publicly trusted. Use a tunnelling tool for local development.
  • Perceived sandbox delay is usually the retry schedule. If a first delivery fails, the next attempts follow a growing back-off — see Webhook retry for the schedule. A notification that “took minutes to arrive” almost always means the first attempts were rejected — check the Portal webhook log for the earlier failed attempts on the same record before concluding the sandbox is slow.

Which test card numbers should I use?

Use the quick-fill buttons on the sandbox checkout page when a flow asks you to enter a card. They populate the card number, an expiry and a CVV for a success or a decline in one click, per card brand, for the brands your sandbox has enabled — which removes both the transcription errors and the guesswork about which value that environment expects. If you need the values written down, the Portal’s own list is at Merchant Portal → Integration → Test Cards, with a copy action per card and two scenario categories: successful and failed. The table in Sandbox Testing FAQ matches the Portal list. The older published simulator page does not agree for every scheme, so prefer the in-product source over any document, and prefer the checkout quick-fill over both.

What do I enter for expiry and CVV? Are they validated?

Any future expiry date, and any CVV of the right length — three digits, four for the schemes that use four. The quick-fill on the checkout page supplies a valid combination for you. What this tells you about coverage: because expiry and CVV are not meaningfully validated, the sandbox cannot prove your handling of an expiry-date rejection or a CVV mismatch. Those belong to the “test against a recorded payload” list.

The Portal test card page shows only success and failure. Where are the 3DS, insufficient-funds, CVC-error and risk-decline cards?

They do not exist. The Portal test card list has exactly two scenario categories, successful and failed, and there is no card number that maps to a specific decline reason. The consequence for acceptance planning: the sandbox proves that your code takes the right branch on success and on failure. It does not let you enumerate decline reasons. Where your product behaves differently per decline reason — a retry prompt for insufficient funds versus a “use another card” prompt for a hard decline — drive those branches from orderFailedReason in unit tests, using the codes in Error codes.

How do I simulate a renewal, and can I chain periods?

From the subscription management page, which you obtain by calling POST /api/v1/subscription/manage and opening the returned managementUrl. It offers a simulated successful next payment and a simulated failed next payment, and each click advances one period — so you can chain them: period 2 succeeds, period 3 fails. Preconditions, because these are what make the buttons unavailable: If the page renders but the simulation controls are absent, check the subscription’s status first — an unactivated or already-cancelled subscription is by far the most common cause.

Will a simulated failed period then retry on the normal schedule?

No — and this is the most important thing on this page. Simulating a failed renewal sets the renewal retry allowance to zero first, so the failed period goes straight to its terminal state instead of entering the retry schedule. Two consequences to plan around:
  • You cannot observe renewal retry behaviour in the sandbox by simulating a failure. The retry schedule that runs in production is bypassed by the simulation itself.
  • The change persists for that sandbox subscription’s configuration. Renewal retries stay disabled afterwards, so a subscription you used to simulate a failure is no longer a clean subject for retry testing. Create a fresh subscription for anything retry-related.
To test your handling of the outcome of an exhausted retry sequence, the simulated failure is exactly right — it produces the same terminal period state and the same notification. To test the sequence itself, you need production behaviour or a recorded set of payloads.

Can I simulate the customer cancelling inside their wallet app?

Yes, for the payment methods where it is supported. The simulation produces the same SUBSCRIPTION_STATUS_NOTIFICATION with USER_CANCELLED that a real customer-side cancellation produces, so your handler sees the real thing. Two gates decide whether it works for a given subscription:
  1. The subscription must be ACTIVE.
  2. The payment method must support it. Wallet-side cancellation is simulated by reproducing the message that payment method actually sends on cancellation, so it exists only for methods where that message is modelled. Where it is not, the call fails with a dedicated “this payment method does not support channel cancel” error rather than silently doing nothing — which is itself the answer to whether your method is covered: try it and read the error.
If your method is not covered, test the handler directly against a USER_CANCELLED payload. The notification shape does not vary by payment method.

Can I test a chargeback in the sandbox?

No. There is no chargeback or dispute simulation in the sandbox — no reserved amount, no button, no endpoint. What to do instead: Also worth knowing before you plan around it: the chargeback notification is only delivered if the Chargeback Notify URL is configured in the Portal, and it is Portal-configured only — there is no request parameter. So the first thing to verify is that the URL is set, in both environments.

An order is stuck in an unknown state. How do I drive it to a final result?

E0001 is returned at create time by a reserved amount, and the request is rejected before any order is created — an inquiry on that request id comes back as “order does not exist”. That is the point: an unknown-status response tells you nothing about whether an order exists, so the behaviour to prove is your recovery logic — treat the result as undetermined, inquire, and act on what the inquiry returns; never mark the order failed or close it yourself. When the inquiry confirms nothing exists, re-submit with identical parameters (your paymentRequestId makes that safe). There is no sandbox control that produces an order which then sits in an unknown state and flips to a final result later. So the behaviour to demonstrate is the inquire-then-decide loop and the “did not self-close” property, not a final state you produced by hand. The acceptance criteria phrase this as: do not close the order, retry with identical parameters, and wait for the inquiry result or the notification. See Integration acceptance criteria.

Do I need a network exit in a particular country to test?

Not for the sandbox. Nothing in the sandbox payment path checks where your request or your browser comes from, and because the sandbox does not connect to real payment channels there is no channel-side geographic restriction to satisfy either. A sandbox run from anywhere is a valid sandbox run. Where geography does matter is production verification of methods that genuinely depend on the customer’s region — device or account region settings for the mobile wallet products, and the supported-country lists those products publish. Those checks are listed in Sandbox and testing under the per-payment-method sections, and they are production checks, not sandbox ones.

Which things can only be verified in production?

Keep this list next to your go-live plan, because each item is a place where a green sandbox run proves nothing: The mobile wallet checks in particular have their own prerequisite lists — accounts, cards, device regions, in-app browser configuration, and a production access request that must be approved before launch. Work through Sandbox and testing and Payment method integration notes rather than discovering them at cutover.

Do I have to test every contracted payment method individually?

No. The acceptance criteria set out representative coverage rather than exhaustive coverage: at least one card, at least one per country per type, at least one virtual account, every method with special required parameters, and manual device testing for the mobile wallets. The full rule set is in Integration acceptance criteria. Two follow-ups that come up constantly:
  • A method your agreement does not allow refunds on does not need a refund case. Run the conditional cases only for the APIs and behaviours your integration actually includes — the templates mark them as conditional for that reason.
  • A second integration is not a full re-run. Once you have passed acceptance at least once, a subsequent one-time-payment integration uses the additional integration template, which covers only the delta. Your first integration always uses the standard template.

Next: Go-live checklist for the switch itself, and Sandbox Environment & Access FAQ for what does and does not carry over from the sandbox.