Your app wants to show "You have 1,250 VibeCoins · Silver" on the account screen. The rule is simple: an API key never leaves your server. The app gets a short-lived token for one member instead.
The flow
- The shopper signs in to your app as usual.
- Your backend, which knows who they are, asks us for a member session token.
- The app calls
GET /v1/public/memberwith that token — directly, from the device. CORS is open on this endpoint only. - The token dies after 15 minutes; the app asks your backend for a new one when it gets
401. (A404means the member has been erased or suspended.)
Server side
Needs the read scope. Identify the member by your own customer id so you never have to store ours:
curl -X POST https://stickytier.com/v1/members/ref:CUST-1001/session-tokens \
-H "Authorization: Bearer $KEY"{ "data": { "token": "smt_eyJ0Ijoi…", "expires_at": "2026-09-22T10:15:00.000Z", "member_id": "M-6EFEAB76DFCC" } }404 means the customer is not a member yet: show a "Join" screen and enrol them with POST /v1/members (scope act) from the server.
Client side
const res = await fetch("https://stickytier.com/v1/public/member", {
headers: { Authorization: `Bearer ${token}` },
});
if (res.status === 401) return refreshTokenAndRetry();
const { data } = await res.json();
// data.balances.spendable_cents, data.balances.pending_cents,
// data.tier?.name, data.referral_code, data.currency_nameThe response carries no contact details — only balances, tier, referral code and the programme's names — so a token found in a device log exposes nothing personal. It is limited to 60 requests a minute per member; cache it for the screen's lifetime.
Redeeming from the app
Redemption is a write and needs act, so it goes through your backend: the app calls your API, your server calls POST /v1/redemption-quotes and then reserve / confirm against the checkout. See Integrate a custom store.
"My rewards" button
To drop the shopper into the full hosted rewards page already signed in, your server calls POST /v1/members/ref:CUST-1001/portal-links (scope act, live keys only) and the app opens the returned data.url. The link is single-use and lives five minutes. It opens on a “Continue signing in” button, and the shopper is signed in when they press it — opening or prefetching the link alone changes nothing.
Web instead of native?
The balance widget does all of this for a web page: your server renders a fresh member session token into the page, the script shows the balance.