---
title: "Unified Chat Completions"
method: POST
path: "/v1/chat/completions"
tags: ["v1 chat"]
---

# Unified Chat Completions

`POST /v1/chat/completions`

Unified generation endpoint that accepts the Universal Schema plus configuration
    objects for any outputs (Text, Image, Audio, or all at once).
    
    This is the "Omni" endpoint for the Elicit Labs Modal System.
    It acts as a thin orchestrator:
    
    **Flow:**
    1. Extracts text + multimodal content from the messages array
    2. Classifies the desired output modality via LLM (text / image / audio / agent)
    3. Delegates to the appropriate handler:
       - text  → POST /v1/text/generations
       - image → POST /v1/images/generations
       - audio → POST /v1/audio/generations
       - agent → Agent tool-calling loop (multi-step orchestration)
    4. Returns unified response with text + optional image/audio
    
    All validation, memory retrieval, and generation logic lives in the
    dedicated routers. This endpoint just classifies and dispatches.
    
    **Authentication**: Requires valid API key or JWT token

## Request body

- ChatCompletionRequest — Request model for unified chat completions
  - `user_id` string, required — The end-user ID
  - `project_id` string, nullable — The project ID
  - `persona_id` string, nullable — The specific system persona/voice to use
  - `disabled_learning` boolean — If true, this request is ignored by long-term memory
  - `use_reasoning` boolean — Enable Chain-of-Thought/Reasoning steps before answering
  - `max_reasoning_iterations` integer — Max reasoning steps if reasoning is enabled
  - `stream` boolean — Enable streaming response (SSE)
  - `messages` MessageContent[], required — List of messages (system, user, assistant) with text, images, video, or audio
    - `role` string, required — Message role: 'system', 'user', or 'assistant'
    - `content` union, required — Message content - can be: - A simple text string - An array of content parts for multimodal input: [ {"type": "text", "text": "What's in this image?"}, {"type": "image", "content": "base64_encoded_image..."}, {"type": "image_url", "image_url": {"url": "data:image/jpeg;base64,..."}}, {"type": "video", "content": "base64_encoded_video..."}, {"type": "audio", "content": "base64_encoded_audio..."} ]
      - string
      - ContentPart[]
        - `type` string, required — Content type: 'text', 'image', 'video', 'audio', or 'image_url'
        - `text` string, nullable — Text content (when type='text')
        - `content` string, nullable — Base64 encoded content (for image/video/audio)
        - `url` string, nullable — Signed GCS URL to download the asset (expires after 24 h)
        - `format` string, nullable — Asset format, e.g. png, jpeg, mp3, wav, mp4
        - `image_url` object, nullable — Image URL object with 'url' key (can be data:image/... base64)
        - `video_url` object, nullable — Video URL object with 'url' key
        - `audio_url` object, nullable — Audio URL object with 'url' key
      - object[]
  - `agent_mode` boolean — Enable agent mode for multi-step tool-calling workflows. When True (or when the classifier detects agentic intent), the request is handled by the agent service which can orchestrate memory retrieval, video analysis, segmentation, image generation, and more.
  - `auto_detect_agent` boolean — When True (default), the modality classifier may auto-route to agent mode even if not explicitly requested. Set to False for deterministic routing (e.g. Instagram integration) where you want only the modalities you specify.
  - `load_history` boolean — When True, loads prior conversation turns from the database using session_id and prepends them to messages. Use this for stateless callers (e.g. Instagram webhooks) that send only the latest message and rely on server-side history. Requires session_id to be set.
  - `history_limit` integer — Maximum number of prior turns to load when load_history is True
  - `modalities` string[] — List of desired outputs: 'text', 'image', 'audio'. When 'agent' is included or agent_mode is True, the agent loop handles the request.
  - `image_config` ImageConfig — Configuration overrides for image generation
    - `model` string, nullable — Image generation model (e.g., gemini-3-flash, dall-e-3)
    - `size` string, nullable — Image dimensions
    - `seed` integer, nullable — Random seed for reproducibility
  - `audio_config` AudioConfig — Configuration overrides for audio generation
    - `model` string, nullable — Audio generation model
    - `voice` string — Voice to use — ElevenLabs voices (Rachel, Drew, Clyde, etc.) or OpenAI voices (alloy, echo, fable, onyx, nova, shimmer)
    - `audio_type` string — Type: 'speech' (TTS), 'music', or 'sfx'
    - `speed` number — Speech speed (0.25-4.0)
    - `duration` number, nullable — Duration in seconds for music/sfx
  - `model` string — LLM model to use for generation
  - `session_id` string, nullable — Session ID for conversation context
  - `skip_initial_retrieval` boolean — When True, the agent skips the automatic memory retrieval at the start of each turn. Use this when the caller has already embedded user context in the system prompt (e.g. Instagram integration) and wants the agent to retrieve memories on-demand via the tool instead.
  - `video_refs` object, nullable — Map of video labels (video_0, video_1, …) to GCS S3 keys from conversation history.

## Response `200`

Successful Response

- ChatCompletionResponse — Response model for chat completions - returns the full conversation including the assistant's reply
  - `session_id` string, required — Session ID for conversation context
  - `messages` MessageContent[], required — Full conversation: the original user messages plus the assistant's response appended
    - `role` string, required — Message role: 'system', 'user', or 'assistant'
    - `content` union, required — Message content - can be: - A simple text string - An array of content parts for multimodal input: [ {"type": "text", "text": "What's in this image?"}, {"type": "image", "content": "base64_encoded_image..."}, {"type": "image_url", "image_url": {"url": "data:image/jpeg;base64,..."}}, {"type": "video", "content": "base64_encoded_video..."}, {"type": "audio", "content": "base64_encoded_audio..."} ]
      - string
      - ContentPart[]
        - `type` string, required — Content type: 'text', 'image', 'video', 'audio', or 'image_url'
        - `text` string, nullable — Text content (when type='text')
        - `content` string, nullable — Base64 encoded content (for image/video/audio)
        - `url` string, nullable — Signed GCS URL to download the asset (expires after 24 h)
        - `format` string, nullable — Asset format, e.g. png, jpeg, mp3, wav, mp4
        - `image_url` object, nullable — Image URL object with 'url' key (can be data:image/... base64)
        - `video_url` object, nullable — Video URL object with 'url' key
        - `audio_url` object, nullable — Audio URL object with 'url' key
      - object[]
  - `assistant_output` AssistantOutput — Convenience extraction of just the assistant's reply — useful for stateless integrations like Instagram that only need the response.
    - `text` string, nullable — Plain-text portion of the reply
    - `image_base64` string, nullable — Base64-encoded image (if any)
    - `audio_base64` string, nullable — Base64-encoded audio (if any)
    - `image_url` string, nullable — Signed URL for the image (if any)
    - `audio_url` string, nullable — Signed URL for the audio (if any)
  - `agent_trace` object[], nullable — Agent execution trace — present only when the request was handled by the agent service

## Other responses

- `400` — Bad Request
- `401` — Unauthorized
- `404` — User/Persona/Project Not Found
- `422` — Validation Error
- `500` — Internal Server Error

---

[API](https://skmtc.net/elicitlabs/apis/elicit-labs-api.md) · [All operations](https://skmtc.net/elicitlabs/apis/elicit-labs-api/llms.txt) · [OpenAPI document](https://skmtc-service-staging.skmtc.workers.dev/v1/apis/elicitlabs/elicit-labs-api/revisions/27701839a070/schema)
