Guide · 10 / 10

Going live

The production readiness checklist.

Before you switch traffic from sandbox to production, work through this checklist.

Credentials & environment

  • Use production keys against the production base URL. Swap https://sandbox.api.wasaapay.com/v1 for https://api.wasaapay.com/v1 and issue a fresh production API key from the dashboard. Sandbox keys do not work in production.
  • Scope keys tightly. Give each workload the narrowest scope it needs — read_only, write, payout_only, or full. Isolate payout ability in a dedicated payout_only key. See Authentication → Scopes.
  • Store secrets in a secret manager, never in source or client bundles. The web SDK's HMAC signer runs server-side only — the secret must never reach a browser or a mobile binary.
  • Rotate on a schedule and immediately if a key is exposed. Rotation returns a new secret once and revokes the old key.

Security

  • HTTPS everywhere. All production traffic — API calls and webhook endpoints — must be HTTPS. Webhook endpoints resolving to private/loopback ranges, or served over plain HTTP, are rejected in production.
  • Verify every webhook signature. Reject deliveries whose X-WasaaPay-Signature doesn't match and whose X-WasaaPay-Timestamp is more than 300 seconds old. See Webhooks → Verifying the signature.
  • Keep clocks in sync (NTP). Request signing and webhook verification both enforce a ±300s timestamp window; clock drift causes spurious AUTH_SIGNATURE_MISMATCH.
  • Consider an IP allowlist on production keys (issued with an ip_allowlist) so a leaked key is unusable from an unknown source.

PCI — never touch card data

  • Never send a raw PAN or CVV to WasaaPay. The card rail accepts only tokens. Use the tokenizing checkout SDK / CyberSource Unified Checkout so card data goes straight to the certified processor and only a tok_* reference reaches your servers and this API.
  • On mobile, inject the certified card tokenizer into the SDK's CheckoutConfiguration — the default tokenizer is a sandbox placeholder and must not ship in production.
  • Prefer the hosted checkout session or the mobile checkout UI so you keep card handling out of your own systems entirely.

Correctness & resilience

  • Send an Idempotency-Key on every fund-moving POST (collections, refunds, checkout-session create/pay, sub-merchant create, payouts, bulk payouts). Reuse the same key across retries of one logical attempt; use a new key for a new operation. See Making requests → Idempotency.
  • Treat the create response as non-final. A collection/payout is usually pending; wait for the transaction.* / payout.* webhook (or poll) for the terminal state. Make your webhook handler idempotent and dedupe on event.id — events fire on every status change and can be redelivered.
  • Handle the full error catalog. Branch on error.code and HTTP status: back off on 429 (honor Retry-After) and 503 RAIL_UNAVAILABLE, surface 402 INSUFFICIENT_FUNDS and 403 COMPLIANCE_HOLD, and never retry a 422 VALIDATION_ERROR unchanged. See Making requests.
  • Log meta.request_id on every call — it's the fastest path to support.
  • Respond 2xx to webhooks quickly and do heavy work asynchronously; slow responses count as failed deliveries and get retried.

Operational

  • Register production webhook endpoints and store each signing_secret securely (it's shown once). Subscribe only to the events you consume.
  • Rehearse failure paths in sandbox first using the magic values — declines, timeouts, insufficient funds, 3-D Secure — so your handling is proven before real money is involved. See Testing.
  • Reconcile. Keep your own ledger in step with transaction.*, payout.*, and escrow.* webhooks and with GET /transactions.

Account provisioning. Self-serve production signup is not yet available — production merchant accounts and go-live are provisioned with WasaaPay. Reach out to your WasaaPay contact to complete KYB and enable live processing.