Skip to Content
The AKIN Travel developer platform is in beta — APIs may change. Get started →
Server-to-server reads

Server-to-server reads

Some integrations never put a member through AKIN Travel’s sign-in. If your backend already authenticates users (your own identity stack — Supabase, Auth0, a session cookie, anything), you can read a member’s loyalty standing server-to-server, keyed by email, authorized on your partner API key alone.

No member token required. Unlike the member-scoped API, this path does not use Firebase / GIP ID tokens. There is no requestMagicLink, no signInWithCustomToken, no Authorization: Bearer header. Your x-partner-api-key is the only credential. That’s the whole point — your users never touch AKIN auth.

This is the right tool when your backend needs a member’s tier or points to render your own UI, gate a benefit, or sync state — and you already know who the user is.

On Node? The typed Server SDK wraps these reads (and enrollment) with a method per operation, structured errors, and rate-limit handling — so you don’t hand-roll the requests below.

Authentication

Send only your partner API key. No bearer token.

HeaderValue
content-typeapplication/json
x-partner-api-keyyour pk_test_* / pk_live_* key

The key identifies your partner. Every server-to-server read is scoped to members enrolled with your partner — you can never read a member who isn’t yours. The partner is derived from the key; there is no partnerId argument to pass (or spoof).

memberByEmail

Resolve a member by email and get their identity plus current loyalty standing.

curl https://staging-api.akintravel.com/graphql \ -H 'content-type: application/json' \ -H 'x-partner-api-key: pk_test_...' \ -d '{"query":"query($email:String!){ memberByEmail(email:$email){ memberId email firstName lastName tier points } }","variables":{"email":"guest@example.com"}}'
{ "data": { "memberByEmail": { "memberId": "8f3c…", "email": "guest@example.com", "firstName": "Ada", "lastName": "Lovelace", "tier": "TIER3", "points": 4200 } } }
FieldMeaning
memberIdAKIN member ID — stable, safe to persist as a foreign key on your side
emailMember’s primary email
firstName / lastNameMember identity (may be null)
tierCurrent calculated tier with your partner for the current membership year
pointsCurrent AKIN points balance with your partner for the current membership year (0 if no activity yet)

Email matching is case-insensitive, and historical emails are matched too — if a member changed their email after you first saw them, the old address still resolves.

memberByExternalId

If you key members by your own loyalty identifier rather than email, resolve them by that identifier instead. The external_id is the value you supplied when you enrolled the member server-to-server — AKIN stores it against the enrollment so you don’t have to persist the AKIN member ID everywhere.

curl https://staging-api.akintravel.com/graphql \ -H 'content-type: application/json' \ -H 'x-partner-api-key: pk_test_...' \ -d '{"query":"query($externalId:String!){ memberByExternalId(externalId:$externalId){ memberId email firstName lastName tier points } }","variables":{"externalId":"your-loyalty-key-9001"}}'
{ "data": { "memberByExternalId": { "memberId": "8f3c…", "email": "guest@example.com", "firstName": "Ada", "lastName": "Lovelace", "tier": "TIER3", "points": 4200 } } }

The response is the identical PartnerMemberRead shape as memberByEmail — same fields, same meanings (see the table above). The only difference is the lookup key.

External IDs are scoped to your partner. The same string can belong to a different member under a different partner; this lookup only ever resolves the enrollment you set, so it can never reach another partner’s members. Only active enrollments resolve.

Not found

A lookup that doesn’t resolve to one of your enrolled members returns a MEMBER_NOT_FOUND error (not an auth error):

{ "errors": [{ "message": "member not found", "extensions": { "code": "MEMBER_NOT_FOUND" } }] }

This is deliberately indistinguishable between “no such member anywhere” and “this member exists but isn’t enrolled with you” — so neither endpoint can be used to probe whether an arbitrary email or external ID belongs to the AKIN network under a different partner. Branch on extensions.code, never the message. See Error handling.

Rate limits

Server-to-server reads count against the same per-key budget as the rest of the API and report RateLimit-* headers. See Rate limits.

Last updated on