Skip to main content
What this is for: build a custom integration against the selected /v1 request and response shapes Comis implements. Who it’s for: developers who can validate and adapt their client to this documented subset. Comis mounts experimental OpenAI-shaped routes at the /v1/ prefix. The shapes are intentionally limited, unknown request fields are rejected, and Comis’s agent and session semantics differ from the upstream APIs. This is not a general compatibility guarantee for OpenAI SDKs, proxies, or third-party tools. Test the exact client and fields you intend to use. Authentication uses gateway bearer tokens with rpc, api, or wildcard scope.

Endpoints

The gateway also mounts the experimental POST /v1/responses route. It is listed in the HTTP Gateway routes reference but is intentionally not described here because it has a separate schema and event model.

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 preserved in their original system-message order and passed through the system-prompt path. User and assistant turns are preserved in their original order with explicit role boundaries, so a request can supply its full conversation history. Caller-supplied context remains untrusted; imported system and assistant content receives explicit external-content fences before entering the agent prompt. If no non-empty 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 the implemented OpenAI-shaped values. Unknown reasons default to "stop".
Source: FINISH_REASON_MAP in packages/gateway/src/openai/openai-types.ts

Session Key

Each request to /v1/chat/completions 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 server-retained conversation history between requests. Each call is stateless, while the complete history supplied in that request remains available to the agent.
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 experimental OpenAI-shaped routes are mounted 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