Appearance
API Authentication
All API requests require authentication via JSON Web Tokens (JWT). This guide covers how to obtain, use, and refresh tokens.
Overview
The API uses Bearer token authentication. After a successful login, the server issues a JWT that must be included in the Authorization header of every subsequent request. Tokens are short-lived and can be refreshed without re-entering credentials.
Getting a Token
Authenticate with your email and password to receive a JWT access token.
Endpoint: POST /api/v1/auth/login
Request body:
| Field | Type | Required | Description |
|---|---|---|---|
email | string | Yes | Your account email |
password | string | Yes | Your account password |
Example:
bash
curl -X POST https://your-domain.com/api/v1/auth/login \
-H "Content-Type: application/json" \
-d '{
"email": "user@example.com",
"password": "your-password"
}'Success response (no 2FA):
json
{
"access_token": "eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9...",
"token_type": "bearer",
"two_factor_required": false,
"two_factor_setup_required": false,
"two_factor_method": null,
"temp_token": null
}Use the access_token value for all authenticated requests.
Two-Factor Authentication (2FA) Flow
When 2FA is enabled on an account, the login endpoint does not return an access token directly. Instead, it returns a temporary token that must be exchanged by verifying a one-time code.
Step 1: Detect the 2FA challenge
The login response indicates a 2FA challenge when two_factor_required is true:
json
{
"access_token": null,
"token_type": "bearer",
"two_factor_required": true,
"two_factor_setup_required": false,
"two_factor_method": "totp",
"temp_token": "eyJhbGciOiJIUzI1NiIs..."
}The two_factor_method field tells you which method the user has configured ("totp" or "email"). For the email method, the server automatically sends a code to the user's email address as part of the login call.
Step 2: Verify the code
Submit the temporary token along with the verification code from your authenticator app (TOTP) or email.
Endpoint: POST /api/v1/auth/verify-2fa
Request body:
| Field | Type | Required | Description |
|---|---|---|---|
temp_token | string | Yes | The temporary token from the login response |
code | string | Yes | The 6-digit OTP or a one-time backup code |
Example:
bash
curl -X POST https://your-domain.com/api/v1/auth/verify-2fa \
-H "Content-Type: application/json" \
-d '{
"temp_token": "eyJhbGciOiJIUzI1NiIs...",
"code": "123456"
}'Success response:
json
{
"access_token": "eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9...",
"token_type": "bearer",
"two_factor_required": false,
"two_factor_setup_required": false,
"two_factor_method": null,
"temp_token": null
}Resending an email code
If the 2FA method is "email" and the user did not receive the code, you can request a new one.
Endpoint: POST /api/v1/auth/resend-2fa
bash
curl -X POST https://your-domain.com/api/v1/auth/resend-2fa \
-H "Content-Type: application/json" \
-d '{
"temp_token": "eyJhbGciOiJIUzI1NiIs..."
}'Organization-enforced 2FA setup
If the login response has two_factor_setup_required: true instead, the user's organization requires 2FA but the user has not set it up yet. In this case, use the POST /api/v1/auth/2fa/setup-with-temp and POST /api/v1/auth/2fa/confirm-with-temp endpoints with the temp_token to complete setup before obtaining an access token.
Using the Token
Include the token in the Authorization header as a Bearer token on every API request:
Authorization: Bearer <access_token>Example:
bash
curl https://your-domain.com/api/v1/users/me \
-H "Authorization: Bearer eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9..."Refreshing a Token
Obtain a new access token without re-authenticating. The request must include a valid (non-expired) token in the Authorization header.
Endpoint: POST /api/v1/auth/refresh
Example:
bash
curl -X POST https://your-domain.com/api/v1/auth/refresh \
-H "Authorization: Bearer eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9..."Response:
json
{
"access_token": "eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9...",
"token_type": "bearer"
}Replace your stored token with the new access_token value.
Token Expiration and Error Handling
Tokens have a limited lifetime. When a token expires or is otherwise invalid, the API responds with HTTP 401 Unauthorized.
Example 401 response:
json
{
"detail": "Invalid or expired token"
}Common 401 scenarios
| Scenario | detail message |
|---|---|
| Token expired | Invalid or expired token |
| Malformed or missing token | Invalid or expired token |
| Invalid login credentials | Invalid email or password |
| Account disabled | Account is disabled |
| Invalid 2FA code | Invalid code |
| Expired temporary token | Invalid or expired token |
Rate limiting on 2FA
The POST /api/v1/auth/verify-2fa endpoint enforces rate limiting. If too many failed verification attempts are made in a short period, the server responds with HTTP 429 Too Many Requests:
json
{
"detail": "Too many attempts. Try again later."
}Recommended client behavior
- Store the access token securely after login.
- Include it in the
Authorizationheader for every request. - When you receive a
401response, attempt a token refresh viaPOST /api/v1/auth/refresh. - If the refresh also returns
401, redirect the user to log in again. - Never store tokens in localStorage in browser environments; prefer httpOnly cookies or in-memory storage.