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.
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) and the app opens the returned URL. The link is single-use and lives five minutes.
Web instead of native?
The balance widget does all of this for a web page: include the script, give it a token endpoint on your server, done.