Mintcash
Get started

Sandbox vs Live

How the two environments differ, how to keep them isolated, and what changes when you flip your code from test mode to production.

Every MintCash merchant runs in two parallel worlds: sandbox and live. They share zero state. Different API endpoints, different keys, different webhook destinations, different ledgers.

At a glance

PropertySandboxLive
Base URLhttps://sandbox.mintcash.mehttps://api.mintcash.me
API key prefixpk_test_… / sk_test_…pk_live_… / sk_live_…
Webhook environment"test""live"
Cards chargedReusable test numbers onlyReal cards
Money movementNone — no settlementReal settlement to your accounts
Provider behaviourDeterministic by test cardProvider's actual decision
IP allow listsOff by defaultRecommend on
Rate limitsGenerousPer-merchant configured

The webhook envelope tells you which one

Every webhook MintCash sends includes an environment field. Use it as a defensive check so a misconfigured test webhook can never trigger live-side fulfilment:

if (event.environment !== process.env.MINTCASH_ENV) {
  return Response.json({ error: "wrong environment" }, { status: 400 });
}

Don't share keys across environments

A live secret key pasted into a staging server is the kind of mistake that becomes a chargeback. Treat the two key pairs like database credentials for prod vs. test — they should never sit next to each other in config.

What test cards can do for you

In sandbox you have a small set of test cards that deterministically produce success, 3DS challenges, or specific failure conditions. The same card always behaves the same way, so you can exercise every branch of your code, and a specific failure resolution can be requested by varying the expiry.

See the test cards reference for the full grid of card numbers, expiries, and outcomes.

What you should test before going live

Run all of these against sandbox, in this order:

  1. Happy-path one-time payment — HPP flow ends in payment.succeeded and you fulfil correctly.
  2. Decline handling — your code does the right thing on payment.failed. Refund/return logic is exercised.
  3. Webhook signature verification — you reject unsigned and tampered webhooks with 401.
  4. Duplicate webhook delivery — your handler is idempotent on eventId.
  5. Subscription create + retry — first invoice, then a deliberately-failing retry, then subscription.cancelled after retries exhaust.
  6. Refund — full and partial refund flows; both payment.refunded and payment.partially_refunded reach you.
  7. Wrong-environment webhook rejection — your endpoint refuses webhooks tagged with the wrong environment.

When all eight pass, swap keys and run the same shape of test against your live integration with a real card you control. After that, you're production-ready.

Going live checklist →