Skip to main content

Overview

API Mode gives you complete control over the authentication experience. Instead of redirecting users to a hosted UI, your application presents a custom login interface where users authenticate and authorize your application to act on their behalf. Your application then generates the authorization code through API calls. This is ideal for mobile apps, custom branded experiences, or headless systems.
More complexity, more control: API mode requires 5 steps and additional security considerations. Only use this if you need full control over the user experience.
User Authorization Model: Even with custom UI, the user remains in control of the authentication process and grants your application permission to access their account.

When to Use API Mode

Ideal For

  • Native mobile applications
  • Custom branded login experiences
  • Headless/API-only architectures
  • Embedded authentication flows
  • White-label solutions

Not Ideal For

  • Quick integrations
  • Standard web applications
  • Third-party integrations
  • Limited development resources

Prerequisites

Before starting, ensure you have:
  • ✅ API keys (x-client-key and x-secret-key)
  • ✅ Secure credential storage mechanism
  • ✅ Understanding of PKCE implementation
  • ✅ Ability to handle user credentials securely
  • ✅ Implementation of proper error handling

Flow Diagram

Implementation Guide

Step 1: Initiate OAuth with API Mode

Start the OAuth flow with mode=api parameter to indicate you’ll handle authentication directly.
Request Parameters: Response:
Important: The token returned here is a JWT for the OAuth flow session (valid 10 minutes). It’s NOT an access token for API calls.

Step 2: Authenticate User

Present your custom login UI to the user and authenticate them through the API.
Request Body: Response:
Security: Never log or expose user passwords. Always transmit over HTTPS in production.

Step 3: Generate Authorization Code

Use both tokens from Steps 1 and 2 to generate the authorization code.
Request Requirements: Response:
Token Confusion Prevention:
  • JWT Token (Step 1): Used ONLY in this request body
  • Access Token (Step 2): Used ONLY in the Authorization header here
  • Neither of these are the final tokens you’ll use for API calls

Step 4: Exchange Code for Long-Lived Tokens

Exchange the authorization code for access and refresh tokens that you’ll use for actual API calls.
Request Body: Response:
These are your final tokens:
  • Access token: Use this for all API calls (6 hour expiry)
  • Refresh token: Use this to get new access tokens (7 day expiry)

Step 5: Use Access Token for API Calls

Now use the access token from Step 4 to make API requests on behalf of the user for all authenticated operations.
User Authorization Boundaries: The access token enables your application to act on behalf of the user. Ensure all API calls align with the user’s expectations and the permissions they granted.

Token Management

Refresh Access Token

When the access token expires (6 hours), use the refresh token to obtain a new one:
Learn more in the Token Management Guide.

Complete Implementation Example

Here’s a complete mobile app implementation using React Native:

Error Handling

Cause: Too much time between Step 1 initiation and Step 3 authorization.Solution:
  • Restart from Step 1
  • Implement session expiry monitoring
  • Show countdown timer to users
Cause: Wrong email/password in Step 2.Solution:
  • Display clear error message
  • Allow retry with rate limiting
  • Implement “forgot password” flow
Cause: Using wrong token in wrong step.Solution:
  • JWT Token: Only in Step 3 request body
  • Access Token (Step 2): Only in Step 3 Authorization header
  • Access Token (Step 4): For all subsequent API calls
Cause: User has 2FA enabled.Solution:
  • Check requiresOtp in login response
  • Call POST /v1/auth/login/otp to send code
  • Prompt user for OTP
  • Retry login with otpCode field

Security Considerations

Credential Security

  • Never log passwords
  • Clear password fields after use
  • Use HTTPS only
  • Implement rate limiting

Token Storage

  • Use platform-specific secure storage
  • Never store in AsyncStorage (RN)
  • Never store in localStorage (web)
  • Encrypt if possible

PKCE Validation

  • Store code_verifier securely
  • Don’t reuse code_verifier
  • Validate state parameter
  • Clear after exchange

Error Handling

  • Don’t expose internal errors
  • Log security events
  • Implement retry limits
  • Clear sensitive data on error
Learn more in the Security Guide.

Testing Checklist

Before production:
  • All 5 steps complete successfully
  • PKCE code_verifier validation works
  • State parameter prevents CSRF
  • Session timeout (10 min) is handled
  • Invalid credentials show appropriate error
  • OTP flow works if enabled
  • Token refresh works automatically
  • Expired refresh token triggers re-auth
  • API calls use correct access token
  • Secure storage is implemented
  • Network errors are handled gracefully
  • User can logout and revoke tokens

Next Steps

Token Management

Master token lifecycle and refresh strategies

Security Best Practices

Essential security guidelines for production

Troubleshooting

Common issues and solutions

API Reference

Detailed endpoint documentation