Authentication
The Appilot API uses JWT (JSON Web Tokens) for authentication. Every request to a protected endpoint carries a valid token.
Base URL
| Environment | Base URL |
|---|---|
| Production | https://api.appilot.space |
| Local development | http://localhost:6001 |
Routers are mounted at the root of that origin. There is no /api prefix, so the login endpoint is https://api.appilot.space/auth/login. Every path on this page is relative to the base URL.
Obtaining a token
Login
curl -X POST https://api.appilot.space/auth/login \
-H 'Content-Type: application/json' \
-d '{"email":"user@example.com","password":"your-password"}'
Response:
{
"token": "eyJhbGciOiJIUzI1NiIs...",
"user": {
"id": 1,
"email": "user@example.com",
"role": "admin",
"status": "active",
"organization_id": 1,
"is_super_admin": false
},
"organization": {
"id": 1,
"name": "My Organization",
"slug": "my-organization"
},
"availableOrganizations": [
{
"id": 1,
"name": "My Organization",
"slug": "my-organization",
"role": "admin",
"status": "active"
}
]
}
Login failures are reported separately, because they call for different answers from the caller. A member waiting for approval has to be told their password was right and the wait is the problem:
| Status | errorCode | Meaning |
|---|---|---|
400 | CREDENTIALS_REQUIRED | Email or password missing from the body |
401 | INVALID_CREDENTIALS | No such account, or the password does not match |
403 | NO_ACTIVE_MEMBERSHIP | The password was correct, but every membership is still waiting for an administrator's approval |
403 | ACCOUNT_NOT_ACTIVE | The account itself is suspended or pending |
Roles: an account is a User or an Admin of the organization it is active in. Federated identities that arrive through a host app's identity relay carry Guest, Member or None instead. The two vocabularies are explained in Who can configure.
Appilot is in closed beta. POST /auth/register accepts an approved invitation token (inviteToken) or an organization join code (joinCode); without one it answers 403 with code INVITE_REQUIRED. Request an invitation at appilot.space.
Using the token
Include the token in the Authorization header:
curl https://api.appilot.space/knowledge/content \
-H 'Authorization: Bearer eyJhbGciOiJIUzI1NiIs...'
Two endpoints exist to inspect the current token: GET /auth/me returns the authenticated user, and GET /auth/validate confirms the token is still good and returns the active organization context.
Organization context
The token carries the user's active organization. Calls are scoped to it, and the organization is never a field in a request body.
To switch organizations, for a user who belongs to more than one:
curl -X POST https://api.appilot.space/auth/switch-org \
-H 'Authorization: Bearer <token>' \
-H 'Content-Type: application/json' \
-d '{"organizationId": 2}'
This returns a new token with the updated organization context. The old token keeps its old context until it expires, so replace it everywhere the client stores it.
Widget authentication
The embeddable widget sends two things: a widget key that identifies the embed, and a user token that identifies the person. Both are required on a message.
curl -X POST https://api.appilot.space/widget/message \
-H 'X-Widget-Key: wk_live_a1b2c3d4e5f6...' \
-H 'X-Widget-Session: ws_session_id_here' \
-H 'Authorization: Bearer <widget user token>' \
-H 'Content-Type: application/json' \
-d '{"message":"How do I fill out this field?"}'
Widget keys:
- Start with
wk_live_(production) orwk_test_(your own machine). Both are checked against the key's allowed domains; a test key is accepted only while that list holds loopback addresses only - Resolve the organization, so no
organizationIdis sent - Are checked against the key's allowed domains using the
Origin/Refererheader, except onPOST /widget/token, which is server to server and is authenticated by the widget secret instead - Are rate-limited per key
The key is a public identifier, visible in your page source. It does not authorize a turn on its own. Every turn is attributed to an identified user, obtained from your own backend relay through POST /widget/token and presented as Authorization: Bearer. There is no anonymous widget usage. See Identity and sign-in.
Create widget keys under Widget Keys in the Backoffice sidebar. See Widget API Keys.
Token lifecycle
- User tokens are valid for 24 hours
- The payload carries the user id, email, active role and active organization id
- An expired or invalid token returns
401 Unauthorized
A client that treats a 401 as a signal to sign in again, rather than as a transport failure, behaves correctly here: Appilot's own surfaces do the same.
Roles
| Role | Access |
|---|---|
user | Chat, read knowledge, create knowledge requests, read own activity and usage |
admin | Organization management: knowledge, domains, content model, members, keys |
super_admin | Platform-wide access, used by Platform Admin only |
An admin role is scoped to the caller's own organization. It never grants access to a row belonging to another one.