Returns the subset of the caller's authenticated session that
is safe to surface to the client. A 200 confirms the JWT is
still valid and the custom authorizer has accepted it; any
other status (typically 401 from the authorizer) means the
client should re-authenticate.
This endpoint runs no domain logic — it only reflects what the
authorizer already decided. Use it as a cheap "am I still
logged in?" probe on app resume or before a sensitive UI
transition.
| Time | Status | User Agent | |
|---|---|---|---|
Retrieving recent requests… | |||
Why this endpoint exists
Your storefront needs to answer "is this customer still signed in?" without side effects and without guessing. Access tokens expire, sessions get revoked, and a client that assumes it is authenticated will discover otherwise at the worst moment — usually mid-checkout, where the failure is silent rather than loud.
This endpoint runs no domain logic. It reflects what the authorizer already decided and returns the safe subset of the session. A 200 means the token is valid; anything else — almost always 401 — means re-authenticate.
That makes it the right thing to call on app resume, on tab focus after a while, and before a sensitive UI transition. It is deliberately cheap.
Request
curl https://api.acc.funtrips.io/v2/me \
-H "Authorization: Bearer $END_USER_TOKEN"No headers beyond the credential. No x-campaign-id — the campaign comes from the token's campaign claim, which is authoritative and cannot be overridden by a header.
Response
{
"data": {
"session_id": "9f8e7d6c-5b4a-4938-8271-6a5b4c3d2e1f",
"external_user_id": "customer-4815162342",
"campaign_id": "3c1e5a90-7b2d-4f61-9a83-1d4e7f2b8c05",
"locale": "nl-NL"
},
"meta": { "correlation_id": "…" }
}| Field | Meaning |
|---|---|
session_id | The platform's session/user id — the JWT sub claim |
external_user_id | Your identifier, exactly as you supplied it at POST /session |
campaign_id | Campaign scope resolved from the token |
locale | Negotiated language for this request, from Accept-Language and the campaign's supported locales |
external_user_id is the useful one: it lets your front-end assert that the platform session belongs to the customer your app thinks is signed in. Compare it against your own session, and you will catch a whole class of stale-token bug — the customer who logged out and back in as someone else while an old storefront tab stayed open.
Why this matters before checkout
The checkout routes accept an optional token: a missing, malformed or expired credential is treated as guest, not as an error. That is what makes guest checkout work, and it has a sharp edge — a silently expired session sells at full price, with no loyalty discount, and returns 200.
So if applying loyalty or membership discounts matters, probe with GET /me before building the basket. A 401 here is your chance to refresh the session while the customer is still browsing, rather than discovering the problem when they query why their discount vanished.
async function ensureSession() {
const res = await fetch(`${BASE}/me`, { credentials: 'include' });
if (res.ok) return (await res.json()).data;
const refreshed = await fetch(`${BASE}/session/token/refresh`, {
method: 'POST', credentials: 'include',
});
if (refreshed.ok) return (await (await fetch(`${BASE}/me`, { credentials: 'include' })).json()).data;
return null; // genuinely signed out — restart the hand-off
}Errors
| Status | type | Meaning |
|---|---|---|
401 | — | Token missing, expired, malformed or revoked. Try refresh; if that fails, restart the hand-off |
500 | — | Unexpected fault. Retryable |
A 401 here carries no type slug — the credential was rejected before the request was admitted. Treat it purely as "re-authenticate".
