Skip to main content

Documentation Index

Fetch the complete documentation index at: https://mintlify.com/agent0ai/space-agent/llms.txt

Use this file to discover all available pages before exploring further.

Space Agent uses a file-backed authentication model. User credentials are stored as sealed SCRAM verifier envelopes in L2/<username>/meta/password.json. Active sessions are tracked in L2/<username>/meta/logins.json as signed verifier records. The space_session cookie issued by a successful login acts as the bearer token for every subsequent authenticated request.
Single-user mode — When SINGLE_USER_APP=true, every request automatically resolves to the implicit user principal. No cookie is checked and no login flow is required. The /api/login and /api/password_change endpoints return 403 in this mode.

Login Flow

Normal password login uses a two-step SCRAM challenge-proof exchange. The browser calls login_challenge first to obtain a server nonce and the account’s userCrypto state, then calls login with the computed client proof to complete authentication and receive the session cookie.
1

Call /api/login_challenge

Send the username to start a SCRAM challenge. The response includes a server nonce and the current userCrypto state for the account.
2

Compute the client proof

Use the server nonce, the user’s password, and the SCRAM algorithm to compute a clientProof and a challengeToken to prove knowledge of the password without sending it.
3

Call /api/login

Send the challengeToken and clientProof. On success, the server issues the space_session cookie and returns a sessionId plus the userCrypto unlock payload needed by the browser session.

POST /api/login_challenge

Initiates a SCRAM login challenge for the given username. Returns the server nonce, SCRAM parameters, and the account’s userCrypto bootstrap state. This endpoint is public (no session required). In clustered mode, challenges are stored in the primary-only login_challenge state area so workers cannot issue conflicting nonces.
When LOGIN_ALLOWED=false, login_challenge still accepts guest usernames when guest users are enabled, so background guest-bootstrap flows can complete without showing the login form.

Request

username
string
required
The username to challenge.
clientNonce
string
required
Client-generated nonce used to build the SCRAM auth message. The browser generates this; it must be unique per challenge.

Response

challengeToken
string
Opaque server-side challenge token to supply to /api/login.
serverNonce
string
SCRAM server nonce to incorporate into the client proof.
iterations
number
SCRAM iteration count for the password KDF.
salt
string
Base64-encoded SCRAM salt for the password KDF.
passwordScheme
string
Password scheme identifier for the sealed verifier.
userCrypto
object
Account crypto state object.
{ "username": "alice", "clientNonce": "cVe3Zq..." }

POST /api/login

Completes the SCRAM login flow using the challenge token and client proof from the previous login_challenge call. On success, sets the space_session cookie and returns session and crypto metadata. This endpoint is public (no session required). If the account had a missing userCrypto state, the server persists the browser-generated wrapped record before issuing the cookie. If provisioning cannot complete, login is refused rather than issuing a cookie that would require immediate logout.

Request

challengeToken
string
required
The opaque token returned by /api/login_challenge.
clientProof
string
required
SCRAM client proof derived from the user’s password and the server nonce.
userCryptoProvisioning
object
Browser-generated wrapped key record to persist for accounts with userCryptoState: "missing".

Response

Sets Set-Cookie: space_session=<token>; HttpOnly; SameSite=Strict; Path=/; Max-Age=2592000.
authenticated
boolean
Always true on success.
username
string
The authenticated username.
sessionId
string
Backend session ID. Used by the browser to bind its session-scoped userCrypto cache.
serverSignature
string
SCRAM server signature for the browser to verify.
userCrypto
object
The wrapped user master key record needed to unlock the current browser session.
{
  "challengeToken": "abc123...",
  "clientProof": "hvYD5s5..."
}

GET /api/login_check

Checks whether the current request’s session cookie is still valid. Returns the authentication state and, if authenticated, the username. This endpoint is public — it stays available even when LOGIN_ALLOWED=false. If the session cookie is present but references a cleared or expired session, the response includes a Set-Cookie header that clears the stale cookie.

Response

authenticated
boolean
Whether the current session is valid.
username
string
The authenticated username, or an empty string if not authenticated.
curl -b "space_session=<token>" \
  https://your-space-agent.example/api/login_check
{ "authenticated": true, "username": "alice" }

GET /api/user_self_info

Returns the authenticated user’s identity snapshot and browser crypto bootstrap metadata. This is the canonical frontend call for determining writable roots, group membership, and current key state. Requires a valid session.

Response

username
string
Authenticated username.
fullName
string
Display name from user.yaml, falling back to username.
groups
array
Ordered list of group IDs the user belongs to.
managedGroups
array
Group IDs where the user has admin/manager rights.
sessionId
string
Current backend session ID.
userCryptoKeyId
string
ID of the current wrapped user crypto key.
userCryptoState
string
Crypto state for the current account: "ready", "missing", or "invalidated".
curl -b "space_session=<token>" \
  https://your-space-agent.example/api/user_self_info
{
  "username": "alice",
  "fullName": "Alice Smith",
  "groups": ["team-alpha"],
  "managedGroups": [],
  "sessionId": "sess_xyz789",
  "userCryptoKeyId": "key_001",
  "userCryptoState": "ready"
}

POST /api/password_change

Changes the current user’s password. Validates the supplied currentPassword against the sealed verifier before writing the new one. On success:
  • Rewrites meta/password.json with the new sealed verifier.
  • Rewraps meta/user_crypto.json with the new password when the account has ready browser crypto (requires userCryptoRecord).
  • Clears all entries in meta/logins.json, invalidating every active session.
  • Clears the current browser cookie via Set-Cookie.
Not available in single-user mode (SINGLE_USER_APP=true). Failed attempts are artificially delayed by at least 1 second to slow enumeration.

Request

currentPassword
string
required
The user’s current password, as a plain string.
newPassword
string
required
The desired new password, as a plain string.
userCryptoRecord
object
Browser-produced replacement wrapped key record. Required when the account’s userCryptoState is "ready" to preserve the encrypted user data key through the password rotation.

Response

Clears the space_session cookie via Set-Cookie.
passwordChanged
boolean
Always true on success.
signedOut
boolean
Always true — all sessions are cleared.
username
string
The username whose password was changed.
{
  "currentPassword": "old-secret",
  "newPassword": "new-strong-password"
}

POST /api/guest_create

Creates a new guest account with a randomly generated guest_<id> username. Available when ALLOW_GUEST_USERS=true is set in runtime config. This endpoint is public — it works even when LOGIN_ALLOWED=false, because guest accounts are used for hosted-share flows that bypass the normal login form. After receiving this response, the caller completes authentication by running the normal /api/login_challenge + /api/login flow with the returned username and password.

Response

username
string
The newly created guest username (e.g. guest_a7f3c2).
password
string
The randomly generated plaintext password for the guest account. Use this with /api/login_challenge to complete background authentication.
{
  "username": "guest_a7f3c2",
  "password": "xK9mP2..."
}

POST /api/user_crypto_bootstrap

Authenticated recovery endpoint for the current user’s browser encryption state. Returns the current userCrypto state and, when the state is missing, can return a provisioning share and accept a browser-generated wrapped record — allowing the first authenticated app load to self-heal without a second login. When called without a request body (or with a body that omits record), the server returns the current state. If state is "missing", the response also includes a provisioningShare the browser should use to create the wrapped record. On the second call, supply record and provisioningShare to persist the new wrapped key.

Request (optional — for provisioning)

record
object
Browser-generated wrapped key record to persist. Required on the second call when state is "missing".
provisioningShare
string
The provisioning share returned by the first call. Required alongside record to complete provisioning.

Response

keyId
string
ID of the current wrapped user crypto key.
record
object
Client-facing wrapped key record.
serverShare
string
Backend server share (present and non-empty when state is "ready").
state
string
Current crypto state: "ready", "missing", or "invalidated".
provisioningShare
string
One-time provisioning share (only present when state is "missing" and no record was supplied in the request).

GET /api/user_crypto_session_key

Returns the session-scoped localStorage wrapping key for the current browser session. The key is derived by HMACing the live backend sessionId with the server-held session secret. The browser uses this key to encrypt or decrypt the single localStorage blob that caches the unlocked user master key. The server never stores this derived key or any copy of the user master key. Calling this endpoint is the only way for the browser to recover the wrapping key after a page reload without requiring a fresh login.

Response

sessionKey
string
Derived wrapping key (base64-encoded).

POST /api/password_generate

Generates a backend-sealed password verifier envelope for a given plaintext password. This is an authenticated utility endpoint used by admin tooling and the _core/user management page to pre-seal new or reset passwords before writing them to meta/password.json. Requires a valid session.

Request

password
string
required
The plaintext password to seal into a SCRAM verifier envelope.

Response

Returns the backend-sealed password.json payload object. The exact shape is owned by the auth service; it includes the SCRAM verifier, salt, iteration count, and scheme identifier in a server-sealed envelope.
{ "password": "correct-horse-battery-staple" }

Logout

GET /logout is a browser-facing endpoint (not under /api/). It clears the space_session cookie with a Set-Cookie: space_session=; Max-Age=0 header and redirects to /login. No JSON body is required.
curl -b "space_session=<token>" \
  -L https://your-space-agent.example/logout

Build docs developers (and LLMs) love