Management APIAuthentication

Authentication

The Management API uses JWT (JSON Web Tokens) for authentication. Clients authenticate with email and password to receive an access token and a refresh token. The access token is included in all subsequent requests.

Login

POST /v1/admin/auth/login

Authenticate with email and password to receive a token pair.

Request:

{
  "email": "admin@example.com",
  "password": "your-secure-password"
}

Response:

{
  "access_token": "eyJhbGciOiJIUzI1NiIs...",
  "refresh_token": "eyJhbGciOiJIUzI1NiIs...",
  "token_type": "Bearer",
  "expires_in": 900
}
FieldTypeDescription
access_tokenstringJWT access token for API requests
refresh_tokenstringJWT refresh token for obtaining new access tokens
token_typestringAlways "Bearer"
expires_inintegerAccess token TTL in seconds (900 = 15 minutes)

Status codes: 200 on success, 401 for invalid credentials, 429 if rate-limited.

⚠️

The login endpoint is rate-limited to 10 attempts per minute per email address to prevent brute-force attacks. After 5 consecutive failed attempts, the account is temporarily locked for 15 minutes.

Refresh Token

POST /v1/admin/auth/refresh

Exchange a valid refresh token for a new access token. Use this to maintain a session without re-authenticating.

Request:

{
  "refresh_token": "eyJhbGciOiJIUzI1NiIs..."
}

Response:

{
  "access_token": "eyJhbGciOiJIUzI1NiIs...",
  "refresh_token": "eyJhbGciOiJIUzI1NiIs...",
  "token_type": "Bearer",
  "expires_in": 900
}

A new refresh token is issued with each refresh request. The previous refresh token is invalidated (rotation).

Status codes: 200 on success, 401 if the refresh token is invalid or expired.

Refresh token rotation ensures that a compromised refresh token can only be used once. If a rotated-out token is reused, all tokens for that user are revoked as a security precaution.

Token Lifetimes

TokenTTLConfigurable Via
Access token15 minutesACCESS_TOKEN_TTL environment variable
Refresh token7 daysREFRESH_TOKEN_TTL environment variable

JWT Claims

Access tokens contain the following claims:

{
  "sub": "usr_abc123",
  "org_id": "org_xyz789",
  "role": "admin",
  "exp": 1740500400,
  "iat": 1740499500
}
ClaimTypeDescription
substringUser ID
org_idstringOrganisation ID the user belongs to
rolestringUser role: owner, admin, editor, or viewer
expintegerToken expiration time (Unix timestamp)
iatintegerToken issued-at time (Unix timestamp)

Using Tokens in Requests

Include the access token in the Authorization header of every API request:

curl -X GET http://localhost:8084/v1/admin/sources \
  -H "Authorization: Bearer eyJhbGciOiJIUzI1NiIs..."

If the token is missing, malformed, or expired, the API returns a 401 Unauthorized response:

{
  "error": {
    "code": "EXPIRED_TOKEN",
    "message": "The access token has expired. Use the refresh endpoint to obtain a new one."
  }
}

Token Storage Recommendations

  • Browser apps: Store the access token in memory (JavaScript variable). Store the refresh token in an HttpOnly cookie or secure storage.
  • Server apps: Store both tokens in a secure credential store or environment variable.
  • Never store tokens in localStorage or expose them in URLs.

Logout

To end a session, discard the tokens on the client side. There is no explicit logout endpoint — tokens are stateless and will expire on their own. If you need to immediately revoke a user’s access, an admin can remove the user via the Users API, which invalidates all their tokens.