HTTP API
Base Surface
The current backend exposes FastAPI routers under:
/api/aibs/auth/api/aibs/admin/users/api/aibs/workspaces/api/aibs/conversations/api/aibs/documents/api/aibs/chat
The app is served by FastAPI and publishes OpenAPI docs at /docs.
Identity Boundary
The API uses an AIBS auth boundary at the interface layer.
POST /api/aibs/auth/loginvalidates credentials through the configured OpenSearch identity store.Successful login requires the
aibs-accessrole and sets an HTTP-only session cookie.Workspace, document, conversation, and chat routes resolve their
UserContextfrom that cookie session.Workspace-local authorization is role based:
owner: full control, including workspace deleteadmin: manage workspace state, non-owner members, and documentsmember: upload/process documents and ask questionsviewer: read workspace state and ask questions
The legacy
X-AIBS-User-Idheader is accepted only whenAIBS_AUTH_DEV_MODE=true.Phase 1 sessions use a fixed TTL and process-local memory; single-worker API deployment is required until a persistent session store lands.
AIBS product-user administration is guarded by both
aibs-accessandaibs-admin.Workspace membership is separate from product administration. AIBS admins do not automatically see every workspace.
Endpoints
POST /api/aibs/auth/login
Purpose:
validate credentials against the configured OpenSearch cluster and create a cookie-backed AIBS session
Request:
JSON body:
username(required)password(required)
Success:
200 OKsets an HTTP-only session cookie
returns
{ "success": true, "data": { "expires_at", "user": { "user_id", "provider", "subject", "username", "roles", "apps", "email", "display_name" } } }
POST /api/aibs/auth/logout
Purpose:
revoke the current cookie session
Behavior:
reads the configured session cookie
clears the cookie even when the session is missing or already expired
Success:
200 OKreturns
{ "success": true, "data": {} }
GET /api/aibs/auth/session
Purpose:
return the user profile attached to the current cookie session
Behavior:
requires a valid session cookie
Success:
200 OKreturns the same session payload as login
GET /api/aibs/admin/users
Purpose:
list product users from the configured AIBS user directory
Query parameters:
q(optional username/search text)limit(default50, min1, max500)include_non_aibs(defaultfalse; when true, include directory users that do not currently haveaibs-access)
Behavior:
requires a principal with both
aibs-accessandaibs-admin
Success:
200 OKreturns
{ "users": [UserDirectoryRecordResponse] }
GET /api/aibs/admin/users/{username}
Purpose:
fetch one user from the configured user directory
Behavior:
requires a principal with both
aibs-accessandaibs-adminreturns
404when the user is not found
Success:
200 OKreturns
UserDirectoryRecordResponse
POST /api/aibs/admin/users
Purpose:
create an AIBS product user in the backing directory
Request:
JSON body:
username(required)password(required)display_name(optional)email(optional)aibs_admin(optional, defaultfalse)
Behavior:
requires a principal with both
aibs-accessandaibs-admincreated users always receive
aibs-accesscreated admin users also receive
aibs-admin
Success:
201 Createdreturns
UserDirectoryRecordResponse
PUT /api/aibs/admin/users/{username}/entitlements
Purpose:
grant or revoke AIBS product roles for an existing directory user
Request:
JSON body:
access(required boolean)admin(required boolean)
Behavior:
requires a principal with both
aibs-accessandaibs-adminpreserves non-AIBS directory roles
refuses to remove or disable the last enabled AIBS admin
Success:
200 OKreturns
UserDirectoryRecordResponse
PUT /api/aibs/admin/users/{username}/password
Purpose:
reset a directory user’s password
Request:
JSON body:
new_password(required)
Behavior:
requires a principal with both
aibs-accessandaibs-admin
Success:
204 No Content
PUT /api/aibs/admin/users/{username}/disable
Purpose:
disable a directory user when supported by the backing provider
Behavior:
requires a principal with both
aibs-accessandaibs-adminrefuses to disable the last enabled AIBS admin
Success:
204 No Content
POST /api/aibs/workspaces
Purpose:
create a new backend-owned workspace
Request:
JSON body:
name(required)visibility(optional, defaults toprivate)
Success:
201 Createdreturns
WorkspaceResponse
GET /api/aibs/workspaces
Purpose:
list workspaces visible to the current identity
Query parameters:
limit(default50, min1, max200)offset(default0)
Success:
200 OKreturns
WorkspaceListResponse
GET /api/aibs/workspaces/{workspace_id}
Purpose:
fetch one workspace the current identity belongs to
Success:
200 OKreturns
WorkspaceResponse
PUT /api/aibs/workspaces/{workspace_id}
Purpose:
rename a workspace through the backend-owned workspace service
Behavior:
requires workspace owner or admin
rejects rename while workspace delete is already in progress
applies the aggregate rename rule and persists the updated workspace
Success:
200 OKreturns
WorkspaceResponse
GET /api/aibs/workspaces/{workspace_id}/members
Purpose:
list the members and roles for one workspace
Behavior:
requires any workspace role
rejects reads while workspace delete is already in progress
Success:
200 OKreturns
list[WorkspaceMemberResponse]
POST /api/aibs/workspaces/{workspace_id}/members
Purpose:
add a user to a workspace with a workspace-local role
Request:
JSON body:
username(preferred)user_id(deprecated compatibility field)role(required:owner,admin,member, orviewer)
Behavior:
requires workspace owner or admin
at least one of
usernameoruser_idis requiredusername-based adds resolve through the AIBS user directory
unknown usernames are rejected
if both
usernameanduser_idare supplied, they must resolve to the same useradding an owner requires the requester to be an owner
rejects duplicate membership through the workspace aggregate
rejects changes while workspace delete is already in progress
Success:
201 Createdreturns
WorkspaceMemberResponse
PUT /api/aibs/workspaces/{workspace_id}/members/{user_id}
Purpose:
change an existing workspace member role
Request:
JSON body:
role(required:owner,admin,member, orviewer)
Behavior:
requires workspace owner or admin
promoting to owner or demoting an owner requires the requester to be an owner
preserves the aggregate invariant that a workspace must keep at least one owner
rejects changes while workspace delete is already in progress
Success:
200 OKreturns
WorkspaceMemberResponse
DELETE /api/aibs/workspaces/{workspace_id}/members/{user_id}
Purpose:
remove a user from a workspace
Behavior:
requires workspace owner or admin
removing an owner requires the requester to be an owner
preserves the aggregate invariant that a workspace must keep at least one owner
rejects changes while workspace delete is already in progress
Success:
204 No Content
POST /api/aibs/workspaces/{workspace_id}/archive
Purpose:
archive a workspace through the governance layer
Behavior:
requires workspace owner or admin
performs the domain archive transition
persists the archived workspace state
Success:
200 OKreturns
WorkspaceResponse
DELETE /api/aibs/workspaces/{workspace_id}
Purpose:
destructively delete a workspace and its bounded resources
Behavior:
requires workspace ownership
closes the in-process workspace boundary before destructive cleanup starts
rejects deletion if any bounded document is currently processing
deletes bounded documents first
deletes conversations next
removes the workspace record last
Success:
204 No Content
POST /api/aibs/workspaces/{workspace_id}/conversations
Purpose:
create a lightweight persisted conversation bound to one workspace
Request:
JSON body:
title(optional)
Success:
201 Createdreturns
ConversationResponse
GET /api/aibs/workspaces/{workspace_id}/conversations
Purpose:
list conversations within one workspace for the current identity
Query parameters:
limit(default50, min1, max200)offset(default0)
Behavior:
requires active workspace membership
returns conversations created by the current identity
also returns legacy conversations that do not have
created_byrecorded yet
Success:
200 OKreturns
ConversationListResponse
GET /api/aibs/conversations/{conversation_id}
Purpose:
fetch one conversation if the current identity created it
Behavior:
requires workspace membership for the conversation’s workspace
requires the conversation creator after workspace membership is confirmed
legacy conversations with missing
created_byremain readable by workspace members
Success:
200 OKreturns
ConversationResponse
PUT /api/aibs/conversations/{conversation_id}
Purpose:
rename a workspace-bound conversation record
Behavior:
loads the conversation through the backend-owned conversation service
rejects rename while workspace delete is already in progress
requires the conversation creator after workspace membership is confirmed
updates the conversation title and
updated_at
Success:
200 OKreturns
ConversationResponse
DELETE /api/aibs/conversations/{conversation_id}
Purpose:
delete one workspace-bound conversation record
Behavior:
loads the conversation through the backend-owned conversation service
rejects delete while workspace delete is already in progress
requires the conversation creator after workspace membership is confirmed
removes only the lightweight conversation record
Success:
204 No Content
GET /api/aibs/conversations/{conversation_id}/history
Purpose:
reload one conversation from persisted query and answer records
Behavior:
requires workspace membership for the conversation’s workspace
requires the conversation creator after workspace membership is confirmed
legacy conversations with missing
created_byremain readable by workspace membersreturns both grounded and insufficient turns truthfully
returns fallback conversation-context turns when published answer lineage exists
Success:
200 OKreturns
ConversationHistoryResponse
POST /api/aibs/documents
Purpose:
upload, register, and queue a new document for processing
Request:
multipart/form-datafields:
workspace_id(required)file(required)title(optional)
Behavior:
validates upload size before reading
stages the file to disk
computes checksum
stores the managed file
creates a
registereddocument recordsubmits (or reuses an active) ingestion job in OpenSearch before returning
rolls back registration if job submission fails
requires workspace owner, admin, or member
Success:
201 Createdreturns
DocumentResponse
GET /api/aibs/documents/catalog
Purpose:
return a paged workspace document catalog for the source-list UI
Query parameters:
workspace_id(required)limit(default100, min1, max500)offset(default0)q(optional metadata/title/search text, max200)language(optional ISO/language filter)status(optional, repeatable document status filter)
Behavior:
requires any active workspace role
reads from the OpenSearch-backed document catalog projection
returns lightweight document metadata, not full aggregate JSON
summarydescribes the full workspace;page.total_matchesdescribes the current filtered result set
Success:
200 OKreturns
DocumentCatalogResponse
GET /api/aibs/documents/search
Purpose:
search documents independently from the assistant conversation flow
Query parameters:
workspace_id(required)q(required fortext,semantic, andhybrid; optional metadata fallback)mode(defaultmetadata; supported:metadata,text,semantic,hybrid)limit(default50, min1, max500)offset(default0)language(optional for metadata mode)status(optional, repeatable for metadata mode)include_disabled(defaulttrue; when false, excludes documents disabled from assistant knowledge retrieval)
Behavior:
metadatadelegates to the catalog projection for title/language/status searchtextsearches indexed chunk text and returns highlighted snippetssemanticembeds the query, searches chunk vectors, and returns semantic evidence snippetshybridis the backend Smart mode: it combines metadata, text, and semantic signals with Reciprocal Rank Fusion (k=60), and may use guarded assistant-backed query expansionSmart query expansion never runs for plain catalog, text, or semantic modes; if expansion fails, deterministic hybrid results are still returned
Success:
200 OKreturns
DocumentCatalogResponse
GET /api/aibs/documents
Purpose:
list documents within one workspace through the legacy simple list route
Query parameters:
workspace_id(required)limit(default50, min1, max200)offset(default0)
Success:
200 OKreturns
DocumentListResponse
PATCH /api/aibs/documents/{document_id}/knowledge
Purpose:
enable or disable a document for assistant knowledge retrieval while keeping it visible as an uploaded workspace artifact
Request:
JSON body:
enabled(required boolean)
Behavior:
requires workspace owner or admin
disabled documents remain catalog-searchable and previewable unless the caller explicitly asks search to exclude them with
include_disabled=falsedisabled documents are excluded from assistant knowledge retrieval
Success:
200 OKreturns
DocumentResponse
GET /api/aibs/documents/{document_id}/snippets
Purpose:
return a small set of indexed chunk previews for a document
Query parameters:
workspace_id(required)n(default3, min1, max10)
Behavior:
requires any active workspace role
returns an empty list for documents that are not indexed/searchable yet
does not call the LLM
Success:
200 OKreturns
DocumentSnippetListResponse
GET /api/aibs/documents/{document_id}/preview
Purpose:
stream the original uploaded document for inline preview or download
Query parameters:
workspace_id(required)download(defaultfalse; when true, uses attachment disposition)
Behavior:
requires any active workspace role
disabled knowledge documents remain previewable
inline preview is capped by
AIBS_MAX_UPLOAD_SIZE_BYTES; download bypasses that preview cap
Success:
200 OKreturns the file stream
GET /api/aibs/documents/{document_id}
Purpose:
fetch one document by id inside a specific workspace
Behavior:
enforces workspace membership
loads the document
enforces that the document belongs to the requested workspace
Success:
200 OKreturns
DocumentResponse
POST /api/aibs/documents/{document_id}/process
Purpose:
submit or reuse a durable ingestion job for a document (manual retry/recovery path)
Behavior:
requires workspace owner, admin, or member
rejects documents in draft, uploaded, or other invalid pre-registration states
creates a new ingestion job in OpenSearch or reuses the existing active job for the same document (no duplicate jobs per document)
returns immediately — actual parse/chunk/index work happens asynchronously in the ingestion worker loop
Success:
202 Acceptedreturns
ProcessAcceptedResponse
Important note:
processing_started=falsemeans an active job already existed and was reused, not that processing failedjob_idin the response identifies the OpenSearch job record for traceability
DELETE /api/aibs/documents/{document_id}
Purpose:
delete one document and its bounded indexed content
Behavior:
requires workspace owner or admin
rejects deletion if the document is currently in the in-flight processing registry
rejects deletion if the persisted document status is a processing state
Success:
204 No Content
POST /api/aibs/chat/
Purpose:
answer a workspace-scoped question over the current conversation orchestration seam
Behavior:
enforces active workspace membership; viewers may ask questions
resolves or creates a real persisted conversation bound to the workspace
rejects explicit document ids that do not belong to the workspace
accepts
execution_mode_overridevaluesauto,creative, orgrounded(casualis accepted only as a legacy compatibility alias forcreative)streams an SSE response
Current note:
chat now runs through evidence-regime routing followed by workload planning
public evidence regimes are:
creative- evidence optional, with citations when source evidence is usedgrounded- strict evidence required for factual claims
internal workload strategies are:
chatchat_map_reduceagent_map_refine_compose
turns can complete as:
creativedocument_groundedconversation_contextinsufficient
the SSE contract includes query and answer ids plus answer-mode truth
Success:
200 OKreturns
text/event-stream
Response Models
WorkspaceResponse
Fields:
workspace_idnamevisibilitystatusmember_countowner_countcreated_atupdated_atcurrent_user_role
WorkspaceListResponse
Fields:
workspaces: list[WorkspaceResponse]
WorkspaceMemberResponse
Fields:
membership_iduser_idrolejoined_at
ConversationResponse
Fields:
conversation_idworkspace_idtitlecreated_bycreated_atupdated_at
ConversationListResponse
Fields:
conversations: list[ConversationResponse]
ConversationHistoryResponse
Fields:
conversation_idturns: list[ConversationHistoryTurnResponse]
ConversationHistoryTurnResponse
Fields:
query_idworkspace_idconversation_idquestion_textquery_statusanswer_idanswer_textpublication_statusconfidence_labelcitationsis_fallbackgroundedasked_atanswered_at
DocumentResponse
Fields:
document_idworkspace_idtitlemedia_typestatusis_degradedfailure_reasonknowledge_enabledingestion_activelanguagechunk_countpage_countsearch_scoresearch_match_reasonssearch_snippetscreated_atupdated_at
DocumentListResponse
Fields:
documents: list[DocumentResponse]
DocumentCatalogResponse
Fields:
documents: list[DocumentResponse]summary: DocumentCatalogSummaryResponsepage: DocumentCatalogPageResponse
Notes:
summaryis workspace-wide, even when a search/filter is active.page.total_matchesis the result denominator for the current catalog/search request. For semantic and hybrid search, it can be bounded by the candidate window rather than an exact full-workspace count.
DocumentCatalogSummaryResponse
Fields:
totalreadyprocessingqueuedreviewchunks
DocumentSnippetResponse
Fields:
chunk_idtitletextpage_startpage_endmatch_reasonhighlights
DocumentSnippetListResponse
Fields:
document_idsnippets: list[DocumentSnippetResponse]
ProcessAcceptedResponse
Fields:
document_idstatusprocessing_startedjob_id(the OpenSearch ingestion job id;nullwhen the route short-circuits before submission)
Error payload
The app maps AIBSError subclasses into JSON responses shaped like:
{
"error": "Error message description",
"code": "stable_error_code"
}
Typical status mapping:
400validation errors403authorization failures404missing entities409duplicates / invalid state transitions422invariant violations502external service errors500persistence and unexpected backend failures
Current Contract Boundaries
Workspace and conversation truth now live in backend-owned persistence.
Conversation reload is rebuilt from persisted
QueryExecutionandAnswerArtifactrecords rather than a separate transcript store.Auth is active. Non-dev mode requires cookie-backed sessions from OpenSearch/Logserver credentials and explicit
aibs-access.Product administration requires both
aibs-accessandaibs-admin.Workspace membership remains the workspace authorization source of truth.
Ingestion is a durable OpenSearch-backed job API with OCC-based claiming and lease reaping.
Document catalog/search reads are backed by a separate OpenSearch projection; document JSON remains the aggregate source of truth.
Smart document search is
mode=hybrid; assistant-backed query expansion is guarded and best-effort inside that mode only.