Skip to content

Authentication ​

The API uses session tokens or API keys. You get a session by signing in and send it as a cookie (browsers) or a bearer token; servers and scripts can use an API key instead.

Sign in ​

http
POST /auth/login
Content-Type: application/json

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

The response is { "userId": "…", "accountType": "client", "tenantId": "…" } and sets an HttpOnly cookie named lex_session (SameSite=Lax, Secure in production). Sessions last 7 days by default. POST /auth/logout ends the session (204).

New users can create an account with POST /auth/register (email, password, optional displayName and workspaceName). Every client account gets its own personal workspace.

Account types ​

Lex has two separate account systems you can integrate with. Each app signs in only its own type, and the same email can have one account of each type with different passwords.

Account typeAppx-lex-clientSession cookieSign-up
clientLex appany other value (e.g. my-app)lex_sessionPOST /auth/register
contributorContributor platform (Mini Program developers)contributor-dashboardlex_contributor_sessionPOST /auth/register

The x-lex-client header on /auth/login and /auth/register picks the account type. Every endpoint is for one account type: client endpoints answer 403 FORBIDDEN ("A Lex client account is required.") to contributor sessions, and /contributor/* refuses client sessions.

From a browser ​

Send the cookie with every request and add the client header to every request that changes something (POST, PUT, PATCH, DELETE):

ts
const API = 'https://api.lexcetha.com/api/v1';

async function api(path: string, init: RequestInit = {}) {
  const res = await fetch(`${API}${path}`, {
    ...init,
    credentials: 'include',
    headers: { 'content-type': 'application/json', 'x-lex-client': 'my-app', ...init.headers },
  });
  if (!res.ok) throw (await res.json()).error;
  return res.status === 204 ? undefined : res.json();
}

The x-lex-client header protects cookie sessions against cross-site request forgery: a plain HTML form on another site can't add it, so it can't change anything. Requests without it get 403 FORBIDDEN ("Missing client header").

Allowed origins

Browsers can only call the API from origins on its CORS allowlist. Lex's own apps are on it. To call the API from your own web app, ask the platform team to add your origin.

For a server, a backend job or CI, use an API key instead of a password.

  1. In the contributor platform (platform.lexcetha.com), switch the sidebar to API Integration.
  2. Link your Lexcetha workspace: sign in with your Lexcetha app account. Keys act as that account, in its workspace.
  3. Create a key with only the scopes it needs, and an optional expiry. The key (lx_…) is shown once; Lexcetha stores only its hash.

Send it as a bearer token:

bash
curl https://api.lexcetha.com/api/v1/bots \
  -H "Authorization: Bearer lx_…"
ScopeEndpoints
bots:read / bots:write/bots, /desktop-sessions, /skills
chat:read / chat:write/agent-runs, /chats, /conversations, /attachments, /speech, /transcriptions, /realtime-calls
approvals:read / approvals:write/approvals
connectors:read / connectors:write/integrations, /connector-providers, /connector-connections, /catalog/connectors
schedules:read / schedules:write/schedules, /scheduled-runs
documents:read / documents:write/documents, /document-folders, /document-proposals
catalog:read/catalog, /plugins, /mini-programs
usage:read/usage

read covers GET; write covers everything else and includes read. Any key may call GET /me and GET /tenants/current. Keys never reach sign-in, saved logins, memories, export or account deletion: those answer 403 FORBIDDEN, as does an endpoint outside the key's scopes ("This API key does not have the bots:write scope."). A revoked, expired or unknown key gets 401 UNAUTHENTICATED. Unlinking the workspace revokes every key. Actions through a key follow the same approvals as in the app.

From a server or script ​

Read the session token from the Set-Cookie header of /auth/login and send it as a bearer token. Bearer requests don't need the client header.

bash
TOKEN=$(curl -s -D - -o /dev/null -X POST https://api.lexcetha.com/api/v1/auth/login \
  -H 'Content-Type: application/json' \
  -d '{"email":"you@example.com","password":"your-password"}' \
  | sed -n 's/^set-cookie: lex_session=\([^;]*\).*/\1/ip')

curl https://api.lexcetha.com/api/v1/bots -H "Authorization: Bearer $TOKEN"

For a contributor account, add -H 'x-lex-client: contributor-dashboard' to the login request and read lex_contributor_session instead.

Keep tokens secret: anyone with the token acts as you until it expires or you sign out.

The current user and workspace ​

GET /me returns the user, their account type and, for client accounts, their workspace:

json
{
  "id": "…", "accountType": "client", "email": "you@example.com", "displayName": "Ana",
  "activeTenantId": "…", "role": "owner",
  "memberships": [{ "tenantId": "…", "role": "owner", "tenant": { "id": "…", "name": "Ana's workspace", "slug": "ana-s-workspace-x1y2" } }]
}

A client account owns exactly one workspace (role is owner). Workspaces have no other members: contributors use their own account type and never join a workspace. Contributor accounts return activeTenantId: null, role: null and no memberships.

Mini Programs built by contributors reach a workspace through the marketplace: GET /catalog/mini-programs lists every published Mini Program with this workspace's installation, and POST /mini-program-installations with { "miniProgramId": "…", "acceptedPermissions": [...] } installs one after accepting every permission it asks for.

Lex by Gavalytics AI