Chat completions
Build supported chat-completion requests and interpret validation, routing controls, responses, Ethen metadata, streaming, and errors.
Chat completions
The chat-completions route is the best-defined public Gateway contract in the supplied repository evidence. This guide documents only the implemented request fields, validation path, response forms, routing controls, and errors.
The route is implemented, but compatibility and release maturity remain under review.
A robust client should retain both the model-facing result and the Gateway-facing explanation of how that result was produced. The assistant message is the application payload; the Ethen extension, status header, attempts, warnings, and usage are operational context. Keeping those layers available makes it possible to diagnose a provider change, fallback, alias selection, or budget failure without parsing user-visible text. It also allows the application to remain conservative about request fields that resemble OpenAI options but are not implemented in the inspected handler.
Endpoint
Send POST requests to /api/gateway/v1/chat/completions.
The handler requires JSON input and a valid project Gateway key with invoke scope.
The request path should not be confused with the models GET endpoint or product UI routes.
The chat-completions endpoint is the verified execution entry point for this batch. It combines Ethen authentication and readiness checks with provider routing, then returns either a completed JSON response or an SSE stream.
Temperature, max_tokens, max_completion_tokens, stream, metadata, and Gateway provider options are optional.
Validation, key, model-readiness, budget, provider, streaming, and internal errors are represented by distinct error codes.
Request body
max_tokens and max_completion_tokens both express completion-length intent, but clients should avoid sending contradictory values. Routing preferences belong inside providerOptions.gateway, while application annotations belong in metadata; neither replaces the required model and messages. Unsupported top-level fields should be removed rather than passed through in the hope that a downstream provider adapter will accept them accidentally. This keeps client behavior tied to the Gateway contract instead of an accidental provider-specific extension. Reject unexpected fields during local client-side validation whenever practical.
If both completion-token fields are considered by a client, verify the handler behavior before sending them together. The source confirms that each field is recognized but does not define a universal precedence rule for every adapter.
The body requires a model string and a nonempty messages array. Optional fields visible in the handler are temperature, max_tokens, max_completion_tokens, stream, metadata, and providerOptions.gateway. Unknown compatibility fields should be removed unless a newer inspected contract explicitly adds them.
providerOptions.gateway can express request-level routing preferences, including provider order, an only restriction, provider-specific model mappings, and provider timeouts. These options narrow or modify an eligible project route; they do not bypass model runtime status, provider availability, allow-lists, policy preflight, credentials, budget, or circuit breakers.
Optional fields directly represented are temperature, max_tokens, max_completion_tokens, stream, metadata, and providerOptions.gateway.
The handler validates missing model and empty or missing messages before entering the routing runtime.
The required body is small: model and a nonempty messages array. Optional temperature, token limits, metadata, streaming, and Gateway routing controls should be added only when the application has a reason to use them.
Gateway options can express provider order, an only list, model aliases, and provider timeouts. The endpoint is POST /api/gateway/v1/chat/completions.
Non-streaming responses include selected provider, selected model alias, attempt count, fallback state, warnings, and usage. The handler requires a model and at least one message after Gateway authentication succeeds.
Messages
Tool messages, function-call messages, audio content, and provider-specific message extensions are not verified. Keep role and content handling within the inspected shape, and add new message variants only after the route implementation is rechecked.
Content may be plain text or an array of typed entries containing text or image URLs. The inspected route does not perform complete image handling: image entries are reduced to a placeholder. Applications that need verified multimodal behavior should not infer it from the accepted array type.
At least one message is required. A missing or empty message set returns missing_messages, while malformed JSON returns invalid_json. Keep role values and content simple in the first integration because the source bundle does not define every role validation rule or advanced message feature.
Each message includes a role and content.
Content may be a string or an array containing text and image_url-shaped items.
The current normalization fully preserves text but replaces image entries with a placeholder, so this route should not be presented as verified image understanding.
Minimal text request
{
"model": "YOUR_RUNNABLE_MODEL_ID",
"messages": [
{"role": "user", "content": "Explain the requested topic in two sentences."}
]
}Request with Gateway routing controls
{"role": "user", "content": "Return a concise status summary."}
],
"providerOptions": {
"gateway": {
"order": ["openai", "anthropic"],
"only": ["openai", "anthropic"],
"models": {
"openai": "YOUR_PROVIDER_MODEL_ALIAS"
},
"providerTimeouts": {
"openai": 30000Use only provider identifiers and aliases that are configured and eligible in the target project.
Messages accept a role and either text content or an array of content entries. The current route does not provide full image handling; image URL entries are normalized to a placeholder, so multimodal behavior must not be inferred from the TypeScript shape alone.
Model selection
The client supplies a model identifier; the routing layer decides which eligible provider can serve it. Request-level Gateway options may narrow provider order or restrict candidates, but they cannot make an unavailable provider healthy or grant a project permission that policy denies. When aliases are configured, the router can translate the requested model into a provider-specific identifier without requiring the client to hardcode that provider name.
When a model is not runnable, select another verified catalog ID rather than sending a provider alias as a substitute. Provider aliases are resolved inside the route and can differ by provider; exposing them to callers would couple application code to one backend.
The requested model is checked against the catalog runtime status before routing. Catalog-only records, missing provider credentials, unsupported modality, and other non-runnable states stop the request before or during route eligibility. If the model is eligible, the runtime resolves a profile, provider order, filters, project restrictions, policy, aliases, timeouts, retries, and fallbacks.
The response may report a selected model alias that differs from the client-visible model ID. That alias is provider-specific routing metadata, not a replacement for the original requested model in application state.
The requested model is checked against catalog runtime status before provider execution.
providerOptions.gateway can influence provider order, restrict eligible providers, map provider-specific model aliases, and set provider timeouts.
Project allow-lists, policy preflight, credentials, circuit state, and budget can narrow the final route further.
The requested model remains distinct from the provider-specific alias selected during routing. Provider order and only constraints can narrow candidates, but policy, availability, credentials, and circuit state still determine eligibility.
A retry adds another attempt against the same provider; a fallback changes the provider route and should be reported separately.
Start with text content and the verified body fields; preserve the response identifiers so a failure can be correlated with logs and provider attempts.
The endpoint is POST /api/gateway/v1/chat/completions. Request-level restrictions can narrow a project profile, but they cannot create provider support or override a policy exclusion.
Response
Client applications should retain the response identifiers even when they do not display them.
The response’s route metadata should be treated as structured operational data, not as display-only decoration. Preserve it through application boundaries so downstream logs can associate user-visible output with the selected provider, alias, warnings, attempts, fallback state, and token usage. Without that data, later incident review can identify the answer but not the execution path that produced it.
A successful non-streaming response follows an OpenAI-style chat.completion envelope and adds an ethen extension. The extension can identify the request, trace, project, selected provider, selected alias, attempt count, attempt details, fallback usage and reason, route source or mode, warnings, and usage.
Keep both the visible completion and the route metadata. The text answers the application request; the metadata explains how Ethen executed it. When fallback occurred, the attempt list is more informative than the final provider field alone.
A non-streaming success uses an OpenAI-style chat.completion object.
The ethen extension identifies request, trace, project, selected provider, attempts, fallback, and route information.
Usage and model-status metadata should be treated as request-specific observations rather than permanent model facts.
Non-streaming responses include normal chat-completion fields plus Ethen metadata. Keep request, trace, provider, selected alias, attempts, fallback status, warnings, and usage available to diagnostics rather than stripping them at the client boundary.
The endpoint is POST /api/gateway/v1/chat/completions.
A non-streaming success follows an OpenAI-style chat.completion structure, but the Ethen metadata is part of the operational contract. Record the request and trace identifiers, selected provider, selected model alias, attempt count, fallback state, routing source or mode, and warnings. The client-visible model request and the provider-specific alias should remain separate so later requests do not become accidentally tied to one backend.
Validation occurs before routing. The handler rejects malformed JSON, a missing model, and an empty or missing message list; authentication and scope checks follow the key contract; model-status and budget checks can then prevent provider execution. If routing proceeds, provider restrictions, project allow-lists, policy preflight, credentials, aliases, timeouts, retries, and fallback can affect the final result. A client should therefore interpret an error code together with the presence or absence of provider attempts rather than retrying every failure as though it came from a transient adapter.
Examples
A minimal request should exercise only the verified contract:
"role": "user",
"content": "Return a short confirmation."After this succeeds, optional fields can be introduced individually. Add temperature to test sampling behavior, one completion-token field to constrain output, metadata for application context, or providerOptions.gateway for route preferences. Do not add multiple unverified compatibility fields at once, because an error would no longer identify which field exceeded the handler’s contract.
For a response, validate the OpenAI-style identifier, object type, choices, and usage together with the Ethen extension. The selected provider and alias explain execution; attempt and fallback fields explain resilience; warnings identify route conditions that did not necessarily fail the request. Store these operational fields separately from the generated message so they remain available for support and cost analysis.
A minimal supported example contains a model and one text message.
An advanced grounded example may add stream or gateway provider controls, but should not introduce unverified fields.
Use a neutral credential placeholder and an environment-specific approved origin.
A minimal example should demonstrate only supported fields. A routing example may add providerOptions.gateway, but it must not imply that the preferred provider is always used or that aliases and timeouts exist for every provider.
The endpoint is POST /api/gateway/v1/chat/completions.
A minimal example should prove only the supported path: one model, one user message, a Bearer key, and no undocumented options. A routing example can add providerOptions.gateway to express provider order or an only restriction, but it should show that these controls narrow eligibility rather than guarantee execution. Do not add tool calls or response-format fields to make the example resemble a broader API.
Errors
provider_stream_error belongs to the streaming path and can arrive after partial output. Non-streaming adapter failures may surface through the last relevant runtime error after configured attempts are exhausted. In both cases, preserve the public code and redacted attempt history. Do not expose raw adapter exceptions or credentials to the application user.
The handler exposes separate errors for JSON and required fields, key state and scope, setup, catalog and provider readiness, budget, provider streaming, and internal failure. That separation allows clients to avoid unsafe retry behavior. For example, invalid_api_key should not be retried against another provider, and budget_exceeded should not be treated as a transient adapter outage.
Provider-attempt errors are redacted before logging. Return the public error code to application logic, and use request and trace identifiers to correlate the failure with operational records.
Request errors distinguish invalid JSON, missing model, and missing messages.
Authentication and readiness errors distinguish key state, scope, setup, catalog-only status, missing provider key, and non-runnable model.
Budget, provider-stream, and internal errors require different operational responses and should not be collapsed into a single retry rule.
Error handling should branch by stage. Validation and key errors require client correction; setup and model-status errors require environment or catalog work; budget and provider failures require operational review; internal errors need trace-based escalation.
Image-array entries are normalized to a placeholder in the inspected route, and unsupported OpenAI request fields must not be assumed to work.