OAuth 2.1

OAuth Errors

Whatalo OAuth 2.1 error codes, their meaning, and how to resolve them.

Whatalo OAuth errors follow the standards RFC 6749 §4.1.2.1, RFC 6749 §5.2, and RFC 7009. The format and delivery channel of the error depend on which endpoint it occurs on.

Error format

The token, introspection, and revocation endpoints always return JSON:

{
  "error": "invalid_grant",
  "error_description": "Authorization code has expired or was already used"
}

Error code table

CodeHTTPEndpoint(s)CauseResolution
invalid_request400AllMissing, duplicate, or malformed parameterCheck the required parameters for the endpoint
unauthorized_client401/authorize, /tokenThe client is not authorized for the requested grant typeVerify the grant_type is in the registered grant_types
access_denied302 / HTML/authorizeThe user declined consentShow an appropriate message to the user
unsupported_response_type400/authorizeresponse_type other than codeUse response_type=code
invalid_scope400/authorize, /tokenUnknown scope or scope exceeding those grantedCheck the scope table
server_error500AllInternal Whatalo errorRetry with exponential backoff
temporarily_unavailable503AllTemporary maintenance or overloadRetry after the indicated Retry-After
invalid_client401/token, /introspect, /revokeIncorrect or missing client_secretVerify client credentials
invalid_grant400/tokenCode expired, already used, or incorrect PKCE code_verifierRestart the authorization flow
invalid_redirect_uri400/authorizeredirect_uri not registered for the clientRegister the exact URI via DCR
invalid_target400/authorize, /tokenInvalid or disallowed resource parameter (RFC 8707)Verify the resource parameter value
rate_limit_exceeded429/token, /registerRate limit exceededWait for the time indicated in Retry-After

Error routing

The channel through which you receive the error depends on whether Whatalo can validate the client_id and redirect_uri:

Redirectable errors (authorization flow)

When the client_id and redirect_uri are valid and known, Whatalo redirects the error back to your app:

https://my-app.com/oauth/callback?
  error=access_denied
  &error_description=The+user+cancelled+consent
  &state=ORIGINAL_STATE_VALUE

Errors that are redirected: access_denied, invalid_scope, unsupported_response_type, server_error, temporarily_unavailable.

Non-redirectable errors

When Whatalo cannot verify the client_id or redirect_uri (because they are invalid or unknown), it cannot redirect — doing so could be an attack vector. In that case, Whatalo displays a branded error page at /oauth/error.

Errors that show a branded page: invalid_client, invalid_redirect_uri.

Token endpoint errors

The /oauth/token, /oauth/introspect, and /oauth/revoke endpoints always return JSON — never HTML or redirects.

Exponential backoff for 429 and 503

async function callWithRetry(fn, maxAttempts = 4) {
  for (let attempt = 0; attempt < maxAttempts; attempt++) {
    try {
      return await fn();
    } catch (err) {
      if (err.status !== 429 && err.status !== 503) throw err;

      const retryAfter = err.headers?.get("Retry-After");
      const waitMs = retryAfter
        ? Number(retryAfter) * 1000
        : Math.pow(2, attempt) * 500;

      await new Promise((r) => setTimeout(r, waitMs));
    }
  }
  throw new Error("Max retry attempts exceeded");
}

Handling invalid_grant

invalid_grant on the token endpoint means the authorization flow must be restarted:

async function refreshAccessToken(refreshToken) {
  const res = await fetch("https://app.whatalo.com/oauth/token", { ... });
  const data = await res.json();

  if (data.error === "invalid_grant") {
    // Token family revoked — user must re-authorize
    clearStoredTokens();
    redirectToAuthorizationFlow();
    return;
  }

  if (!res.ok) throw new Error(data.error_description);
  return data;
}

Rate limits per OAuth endpoint

EndpointLimit
POST /oauth/token60 req/min per IP + 30 req/min per client_id
POST /oauth/register10 req/hour per IP
POST /oauth/introspectIncluded in the general API limit
POST /oauth/revokeIncluded in the general API limit

For general REST API limits, see Rate Limits.

On this page