Authentication

API authentication, session lifecycle, and security best practices

Authentication API

Cliqer authenticates with an httpOnly session cookie (session_token), minted by POST /api/auth/login. Browsers send it automatically on every request; server-to-server tooling keeps it in a cookie jar. Studio and Enterprise teams can additionally mint API keys for server-to-server access, sent as Authorization: Bearer cliqer_<key> — see below.

Session Model

CredentialWhere it livesHow it is obtained
Session cookie (session_token)httpOnly, Secure cookie on your Cliqer hostSet by POST /api/auth/login, rotated by POST /api/auth/refresh

The cookie is HttpOnly, so it is not readable from JavaScript. Its lifetime follows the server session TTL and is renewed transparently whenever you call GET /api/auth/me or POST /api/auth/refresh.

Session Lifecycle

Using the Session

Browsers attach the cookie automatically. For server-to-server clients, persist the cookie the login response sets and send it on subsequent requests:

# Save the session cookie on login, then reuse it
curl -X POST "$BASE_URL/api/auth/login" \
  -H "Content-Type: application/json" \
  -c cookies.txt \
  -d '{"email":"user@example.com","password":"your_password"}'

curl -X GET "$BASE_URL/api/auth/me" -b cookies.txt

API Key Authentication

Studio and Enterprise teams can mint long-lived API keys for server-to-server access, an alternative to holding a user's login credentials. Create and revoke them in the dashboard under Team → API keys (/dash/team/api-keys); minting requires the team owner (or a custom role granted the API-keys permission). Key management is available on the Studio and Enterprise plans only.

A key is shown once at creation, in the form cliqer_<prefix>_<secret>. Store it securely — it cannot be recovered, so revoke and re-create if it is lost. Send it as a Bearer token on any endpoint that accepts a session:

curl -X GET "$BASE_URL/api/licenses/status?license_key=YOUR_LICENSE_KEY" \
  -H "Authorization: Bearer cliqer_ab12cd34_your_secret_here"

The key authenticates as the user who created it, scoped to that user's team and plan. A revoked or unknown key returns 401, exactly like a missing session. Admin-only endpoints always reject API keys with 403. Keys are subject to the same rate limits as session requests.

Treat an API key like a password. Anyone holding it can act as your account on documented endpoints until you revoke it.

Log In

Exchange user credentials for a session. On success the response sets the session_token cookie.

Endpoint: POST /api/auth/login

ParameterTypeRequiredDescription
emailstringYesUser email (a WordPress username is also accepted)
passwordstringYesUser password
otpstringNoTOTP code, when the account uses an authenticator app
email_otpstringNoEmailed PIN, when the account uses email 2FA
request_email_otpbooleanNoAsk the server to send an email PIN (for both method)
curl -X POST "$BASE_URL/api/auth/login" \
  -H "Content-Type: application/json" \
  -c cookies.txt \
  -d '{"email":"user@example.com","password":"your_password"}'

Response (success): sets the session_token cookie and returns the session metadata.

{
  "data": {
    "expires": 604800000
  }
}

Response (2FA required): a 200 control-flow signal, not an error. Resubmit POST /api/auth/login with the same credentials plus otp (authenticator) or email_otp (emailed PIN).

{
  "requires_otp": true,
  "method": "totp"
}

method is one of totp, email, or both. For email/both the server emails a PIN (set request_email_otp: true to trigger it on the both method).

Invalid credentials return 401. A wrong or expired 2FA code also returns 401.

Refresh Session

Rotate the session cookie before it expires. Uses the inbound cookie, there is no request body.

Endpoint: POST /api/auth/refresh

curl -X POST "$BASE_URL/api/auth/refresh" -b cookies.txt -c cookies.txt

Response: rotated session_token cookie plus { "data": { "expires": 604800000 } }. Returns 401 when there is no session to refresh.


Current User

Return the authenticated user's profile, or { "data": null } when there is no valid session (anonymous-friendly, never a 401).

Endpoint: GET /api/auth/me

curl -X GET "$BASE_URL/api/auth/me" -b cookies.txt

Response:

{
  "data": {
    "id": "uuid",
    "email": "user@example.com",
    "first_name": "Jane",
    "last_name": "Doe",
    "role": "uuid",
    "tfa_method": "none",
    "is_admin": false,
    "biometric_unlocked": false
  }
}

Log Out

Terminate the session for the current cookie and clear it from the browser.

Endpoint: POST /api/auth/logout

curl -X POST "$BASE_URL/api/auth/logout" -b cookies.txt -c cookies.txt

Response:

{
  "success": true
}

Security Best Practices

Recommended Security Measures
  1. Use HTTPS only - The session cookie is Secure; all requests must use TLS 1.2+.
  2. Never read the cookie from JavaScript - It is HttpOnly by design; keep it that way.
  3. Refresh proactively - Call POST /api/auth/refresh (or rely on GET /api/auth/me) before the session expires on long-lived tabs.
  4. Log out to revoke - POST /api/auth/logout terminates the session server-side immediately.
  5. Store credentials, not sessions - Server-to-server integrations should hold the login credentials in a secret manager and re-establish a session, never persist the cookie in source.
See Security Overview for enterprise security features.