Authentication & Access
Authentication & Access
OAuth 2.0 client credentials, credential-bound tenancy, and the auth failures you can hit.
The WestIQ Platform API uses the OAuth 2.0 client credentials grant for
server-to-server access — there is no user/password or browser-redirect flow.
Each approved partner receives a client_id and client_secret during
onboarding (delivered through your onboarding pack, never over email or in
these docs).
Treat your client_secret like a password. Store it in a secrets manager,
never in source control, and rotate it if you suspect exposure.
1. Get a token
Exchange your client credentials for a short-lived bearer access token at the staging token endpoint:
Authenticate the token request itself with HTTP Basic
(client_id:client_secret), and request the westiq/search scope in the
form body:
If your HTTP client can’t send Basic auth, client_id and client_secret
may instead go in the form body alongside grant_type and scope — both
styles are accepted.
Send the token on every request as Authorization: Bearer <token>, and cache
it until expires_in (about an hour) elapses rather than requesting one per
call.
Only access tokens are accepted. Sending an ID token — or any token whose
token_use is not access — is rejected with 401 auth.invalid_token.
To use the API Reference playground, fetch a token with
the curl above and paste the access_token value into the playground’s
auth field — every “Try it” request then sends it as the bearer. The token
endpoint itself is documented in the reference too, under
Authentication.
2. Your credential IS your airline
Every partner credential is bound to its airline on the WestIQ side: the
token’s client_id is resolved through a server-side mapping to your
airline_id. You never send an airline identifier — not as a header, not as
a body field, not as a token claim. There is nothing to configure and nothing
to get wrong.
This is a deliberate isolation property, not a convenience:
- A request can only ever act as the airline its credential is bound to. Tenancy cannot be forged, because the request carries no tenancy input.
- A credential with no airline mapping is rejected with
403 auth.unknown_client— never resolved to a default tenant. - Your searches see your airline’s catalog namespace plus the shared
globalnamespace, and nothing else.
You can observe the resolution in every search response:
parsed.filters.airlineId is the airline your credential resolved to.
3. One scope: westiq/search
Every /v1 endpoint — search, events, and all of the personalization
endpoints alike — requires the single westiq/search scope on the access
token. There are no per-endpoint scopes. Request it in the token call (as in
the example above). A token without it is rejected with
403 auth.insufficient_scope.
4. Some endpoints also need a session locator
Authentication gets you in; it does not by itself identify a passenger
session. The session-scoped personalization endpoints additionally require an
X-Session-Id header (or, for the SSE routes, a session id in the path), and
the per-member calls take seatId / memberSlot locators. Those mechanics —
which endpoints, the exact value rules, and the 400 session.unresolved you
get without them — are covered in Sessions & Member
Locators.
5. Auth failures you will see
All auth failures return the standard error envelope:
Unmatched routes also return 401, by design (the API denies by default). If a request 401s unexpectedly, check the path before debugging your token.
Rate limits
Two independent layers, tied to different identities:
- Per client credential — AI-backed
/v1endpoints enforce a per-client, per-endpoint-class request-rate limit. Over it you get429 rate.limited(standard error envelope) with aRetry-Afterheader. Back off for that many seconds. - Per IP, at the edge — the platform edge applies a limit of 2000
requests per 5-minute window. Over it, requests are blocked at the edge
with a plain
403— without the API’s error envelope — and the block clears on its own once your request rate drops.
Both layers, how to tell the responses apart, and the endpoint classes are covered in Errors & Limits.