Authentication
API keys, scopes, and how the buyer browser is authorized.
ShiftxPay has two distinct trust boundaries. Server-to-server calls are authenticated with a secret API key. The public hosted-checkout calls that the buyer's browser makes are authorized by a per-session secret instead. They are never interchangeable.
API keys (server-to-server)
Your backend authenticates with a secret API key, sent as a bearer token on every request:
Authorization: Bearer sk_test_...In the sandbox, keys are prefixed sk_test_. The key is a secret and must stay on
your server. A request with a missing or invalid key returns 401 unauthorized.
Scopes
Keys carry scopes that bound what they can do:
| Scope | Allows |
|---|---|
payments:read | Read payments, refunds, and checkout sessions. |
payments:write | Create checkout sessions, payments, and refunds. |
A key without the scope required for an endpoint is rejected with 403 forbidden.
The buyer browser (session secret)
The public hosted-checkout endpoints — GET /v1/checkout/{id} and
POST /v1/checkout/{id}/confirm — are not API-key authenticated. They are
gated by the checkout session's own secret, cs_secret_..., passed as ?secret=
in the query string or in the URL fragment.
This secret is minted when you create the checkout session and is scoped to that one session: it can resolve and confirm that session, and nothing else. It is the only credential that should ever cross from your server into the browser.
What the SDK uses
The @shiftx-mu/lite-checkout SDK runs in the browser and only ever uses the
session secret. It never holds, sees, or needs an API key.
Never expose a secret API key in the browser, in client-side code, in a public repository, or in a mobile app bundle. If a key leaks, roll it in the merchant console immediately. Keep API keys on the server; give the browser only the session secret.