Core Concepts
Test Mode
Every LuniPay account has a fully-isolated sandbox. Build, break, and rebuild without touching a real card, a real bank account, or a real customer.
What test mode is
Test mode is a parallel universe with the same schema, the same API surface, and the same dashboard — but none of the data is real. A test payment is a simulated charge; a test payout is a simulated payout; a test refund never moves money. You can reset the sandbox by rotating keys, but you can also just leave it there.
Test mode is keyed on the API key you use. A sk_test_… request always writes to test state; a sk_live_… request always writes to live state. There is no per-request toggle and no shared rows.
What is isolated
- Resources: customers, invoices, payments, payment links, and checkout sessions are filtered by livemode on every query.
- Webhook endpoints: test-mode endpoints only receive test events. Live endpoints only receive live events.
- Ledger and payouts: test payouts never hit Stripe Connect. They exist only as simulated rows in your LuniPay ledger.
- Rate limits: test and live share the same quota so you cannot use test to bypass live-mode throttling.
Test cards
LuniPay accepts every Stripe test card in test mode. Use any future expiry, any CVC, and any ZIP code:
| Number | Result |
|---|---|
| 4242 4242 4242 4242 | Approved. |
| 4000 0027 6000 3184 | Triggers 3D Secure authentication. |
| 4000 0000 0000 9995 | Declined — insufficient funds. |
| 4000 0000 0000 0002 | Declined — generic. |
| 4000 0000 0000 0069 | Expired card. |
| 4000 0000 0000 0127 | Incorrect CVC. |
Test mode in the dashboard
Every page in the LuniPay dashboard has a topbar toggle between Test and Live. In test mode a bright orange banner is shown so there is no ambiguity about which mode you are looking at. Test keys live under their own tab in Settings → Developer.
Going live
When you are ready to accept real money, swap your server-side secret from sk_test_… to sk_live_…, re-register your webhook endpoints in live mode, and re-run your integration tests. Nothing else changes — the API shape and response format are identical.
Sanity check before you flip
Resetting test data
There is no destructive "reset" button — rows accumulate as you test. If you need a clean slate, rotate your test keys to invalidate old idempotency caches and register a fresh test-mode webhook endpoint in the dashboard. You can also delete individual customers and invoices from the UI.
Filtering your own queries
Every response from LuniPay includes a top-level livemode boolean. If you persist LuniPay ids in your database, store the livemode alongside them so you can reliably filter test rows from your own reports.
{
"id": "pay_01JRZK9XA0PMK4JHGF7Z3V8TRC",
"object": "payment",
"livemode": false,
"status": "SUCCEEDED",
"amount_cents": 5000,
"currency": "usd"
}