WalletD developers
Platform

Going live

What to have in place before you point a live key at real money, and how to prove each item rather than assume it.

Sandbox and live differ in one thing only: whether the money is real. The API surface is identical, so going live is not a migration. It is a checklist of things that were survivable in testing and are not survivable in production.

Each item below says how to prove it, because "we handle that" and "we tested that failing" are different states.

Credentials

  • A live key exists and the sandbox key is not in the deployment. Keys carry their environment in the token (sk_live_ versus sk_sandbox_), so a sandbox key pointed at production fails to authenticate rather than doing something expensive. Prove it by grepping your deployed configuration for sk_sandbox_.
  • The key is in a secret manager, not in an image, a repository or an environment file in version control. It is shown once at issuance and stored only as an Argon2id hash, so a lost key is reissued, never recovered.
  • You know the key expires. Keys are issued with a 365-day lifetime. Put the date in the same calendar that holds your certificate renewals, because the expiry arrives as an ordinary 401 with no warning.
  • Rotation is create, deploy, verify, then revoke, in that order. Revoking first is an outage. Revocation reaches the platform within its introspection cache, so allow a minute before assuming an old key is dead.
  • Scopes are the narrowest that work. A key with * is a key whose blast radius is the whole tenant.

Idempotency

  • Every money-moving call sends an Idempotency-Key derived from a business object, not a fresh UUID per attempt and not a timestamp. A key that changes on retry defeats the entire mechanism.
  • You have tested a replay. Send the same request twice with one key and assert one movement and an identical response. See Idempotency.

Webhooks

  • The receiver verifies the signature over the raw bytes, in constant time, before parsing. Re-serialising the body changes the hash.
  • The receiver rejects deliveries outside a tolerance you chose. The platform signs with the current time on every attempt and enforces no window of its own, so replay protection is yours. Five minutes is a reasonable default.
  • The receiver is idempotent on the verified body’s (tenant_id, id). X-Wallet-Event-Id is unsigned and advisory; changing it must not create work.
  • It acknowledges only after durable inbox acceptance, then works asynchronously. A slow receiver does not slow your payments, but it does burn your retry budget.
  • You have tested a bad signature. Flip one byte of a delivery body and assert your endpoint refuses it. See Webhooks.

Money handling

  • Nothing treats a client-side callback as a credit. A balance rises when a verified gateway confirmation arrives, never when a browser says the payment succeeded. See Top-ups.
  • Your UI shows available, not balance. Showing balance tells a user they have money that an uncaptured authorization has already spoken for.
  • Amounts are integer minor units end to end, with no float anywhere on the path in or out.
  • You branch on the code field of an error, never on title or detail. See Errors.

Reconciliation and monitoring

  • You reconcile against GET /v1/ledger/summary, which reports the identity that has to hold between what entered, what users and merchants hold, and what has left. See The money model.
  • You alert on the events that mean something went wrong rather than nothing happening: topup.amount_mismatch (the processor took a different amount than the intent), payment.expired (a hold was never captured), and the dunning events on subscriptions.
  • You have a retry and dead-letter path for your own webhook processing. Event history is retained for 30 days and redelivery is available inside that window, but the platform's history is a recovery buffer, not your system of record.

Limits

  • You have read the rate budgets and concurrency compartments and your traffic shape fits them, including your retry behaviour under failure. A retry storm is a traffic shape.
  • You handle 429 and 503 by honouring Retry-After rather than retrying immediately.

Support

  • You know your severity levels and how to raise an incident. See Support, SLAs and status.
  • You know that WalletD support cannot read your data without a grant you create, and who on your side is allowed to create one.

Sign-off

AreaProven byOwnerDate
Credentials in a secret manager, scoped, rotation rehearsed
Idempotent replay tested
Webhook signature, tolerance and replay tested
No client-side credit path
Reconciliation running against the ledger summary
Alerts on mismatch, expiry and dunning
Behaviour under 429 and 503 tested
Incident path and contacts agreed

On this page