The SDK and the backend API are not two separate flows. Every Cashier integration has two parts: your backend creates a session, and your frontend opens it.
Call POST /public/cashier/session from your backend to create a session and get back a sessionId (and hosted URLs). Full field tables, paymentTypes, fee, deposit/withdrawal-only and the response are documented on the API page — see APIs → Cashier Session.
curl -X POST "https://api.omno.com/public/cashier/session" \
-H "Authorization: Bearer <access_token>" \
-H "Content-Type: application/json" \
-d '{
"currency": "EUR",
"paymentTypes": ["CARD", "APM", "CRYPTO"],
"customer": { "externalUserId": "3183818381183" }
}'The response contains sessionId, token, checkoutUrl, depositUrl and withdrawalUrl.
The token is a short-lived, signed credential (a JWT) that authorizes opening this specific session:
- It is bound to your merchant account and expires with the session (default ~2 hours).
- Pass it from your backend to your frontend together with the
sessionId, and forward it to the SDK — see Part 2. The SDK attaches it to the cashier URL automatically. - It is required once checkout token verification is enabled for your account. Without it, opening the session is rejected. We enable verification per merchant, so upgrade your integration to forward the token before it is turned on for you — otherwise the cashier will fail to open.
- OMNO verifies the token's signature against its published keys (JWKS). You do not verify or decode it yourself — treat it as an opaque credential, pass it through, and never log it.
ℹ️ Make sure you are on a Web SDK version that supports the
tokenparameter (see Web SDK Reference).
Open the session on your frontend with @omno-payment/checkout-js.
import CashierSDK, { CashierEmitEvent } from "@omno-payment/checkout-js";
const cashier = new CashierSDK({ baseUrl: "https://checkout.omno.com" });
cashier.on(CashierEmitEvent.PAYMENT_SUCCESS, (data) => {
// UI reaction only — see the warning below
console.log("Payment success", data);
});
cashier.open({ sessionId, token }); // sessionId and token from your backendThen handle the outcome in your webhook handler (and/or Get Transaction Info) — see Webhooks.
Opening the raw hosted URL works, but you lose these SDK functions:
- Return URL handling after redirects (
returnUrlAfterRedirection) - Close handling: close-button and overlay events (
IFRAME_CLOSE_REQUESTED,IFRAME_CLOSED,OVERLAY_CLICKED) andclose() - Language selection at runtime (dynamic language via
postMessage) - Payment lifecycle events:
PAYMENT_SUCCESS,PAYMENT_FAILED,PAYMENT_PENDING,PAYMENT_CANCELED - KYC error events (
KYC_REQUIRED_FIELD_ERRORS,KYC_REQUIRED_LEVEL_ERRORS) - Deduplicated analytics event (
ANALYTICS_EVENT) - Automatic device detection, and a mobile bottom sheet with configurable height
- Opening directly into Deposit or Withdraw (
paymentAction) - Opening as a modal or inside your own container (
containerId) - Styling (modal and mobile)
- Live chat event (
LIVE_CHAT_CLICKED) reload(),destroy(),isOpen(),getSessionId(),getDeviceType()- Built-in origin validation
Full method, event and configuration detail: Web SDK Reference. If you cannot use the SDK, see Using the Hosted URL without the SDK.
⚠️ Warning: SDK events are for UI updates only. Credit or debit balances only after a webhook or Get Transaction Info confirms the result. Browser events can be lost (closed tab) or spoofed.
If a withdrawal requires manual approval, the payout enters WAITING_FOR_CONFIRMATION; confirm or reject it via the API — see APIs → Confirm / Reject Payout.