Overview
The Reelevant API uses OAuth 2.0 for authentication. Three grant types are supported:
| Grant Type | Use Case |
|---|
authorization_code | Browser-based login with PKCE (recommended for web apps) |
password | Direct username/password exchange (service accounts, scripts) |
refresh_token | Renew an expired access token without re-authenticating |
All token operations use the endpoint POST https://api.reelevant.com/v2/auth/token.
A client_id is required for every grant. Contact [email protected] to obtain one.
Authorization Code Flow (PKCE)
This is the recommended flow for web applications. It uses a browser redirect to authenticate the user, then exchanges an authorization code for tokens.
Step 1: Generate PKCE Challenge
Generate a random code_verifier and derive the code_challenge:
import { randomBytes, createHash } from 'crypto'
const codeVerifier = randomBytes(32).toString('base64url')
const codeChallenge = createHash('sha256')
.update(codeVerifier)
.digest('base64url')
Step 2: Redirect to Authorize
Redirect the user’s browser to the authorization endpoint:
GET https://api.reelevant.com/v2/oauth/authorize
?client_id=<client_id>
&redirect_uri=<redirect_uri>
&response_type=code
&code_challenge=<code_challenge>
&code_challenge_method=S256
&state=<random_state>
&lang=en
| Parameter | Required | Description |
|---|
client_id | Yes | Your OAuth client identifier |
redirect_uri | Yes | Must match a registered redirect URI for the client |
response_type | Yes | Must be code for the authorization code flow |
code_challenge | Yes | Base64url-encoded SHA-256 hash of the code_verifier |
code_challenge_method | No | Only S256 is supported (default) |
state | Recommended | Opaque value to prevent CSRF — returned unchanged in the callback |
lang | No | Login page language (en or fr) |
The user sees a login page. After successful authentication, a consent screen is shown. Upon approval, the browser is redirected to your redirect_uri with an authorization code:
https://your-app.com/callback?code=<authorization_code>&state=<state>
Authorization codes are single-use and expire after 60 seconds. Exchange them immediately.
Step 3: Exchange Code for Tokens
curl -XPOST https://api.reelevant.com/v2/auth/token \
-H "Content-Type: application/json" \
-d '{
"client_id": "<client_id>",
"grant_type": "authorization_code",
"code": "<authorization_code>",
"redirect_uri": "<redirect_uri>",
"code_verifier": "<code_verifier>"
}'
The code_verifier must match the code_challenge sent in Step 2 (the server verifies SHA256(code_verifier) == code_challenge).
Response:
{
"access_token": "xxxxxxxx-xxxx-xxxx-xxxx-xxxxxxxxxxxx",
"refresh_token": "xxxxxxxx-xxxx-xxxx-xxxx-xxxxxxxxxxxx",
"expires_in": 3600,
"token_type": "Bearer"
}
Some OAuth clients are configured with requireAuthorizationCodeFlow: true. For these clients, PKCE parameters are mandatory — the implicit flow is disabled entirely.
Password Grant
For service accounts and automation scripts where browser-based login is not practical.
curl -XPOST https://api.reelevant.com/v2/auth/token \
-H "Content-Type: application/json" \
-d '{
"username": "[email protected]",
"password": "your-password",
"grant_type": "password",
"client_id": "<client_id>"
}'
Response:
{
"access_token": "xxxxxxxx-xxxx-xxxx-xxxx-xxxxxxxxxxxx",
"refresh_token": "xxxxxxxx-xxxx-xxxx-xxxx-xxxxxxxxxxxx",
"expires_in": 3600,
"token_type": "Bearer"
}
Two-Factor Authentication (OTP)
If the user has OTP enabled, include the x-otp-code field:
curl -XPOST https://api.reelevant.com/v2/auth/token \
-H "Content-Type: application/json" \
-d '{
"username": "[email protected]",
"password": "your-password",
"grant_type": "password",
"client_id": "<client_id>",
"x-otp-code": "123456"
}'
Refresh Token Grant
Exchange a valid refresh token for a new access token without re-authenticating:
curl -XPOST https://api.reelevant.com/v2/auth/token \
-H "Content-Type: application/json" \
-d '{
"refresh_token": "xxxxxxxx-xxxx-xxxx-xxxx-xxxxxxxxxxxx",
"grant_type": "refresh_token",
"client_id": "<client_id>"
}'
Response:
{
"access_token": "xxxxxxxx-xxxx-xxxx-xxxx-xxxxxxxxxxxx",
"refresh_token": "xxxxxxxx-xxxx-xxxx-xxxx-xxxxxxxxxxxx",
"expires_in": 3600,
"token_type": "Bearer"
}
Using Access Tokens
Include the access token in every API request via the Authorization header:
Authorization: Bearer <access_token>
Token Lifecycle
| Token Type | Lifetime | Renewal |
|---|
| Access token | 1 hour | Use refresh_token grant to obtain a new one |
| Refresh token | 30 days (rolling) | Refreshed automatically each time it is used to generate a new access token |
| Authorization code | 60 seconds | Single-use — exchange immediately after receiving |
Refresh tokens use a rolling expiry: the 30-day window resets each time you use the refresh token. If you refresh at least once a month, the token never expires.
Revoking Tokens
Revoke an access token or refresh token:
curl -XDELETE https://api.reelevant.com/v2/auth/token/<token_id>
Revoking a refresh token also revokes all access tokens derived from it.
SSO Authentication
Companies with SSO configured are automatically redirected to their identity provider during the OAuth authorize flow. If SSO is mandatory for the company, password-based login is disabled (except for service accounts).
Error Handling
| Error | HTTP Status | Cause |
|---|
invalid_client | 400 | Unknown or inactive client_id |
invalid_redirect_uri | 400 | redirect_uri not in the client’s allowed list |
invalid_request | 400 | Missing required parameters (e.g., code_challenge for PKCE) |
invalid_credentials | 401 | Wrong username or password |
too_many_attempts | 429 | Login attempts exceeded — wait before retrying |
password_expired | 401 | Password must be changed before logging in |
otp_required | 401 | OTP code required but not provided |
invalid_code | 400 | Authorization code is invalid, expired, or already used |
pkce_mismatch | 400 | code_verifier does not match the original code_challenge |