Client Session SDK

The UniPayment Client Session SDK creates a short-lived browser session that links an Invoice to the website where the payment started. Send the returned client_session value with the UniPayment Create Invoice request.

This guide covers both direct UniPayment integrations and integrations where a merchant creates the Invoice through a Payment Service Provider (PSP).

How it works

  1. The merchant page loads the App-specific UniPayment Client Session SDK.
  2. The buyer completes the browser verification when required.
  3. The SDK returns a client_session token.
  4. The merchant sends the token to the server that creates the Invoice.
  5. That server passes the token unchanged in the UniPayment Create Invoice request.

The token is:

  • generated in the buyer's browser;
  • bound to one Payment App and its verified browser origin;
  • valid for 15 minutes;
  • valid for one Invoice only.

Prerequisites

Before integrating the SDK:

  • obtain the UniPayment Payment App ID used to create the Invoice;
  • configure and verify the Payment App's declared domain;
  • serve the merchant page over HTTPS;
  • ensure that the same app_id is used to load the SDK and create the Invoice.

The client_session requirement depends on the Payment App's Client Session Mode:

Disabled

client_session is not required.

Observe

client_session is required, and source information is collected for monitoring.

Check

client_session is required, and the browser origin must match the Payment App's verified declared domain.

Load the SDK

Load the App-specific SDK directly from the UniPayment Gateway. The Payment App ID is public and may be included in browser code.

<div id="unipayment-turnstile-container" aria-label="Browser verification"></div>

<script
  src="https://sandbox-app.unipayment.io/api/v1/client-session/sdk.js?appId=YOUR_PAYMENT_APP_ID">
</script>

The example above uses the Sandbox Gateway. Use the production Gateway URL supplied for your production environment when going live.

The verification container is optional. If it is omitted, the SDK creates a temporary verification container automatically.

Create a client session

Call get_session() immediately before submitting the Create Invoice request:

<button id="pay-button" type="button">Pay now</button>

<script>
  document.getElementById("pay-button").addEventListener("click", async function () {
    const button = this;
    button.disabled = true;

    try {
      const clientSession = await UniPaymentClientSession.get_session();

      const response = await fetch("/api/create-invoice", {
        method: "POST",
        headers: {
          "Content-Type": "application/json"
        },
        body: JSON.stringify({
          order_id: "ORDER_123456",
          price_amount: 99.95,
          price_currency: "USD",
          client_session: clientSession
        })
      });

      const result = await response.json();
      if (!response.ok) {
        throw new Error(result.message || "Unable to create the invoice.");
      }

      window.location.assign(result.invoice_url);
    } catch (error) {
      console.error("Invoice creation failed", error);
    } finally {
      button.disabled = false;
    }
  });
</script>

get_seccisson() remains available as a compatibility alias, but new integrations should use get_session().

Do not expose a UniPayment API access token or other server credentials in browser code. The browser creates only the client session; your server or PSP must call the authenticated Create Invoice API.

Direct UniPayment API integration

For a direct integration, the merchant browser sends client_session to the merchant backend. The merchant backend then includes it in the UniPayment Create Invoice request.

{
  "app_id": "YOUR_PAYMENT_APP_ID",
  "price_amount": 99.95,
  "price_currency": "USD",
  "order_id": "ORDER_123456",
  "title": "Order ORDER_123456",
  "client_session": "cs_..."
}

Create Invoice endpoint:

POST https://sandbox-api.unipayment.io/v1.0/invoices

See the Create Invoice API reference for authentication and the complete request and response schema:

https://unipayment.readme.io/reference/create_invoice

Integration through a PSP

A merchant may submit its payment request to a PSP instead of calling UniPayment directly. In this integration model, the PSP must add client_session to its own create-payment or create-invoice API and pass the value unchanged to UniPayment.

Request flow

  1. The merchant browser generates client_session with the UniPayment SDK.
  2. The merchant sends client_session to the merchant backend or PSP API.
  3. The merchant backend or PSP forwards client_session unchanged to the UniPayment Create Invoice API.
  4. UniPayment validates and consumes the session, then creates the Invoice.

Merchant request to the PSP

The PSP adds an optional or conditionally required client_session string field to its existing API:

{
  "merchant_order_id": "ORDER_123456",
  "amount": 99.95,
  "currency": "USD",
  "client_session": "cs_..."
}

The field should be required when the corresponding UniPayment Payment App uses Observe or Check mode.

PSP request to UniPayment

The PSP copies the same value into the UniPayment request:

{
  "app_id": "YOUR_PAYMENT_APP_ID",
  "price_amount": 99.95,
  "price_currency": "USD",
  "order_id": "ORDER_123456",
  "client_session": "cs_..."
}

The PSP must not:

  • generate the token from a backend server or scheduled job;
  • replace, decode, transform, or prefix the token;
  • reuse one token for multiple Invoice requests;
  • cache a token for later orders;
  • log the complete token;
  • load the SDK with a different Payment App ID from the app_id sent to UniPayment.

Complete test page

The following standalone page demonstrates the SDK flow in Sandbox. Host it on the Payment App's configured and verified HTTPS domain.

<!DOCTYPE html>
<html lang="en">
<head>
  <meta charset="UTF-8">
  <meta name="viewport" content="width=device-width, initial-scale=1">
  <title>UniPayment Client Session Test</title>
</head>
<body>
  <main>
    <h1>Client Session Test</h1>
    <label for="app-id">Payment App ID</label>
    <input id="app-id" autocomplete="off" placeholder="Enter app_id">
    <div id="unipayment-turnstile-container" aria-label="Browser verification"></div>
    <button id="get-session" type="button">Get Session</button>
    <pre id="result">Session will appear here.</pre>
  </main>

  <script>
    const appIdInput = document.getElementById("app-id");
    const button = document.getElementById("get-session");
    const result = document.getElementById("result");
    let loadedAppId = null;

    function loadSdk(appId) {
      if (window.UniPaymentClientSession) {
        if (loadedAppId !== appId) {
          throw new Error("Reload the page before changing app_id.");
        }
        return Promise.resolve();
      }

      return new Promise(function (resolve, reject) {
        const script = document.createElement("script");
        script.src = "https://sandbox-app.unipayment.io/api/v1/client-session/sdk.js?appId="
          + encodeURIComponent(appId);
        script.onload = function () {
          loadedAppId = appId;
          resolve();
        };
        script.onerror = function () {
          reject(new Error("Unable to load the Client Session SDK."));
        };
        document.head.appendChild(script);
      });
    }

    button.addEventListener("click", async function () {
      button.disabled = true;
      result.textContent = "Creating session...";

      try {
        const appId = appIdInput.value.trim();
        if (!appId) {
          throw new Error("Payment App ID is required.");
        }

        await loadSdk(appId);
        const clientSession = await UniPaymentClientSession.get_session();
        result.textContent = JSON.stringify({
          client_session: clientSession
        }, null, 2);
      } catch (error) {
        result.textContent = JSON.stringify({
          code: error.code || "CLIENT_SESSION_FAILED",
          message: error.message || String(error)
        }, null, 2);
      } finally {
        button.disabled = false;
      }
    });
  </script>
</body>
</html>

The test page displays the token for integration testing only. Production applications should immediately send it to their backend or PSP instead of displaying it.

Token lifecycle and retry rules

  • Generate a new client session immediately before each Create Invoice request.
  • Submit it within 15 minutes.
  • Use it for exactly one Invoice.
  • Do not cache or intentionally reuse it after any successful Create Invoice response.
  • If the Create Invoice outcome is uncertain because of a network timeout, first reconcile the order through your normal Invoice query or idempotency process. Do not blindly create multiple Invoices with new sessions.

Error handling

The SDK session endpoint or Create Invoice API may return these client-session errors.

CLIENT_SESSION_REQUIRED

Returned by: Create Invoice API

The Payment App requires client_session, but the field is missing. Generate a session in the browser and include it in the request.

CLIENT_SESSION_INVALID

Returned by: Create Invoice API

The token is malformed, expired, already consumed, or belongs to another App. Generate a new session and verify that both requests use the same Payment App ID.

CLIENT_SESSION_SOURCE_REJECTED

Returned by: Session creation endpoint

The browser origin is not permitted for the Payment App. Verify the declared domain and subdomain settings.

CLIENT_SESSION_TURNSTILE_NOT_CONFIGURED

Returned by: SDK loading or session creation endpoint

Browser verification is not configured for the Payment App. Contact the Payment App administrator or UniPayment support.

CLIENT_SESSION_TURNSTILE_INVALID

Returned by: Session creation endpoint

Browser verification failed or expired. Let the buyer retry from a supported browser and network.

Troubleshooting

The SDK does not load

  • Confirm that the Payment App ID is correct and enabled.
  • Confirm that browser verification is configured for the App.
  • Check Content Security Policy rules and browser extensions that may block the UniPayment, Cloudflare Turnstile, or Fingerprint scripts.

Session creation is rejected by source validation

  • Serve the page over HTTPS.
  • Verify that the current page hostname matches the App's verified declared domain.
  • If subdomains are used, enable subdomain matching in the Payment App configuration.
  • Do not attempt to provide or override the HTTP Origin header manually.

The Create Invoice API reports an invalid session

  • Confirm that the SDK and Create Invoice request use the same Payment App ID.
  • Generate the token shortly before the API call.
  • Ensure that no retry, queue, or PSP middleware reused or modified the token.
  • Generate a separate token for every Invoice.

Multiple Payment Apps are used on one page

The SDK is App-specific and exposes one global UniPaymentClientSession object. Reload the page before switching to a different Payment App ID.