A sign-in issues a session: a short-lived access token that your frontend sends with every request, and a refresh token that renews it. Your backend never calls ShipRev to check a request; it verifies the access token locally with the Server SDK and reads the caller's account, organization and application from it.
What a sign-in returns
Whenever the region issues a session, on sign-in, on sign-up, after a social sign-in or once an end user confirms their email address, it answers with the same fields:
| Field | What it is |
|---|---|
access_token | A signed token for one account, in one buyer organization, for one application. Send it as Authorization: Bearer <access_token> |
expires_in | Seconds until the access token expires: 900, that is 15 minutes |
refresh_token | Renews the session. Send it only to POST /public/v1/auth/refresh and POST /public/v1/auth/logout, never to your own API routes |
account | The end user's profile, their memberships and the current organization |
The hosted pages keep the session on your brand domain. On your own pages, SignInForm and SignUpForm hand it to you, and you store it; see Hosted pages, components or your own.
How long a session lasts
| Event | Effect |
|---|---|
| Access token expires after 15 minutes | Renew it with POST /public/v1/auth/refresh and the refresh token. Each renewal also returns a new refresh token, and the old one stops working |
| No renewal for 30 days | The session ends; the end user signs in again |
The end user signs out (POST /public/v1/auth/logout with the refresh token) | That session can no longer be renewed. Their other sessions continue |
| The end user changes their password | Every other session of theirs ends; the one they changed it from continues |
| The end user resets their password | Every session of theirs ends |
Ending a session stops renewals, not access tokens already issued. Your backend verifies access tokens on its own, so one that was issued before the session ended keeps verifying until it expires, at most 15 minutes later. Keep that window in mind for anything you would revoke at once.
How your backend knows who is calling
Verify the access token with verifyToken() and use what it returns:
const claims = await shiprev.verifyToken(token);
// claims.account_id the end user's account
// claims.organization_id the buyer organization the session is in
// claims.project_id your applicationRule on entitlements and report usage with claims.organization_id, and tie your own records to account_id and organization_id. Never take an organization from a header, a parameter or the request body, because the caller controls those. Protect routes: token, then capability shows the full route in NestJS and without it, and the Server SDK reference lists every claim.
Verification needs no configuration and keeps working while the region is unreachable. It checks the signature against your region's keys, the expiry, and that the token is an end-user session token of your application. It needs the client to have reached the region once after it started.
Why a token is refused
Treat every failure of verifyToken() as a 401. A malformed, badly signed or expired token throws a plain Error. A token that is correctly signed and unexpired but not a session token of your application throws TokenRejectedError, and its reason says why:
reason | What it usually means |
|---|---|
not_ready | Your service has just started and the client has not reached the region yet; every token is refused until it has |
audience_mismatch | The token is not an end-user session token, for example an operator console token |
issuer_mismatch | The token was issued by another region or another sign-in gate |
project_mismatch | The token was issued for another of your applications |
not_a_session_token | The token is a one-time token, such as one from a password reset link |
missing_expiry | The token carries no expiry |
An expired access token is the common case: the frontend renews it and retries. With the React components, onUnauthorized is where that happens; see getAccessToken and onUnauthorized.
Switching organizations
A session is in one buyer organization at a time. An end user who belongs to several switches with POST /public/v1/auth/switch, naming the organization; the answer is a new access token for it, without a refresh token. An organization the end user does not belong to is refused.
The switch is remembered for the next sign-in, which starts in the organization the end user used last. A renewal is different: POST /public/v1/auth/refresh returns a token for the organization the session was opened in, as long as the end user still belongs to it. If your application lets end users switch, switch again after each renewal. Buyer organizations covers the rest.