Test your integration without moving real money.
How the sandbox works
The sandbox is a path, not a separate host. There is no separate sandbox domain. Test traffic uses the same base URL as live — https://api.quatapay.com/api/v1 — but hits the /gateway/sandbox/ path with a test key:
POST https://api.quatapay.com/api/v1/gateway/sandbox/payments
The sandbox path mirrors the live /gateway/payments API — same request and response shape. Only the path and the key prefix differ, so choose the path from the key prefix in your code and going live becomes an environment-variable change.
Sandbox API keys
Use keys with the qpay_test_ prefix. Test payments never touch the real ledger. The live /gateway/payments endpoint rejects a test key with 403, and the sandbox path rejects a live key the same way. A test key only sees test payments.
Generate test keys in your merchant panel under Developer → API keys, with the mode set to Test. The key is shown once.
The Node and Python SDKs call the live path only, so they refuse a test key with 403. Use plain HTTP (cURL, fetch, requests…) while you test.
Completing a test payment
A test-mode checkout cannot be paid in the browser: the hosted page refuses Mobile Money and wallet payments for test payments. Finish a test payment from your server, your terminal or your integration tests with the simulate call, using the payment's slug and your test key:
POST https://api.quatapay.com/api/v1/gateway/sandbox/payments/{slug}/simulate
Authorization: Bearer qpay_test_YOUR_KEY
Content-Type: application/json
{ "outcome": "succeeded" }
To simulate a failure, send { "outcome": "failed", "failure_reason": "INSUFFICIENT_FUNDS" }. POST /gateway/sandbox/payments/{slug}/cancel cancels a test payment.
This sends the same gateway.payment.* webhooks as a real completion, with "simulated": true added to data. There are no special customer_reference values: send whatever your order needs.
A good test run covers: a succeeded payment, a failed one, a cancelled one, the same webhook delivered twice, a webhook with a wrong signature and one with an old timestamp.
Test checkout flow
- Create a test payment with
POST /gateway/sandbox/paymentsand yourqpay_test_key. - Keep
data.payment.idanddata.payment.slug. - Optionally open
data.checkout_urlto see the hosted page (it shows the order but cannot take a test payment). - Call the simulate endpoint.
- Watch the webhook arrive at your endpoint and check your order flips to paid exactly once.
- Read the payment back with
GET /gateway/sandbox/payments/{id}.
Sandbox wallet in the merchant panel
Developer → Sandbox in the merchant panel has a separate throwaway sandbox wallet: fund it, drain it, run simulated payments with the documented test cards, and reset it (a reset clears the history and sets the balance to 0). It is independent of the gateway test mode above.
Differences from production
Going live
- Create a
qpay_live_API key in Developer → API keys and set it only in your production environment. - Register your production webhook URL (Developer → Webhooks) and store its signing secret in the production environment.
- Make sure no test key, test URL or
simulatecall is left in production code. - Make one small real payment and confirm the order is marked paid exactly once.