Sign in

Authentication

API authentication, session lifecycle, and security best practices

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. Ultra and Enterprise teams can additionally mint API keys for server-to-server access, sent as Authorization: Bearer cliqer_<key>, see API Key Authentication 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 automatically by the server

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. There is no separate refresh endpoint to call, keeping a long-lived client polite means calling GET /api/auth/me periodically.

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

Ultra 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 Ultra and Enterprise plans only.

The API keys page in the dashboard, under Team in the sidebar, with the Create key button and a note on sending a key as a Bearer token

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 REST 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"

API keys work on the REST endpoints only. The WebSocket, slide control included, needs a session token.

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
emailstring
Yes
User email (a WordPress username is also accepted)
passwordstring
Yes
User password
otpstring
No
TOTP code, when the account uses an authenticator app
email_otpstring
No
Emailed PIN, when the account uses email 2FA
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",
  "email_sent": false
}

method is one of totp, email, or both. For email the server emails a PIN and email_sent says whether that email went out. A both account signs in with its authenticator code (otp); the emailed PIN is not a login factor for it.

Invalid credentials return 401, as does a wrong or expired TOTP code. A wrong or expired emailed PIN also returns 401 with the same message as a wrong password. A member of an organisation that requires single sign-on gets 403 and must sign in with SSO (see the SSO FAQ).

Session Rotation

There is no separate refresh endpoint. The server rotates the session_token cookie for you: when a session is close enough to expiry, GET /api/auth/me responds with a fresh Set-Cookie alongside the profile. A client that keeps a cookie jar and calls GET /api/auth/me periodically stays signed in indefinitely with no extra work.


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
  }
}

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 GET /api/auth/me before the session expires on long-lived tabs; the server rotates the cookie for you.
  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.