> ## Documentation Index
> Fetch the complete documentation index at: https://docs.therius.io/llms.txt
> Use this file to discover all available pages before exploring further.

# SDK Session Bootstrap: Exchange Key for Client Token

> Create a short-lived JWT client token by calling POST /sdk/session from your server. Pass the token to the browser to initialize the Therius JS SDK.

Before using the JS SDK in the browser, your server must exchange your private API key for a short-lived JWT client token. This token is what the browser receives — your raw private key never leaves your server. Each token is scoped to a single checkout session and expires after 30 minutes.

## Create a session on your server

Call `POST /sdk/session` from your backend with your private API key in the `Authorization` header.

```bash theme={"dark"}
curl -X POST https://api.therius.io/v1/sdk/session \
  -H "Authorization: Bearer prv_production_your_key_here" \
  -H "Content-Type: application/json" \
  -d '{ "customerId": "customer-42", "country": "US" }'
```

The response includes the `clientToken` and its lifetime in seconds:

```json theme={"dark"}
{
  "clientToken": "eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9...",
  "expiresIn": 1800
}
```

## Pass the token to the browser

Deliver `clientToken` to your front-end. Common approaches include:

* **Inline JSON** — embed it in your HTML template when the page is server-rendered.
* **API response** — return it from a lightweight `/api/checkout-session` endpoint that your SPA calls on page load.

The browser does not need to decode or inspect the token — it passes it directly to `new TheriusSDK({ clientToken })`.

## Optional request parameters

| Parameter    | Type   | Description                                                                                                                                                               |
| ------------ | ------ | ------------------------------------------------------------------------------------------------------------------------------------------------------------------------- |
| `country`    | string | Two-letter ISO country code. Required for a full checkout session with a `sessionId`.                                                                                     |
| `customerId` | string | Associates the session with a returning shopper. Enables saved-card features.                                                                                             |
| `amount`     | object | Pre-fills the session amount — useful for wallet payment sheets.                                                                                                          |
| `currency`   | string | Three-letter ISO currency code paired with `amount`.                                                                                                                      |
| `orderCode`  | string | Your internal order reference, attached to the session for reconciliation.                                                                                                |
| `cardOnFile` | object | Declares this session's checkout starts a stored-credential mandate — see [Merchant-managed subscriptions](#merchant-managed-subscriptions) below. Requires `customerId`. |

## Merchant-managed subscriptions

If you run your own recurring billing outside the Therius Subscriptions API — for example, a one-time checkout that should establish a card-on-file mandate you bill against yourself later — pass `cardOnFile` when creating the session, instead of configuring anything in the Checkout Builder:

```bash theme={"dark"}
curl -X POST https://api.therius.io/v1/sdk/session \
  -H "Authorization: Bearer prv_production_your_key_here" \
  -H "Content-Type: application/json" \
  -d '{
        "customerId": "customer-42",
        "country": "US",
        "cardOnFile": { "type": "recurring" }
      }'
```

When `cardOnFile` is set:

* The Checkout Widget skips the optional "save my card" checkbox entirely and shows a fixed disclosure ("Your card will be saved for future charges") instead — there is nothing for the shopper to opt into, since you already declared the intent server-side.
* The resulting charge is tokenized and tagged with the given stored-credential fields (`usage`/`initiatedBy`/`type`, see [Stored Credentials](/guides/stored-credentials)) unconditionally, **regardless of anything the browser sends** — the signed session token is the source of truth, not the request body.
* `customerId` is required — there must be a shopper to attribute the saved card to.

If you omit `cardOnFile`, the session behaves exactly as before: the checkout follows whatever the Checkout Builder's "save my card" (vault-consent) setting says, and any resulting saved card is a plain card-on-file, not a recurring mandate.

<Note>
  There used to be a separate "Starts a merchant-managed subscription" checkbox in the Checkout Builder. It has been removed — this is now a per-transaction, server-controlled setting instead of a static per-checkout-config flag, so a shopper can never see (or suppress) the wrong consent state for a given session.
</Note>

## Initialize the SDK in the browser

Once the browser has the token, initialize the SDK:

```javascript theme={"dark"}
import { TheriusSDK } from '@therius/sdk'

const sdk = new TheriusSDK({ clientToken })
```

The SDK validates the token immediately. If the token is missing or malformed, `TheriusSDK` throws synchronously.

## Token lifetime

Client tokens expire after **30 minutes**. Create a fresh token for each new checkout session — do not cache and reuse tokens across sessions or page loads.

<Warning>
  Never call `POST /sdk/session` from the browser. It requires your private API key (`prv_production_...`). Exposing that key client-side would allow anyone to create sessions and make charges against your account. Always make this call from your backend only.
</Warning>

## Reference

See the [POST /sdk/session API reference](/api-reference/sdk-session) for the full field reference, including error codes and validation rules.
