Sandbox keys and JWKS endpoint are issued manually during onboarding for v1.
Email partners@zennopay.com to receive a sandbox key ID and signing
secret.
Environments. Code below shows the production URL
(
https://api.zennopay.com) for copy-paste readiness. While integrating,
swap in the sandbox host (https://api.sandbox.zennopay.com) — sandbox
HMAC keys are rejected by production and vice versa. See
Environments.1. Get your credentials
You will receive:- A key ID (e.g.
wizz_sandbox_2026q2) and a 32-byte signing secret for HMAC-signed API calls. - A JWKS endpoint URL you publish on your own domain
(
https://your-domain/.well-known/jwks.json), containing the RS256 public key your backend uses to sign session JWTs.
2. Sign and send your first API call
Construct the canonical request string, HMAC-SHA256 it with your signing secret, and send it with the four required headers.200 OK with an intent_id:
3. Mint a session JWT
Sign a JWT with your RS256 private key that authorizes one user to complete one intent. The session expires in 10 minutes max.4. Hand off to the mobile SDK
Pass theintent_id and jwt to the Zennopay SDK on the user’s device:
iOS SDK
Android SDK
5. Receive the webhook
After the payment settles (or fails), Zennopay POSTs a signed webhook to your configured endpoint. See Webhooks for the payload shape and signature verification steps.Common errors
| HTTP | error.code | Likely cause |
|---|---|---|
| 401 | authentication_failed | Bad HMAC signature, expired timestamp, replayed nonce, or IP not in allowlist |
| 401 | jwt_invalid | JWT signature, audience, expiry, or jti (replay) check failed |
| 400 | invalid_corridor | Corridor must be th_promptpay or vn_vietqr |
| 422 | amount_below_minimum | Minimum transaction value not met for the corridor |
request_id
field to correlate with internal logs when contacting support.