Skip to main content
Use the interactive playground below to exercise the Zennopay Partner API against the sandbox environment. Every endpoint defined in openapi.json is callable here — request bodies are validated client-side against the schema before they’re sent.
The playground talks to https://api.sandbox.zennopay.com. Use a sandbox HMAC key ({partner}_sandbox_*) — production keys are rejected by the sandbox host. The legacy api.sandbox.zennopay.in host is still served if your client is pinned to it.

What you’ll need

  • A sandbox HMAC key (X-Zennopay-Key-Id) and shared secret. Compute the signature with the canonical-request recipe from Authentication.
  • For session-token endpoints (GET /v1/payment_intents/{intent_id} and POST /v1/payment_intents/{intent_id}/confirm), the session_token returned by a POST /v1/payment_intents call — send it as Authorization: Bearer. These are the calls the SDK normally makes; you rarely call them by hand.

Endpoints

The playground is generated from /openapi.json and groups endpoints by tag:
  • Payment IntentsPOST /v1/payment_intents, POST /v1/payment_intents/{intent_id}/session, POST /v1/payment_intents/{intent_id}/receipt_token, GET /v1/payment_intents/{intent_id}, POST /v1/payment_intents/{intent_id}/confirm, POST /v1/payment_intents/{intent_id}/cancel

Open the OpenAPI spec

Raw OpenAPI 3.1 document. Drop this into Postman, Insomnia, or your own codegen if you’d rather build a client locally.

Tips for first-time use

The most common causes, in order:
  1. Clock skew. X-Zennopay-Timestamp must be within ±5 minutes of server time. NTP-sync your machine.
  2. Body hash mismatch. The canonical request hashes the exact bytes of the request body. Don’t pretty-print or re-serialize between signing and sending.
  3. Source IP not allowlisted. The sandbox allowlist is configured per partner in the console.
In the default flow the session token is Zennopay-minted, so the usual causes are:
  • Expired. session_expires_at has passed. Create a fresh intent (or re-mint via POST /v1/payment_intents/{intent_id}/session) and use the new session_token.
  • Wrong intent. A token issued for intent A can’t call intent B — the path {intent_id} must match the intent the token was minted for.
  • Already consumed. The confirming call is single-use; re-mint via POST /v1/payment_intents/{intent_id}/session if you need another.
Each X-Zennopay-Nonce is single-use within a 10-minute window. Generate a fresh random 32-byte hex string for every request — never hardcode or reuse one.