ShiftxPay
Get started

Quickstart

From an API key to your first payment, end to end.

This walkthrough takes you from a fresh API key to a completed payment. You will create a checkout session on your server, mount the checkout in the browser, and read the result. The gateway base URL is https://api.lite.shiftxpay.com.

Step 1 — Get an API key

Create an API key in the merchant console. In the sandbox, keys are prefixed sk_test_. The key is a secret: it lives on your server and is sent as a bearer token. Never ship it to the browser.

Authorization: Bearer sk_test_...

Sandbox keys carry the payments:read and payments:write scopes, which is everything you need for this guide.

Step 2 — Create a checkout session (server-side)

Call POST /v1/checkout-sessions from your backend. Amounts are integer minor units (MUR has 2 decimals, so 5000 is Rs 50.00), and the currency is an uppercase ISO 4217 code. Pass an Idempotency-Key so the request is safe to retry.

curl https://api.lite.shiftxpay.com/v1/checkout-sessions \
  -H "Authorization: Bearer sk_test_..." \
  -H "Content-Type: application/json" \
  -H "Idempotency-Key: 6f9619ff-8b86-d011-b42d-00cf4fc964ff" \
  -d '{
    "amount": 5000,
    "currency": "MUR",
    "description": "Order #1234",
    "customer_email": "buyer@example.com"
  }'

A 201 Created returns the session id, the session secret, the render hints, and a hosted checkout URL:

{
  "id": "cs_3Nk2p8c9aBcDeFgHiJkLmNoP",
  "session_secret": "cs_secret_7yQ2r4t6u8w0x2z4a6c8e0g2",
  "amount": 5000,
  "currency": "MUR",
  "status": "open",
  "render": {
    "connector": "peach",
    "surface": "peach-embedded",
    "checkout_id": "8ac7a4a0...",
    "entity_id": "8ac7a4..."
  },
  "checkout_url": "https://api.lite.shiftxpay.com/v1/checkout/cs_3Nk2p8c9aBcDeFgHiJkLmNoP"
}

The session_secret (cs_secret_...) is the only credential that crosses to the browser. The render block tells the SDK which PSP surface to mount.

Step 3 — Mount the checkout (browser)

Install the SDK:

npm install @shiftx-mu/lite-checkout

Hand the session id and secret to the page, then mount the checkout. The SDK resolves the session, draws the Peach embedded widget, and returns a controller you drive from your own UI.

import { mountCheckout } from "@shiftx-mu/lite-checkout";

const controller = await mountCheckout({
  baseUrl: "https://api.lite.shiftxpay.com",
  sessionId: "cs_3Nk2p8c9aBcDeFgHiJkLmNoP",
  sessionSecret: "cs_secret_7yQ2r4t6u8w0x2z4a6c8e0g2",
  container: "#checkout",
  onSuccess: ({ paymentId, status }) => {
    console.log("payment", paymentId, status);
  },
  onError: (err) => {
    console.error(err);
  },
});

document
  .querySelector("#pay")
  ?.addEventListener("click", () => controller.submit());
<div id="checkout"></div>
<button id="pay">Pay</button>

The SDK only ever uses the session secret — never an API key. The card is entered inside the PSP surface and goes straight to the PSP; it never passes through your page or the gateway.

Hosted option. If you would rather not mount the SDK yourself, redirect the buyer to the checkout_url from the session response. ShiftxPay hosts the whole checkout page, and the buyer comes back to your configured return URL.

Step 4 — Confirm and read the result

When the buyer pays, the SDK calls confirm and fires onSuccess with the payment id and status:

onSuccess: ({ paymentId, status }) => {
  // status: "completed"
  // paymentId: "pay_..."
};

Confirm is idempotent: if the buyer clicks twice, or the SDK retries, you get the same payment back rather than a duplicate charge.

For the authoritative outcome, rely on the webhook. The browser result is perfect for updating the buyer's screen, but a buyer can close the tab before confirm runs. The signed payment.succeeded outbound webhook is the source of truth for async outcomes — fulfil orders from there, not from onSuccess alone.

Next steps

On this page