- aren’t PCI-DSS certified and want to keep it that way,
- want the fastest integration with the least code, or
- are happy to send customers to a lite-hosted (but brand-able) page to pay.
How it works
- Create a session. Your server calls
POST /v1/checkout/sessionsand gets back apayment_link. - Redirect the customer. You send them to the
payment_link. They pay on lite’s hosted page. - Customer returns. lite sends cardholders back to your
successorfailureURL, so you can show a result right away. - Confirm with a webhook. lite sends a
payment.capturedevent to your server. This is the source of truth you fulfill from.
Completed, Expired, or Cancelled. The return URL tells you the session resolved; the webhook tells you the money actually moved. Treat the webhook as your source of truth — see Step 4.
Before you begin
This guide assumes your one-time setup is done. You can re-check any of it from the dashboard. You’ll need:- A lite account in good standing.
- Test and live API keys (
sk_test_…/sk_live_…). - At least one channel configured, with its
channel_id(unless you intend to use the default channel option). A channel sets your enabled payment methods, branding, and default redirect URLs. - A webhook endpoint registered, you’ll need it for fulfillment in Step 4.
Step 1: Create a session
Create the session from your backend, so a customer can’t tamper with the amount or currency.Required headers
| Header | Required | Purpose |
|---|---|---|
x-api-key | Yes | Authenticates the request. Use your test key in test mode. Or send Authorization: Bearer <JWT> instead. |
x-idempotency-key | Recommended | A UUID per logical session. Retries with the same key return the original session instead of creating a duplicate. |
x-correlation-id | Optional | A UUID per request, echoed in logs. Quote it in support tickets. |
Key request fields
| Field | Required | Notes |
|---|---|---|
customer | Yes | Customer details. The individual fields (email, name, phone) are each optional. |
amount | Yes | In minor units (4999 = 49.99 SAR). The exponent varies by currency: SAR has 2 decimals, KWD has 3, JPY has 0. |
currency | Yes | ISO 4217 code. |
redirect_urls | Yes | The success and failure URIs the customer returns to. |
order | Yes | Order details as price, quantity, shipping and vat. order.reference (your order ID) is required and comes back as order_id. |
channel_id | No | Applies a channel’s branding, enabled payment methods, and redirect URLs. |
expiry | No | Session lifetime in seconds (60 to 86400). Defaults to 3600. |
three_ds_required | No | Force 3D Secure on. Otherwise it’s applied automatically per scheme and SAMA rules. |
Response
Pending. Hold on to the id (a UUID), you’ll use it to match the webhook, and to look the session up later if you need to. (client_secret is only for the Drop-in SDK; you can ignore it for the hosted redirect.)
By default, 3D Secure is applied automatically based on the card scheme and SAMA rules; for mada and most KSA cards it’s mandatory. Set three_ds_required: true if you want to force it on every payment.
Step 2: Redirect to the hosted page
Send the customer topayment_link with an HTTP 303:
303, not 302, so the browser switches to a GET for the checkout page even though your endpoint received a POST. From here the customer pays entirely on Lite’s domain — you never see their card details.
Step 3: Handle the return
After checkout, lite sends the customer back to one of yourredirect_urls:
success: the payment went through.failure: the payment failed, or the customer cancelled.
[!WARNING] The return URL is not authoritative. A customer can pay and then close the tab or drop offline before your page loads, so the redirect might never reach you. Always fulfill from the webhook in Step 4.If you want to show a definitive state on this page, check the session server-side first; but still fulfill from the webhook. Retrieve the full session, or call the lightweight validity endpoint:
Step 4: Confirm with a webhook
Webhooks are how you reliably learn the outcome of every payment. For the Hosted Page flow, subscribe to these events:| Event | When it fires |
|---|---|
payment.captured | Payment succeeded and funds were captured. Fulfill here. |
payment.authorization_failed | The payment was declined. |
payment.refunded | A refund completed. |
Test and go live
Test mode accepts lite’s published test cards. At a minimum, confirm each of these outcomes:| Scenario | Expected result |
|---|---|
| Successful mada payment | Session Completed, payment.captured webhook fires |
| Successful Visa / Mastercard payment | Session Completed, payment.captured webhook fires |
| Declined card | Session not completed, payment.authorization_failed webhook fires |
- Your account has KYB verification complete and payment acceptance activated.
- Your webhook endpoint verifies the signature and returns
200. - A session creates successfully and returns a
payment_link. - The redirect reaches lite’s hosted page and back to your return URL.
- Fulfillment fires from
payment.captured, not from the return URL. - A declined card shows up correctly on your
failurepage.