Testing your integration
What test mode can and cannot simulate, and how to test each part of your integration.
Test mode is the Monad testnet with test USDC. It runs the same code as live mode: the same checks, limits, confirmation rules and events. That makes it realistic, and it means a test payment needs the same pieces as a live one.
What you need
| Piece | How to get it |
|---|---|
| Test API key | Dashboard in Sandbox, Developers → API keys, mode Test. |
| Merchant on testnet | Dashboard in Sandbox, Go Live (no business verification needed on testnet). |
| Testnet terminal | Dashboard in Sandbox, Settings → POS Terminals, then the POS app set to testnet. |
| Testnet pass | Payer app (pay.zylopay.com) switched to testnet, with testnet MON for the one-time USDC approval and test USDC in the wallet. |
There are no magic amounts, test cards or simulated taps. Ask your ZyloPay contact if you need test USDC or a POS build.
What to test, and how
Without a terminal
- Authentication and scopes. Call each endpoint you use with a key that lacks its scope and check you handle
403 insufficient_scope. - Idempotency. Send the same
POST /v1/payment_intentstwice with one key: the second answer is identical and hasIdempotent-Replayed: true. Change the body with the same key:409 idempotency_key_reused. - Payment intents. Create, retrieve, list and cancel intents. You receive
payment_intent.createdandpayment_intent.canceled. Let one expire (expires_in: 30) and checkcancellation_reason: "expired". - Validation. Send an unknown field and a negative amount:
parameter_unknown,parameter_invalid. - Webhooks. Send test events, rotate the secret and check that both signatures verify during the overlap, then disable and re-enable the endpoint.
- Pagination. Walk lists with small
limitvalues.
With a terminal and a pass
- Terminal-started payments. Take a payment on the terminal; check
payment_intent.succeeded(source: "terminal") andpayment.succeeded, and your reconciliation. - Declines. Tap with a pass whose spending limit is below the amount (
amount_exceeds_approval), or freeze the pass in the payer app (pass_frozen). Check you showlast_payment_error. - Payer confirmation. Pay above the testnet confirmation threshold to get
requires_action, then confirm, decline, or let it expire. - Refunds. Full, partial, and beyond the remaining amount (
amount_too_large).
API-created intents on a terminal
To test the full tap path for an API-created intent, the testnet terminal must run the POS release with intent pickup (rolling out; ask support). Until it does, test the create, cancel and expiry paths, and the tap path with terminal-started payments. The events and objects are the same.
Automated tests
- Unit-test your webhook handler with fixtures signed by your own test code (the algorithm is on Verify signatures), including duplicates and out-of-order events.
- Keep a small test-mode smoke test in your deployment pipeline: create an intent, cancel it, and check both events arrived.
- Never run automated tests against live keys.