Getting Started

Quick Start

Zero to a successful test payment in under 15 minutes. Follow the steps in order — no skipping.

By the end of this guide you will have created a test checkout session, completed a payment with a test card, and verified it landed in your dashboard. No real money moves in test mode.

1. Generate your API keys

Sign in to LuniPay, open Settings → Developer, and click Generate API keys. You will see four keys:

  • sk_test_… — server-side, test mode
  • pk_test_… — client-side, test mode
  • sk_live_… — server-side, live mode
  • pk_live_… — client-side, live mode

Copy the secrets now

The full sk_secrets are shown exactly once. Store them in a password manager or your app's secret store before you close the dialog. If you lose one, rotate it from the same page.

2. Create a checkout session

From your backend, create a checkout session with a test secret key. The response includes a hosted url — that is where your customer will pay. Pick your language:

// npm install lunipay
import LuniPay from 'lunipay';

const lunipay = new LuniPay(process.env.LUNIPAY_SECRET_KEY);

const session = await lunipay.checkout.sessions.create({
  amount: 5000,
  currency: 'usd',
  success_url: 'https://example.com/thanks?session_id={CHECKOUT_SESSION_ID}',
  cancel_url: 'https://example.com/cart',
});

console.log(session.url);

3. Pay with a test card

Copy the url from the response and open it in a browser. Use one of these cards — any future expiry, any CVC, any ZIP:

Card numberScenario
4242 4242 4242 4242Approved payment — the happy path.
4000 0027 6000 3184Requires 3DS authentication.
4000 0000 0000 9995Insufficient funds decline.
4000 0000 0000 0002Generic card decline.

4. Verify it worked

Toggle to Test mode in the dashboard topbar and open the Transactions page. You should see the sandbox payment with a SUCCEEDED status. You can also re-fetch the session by id to confirm its final state:

const session = await lunipay.checkout.sessions.retrieve('cs_01JRZK8WV3FYMPEQRXJ9HA5NTB');
console.log(session.status, session.payment_status);

5. Receive a webhook

Payments in production are fulfilled from the webhook, not the redirect. Register a test-mode webhook endpoint pointing at something like webhook.site or your local tunnel, then re-run the flow. You will see a checkout.session.completed event land within a second of the payment succeeding.

Source of truth

The success_url redirect is a user-experience hint. The signed webhook is the contract — always verify the signature and flip your fulfillment state off the event body, not the redirect.

Where to go next

You have the loop end-to-end. A few natural next steps: