OAuth Integration

Error Codes

Complete reference for OAuth error codes and how to handle them in your application.

This reference covers all error codes you may encounter when using the Euler Stream OAuth system, organized by where they occur in the flow.

Authorization Errors

These errors are returned as query parameters when redirecting back to your redirect_uri:

https://yourapp.com/callback?error=ERROR_CODE&error_description=DESCRIPTION&state=YOUR_STATE

invalid_request

Cause: Missing or malformed required parameters.

error=invalid_request
error_description=Missing required parameter: client_id

Resolution: Ensure all required parameters are present:

  • client_id
  • redirect_uri
  • response_type (must be "code")
  • scope (at least one valid scope)

invalid_client

Cause: The client_id doesn't exist or has been deleted.

error=invalid_client
error_description=Client not found

Resolution: Verify your client ID in the OAuth Dashboard.


invalid_scope

Cause: One or more requested scopes are invalid, or the scope is not in the client's supported_scopes.

error=invalid_scope
error_description=Invalid scopes: webcast:invalid_scope

Resolution: Check the Available Scopes and ensure you're using valid scope identifiers.


unsupported_response_type

Cause: The response_type parameter is not "code".

error=unsupported_response_type
error_description=Only response_type "code" is supported

Resolution: Set response_type=code in your authorization URL.


access_denied

Cause: The user cancelled the authorization or denied permissions.

error=access_denied
error_description=The user denied the authorization request

Resolution: This is a user action, not an error. Handle gracefully:

app.get('/auth/callback', (req, res) => {
  if (req.query.error === 'access_denied') {
    return res.redirect('/connect?message=authorization_cancelled');
  }
  // ... continue with normal flow
});

server_error

Cause: An unexpected server error occurred during authorization.

Resolution: Retry the authorization. If persistent, contact support.


Token Endpoint Errors

These errors are returned as JSON from the /tiktok/oauth/token endpoint. All responses are wrapped in a standard envelope:

{
  "code": 400,
  "message": "Human-readable summary",
  "error": {
    "error": "ERROR_CODE",
    "error_description": "Detailed description"
  }
}

invalid_request

Cause: Missing required parameters in the token request.

{
  "code": 400,
  "message": "Missing client credentials",
  "error": {
    "error": "invalid_request",
    "error_description": "client_id and client_secret are required"
  }
}

Resolution: Ensure all required parameters are included.

For authorization code exchange:

  • grant_type = "authorization_code"
  • code
  • redirect_uri
  • client_id
  • client_secret

For token refresh:

  • grant_type = "refresh_token"
  • refresh_token
  • client_id
  • client_secret

invalid_client

Cause: Invalid client_id or client_secret.

{
  "code": 400,
  "message": "Invalid client credentials",
  "error": {
    "error": "invalid_client",
    "error_description": "Invalid client credentials"
  }
}

Resolution: Verify your client ID and secret. If you regenerated your secret, update your application.


invalid_grant

Cause: The authorization code is invalid, expired, or already used. Also returned when a refresh token is invalid or expired.

{
  "code": 400,
  "message": "Invalid or expired authorization code",
  "error": {
    "error": "invalid_grant",
    "error_description": "Invalid or expired authorization code"
  }
}

Resolution:

  • Authorization codes expire after 10 minutes and can only be used once
  • Refresh tokens expire after 30 days
  • Restart the OAuth flow if this occurs

unsupported_grant_type

Cause: The grant_type is not "authorization_code" or "refresh_token".

{
  "code": 400,
  "message": "Unsupported grant type",
  "error": {
    "error": "unsupported_grant_type",
    "error_description": "grant_type must be authorization_code or refresh_token"
  }
}

Resolution: Use grant_type=authorization_code or grant_type=refresh_token.


API Request Errors

These errors occur when making API requests with an access token via the x-oauth-token header.

401 Unauthorized

Possible Causes:

  1. Expired access token — the token's 1-hour lifetime has elapsed
  2. Invalid access token — the token doesn't exist or has been revoked
  3. Underlying TikTok session expired — the user's TikTok session is no longer valid

Resolution:

async function makeRequest(endpoint: string, tokens: Tokens) {
  const response = await fetch(`https://tiktok.eulerstream.com${endpoint}`, {
    headers: {
      'x-oauth-token': tokens.accessToken,
    },
  });

  if (response.status === 401) {
    // Attempt to refresh the token
    try {
      const newTokens = await refreshAccessToken(tokens.refreshToken);
      // Store the new tokens
      await saveTokens(newTokens);
      // Retry the original request
      return makeRequest(endpoint, newTokens);
    } catch {
      // Refresh failed — need full re-authorization
      throw new ReauthorizationRequiredError();
    }
  }

  return response.json();
}

403 Forbidden — Insufficient Scope

{
  "error": "insufficient_scope",
  "error_description": "Token does not have required scope: webcast:rankings"
}

Resolution: The access token doesn't have the required scope for this endpoint. User must re-authorize with additional scopes.


422 Conflicting Authentication

{
  "error": "conflicting_auth",
  "error_description": "Cannot use both x-oauth-token and x-cookie-header"
}

Cause: Both x-oauth-token and x-cookie-header headers were sent in the same request.

Resolution: Use only one authentication method per request. OAuth-authenticated requests should only include the x-oauth-token header.


Error Handling Best Practices

async function handleTokenEndpointResponse(response: Response) {
  const result = await response.json();

  if (result.code === 200 && result.data) {
    return result.data;
  }

  const error = result.error;
  if (!error) {
    throw new Error(result.message || 'Unknown error');
  }

  switch (error.error) {
    case 'invalid_client':
      // Configuration issue — check client_id and client_secret
      throw new ConfigurationError(error.error_description);

    case 'invalid_grant':
      // Code expired or refresh token invalid — re-authorize
      throw new ReauthorizationRequiredError(error.error_description);

    case 'invalid_request':
    case 'invalid_scope':
    case 'unsupported_grant_type':
      // Developer error — fix the request
      throw new InvalidRequestError(error.error_description);

    default:
      throw new Error(error.error_description || 'Unknown error');
  }
}

Error Code Quick Reference

ErrorStageAction
invalid_requestAuth / TokenFix request parameters
invalid_clientAuth / TokenVerify client credentials
invalid_scopeAuthUse valid scope identifiers
unsupported_response_typeAuthUse response_type=code
access_deniedAuthUser cancelled — handle gracefully
server_errorAuthRetry
invalid_grantTokenCode expired/used or refresh token invalid — re-authorize
unsupported_grant_typeTokenUse valid grant type
insufficient_scopeAPIRe-authorize with required scopes
conflicting_authAPIUse only one auth method per request
401 UnauthorizedAPIRefresh token, then re-authorize if needed