Stable
Sourced from: docs/07-API-REFERENCE.md §0, §1, §5.9; docs/DECISIONS.md D0.1, D0.2, D2.1, D6.6, D8.9, D8.11

Getting started with ZuPayments

ZuPayments is a payment gateway for accepting Zucoins (ZKZ) — never referred to as "ZUC" — on the SplitChain network. Every merchant runs their own treasury node: a self-hosted deployment that holds all cryptographic keys and moves coins. The hosted ZuPayments platform (zupayments.com) never has access to a private key, an action key in plaintext, or a coin flow — it only ever sees ciphertext and optional read-only reporting metadata.

This means the API you integrate against is not a shared api.zupayments.com host. It's the base URL of your own node deployment, e.g. https://pay.acme-merchant.example.

⚠️ There is no sandbox

ZuPayments has no test mode and no sandbox environment. Every session you create, every code your customer pastes into their wallet, and every settlement is against the live SplitChain gateway, moving real, live ZKZ. There are no sk_test_… / cs_test_… key variants — a site key or checkout token is either valid on your live node or it doesn't exist.

Practical implications for integrating:

  • Test your integration with small real amounts on a real customer-side wallet you control. There is no faucet and no fake settlement.
  • Treat your site key with the same care you'd give a production secret on day one — because it is one from the moment your node is deployed.
  • Build and test error handling (expiry, mismatch, cancellation) deliberately — you can't rely on a sandbox to safely explore edge cases.

Base URLs

Surface Base URL Who calls it
Your node — Session API, checkout pages, webhooks origin https://<your-node-host> (your Railway deployment) Your backend (Session API) and your customers' browsers (checkout/embed)
ZuPayments platform — dashboard, node registration, vanity redirect https://api.zupayments.com (API) / https://pay.zupayments.com (vanity redirect) Your browser, when using the hosted dashboard

All API paths in these docs (/v1/sessions, /v1/checkout/..., etc.) are relative to your node's own base URL, not api.zupayments.com, unless stated otherwise. The API version prefix is /v1.

Auth model

Two credentials matter for a typical server-side integration:

  • Site key (sk_<32 bytes>) — sent as Authorization: Bearer sk_... from your backend to your node's Session API (create/get/list/cancel sessions). This is a secret: it must never reach the browser or a customer-facing surface. It is issued from your node's admin API and is deliberately kept separate from the node's internal "two-key" custody model — it only ever creates checkout sessions, it cannot move funds.
  • Checkout token (cs_<48 bytes>) — returned when you create a session. It's public, scoped to exactly one session, and is what powers the customer-facing checkout page or embedded widget. It carries no ability to create sessions or access any other merchant data.

There are no other credentials your integration needs to touch. Your node's admin/action keys (used for wallet management, sweeps, backups) are managed through the node's own admin UI and are out of scope for a standard checkout integration.

Money format

All amounts are JSON strings, never numbers — this applies to every request and response field in these docs. Amounts are trimmed decimal strings (BigNumber, rounded down, up to 32 decimal places, no trailing zeros, no exponent notation): "2", "0.25", "125" are all valid; 2, 0.25e2, or "0.250" are not. Parse and construct amounts with a decimal library (e.g. bignumber.js) in your own backend — never parseFloat/Number — to avoid floating-point drift on a real, live-money integration.

The ticker is always ZKZ. Maximum session amount is 100000000.

Common request/response conventions

  • Idempotency: mutating requests accept an Idempotency-Key header (≤255 chars). It's required on session creation — see Sessions.
  • Timestamps: RFC3339 UTC, unless a field is suffixed _unix (integer Unix seconds).
  • Errors: a single envelope shape — see Sessions for the pattern and the most common codes you'll hit.
  • Rate limits: every response carries X-RateLimit-Limit / X-RateLimit-Remaining / X-RateLimit-Reset; exceeding a limit returns 429 with Retry-After.

Next steps

  1. Sessions — create a checkout session from your backend and track it to settlement.
  2. Webhooks — get notified server-side the moment a payment settles.
  3. Widget embed — embed the checkout experience directly in your page instead of redirecting.