Sandbox & test cards
Manza provides a sandbox environment so you can integrate, test edge cases, and verify webhook handling without moving real money or charging real cards.
Accessing the sandbox#
Use the Manza sandbox for your region. Sandbox and production data are isolated: API keys, customers, payments and webhook endpoints from one environment do not appear in the other. Use a key created in the same sandbox as your API base URL.
| Region | Sandbox dashboard | Sandbox API base |
|---|---|---|
| Morocco | ma.manza.dev | https://ma.manza.dev/api |
| South Africa | za.manza.dev | https://za.manza.dev/api |
Open Settings → Developer → API Keys in that sandbox dashboard and create a dedicated key. Select entity:read for the first request below, plus the scopes needed by your integration. Copy the key when it is shown and store it securely; do not place it in browser code or source control.
Verify API access#
Set MANZA_API_KEY in your backend environment to your sandbox key. Set MANZA_BASE_URL to https://ma.manza.dev for Morocco or https://za.manza.dev for South Africa — the host without the /api suffix, which is what the official SDKs read (they append /api/... themselves). Then make this read-only request:
curl "$MANZA_BASE_URL/api/entity" \
-H "Authorization: Bearer $MANZA_API_KEY"A 200 response returns the workspace associated with your key. Confirm it is the workspace you intended before continuing. API access and workspace activation must be enabled in the sandbox; creating a key does not enable product access.
| Response | What to check |
|---|---|
401 | Check the Bearer token and confirm the key was created in this sandbox, not production or the other region. |
403 with error.type = insufficient_scope | Create a key with the endpoint's required scope. Existing keys do not gain new scopes automatically. |
403 with error.message = Feature not enabled or API access not enabled | Ask support to enable the required access for your sandbox workspace. Share the workspace and sandbox URL, never the API key. |
403 with error.type = entity_inactive | Complete workspace activation or ask support about activation of your sandbox workspace. |
Product feature access and API-key scopes are checked separately. A successful entity request verifies authentication and basic API access; it does not prove every product endpoint is enabled. Follow the relevant API reference for its required scopes and approval flow.
Test cards#
Use these card numbers on any sandbox hosted payment page. Any future expiry date, any 3-digit CVC, and any postcode are accepted.
| Card number | Brand | Result |
|---|---|---|
4242 4242 4242 4242 | Visa | Payment succeeds |
5555 5555 5555 4444 | Mastercard | Payment succeeds |
4000 0000 0000 0002 | Visa | Card declined |
Reconciling payment state#
Two ways to confirm whether a sandbox payment succeeded:
- API — GET the checkout session or payment link and check the status field.
- Webhooks — listen for checkout_session.completed or payment_link.paid. Sandbox webhooks fire identically to production, signed with the same scheme.
A confirmed payment first reads clearing (credited, provider settlement pending, settled_at null) — sandbox included. Fulfill on checkout_session.completed / payment_link.paid; if you also track settlement, listen for checkout_session.settled / payment_link.payment_settled, which fire once settled_at is set.
Going live#
When your sandbox integration is stable:
- Mint a fresh API key from the production dashboard (production keys can't be cloned from sandbox).
- Switch your application's base URL from the sandbox host to production.
- Replace test-card flows with real card collection (the hosted page handles PCI).
- Re-register your webhook endpoint against the production dashboard.