The two credentials
| Credential | Lives | Used for |
|---|---|---|
| Org-API-Key | Your backend only (a secret) | POST /v1/auth/exchange and all server-mode calls |
| Member token | The app / SDK | Every member-mode data call (offers, redemptions, eligibility, wallet, concierge) |
How the flow works
Your backend holds the Org-API-Key and exchanges it for a short-lived member token scoped to one of your users. The app uses that member token as a Bearer credential for data calls, and asks your backend for a fresh one when it nears expiry.Step 1: Exchange (server-side)
Your backend callsexchangeToken with the Org-API-Key. The request identifies
the member by your own stable id, and may set profile fields used elsewhere
(display name, email, and the member’s tier).
Your stable identifier for the member. Scopes the minted token to this user.
Optional display name stored on the member profile.
Optional email stored on the member profile.
Optional tier for the member; flows into eligibility.
TokenGrant:
The short-lived member token. Hand this to the app.
ISO-8601 expiry. Pass it to the SDK as
tokenExpiresAt(Ms) so it can refresh
proactively.Step 2: Use and refresh (in the app)
Initialize the SDK with the member token, its expiry, and arefreshToken hook
that calls back to your backend (which holds the Org-API-Key) to mint a new
token. The hook returns the new token and expiry.
The refresh contract
The SDKs implement refresh identically:Proactive
Before a request, if the token expires within
refreshSkew (default 30s),
the SDK calls refreshToken first and uses the new token.Reactive (once)
If a request still returns
401, the SDK calls refreshToken once and
retries the request a single time with the new token.Provide
tokenExpiresAt(Ms) whenever you can. Without it the SDK cannot refresh
proactively and falls back to reactive (401-triggered) refresh only, which adds
one round-trip on the first expired call.Security checklist
Org-API-Key is only ever read on your backend.
The app receives only member tokens, with their expiry.
refreshToken calls your backend, not the Expys exchange endpoint directly.Member tokens are short-lived; do not persist them beyond their expiry.