Skip to main content

Authentication Methods

CaseXchange exposes two distinct API surfaces, each with its own authentication mechanism:
APIAuth methodHeaderUse case
Public API (/api/public/v1/...)API keyX-API-Key: cxp_std_...Third-party integrations, data syncs, automations
Internal API (/api/v1/...)JWT Bearer tokenAuthorization: Bearer <jwt>CaseXchange dashboard, API key management
This page documents the Internal API JWT flow. It is primarily used for:
  • The CaseXchange web dashboard
  • Creating and managing Public API keys via POST /api/v1/public-api-keys
Most third-party integrations should use the Public API with API key authentication. See the Quickstart to get started. JWT authentication is only needed for CaseXchange dashboard access and API key management.

Overview

JWT authentication is used by the CaseXchange web dashboard and by server integrations that need to manage API keys.
  • POST /api/v1/auth/login exchanges credentials for an access token.
  • HttpOnly cookies (auth_token, refresh_token_id) are also set for browser clients.
  • Use POST /api/v1/auth/refresh-session to rotate short-lived tokens.
Access tokens expire quickly (15 minutes). Always implement refresh logic.

Login Flow

  1. Collect email/password from the integration user.
  2. Send the payload to /api/v1/auth/login.
  3. Cache the returned JWT for Authorization headers.
  4. Store refresh identifiers securely.
POST /api/v1/auth/login
{
  "email": "user@example.com",
  "password": "password"
}
Response:
{
  "meta": {
    "success": true
  },
  "data": {
    "user": {
      "id": "uuid",
      "email": "user@example.com",
      "firstName": "John",
      "lastName": "Doe",
      "role": "member",
      "firmId": "uuid",
      "isActive": true,
      "firm": {
        "id": "uuid",
        "name": "Law Firm Name"
      }
    },
    "accessToken": "eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9...",
    "refreshToken": "refresh_token_string"
  }
}
The accessToken should be used in the Authorization: Bearer <token> header for subsequent Internal API requests. The refreshToken can be used to obtain a new access token when it expires. HttpOnly cookies are also set for browser-based clients.

Using Tokens

Include the JWT in every Internal API request:
Authorization: Bearer <jwt>

Refresh Sessions

  • Endpoint: POST /api/v1/auth/refresh-session
  • Requires the refresh_token_id cookie (for browser clients) or refresh token in the request body (for server-to-server).
  • Returns a brand new JWT access token and rotates refresh identifiers.
  • Access tokens expire after 15 minutes (configurable via JWT_EXPIRES_IN).
  • Refresh tokens expire after 7 days (configurable via JWT_REFRESH_EXPIRES_IN).
For browser clients, the refresh endpoint automatically uses the refresh_token_id cookie:
POST /api/v1/auth/refresh-session
Content-Type: application/json
Cookie: refresh_token_id=<refresh_token_id>

{}
Response:
{
  "meta": {
    "success": true
  },
  "data": {
    "message": "Session refreshed successfully"
  }
}
The response sets new HttpOnly cookies:
  • auth_token - New JWT access token
  • refresh_token_id - New refresh token identifier

Server-to-Server Refresh

For server integrations, include the refresh token in the request:
POST /api/v1/auth/refresh-session
Content-Type: application/json

{
  "refreshToken": "<refresh_token_string>"
}
Use server-side storage for refresh tokens. Browser integrations should rely on HttpOnly cookies. Always implement automatic token refresh logic to handle expired tokens gracefully.
If refresh fails (token expired, revoked, or user inactive), the endpoint clears authentication cookies and returns a 401 error. Your application should redirect to login in this case.

Creating Public API Keys via JWT

After authenticating with JWT, you can programmatically create Public API keys. This is the same mechanism the CaseXchange dashboard uses under the hood.

Create a key

curl -X POST https://api.casexchange.com/api/v1/public-api-keys \
  -H "Authorization: Bearer <jwt>" \
  -H "Content-Type: application/json" \
  -d '{
    "name": "My Key",
    "tier": "STANDARD"
  }'
Supported tiers: READ_ONLY, STANDARD, FULL. See the Quickstart for a breakdown of what each tier permits. Response:
{
  "meta": {
    "success": true
  },
  "data": {
    "id": "uuid",
    "name": "My Key",
    "tier": "STANDARD",
    "key": "cxp_std_abc123def456..."
  }
}
The plaintext key value is only returned once at creation time. Store it securely — you will not be able to retrieve it again.

Switch to API key authentication

Once you have a Public API key, use the X-API-Key header for all Public API calls:
curl https://api.casexchange.com/api/public/v1/firms/me \
  -H "X-API-Key: cxp_std_abc123def456..."
From this point on, the JWT session is no longer needed for day-to-day integration work. Use the API key for all Public API endpoints.

Internal API Error Codes

All Internal API errors follow the standard error response format:
{
  "meta": {
    "success": false
  },
  "error": {
    "code": "token_expired",
    "message": "Access token has expired",
    "details": []
  }
}
Common authentication error codes:
  • no_token — Missing Authorization header
  • token_expired — Access token exceeded its TTL
  • token_invalid — Token signature or claims invalid
  • rate_limited_email / rate_limited_ip — Too many login attempts
  • account_not_fully_activated — User account is inactive
  • account_inactive_login_attempt — Login attempt on inactive account
Standard HTTP status codes:
  • 400 — Bad Request (validation errors, invalid token)
  • 401 — Unauthorized (authentication failed)
  • 403 — Forbidden (account inactive)