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.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-keyandx-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 withmode=api parameter to indicate you’ll handle authentication directly.
| Parameter | Required | Description |
|---|---|---|
mode | Yes | Must be api (this enables API mode) |
response_type | Yes | Must be code |
client_id | Yes | Your application’s client identifier |
redirect_uri | Yes | Callback URL (required but not used in API mode) |
state | Yes | Random string for CSRF protection |
code_challenge | Yes | BASE64URL(SHA256(code_verifier)) |
code_challenge_method | Yes | Must be S256 |
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.| Field | Required | Description |
|---|---|---|
email | Yes | User’s email address |
password | Yes | User’s password |
otpCode | Conditional | Required if OTP is enabled for user |
Step 3: Generate Authorization Code
Use both tokens from Steps 1 and 2 to generate the authorization code.| Requirement | Location | Description |
|---|---|---|
| Access Token | Authorization header | Bearer token from Step 2 login |
| JWT Token | Request body | Session token from Step 1 initiation |
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.| Field | Required | Description |
|---|---|---|
grant_type | Yes | Must be authorization_code |
code | Yes | Authorization code from Step 3 |
redirect_uri | Yes | Must exactly match Step 1 |
code_verifier | Yes | Original PKCE verifier from Step 1 |
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.Token Management
Refresh Access Token
When the access token expires (6 hours), use the refresh token to obtain a new one:Complete Implementation Example
Here’s a complete mobile app implementation using React Native:Error Handling
Session expired (10 minutes)
Session expired (10 minutes)
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
Invalid credentials
Invalid credentials
Cause: Wrong email/password in Step 2.Solution:
- Display clear error message
- Allow retry with rate limiting
- Implement “forgot password” flow
Token mismatch errors
Token mismatch errors
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
OTP required but not provided
OTP required but not provided
Cause: User has 2FA enabled.Solution:
- Check
requiresOtpin login response - Call
POST /v1/auth/login/otpto send code - Prompt user for OTP
- Retry login with
otpCodefield
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
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
