Skip to main content
What this is for: point any OpenAI-API-compatible client at Comis and have it talk to your local agents. Who it’s for: developers integrating Comis into existing OpenAI-shaped tooling (LangChain, custom GPTs, third-party UIs). Comis exposes an OpenAI-compatible REST API at the /v1/ prefix. Any client library, proxy, or tool that speaks the OpenAI Chat Completions protocol can connect to Comis without modification. The API supports chat completions (streaming and non-streaming), model listing, embeddings, and the OpenAI Responses API. Authentication uses the same gateway bearer tokens as JSON-RPC, so a token with rpc or api scope works.

Endpoints

The gateway also mounts POST /v1/responses (OpenAI Responses API). It is listed in the HTTP Gateway routes reference but is intentionally not described here because the OpenAI Responses spec is separate from the Chat Completions spec.

Authentication

All endpoints require a valid bearer token configured in gateway.tokens[]. Pass the token via the Authorization header:
Tokens are defined in config with a minimum 32-character secret and optional scope restrictions:

Chat Completions

Request

POST /v1/chat/completions The request body is validated against ChatCompletionRequestSchema. All fields must match exactly — unknown fields are rejected (strictObject).
Source: ChatCompletionRequestSchema in packages/gateway/src/openai/openai-types.ts

Message Format

Each message in the messages array follows ChatMessageSchema: System messages are concatenated (joined with newline) and passed as the system prompt. The last user message becomes the agent input. If no user message is found, the request returns 400. When content is a content-block array, the text blocks are flattened (joined with newline) into the message text. Vision input is not yet supported via this endpoint: a request whose content carries an image_url block returns a named 400 (“Vision input (image_url) is not yet supported via the /v1 chat completions endpoint…”) rather than silently dropping the image. Send images through a chat channel (Telegram, Discord, etc.) instead.

Stream Options

Example Request

POST /v1/chat/completions

Non-Streaming Response

When stream is false (default), the endpoint returns a single JSON object following the ChatCompletion interface:
ChatCompletion Response
Source: ChatCompletion interface in packages/gateway/src/openai/openai-types.ts

Streaming Response

When stream is true, the endpoint returns Server-Sent Events (SSE). Each event contains a ChatCompletionChunk serialized as JSON. The streaming sequence follows five steps: Step 1: Role chunk — Announces the assistant role.
Step 2: Content chunks — One event per text delta (N chunks).
Step 3: Finish chunk — Contains the finish_reason, empty delta.
Step 4: Usage chunk — Token counts with empty choices array.
Step 5: Terminal marker — Signals end of stream.

ChatCompletionChunk Interface

Source: ChatCompletionChunk interface in packages/gateway/src/openai/openai-types.ts, streaming sequence in packages/gateway/src/openai/openai-completions.ts

Finish Reason Mapping

Comis maps its internal finish reasons to OpenAI-compatible values. Unknown reasons default to "stop".
Source: FINISH_REASON_MAP in packages/gateway/src/openai/openai-types.ts

Session Key

Each OpenAI API request creates an ephemeral session with an auto-generated key:
The peerId uses the completion ID, making each request a unique session. This means there is no conversation history between requests — each call is stateless from the agent’s perspective.
Source: Session key construction in packages/gateway/src/openai/openai-completions.ts

Model Resolution

If the gateway has a resolveModel function wired, the model field is validated against the model catalog. If the model is not found, the endpoint returns a 404 error:

Models

List Models

GET /v1/models Returns all configured models in OpenAI’s List Models format.
GET /v1/models Response

Get Model

GET /v1/models/:model_id Retrieves a single model by its ID. Model IDs use provider/modelId format (e.g., anthropic/claude-sonnet-4-5-20250929). The route uses a wildcard param to accommodate the slash in the ID. Success:
GET /v1/models/anthropic/claude-sonnet-4-5-20250929
Not found:

Model Format

Each model object has the following fields:
Source: toOpenAIModel() in packages/gateway/src/openai/openai-models.ts

Embeddings

Request

POST /v1/embeddings The request body is validated against EmbeddingsRequestSchema.

Example Requests

Single string input
Batch input

Response

POST /v1/embeddings Response
If no embedding provider is configured, the endpoint returns 404:
Source: EmbeddingsRequestSchema and createOpenaiEmbeddingsRoute() in packages/gateway/src/openai/openai-embeddings.ts

Error Responses

All endpoints return errors in the OpenAIErrorResponse format:
Error Response Format

Error Type Mapping

Unknown HTTP status codes fall back to "server_error".
Source: STATUS_TO_ERROR_TYPE and createOpenAIError() in packages/gateway/src/openai/openai-types.ts

Configuration

The OpenAI-compatible API is enabled automatically when the gateway is running. Relevant configuration fields:
Source: GatewayConfigSchema in packages/core/src/config/schema-gateway.ts

HTTP Gateway

Full gateway endpoint reference

JSON-RPC

JSON-RPC method reference

WebSocket

WebSocket streaming reference

Rate Limiting

Rate limiting configuration