API Reference Batch 9 — Avatar, Preferences, System Config & Model Catalog
API Reference Batch 9 — Avatar, Preferences, System Config & Model Catalog
Section titled “API Reference Batch 9 — Avatar, Preferences, System Config & Model Catalog”This batch documents four endpoint groups added or expanded in platform sprints 0050–0053: avatar management, user preferences, system configuration, and the model catalog administration API.
Authentication
Section titled “Authentication”Unless otherwise noted, all endpoints require a valid Bearer token:
Authorization: Bearer <jwt>Admin-only endpoints additionally require the authenticated user to have role: admin.
Avatar Management
Section titled “Avatar Management”Avatar endpoints manage profile pictures for users. Images are resized to 256×256 PNG and stored in frontend/public/avatars/ as {user_id}.png.
Upload User Avatar
Section titled “Upload User Avatar”Upload or replace the current user’s avatar.
PATCH /api/users/me/avatarAuthorization: Bearer <jwt>Content-Type: multipart/form-dataRequest body (multipart form):
| Field | Type | Required | Description |
|---|---|---|---|
file | file | Yes | PNG or JPEG image; max 1 MB |
Processing:
- Image is validated (PNG or JPEG only; > 1 MB rejected with 413).
- Pillow resizes and crops to 256×256 PNG.
- Saved to
frontend/public/avatars/{user_id}.png(overwrites existing). avatar_urlset to/avatars/{user_id}.pnginprofile_settingsJSONB.
Response 200 OK:
{ "default_model_id": null, "preferred_models": [], "default_summarizer_model_id": null, "theme": "system", "avatar_url": "/avatars/a1b2c3d4-uuid.png"}Errors:
| Code | Reason |
|---|---|
400 | File is not PNG or JPEG |
413 | File exceeds 1 MB |
401 | Not authenticated |
Delete User Avatar
Section titled “Delete User Avatar”Remove the current user’s avatar.
DELETE /api/users/me/avatarAuthorization: Bearer <jwt>Deletes frontend/public/avatars/{user_id}.png from disk and clears avatar_url from profile_settings. If no avatar was set, this is a no-op.
Response 204 No Content
Admin: Set User Avatar
Section titled “Admin: Set User Avatar”Set or replace the avatar for any user (admin only).
PATCH /api/admin/users/{user_id}/avatarAuthorization: Bearer <jwt>Content-Type: multipart/form-dataPath parameters:
| Parameter | Type | Description |
|---|---|---|
user_id | UUID | Target user’s ID |
Request body: Same multipart form as user self-upload (file field, PNG/JPEG, max 1 MB).
Same processing pipeline as user self-upload. Returns the updated UserPreferences for the target user.
Response 200 OK — same schema as upload response.
Errors:
| Code | Reason |
|---|---|
404 | User not found |
403 | Not admin |
400 / 413 | Same as user upload |
User Preferences
Section titled “User Preferences”Preferences store per-user UI and model settings in the profile_settings JSONB column. Defaults are returned when the column is null or empty.
Get Preferences
Section titled “Get Preferences”GET /api/users/me/preferencesAuthorization: Bearer <jwt>Response 200 OK:
{ "default_model_id": "claude-3-opus-20240229", "preferred_models": ["claude-3-opus-20240229", "gpt-4o"], "default_summarizer_model_id": null, "theme": "dark", "avatar_url": "/avatars/a1b2c3d4-uuid.png"}| Field | Type | Default | Description |
|---|---|---|---|
default_model_id | string | null | null | Pre-selected model when opening new conversations |
preferred_models | string[] | [] | Ordered list of preferred model IDs for multi-model modes |
default_summarizer_model_id | string | null | null | Pre-selected synthesizer model for Summarize mode |
theme | "system" | "light" | "dark" | "system" | UI color scheme preference |
avatar_url | string | null | null | Path to user’s avatar image |
Update Preferences
Section titled “Update Preferences”Merge new preference values into the current user’s settings. Only supplied fields are updated — omitted fields retain their current value.
PUT /api/users/me/preferencesAuthorization: Bearer <jwt>Content-Type: application/jsonRequest body (all fields optional):
{ "default_model_id": "gpt-4o", "preferred_models": ["gpt-4o", "claude-3-opus-20240229"], "default_summarizer_model_id": "claude-3-opus-20240229", "theme": "dark"}Note:
avatar_urlcannot be set via this endpoint — use the avatar upload endpoint instead.
Response 200 OK — the full updated preferences object (same schema as GET).
System Configuration
Section titled “System Configuration”The system config API manages platform-wide settings. Values resolve with priority: database override > environment variable > compiled default. All keys are admin-only.
List All Config Keys
Section titled “List All Config Keys”GET /api/admin/configAuthorization: Bearer <jwt>Returns all known configuration keys grouped by category.
Response 200 OK:
[ { "key": "auto_title_enabled", "category": "conversation", "value": "true", "default": "true", "editable": true, "description": "Enable automatic conversation title generation" }, { "key": "auto_title_model", "category": "conversation", "value": "anthropic/claude-haiku-3-20240307", "default": "anthropic/claude-haiku-3-20240307", "editable": true, "description": "Model used for auto-title generation (format: provider/model_id)" }]| Field | Type | Description |
|---|---|---|
key | string | Config key name |
category | string | Logical grouping (e.g., conversation, security, auth) |
value | string | Resolved value (DB override > env > default) |
default | string | Compiled-in default |
editable | bool | Whether the key can be changed via the API |
description | string | Human-readable description |
Update Config Key
Section titled “Update Config Key”PUT /api/admin/config/{key}Authorization: Bearer <jwt>Content-Type: application/jsonPath parameters:
| Parameter | Type | Description |
|---|---|---|
key | string | Config key to update (e.g., auto_title_enabled) |
Request body:
{ "value": "false"}All values are stored as strings. Boolean values use "true" / "false".
Response 200 OK — the updated config entry (same schema as list item).
Errors:
| Code | Reason |
|---|---|
404 | Key does not exist |
422 | Key is not editable (editable: false) |
403 | Not admin |
Notable config keys:
| Key | Type | Description |
|---|---|---|
auto_title_enabled | bool | Enable/disable auto-title generation for new conversations |
auto_title_model | string | Model for auto-title (format: provider/model_id) |
governance_enabled | bool | Enable human-in-loop governance prompts |
mfa_required | bool | Require MFA for all users in the organization |
max_conversation_messages | int | Maximum messages per conversation before hard limit |
Model Catalog
Section titled “Model Catalog”The model catalog stores the set of available AI models. Admins can manage catalog entries directly (add, update, disable) and trigger provider discovery to auto-populate from connected providers.
Router prefix: /api/admin/models/catalog
List Catalog
Section titled “List Catalog”GET /api/admin/models/catalog/Authorization: Bearer <jwt>Query parameters:
| Parameter | Type | Default | Description |
|---|---|---|---|
provider | string | — | Filter by provider name (e.g., openai) |
is_active | bool | — | Filter by active/inactive status |
page | int | 1 | Page number |
per_page | int | 50 | Items per page |
Response 200 OK:
{ "items": [ { "id": "uuid", "provider": "anthropic", "model_id": "claude-3-opus-20240229", "display_name": "Claude 3 Opus", "is_active": true, "context_window": 200000, "supports_vision": false, "max_output_tokens": 4096, "created_at": "2026-01-15T10:00:00Z" } ], "total": 42, "page": 1, "per_page": 50}Create Catalog Entry
Section titled “Create Catalog Entry”POST /api/admin/models/catalog/Authorization: Bearer <jwt>Content-Type: application/jsonRequest body:
{ "provider": "openai", "model_id": "gpt-4o-2024-11-20", "display_name": "GPT-4o (Nov 2024)", "is_active": true, "context_window": 128000, "supports_vision": true, "max_output_tokens": 16384}| Field | Required | Description |
|---|---|---|
provider | Yes | Provider name (must match a registered provider) |
model_id | Yes | Provider-specific model identifier |
display_name | No | Human-readable name shown in the UI |
is_active | No | Whether the model appears in the model selector (default: true) |
context_window | No | Maximum context window in tokens |
supports_vision | No | Whether the model accepts image inputs |
max_output_tokens | No | Maximum output tokens per request |
Response 201 Created — the created ModelConfig record.
Errors:
| Code | Reason |
|---|---|
409 | A catalog entry with the same provider + model_id already exists |
Get Catalog Entry
Section titled “Get Catalog Entry”GET /api/admin/models/catalog/{model_config_id}Authorization: Bearer <jwt>Path parameters:
| Parameter | Type | Description |
|---|---|---|
model_config_id | UUID | Catalog entry primary key |
Response 200 OK — the ModelConfig record.
Errors: 404 if not found.
Update Catalog Entry
Section titled “Update Catalog Entry”Partial update — only supplied fields are changed.
PUT /api/admin/models/catalog/{model_config_id}Authorization: Bearer <jwt>Content-Type: application/jsonRequest body (all fields optional):
{ "display_name": "GPT-4o Latest", "is_active": false, "context_window": 128000}Response 200 OK — the updated ModelConfig record.
Errors: 404 if not found.
Delete Catalog Entry
Section titled “Delete Catalog Entry”DELETE /api/admin/models/catalog/{model_config_id}Authorization: Bearer <jwt>Permanently deletes the catalog entry. Models in use by existing conversations retain their model_config_snapshot but can no longer be selected for new requests.
Response 204 No Content
Errors: 404 if not found.
Discover Models
Section titled “Discover Models”Query all connected providers for their available models and return discovered model metadata without persisting to the catalog.
GET /api/admin/models/catalog/discoverAuthorization: Bearer <jwt>Response 200 OK:
[ { "provider": "openai", "model_id": "gpt-4o-2024-11-20", "display_name": "GPT-4o", "context_window": 128000, "supports_vision": true, "already_in_catalog": false }]already_in_catalog: true means a matching provider+model_id pair exists in the catalog. Use this to identify new models available for import.
Sync Models
Section titled “Sync Models”Automatically add discovered models to the catalog. Models already in the catalog (by provider+model_id) are skipped; new models are created with is_active: true.
POST /api/admin/models/catalog/syncAuthorization: Bearer <jwt>Response 200 OK:
{ "added": 3, "skipped": 12, "added_models": [ { "provider": "openai", "model_id": "gpt-4o-2024-11-20" } ]}Bulk Update Catalog Entries
Section titled “Bulk Update Catalog Entries”Enable or disable multiple catalog entries in a single request.
PATCH /api/admin/models/catalog/bulkAuthorization: Bearer <jwt>Content-Type: application/jsonRequest body:
{ "model_ids": ["uuid-1", "uuid-2", "uuid-3"], "is_active": false}| Field | Required | Description |
|---|---|---|
model_ids | Yes | List of ModelConfig UUIDs to update |
is_active | Yes | New active state for all listed models |
IDs that do not match any catalog entry are silently ignored.
Response 200 OK — list of updated ModelConfig records.
Share Links (v2)
Section titled “Share Links (v2)”The share link v2 API provides per-token management for conversation sharing, replacing the single-token share/unshare pattern. Each share link has its own UUID and can be independently revoked.
Router prefix: /api/conversations/{conversation_id}/share_links
Create Share Link
Section titled “Create Share Link”POST /api/conversations/{conversation_id}/share_linksAuthorization: Bearer <jwt>Generates a new unguessable UUID4 share token. Multiple share links can exist for the same conversation.
Response 201 Created:
{ "id": "link-uuid", "token": "a3f82bc1-...", "conversation_id": "conv-uuid", "created_at": "2026-03-12T10:00:00Z", "revoked": false, "url": "https://your-instance.com/shared/a3f82bc1-..."}List Share Links
Section titled “List Share Links”GET /api/conversations/{conversation_id}/share_linksAuthorization: Bearer <jwt>Returns all share links for the conversation — both active and revoked.
Response 200 OK — array of share link objects (same schema as create response).
Revoke Share Link
Section titled “Revoke Share Link”DELETE /api/conversations/{conversation_id}/share_links/{token_id}Authorization: Bearer <jwt>Marks the share link as revoked. The token can no longer be used to access the conversation. The link record is retained for audit purposes.
Response 204 No Content
Errors: 404 if conversation or token not found, or not owned by current user.
Access Shared Conversation (via share link)
Section titled “Access Shared Conversation (via share link)”GET /api/share_links/{token}No authentication required. Returns the conversation and all its messages in read-only mode using the share link token.
Response 200 OK — conversation object with messages array.
Errors: 404 if token is not found or has been revoked.
Related Documentation
Section titled “Related Documentation”- User Profiles Guide — avatar upload and preferences walkthrough
- Conversation Management — auto-title configuration
- Model Catalog Reference — enabling/disabling models for users
- API Reference Batch 8 — Cloud Portal API