Skip to main content

HTTP Endpoints

REST reference for the gateway service. All application routes mount under the /api_lis prefix; only GET /health sits at the root. Every /api_lis endpoint is guarded by Authentication (X-Api-Key + X-User-ID); WebSocket relays are documented separately in the WebSocket Protocol.

Conventions

  • Base path: all session and memory routes are prefixed with /api_lis (for example /api_lis/sessions). GET /health is the only route not under this prefix.
  • Auth: every /api_lis route depends on get_current_user, which requires a valid X-User-ID UUID and — when GATEWAY_API_TOKEN is set — a matching X-Api-Key. A missing or malformed X-User-ID returns 400; a mismatched API key returns 401.
  • User scope: user_id comes from the X-User-ID header and scopes every query. A session or fact that belongs to another user is reported as 404 (not found), never 403.
  • Timestamps: all timestamps are ISO 8601 strings.

Error response shape

Handled AppError responses share one JSON body:

{
"error": "not_found",
"message": "Session not found."
}
StatusMeaning
400Malformed path/header value (bad UUID, missing X-User-ID)
401Invalid or missing X-Api-Key (only when a key is configured)
404Resource not found or not owned by the caller
500Unhandled or repository error ({"error": "internal_error"})

Sessions

GET /api_lis/sessions

List every active session belonging to the authenticated user, keyed by session id.

Response 200 OK (SessionsResponse)

{
"sessions": {
"<session_uuid>": {
"avatar_id": "<avatar_uuid>",
"name": "My session",
"created_at": "2024-01-01T12:00:00Z"
}
}
}

POST /api_lis/sessions

Create a session linked to an avatar. The avatar_id is validated against ml.avatars; the resolved avatar UUID is stored as the session's avatar_id.

Request (CreateSessionRequest)

{
"avatar_id": "<avatar_uuid>"
}

Response 201 Created (SessionSummary)

{
"session_id": "<session_uuid>",
"name": null,
"created_at": "2024-01-01T12:00:00Z"
}

Errors: 404 if the avatar does not exist; 400 if avatar_id is not a valid UUID.

GET /api_lis/sessions/{session_id}/messages

Return conversation history for a session in chronological order. The repository fetches up to the last 1000 turns newest-first, then reverses them.

Response 200 OK (ChatMessagesResponse)

{
"session_id": "<session_uuid>",
"messages": [
{
"id": 1,
"role": "user",
"content": "Hello",
"created_at": "2024-01-01T12:00:00Z"
},
{
"id": 2,
"role": "assistant",
"content": "Hi there!",
"created_at": "2024-01-01T12:00:01Z"
}
],
"count": 2
}
note

The message list does not include attachments. content may be null for turns with no text body.

Errors: 404 if the session does not exist or does not belong to the user; 400 if session_id is not a valid UUID.

PATCH /api_lis/sessions/{session_id}

Update mutable session fields. Only the fields present in the request body are changed (unset fields are left untouched).

Request (PatchSessionRequest)

{
"name": "Renamed session",
"description": "Optional notes"
}

Response 204 No Content

Errors: 404 if the session does not exist or does not belong to the user; 400 if session_id is not a valid UUID.

DELETE /api_lis/sessions/{session_id}

Soft-delete a session by setting its status to deleted. The row is retained.

Response 204 No Content

Errors: 404 if the session does not exist or does not belong to the user; 400 if session_id is not a valid UUID.

Memory

The memory router is mounted with its own /memory prefix under /api_lis, so the full paths are /api_lis/memory and /api_lis/memory/{fact_id}.

GET /api_lis/memory

List the authenticated user's memory facts, ordered by last_seen_at descending. Defaults to active facts only.

Query parameters

ParamTypeDefaultDescription
avatar_iduuidFilter to a specific avatar
statusesstring[]["active"]Filter by status; repeatable (e.g. ?statuses=active&statuses=superseded)

Response 200 OK (MemoryListResponse)

{
"facts": [
{
"fact_id": "<uuid>",
"avatar_id": "<uuid>",
"category": "preference",
"fact_key": "language",
"fact_value": "English",
"confidence": 0.92,
"status": "active",
"last_seen_at": "2024-01-01T12:00:00Z",
"created_at": "2024-01-01T10:00:00Z"
}
],
"total": 1
}

DELETE /api_lis/memory/{fact_id}

Soft-delete a single memory fact owned by the caller (sets status to deleted). Only the owning user can delete their own facts.

Response 204 No Content

Errors: 400 if fact_id is not a valid UUID.

note

There is no POST /api_lis/memory endpoint. Memory facts are created by the separate memory_service extraction pipeline, not through the gateway.

Health

GET /health

Liveness and dependency probe. Not under /api_lis and not authenticated. The gateway makes a 2-second HTTP call to the conversation engine's /health and reports ok only when the engine reports ok, otherwise degraded.

Response 200 OK (HealthResponse)

{
"status": "ok",
"service": "gateway_service",
"dependencies": {
"conversation_engine": { "status": "ok" }
}
}
note

Only the conversation engine is probed. STT, TTS, and the database pool are not checked by this endpoint.

WebSocket endpoints

The gateway also exposes three authenticated WebSocket relays under /api_lis: /api_lis/sessions/{session_id}/message, /api_lis/transcribe, and /api_lis/voiceover. Their frame formats, events, and close codes are covered in the WebSocket Protocol.