Skip to content

Auth, accounts and security API

Routes under /auth, /me/security, /audit and /system. Permission levels are defined in the API overview.

Method Path Permission Body Returns
POST /auth/login Public, 60/min {email, password} {user, access}, or {mfaRequired: true, challenge} when the account has 2FA
POST /auth/login/mfa Public, 30/min {challenge, code}. code is a TOTP code or a recovery code. {user, access}
GET /auth/me Authenticated The current user, without the password hash
POST /auth/change-password Authenticated {oldPassword, newPassword} (at least 8 characters) {detail, access}. Other sessions are signed out.
POST /auth/logout Authenticated {detail}. Invalidates the session JWT used. Does nothing for an API token.
POST /auth/sessions/revoke Authenticated {access}. Signs out every other session. API tokens aren’t affected.

When to use: /auth/login to get a session token for the WebSockets or a short script. Prefer an API token for automation. The MFA challenge is valid for 5 minutes. Too many failures return 429 until the throttle window ends.

Terminal window
curl -sX POST https://panel.example.com/auth/login \
-H 'Content-Type: application/json' \
-d '{"email": "you@example.com", "password": "…"}'
Method Path Permission Body Returns
GET /auth/totp Authenticated {enabled, recoveryCodesRemaining}
POST /auth/totp/setup Authenticated, 10/min {password} {secret, otpauthUri} to add to an authenticator app
POST /auth/totp/enable Authenticated, 10/min {code} {recoveryCodes, access}. Other sessions are signed out.
POST /auth/totp/disable Authenticated, 10/min {password, code}. code may be a recovery code. {detail}
POST /auth/totp/recovery-codes Authenticated, 10/min {code} (an authenticator code) {recoveryCodes}, replacing the old ones

When to use: setup, then enable with the first code the app shows. Store the ten recovery codes. Each works once.

Method Path Permission Body Returns
GET /auth/users Superuser {results, count}. Each user has totp_enabled.
POST /auth/users Superuser {email, password, firstName?, lastName?, isSuperuser?} {user, team}. Each new user gets a personal team.
PATCH /auth/users/{id} Superuser {firstName?, lastName?, isActive?, isSuperuser?} The user. You can’t remove your own superuser flag (400 cannot_demote_self).
DELETE /auth/users/{id}/totp Superuser {detail}. Turns the user’s 2FA off and signs them out.
DELETE /auth/users/{id} Superuser {detail}. You can’t delete yourself (400 cannot_delete_self).

When to use: there is no public sign-up, so this is how accounts are created. Deactivate (isActive: false) instead of deleting to keep history.

Method Path Permission Body Returns
GET /me/security/tokens Authenticated {results}: your tokens as rows (id, user_id, name, prefix, token_hash, last_used_at, expires_at, created_at). The hash isn’t stripped (the exclusion uses the camelCase name).
POST /me/security/tokens Authenticated {name, expiresInDays?} {token, plain, warning}. plain (gsl_…) is shown only here.
DELETE /me/security/tokens/{id} Authenticated (own tokens) {detail}

When to use: CI, scripts and AI assistants. See Use the API with tokens.

Used as deploy keys for cloning private git repositories.

Method Path Permission Body Returns
GET /me/security/ssh-keys Authenticated {results}
POST /me/security/ssh-keys Authenticated {name, publicKey, algorithm?}. publicKey must start with ssh-rsa, ssh-ed25519, ssh-dss or ecdsa-sha2-…. The key
POST /me/security/ssh-keys/generate Authenticated {name, algorithm}. algorithm is ed25519 (default), rsa-4096, rsa-2048, ecdsa-p256 or ecdsa-p384. {key, privateKey, warning}. The private key is returned once.
DELETE /me/security/ssh-keys/{id} Authenticated (own keys) {detail}

Keys are returned as rows: id, user_id, name, algorithm, public_key, is_deploy_key, fingerprint, created_at.

When to use: generate a key, add its public half to the repository as a deploy key, then set the app’s deployKeyId. An app can only use keys owned by the user who sets it (a superuser can use any).

Method Path Permission Query Returns
GET /audit/ Authenticated limit (default 100), offset (default 0) {results, count}: your own state-changing requests and sign-in events, newest first

Each entry has actor_id, team_id, action, target_type, target_id, ip_address, user_agent, data and created_at.

Method Path Permission Returns
GET /system/info Authenticated {hostname, publicIp, privateIps, version: {panel: {version, commit, builtAt}, agent}}

When to use: to find the address DNS records should point at, and to check that the panel and agent versions match. publicIp is PUBLIC_IP from /etc/gisila/.env when set, otherwise looked up and cached for an hour. agent is null if the agent binary can’t be asked.