Token Introspection (RFC 7662)
Validate Whatalo Bearer tokens from your Resource Server.
The introspection endpoint (RFC 7662) lets your Resource Server verify whether a Bearer token is valid and active, and retrieve the associated claims.
Endpoint
POST https://app.whatalo.com/oauth/introspect
Content-Type: application/x-www-form-urlencodedAuthentication required
Introspection requires the Resource Server to authenticate as a confidential OAuth client. Use HTTP Basic or body params:
POST /oauth/introspect
Content-Type: application/x-www-form-urlencoded
Authorization: Basic BASE64(rs_client_id:rs_client_secret)
token=THE_BEARER_TOKEN_TO_VALIDATEOr with body params:
token=THE_BEARER_TOKEN_TO_VALIDATE
&client_id=rs_client_id
&client_secret=rs_client_secretThe Resource Server credentials (client_id and client_secret) belong to a confidential OAuth client registered for that purpose. If you are building an MCP server or other Resource Server, register it via Dynamic Client Registration with token_endpoint_auth_method: "client_secret_post" (or client_secret_basic).
Response — active token
{
"active": true,
"scope": "read:products read:orders",
"client_id": "abc123def456ghi789jkl012",
"sub": "usr_7f3a9b2c1d4e5f6a",
"exp": 1777719020,
"iat": 1777715420,
"token_type": "Bearer",
"aud": "https://api.whatalo.com",
"iss": "https://app.whatalo.com",
"whatalo_store_id": "str_8k2m4n6p"
}Response fields
| Field | Type | Description |
|---|---|---|
active | boolean | true if the token is valid, not expired, and not revoked |
scope | string | Granted scopes, space-separated |
client_id | string | client_id of the OAuth client that obtained the token |
sub | string | Identifier of the user who authorized access |
exp | number | UNIX expiry timestamp |
iat | number | UNIX issuance timestamp |
token_type | string | Always Bearer |
aud | string | Audience. Reflects the resource parameter (RFC 8707) if sent in the authorize request |
iss | string | Always https://app.whatalo.com |
whatalo_store_id | string | Public store ID the token is bound to — the same short ID used in Whatalo URLs |
The whatalo_store_id field is key for multi-tenant Resource Servers. It tells you exactly which store authorized access, so you can route operations to the correct context without relying on additional headers.
Response — inactive token
{ "active": false }Inactive tokens (expired, revoked, or simply non-existent) return only { "active": false }. No other claims are exposed for invalid tokens.
Audience binding (RFC 8707)
If the OAuth client included the resource parameter when starting the authorization flow, the aud field of the token reflects that value. Your Resource Server can validate that the token was issued for it:
const { active, aud } = await introspect(bearerToken);
if (!active) return unauthorized();
if (aud !== "https://my-resource-server.com") return unauthorized();Caching recommendations
| Case | Recommendation |
|---|---|
Token active: true | Cache for at most 60 seconds |
Token active: false | Do not cache — the result may change if the token is renewed |
If you cache active: true responses for more than 60 seconds, a revoked token will continue to be accepted by your Resource Server for that period. See Revocation to understand cascade revocation behavior.
Complete Node.js example
async function introspectToken(bearerToken, rsClientId, rsClientSecret) {
const credentials = Buffer.from(`${rsClientId}:${rsClientSecret}`)
.toString("base64");
const res = await fetch("https://app.whatalo.com/oauth/introspect", {
method: "POST",
headers: {
"Content-Type": "application/x-www-form-urlencoded",
"Authorization": `Basic ${credentials}`,
},
body: new URLSearchParams({ token: bearerToken }),
});
const data = await res.json();
if (!data.active) {
throw new Error("Token is not active");
}
// data.whatalo_store_id tells you which store was authorized
return data;
}Next step
To revoke an active token, use the revocation endpoint.