Authentication Endpoints

Base URL: https://auth.calimatic.com/api/v1/auth/headless

All endpoints require App Client authentication via x-client-id and x-client-secret headers. These credentials identify your registered application client.


Authentication

All endpoints in this group use App Client authentication:

HeaderValueDescription
x-client-idcca_...Your app client ID
x-client-secretccas_...Your app client secret
Content-Typeapplication/jsonRequired for POST requests

Endpoints Overview

MethodEndpointDescription
POST/loginAuthenticate with email + password
POST/signupRegister a new user account
POST/refreshRefresh an access token
POST/logoutRevoke a refresh token (logout)

POST /api/v1/auth/headless/login

Authenticate a user with email and password. Returns a full token set on success, or an MFA challenge if the user has TOTP enrolled.

Authentication: App Client (x-client-id + x-client-secret)

Request Body

FieldTypeRequiredDescription
emailstringYesUser's email address
passwordstringYesUser's password

Response — Success (200 OK)

When MFA is not enrolled or not required:

{
  "accessToken": "eyJhbGciOiJSUzI1NiIsInR5cCI6IkpXVCJ9...",
  "refreshToken": "eyJhbGciOiJSUzI1NiIsInR5cCI6IkpXVCJ9...",
  "idToken": "eyJhbGciOiJSUzI1NiIsInR5cCI6IkpXVCJ9...",
  "expiresAt": "2025-01-15T11:00:00.000Z",
  "user": {
    "userId": "a1b2c3d4-e5f6-7890-abcd-ef1234567890",
    "email": "user@example.com",
    "firstName": "Jane",
    "lastName": "Doe",
    "organizationId": "org-uuid",
    "orgName": "Acme Corp",
    "licenses": ["app-id-1", "app-id-2"]
  }
}

Response — MFA Challenge (200 OK)

When the user has MFA enrolled, mfaRequired: true is returned. Pass mfaToken to POST /mfa/verify:

{
  "mfaRequired": true,
  "mfaToken": "mfa_eyJhbGciOiJIUzI1NiJ9...",
  "expiresIn": 300,
  "methods": ["totp", "backup_code"],
  "user": {
    "userId": "a1b2c3d4-e5f6-7890-abcd-ef1234567890",
    "email": "user@example.com",
    "firstName": "Jane"
  }
}

Error Codes

CodeHTTP StatusDescription
INVALID_CREDENTIALS401Email or password is incorrect
ACCOUNT_LOCKED423Account temporarily locked due to too many failed attempts
RATE_LIMITED429Request rate limit exceeded
EMAIL_NOT_VERIFIED403User's email address has not been verified
INVALID_CLIENT401App client credentials are missing or invalid

SDK Method

const result = await client.auth.login({ email: 'user@example.com', password: 'secret' });
if ('mfaRequired' in result) {
  // Handle MFA challenge — pass result.mfaToken to client.mfa.verify
} else {
  console.log(result.accessToken);
}

curl Example

curl -X POST https://auth.calimatic.com/api/v1/auth/headless/login \
  -H "Content-Type: application/json" \
  -H "x-client-id: cca_aBcDeFgHiJkL" \
  -H "x-client-secret: ccas_xYzAbCdEfGhI" \
  -d '{
    "email": "user@example.com",
    "password": "SecurePass1"
  }'

POST /api/v1/auth/headless/signup

Register a new user account. Automatically sends an email verification link to the registered address.

Anti-enumeration: Returns 200 even if the email already exists.

Authentication: App Client (x-client-id + x-client-secret)

Request Body

FieldTypeRequiredDescription
emailstringYesEmail address for the new account
passwordstringYesPassword (min 8 chars, uppercase, lowercase, digit)
firstNamestringYesUser's first name (max 100 characters)
lastNamestringYesUser's last name (max 100 characters)

Response (200 OK)

Returns an empty body on success. A verification email is sent to the provided address.

{}

Error Codes

CodeHTTP StatusDescription
VALIDATION_ERROR400Input failed validation (password policy, invalid email, etc.)
RATE_LIMITED429Request rate limit exceeded
INVALID_CLIENT401App client credentials are missing or invalid

SDK Method

await client.auth.signup({
  email: 'user@example.com',
  password: 'SecurePass1',
  firstName: 'Jane',
  lastName: 'Doe',
});

curl Example

curl -X POST https://auth.calimatic.com/api/v1/auth/headless/signup \
  -H "Content-Type: application/json" \
  -H "x-client-id: cca_aBcDeFgHiJkL" \
  -H "x-client-secret: ccas_xYzAbCdEfGhI" \
  -d '{
    "email": "user@example.com",
    "password": "SecurePass1",
    "firstName": "Jane",
    "lastName": "Doe"
  }'

POST /api/v1/auth/headless/refresh

Refresh an access token using a valid refresh token. Uses a promise-based single-flight mutex internally to prevent invalid_grant races on concurrent requests.

Authentication: App Client (x-client-id + x-client-secret)

Request Body

FieldTypeRequiredDescription
refreshTokenstringYesThe refresh token from a previous login or refresh

Response (200 OK)

{
  "accessToken": "eyJhbGciOiJSUzI1NiIsInR5cCI6IkpXVCJ9...",
  "refreshToken": "eyJhbGciOiJSUzI1NiIsInR5cCI6IkpXVCJ9...",
  "idToken": "eyJhbGciOiJSUzI1NiIsInR5cCI6IkpXVCJ9...",
  "expiresAt": "2025-01-15T12:00:00.000Z",
  "user": {
    "userId": "a1b2c3d4-e5f6-7890-abcd-ef1234567890",
    "email": "user@example.com",
    "firstName": "Jane",
    "lastName": "Doe"
  }
}

Error Codes

CodeHTTP StatusDescription
TOKEN_EXPIRED401Refresh token is expired or has been revoked
INVALID_CLIENT401App client credentials are missing or invalid
RATE_LIMITED429Request rate limit exceeded

SDK Method

const tokens = await client.auth.refresh({ refreshToken: storedRefreshToken });
console.log(tokens.accessToken);

curl Example

curl -X POST https://auth.calimatic.com/api/v1/auth/headless/refresh \
  -H "Content-Type: application/json" \
  -H "x-client-id: cca_aBcDeFgHiJkL" \
  -H "x-client-secret: ccas_xYzAbCdEfGhI" \
  -d '{
    "refreshToken": "eyJhbGciOiJSUzI1NiIsInR5cCI6IkpXVCJ9..."
  }'

POST /api/v1/auth/headless/logout

Revoke a refresh token to end a user's session. Any access tokens previously issued from this refresh token will remain valid until their natural expiry.

Authentication: App Client (x-client-id + x-client-secret)

Request Body

FieldTypeRequiredDescription
refreshTokenstringYesThe refresh token to revoke

Response (200 OK)

Returns an empty body on success.

{}

Error Codes

CodeHTTP StatusDescription
TOKEN_EXPIRED401Refresh token is already expired or revoked
INVALID_CLIENT401App client credentials are missing or invalid
RATE_LIMITED429Request rate limit exceeded

SDK Method

await client.auth.logout({ refreshToken: storedRefreshToken });

curl Example

curl -X POST https://auth.calimatic.com/api/v1/auth/headless/logout \
  -H "Content-Type: application/json" \
  -H "x-client-id: cca_aBcDeFgHiJkL" \
  -H "x-client-secret: ccas_xYzAbCdEfGhI" \
  -d '{
    "refreshToken": "eyJhbGciOiJSUzI1NiIsInR5cCI6IkpXVCJ9..."
  }'