This API is designed for the application’s own browser client and is not
versioned for external consumers. Endpoint shapes can change between releases.
For installation automation,
/api/health, /api/setup, and the versioned
/api/admin/provision manifest are the stable entry points.Authentication
Most endpoints require a session cookie issued at login and signed withBETTER_AUTH_SECRET. Requests are authorized per record: handlers verify that
the authenticated user owns the object being accessed.
Public endpoints
Public
Liveness and readiness probe. Executes
select 1 against PostgreSQL.Returns 200 {"ok":true} when healthy and 503 {"ok":false} when the
database is unreachable.Public
Reports installation setup state.
required is true only when setup has not completed and no users exist.Public, one-time
Creates the first administrator in a single transaction and permanently closes
public setup.Returns
403 when the claim token does not match.Public
Branding, setup state, and SSO button configuration needed before login.
Served with
cache-control: no-store. Contains no credentials or user data.Public
Authentication routes: sign-in, sign-out, session, and OIDC callbacks at
/api/auth/oauth2/callback/<provider-key>.Session endpoints
Session
Returns
{user} with only id, name, email, role, enabled,
mustChangePassword, providerSettingsEnabled, and mcpSettingsEnabled. No
session object or credentials are included. All responses use cache-control: no-store; unauthenticated requests return 401 and disabled accounts return
403. This profile contract does not change Better Auth’s separate
/api/auth/* response contracts, which can include session credentials.Session
Returns
{ providers, canEdit, modelTiers } for the user’s community catalogue
or the shared managed installation. modelTiers is the ordered array of
{ value, label } definitions. API keys are never returned; each provider
carries a hasApiKey flag. Custom headers are decrypted for authorized
editors so they remain editable.Session
Creates a provider from a name, base URL, optional API key, and optional
headers.
Session
Updates a provider. Omitting the API key leaves the stored one unchanged.
Session
Deletes a provider and its models. If it owned the default model, the oldest
remaining enabled model is promoted.
Session
Validates a provider by requesting
<base URL>/models through the outbound
guard.Session · Provider edit access
Replaces the ordered tier definitions with Supply 1–32 definitions, with unique positive integer IDs up to 2147483647.
Labels are trimmed, nonempty, at most 40 characters, and unique ignoring case.
IDs remain stable across rename/reorder operations; array order controls display.
Removing an ID referenced by any model, including disabled models, returns
{ "tiers": [...] } and returns
{ "modelTiers": [...] }. Community users edit their own catalogue; managed
installation changes require an administrator. The same provider-settings
permissions apply as for model edits.409. Reassign or delete those models before removing the tier. New catalogues
start with Low (1), Medium (2), High (3), and Maximum (4).Session
Creates a model with a provider model ID, display name, an explicit
tier
referencing a configured tier ID, context window, and maximum output tokens.
The first model becomes the default.Session
Updates a model, including its configured
tier, making it the default, or
toggling enabled. Default changes release the previous holder first.Session
Deletes a model, promoting a replacement default when needed.
Session
Lists the user’s conversations.
?archived=1 lists archived conversations
instead.Session
Creates a conversation. A conversation cannot start in an archived project.
Session
Updates a conversation:
title renames it, archived archives or restores
it, and projectId moves it into a project, or out of one with null. Moving
a standalone conversation into a project moves its files too, keeping their
paths unless one is taken, in which case they all move into one folder named
after the conversation; the response reports movedArtifacts and
artifactFolder. A conversation cannot move while a response is running, or
into an archived project.Session
Deletes a conversation and its messages.
Saved-message acknowledgements and retries
POST /api/chat/start accepts a chatId, a message with a client-generated
id and parts, and a model decision. It durably saves/enqueues the input and
returns 201 { messageId }; this acknowledges admission, not the model’s reply.
POST /api/chat/turn-inputs similarly saves a queued input and returns
{ input }, whose id is the submitted message identity.
Keep the same message ID, endpoint and request body when retrying a lost or
unreadable acknowledgement. A retry may return an already-applied or cancelled
queued input; it must not enqueue it again. Changed content/model/ownership is
not a retry and can return 409 input_conflict. Do not switch a network-uncertain
start request to the queue endpoint or invent a new ID.
The browser stores an owner- and conversation-scoped submission receipt before
sending. While a save is pending the draft is disabled. If its outcome is
uncertain, Retry saved submission resends the stored request, including after
reload; editing stays disabled until acknowledged. Browser storage must remain
available. Clearing site data or switching browsers removes that local recovery
receipt: inspect the saved conversation/inbox before submitting a replacement.
There is no automatic expiry or silent re-submission of uncertain receipts.
Session
The streaming chat endpoint. Resolves the model, decrypts credentials, ensures
the workspace is running, and streams text, reasoning, and tool calls back to
the browser for a saved
messageId (or explicit resume). detach: true
returns 202 { admitted: true, assistantId } instead of a duplicate stream;
the browser follows /api/chat/CHAT_ID/stream. Disconnect is not Stop.
Messages and tool results are persisted as they complete. A
request states its model decision with modelPinned: true with a modelId
pins that model to the conversation, false follows the current default.
Without modelPinned, its modelId runs for that turn only, otherwise the
conversation’s pinned model, otherwise the default.Session
Renames a project, or archives and restores it with
archived. Owners and
admins only. An archived project is hidden from every member’s sidebar and
runs no new responses until it is restored; nothing in it is deleted.Session
Returns
{ servers, canEdit } for the signed-in user, including known tools,
enabled/trust state, and hasHeaders, but never header values or encrypted
envelopes. Add ?id=SERVER_ID to load { server, canEdit } with decrypted
headers for editing. Detail requires edit access and uses cache-control: no-store.Session · MCP edit access
Adds a server with
name, url, transport (http or sse, default
http), optional headers (a string-to-string object), and enabled
(default true). Headers are encrypted at rest. New servers require testing
and trust before use.Session · MCP edit access
Accepts
id and any configuration fields from POST. Omitted headers are
preserved; headers: {} clears them. Changing the URL, transport, or headers
requires renewed trust. Renaming or enabling/disabling alone does not.Session · MCP edit access
Removes an MCP server.
Session · MCP edit access
Body:
{ "id": "server-id" }. Test discovers tools and reports drift without
granting trust. Trust accepts the current tool definitions.mcpSettingsEnabled is false, a non-admin user can still list and select
configured servers in chat, but cannot add, edit, delete, test, trust, or read
stored headers. These restrictions are enforced server-side with 403 mcp_settings_disabled, in both editions. Admins retain access. A userId on
self-service endpoints never switches ownership.
Artifact endpoints
Session
Lists, searches, previews, stats, or downloads remote artifacts for an
authorized project/chat context.
Session
Uploads browser files into the active project’s or standalone chat’s artifact
namespace. Artifact metadata includes the immutable
id used by canonical
[filename](artifact://<artifact-id>) message references.Session
Moves or renames remote artifacts within one authorized namespace.
Session
Deletes a remote artifact or directory prefix.
Workspace
Streaming workspace-identity API used by
r5dchat artifacts. Reads, stats,
and deletes accept a namespace path or immutable artifact id. Requires
x-artifact-scope; the server resolves it and re-checks project membership or
standalone-chat participation before reading or mutating bytes.Workspace endpoints
Session
Current workspace phase:
running, starting, stopped, or disabled, plus
a readiness flag and the mode.Session
Starts the workspace and waits for readiness.
Session
Requests an immediate scale to zero, clearing active leases.
Admin endpoints
Admin
Lists all users.
Admin
Creates a user account directly. In the community edition, the optional
providerSettingsEnabled boolean controls provider settings access (default
true). In both editions, optional mcpSettingsEnabled controls MCP settings
access (default true).Admin
Updates a user’s role, enabled state, or (community edition)
providerSettingsEnabled. Send { "id": "user-id", "providerSettingsEnabled": false }
to restrict one user. Send { "all": true, "providerSettingsEnabled": false }
to restrict all current non-admin accounts in one operation; use true to
restore access. Administrators retain provider access, and newly created
accounts are unaffected by earlier bulk changes.In both editions, send { "id": "user-id", "mcpSettingsEnabled": false }
to restrict one user’s MCP settings, or { "all": true, "mcpSettingsEnabled": false } for all current non-admin users. Use true
to restore access. This is independent of provider and account access;
administrators remain able to configure servers for any user.Admin
Available in both editions. GET lists the target user’s servers; add
&id=SERVER_ID to load all configuration fields including decrypted headers.
POST, PATCH, and DELETE use the same bodies and id query parameter as
/api/mcp, scoped to that user, even when their MCP settings are disabled.
Missing userId returns 400; unknown users or servers owned by a different
user return 404. List and mutation responses do not expose header values.Admin
Tests or trusts a server for the specified user. Body:
{ "id": "server-id" }.
Use these after creating or changing a server on the user’s behalf.Admin · Community
GET lists that user’s providers with editable headers and their ordered
modelTiers definitions. POST, PATCH, and DELETE use the same bodies and id
query parameter as /api/providers, scoped to the specified user. They work
even when that user’s provider settings are disabled. API keys remain
write-only. A missing user ID returns 400; an unknown user, or a provider
owned by another user, returns 404.Admin · Community
Tests that user’s provider and discovers its models. Body:
{ "id": "provider-id" }.Admin · Community
POST, PATCH, and DELETE manage models for the specified user using the same
bodies and
id query parameter as /api/models. Provider/model ownership and
default-model rules remain scoped to that user.Admin · Community
Replaces the specified user’s tier definitions, even when their provider
settings are disabled. Uses the same
{tiers} body, {modelTiers} response,
validation, and in-use removal rules as /api/model-tiers. Requires userId.
Managed administrators instead use /api/model-tiers for the shared
installation catalogue.Admin
Returns branding and OIDC configuration. Client secrets are not returned in
plaintext.
Admin
Updates branding and OIDC configuration.
Admin
Applies a versioned, repeatable installation manifest. Version 1 can upsert
users and roles, configure branding and OIDC, seed providers and models, and
import conversations. Imported conversations receive the same owner,
participant preference, and artifact-namespace records as conversations
created through the interface. Existing conversations with the same ID are
left untouched, so rerunning a migration cannot overwrite subsequent user
work.Manifests put each user’s private credentials in API keys and OIDC client secrets are encrypted immediately with
users[].providers.
Users created without passwords authenticate through OIDC after exact,
verified-email linking is enabled. Every model in the manifest must explicitly
set tier to a configured positive integer ID. Optional modelTiers defines
an ordered array of { value, label } at the root for managed installations or
on each users[] entry for community catalogues. Omitting it retains existing
definitions (new catalogues get the initial four defaults). The same limits,
unique labels/IDs, membership, and in-use removal rules as /api/model-tiers
apply. This community example uses three custom tiers in nonnumeric order:SETTINGS_ENCRYPTION_KEY and are never returned. Stream manifests from a
protected process and avoid shell tracing or ordinary build artifacts.Admin
Streams one artifact into an existing conversation or project during a data
migration. Send
multipart/form-data with exactly one of chatId or
projectId, plus artifactId (UUID), importSource, path, file, and
optional mediaType and RFC 3339 createdAt fields.artifactId lets an importer write canonical artifact://<artifact-id> links
into conversation messages before uploading bytes. importSource makes the
operation repeatable: retrying the same source, ID, namespace, and path returns
the existing record with skipped: true; reusing a source for a different
target returns 409. The upload limit is ARTIFACT_MAX_UPLOAD_BYTES.Admin
Validates OIDC discovery and client credentials against the real provider
before enabling it.
Admin
Creates an invitation for a new account.
Public
Redeems an invitation to create an account.
Workspace-authenticated endpoints
Workspace
Backs the
r5dchat conversation commands. Authenticates with the workspace
bearer identity, then re-checks that the workspace’s user owns the requested
conversation. Supports overview, single-turn, and full-read modes in Markdown
or JSON.Errors
Errors return a JSON body with a machine-readable code:Monitoring
Use/api/health for liveness and readiness. It is unauthenticated and checks
database connectivity, making it a meaningful signal rather than a static
response.