platforms/devplace/openai_gateway.md

DevPlace OpenAI-Compatible Gateway

The OpenAI-compatible proxy at /openai/v1: chat completions and streaming, the generic molodetz model names, embeddings, vision augmentation that rewrites images to text, forced-model behaviour, and per-call usage and cost accounting.

An OpenAI-compatible proxy mounted at /openai/v1. It forwards requests to a configured upstream using the gateway's own credentials, so no DevPlace key is required - but an administrator must enable the openai service first. Point any OpenAI-compatible client at https://devplace.net/openai/v1.

This gateway is the single point of truth for AI on the platform. Every other DevPlace service (news, bots, Devii) calls it by default instead of an external provider, sends the generic model name molodetz, and authenticates with an internal key that is auto-generated on first boot. The real provider URLs, models, and keys (DeepSeek, OpenRouter) live only here, so an operator switches providers or backends in one place. DEEPSEEKAPIKEY and OPENROUTERAPIKEY are migrated into the editable settings on boot and the value in use is shown. Because Force model is on by default, the upstream always receives the configured model regardless of what a client (or molodetz) requests.

The gateway also performs vision augmentation: when a request includes an image, the gateway describes the image with a configured vision model and rewrites it to text, so a vision-less upstream still works. The vision model, URL, and key are configured alongside the other gateway settings.

The gateway additionally serves text embeddings at /openai/v1/embeddings. Clients request the generic model molodetz~embed, which the gateway maps to the configured embedding model (OpenRouter's Qwen3 8B embedding model by default). Usage and cost are tracked per call exactly like chat and vision.

The gateway also serves image generation at /openai/v1/images/generations. Clients request the generic model molodetz-img-small, which the gateway maps to the configured image model (OpenRouter's Flux 1.1 Pro by default). Cost is tracked per call with a flat per-image price when the upstream returns no native cost.

Quick start

Copy the command below and paste it into a terminal. If you are signed in the 63995001-2291-45bf-9fe3-45dae21cfcee and user-retoor-app-v-1-0-0 placeholders are already filled in with your own values; otherwise replace them with the API key from your profile page and any application identifier.

curl -X POST "https://devplace.net/openai/v1/chat/completions"   -H "Authorization: Bearer 63995001-2291-45bf-9fe3-45dae21cfcee"   -H "X-App-Reference: user-retoor-app-v-1-0-0"   -H "Content-Type: application/json"   -d '{
    "model": "molodetz",
    "messages": [{"role": "user", "content": "Hello, how are you?"}]
  }'

The response carries X-Gateway-* headers with token counts and dollar cost for the call. For streaming, add "stream": true to the JSON body.

Model routing and providers

On top of the single default upstream above, an administrator can register additional named providers and map any number of requested model names onto them, so one gateway can front many models across many backends. A model route binds a source model name (what a client sends) to a target provider and upstream model, and carries:

  • its own pricing economy (input, output, and cache-hit / cache-miss prices per million tokens),
  • used to compute that call's cost when the upstream returns no native cost;

  • an optional vision model, which turns on the image-to-text merge for that route (so a text-only
  • model can answer about images);

  • an optional context window used for the context-utilization header.

Resolution is transparent to clients: when the requested model matches an active route, the gateway forwards to that route's provider and target model and meters the call against the route's economy. When it matches no route, the request falls through to the default upstream unchanged (so molodetz, molodetz~embed, and any existing client keep working exactly as before). Providers and routes are managed by administrators on the Gateway page (/admin/gateway).

Per-call cost and usage headers

Every gateway response - chat, embeddings, and passthrough, on both success and error - carries X-Gateway-* response headers describing that single call, so a client can read its own token usage and dollar cost directly from the response with no extra request:

HeaderMeaning
X-Gateway-ModelUpstream model actually used for the call
X-Gateway-BackendBackend that served it: chat, embed, image, or passthrough
X-Gateway-Prompt-TokensInput (prompt) tokens
X-Gateway-Completion-TokensOutput (completion) tokens
X-Gateway-Total-TokensTotal tokens (prompt + completion)
X-Gateway-Cache-Hit-TokensPrompt tokens served from the upstream prompt cache
X-Gateway-Cache-Miss-TokensPrompt tokens not served from cache
X-Gateway-Reasoning-TokensReasoning tokens, when the model reports them
X-Gateway-Cost-USDTotal cost of the call in US dollars
X-Gateway-Input-Cost-USDInput portion of the cost in US dollars
X-Gateway-Output-Cost-USDOutput portion of the cost in US dollars
X-Gateway-Cost-Native1 if the dollar cost is the upstream's own reported cost, 0 if computed from the configured per-million pricing
X-Gateway-Tokens-Per-SecondOutput tokens per second for the call
X-Gateway-Upstream-Latency-MsUpstream round-trip latency in milliseconds
X-Gateway-Total-Latency-MsFull end-to-end gateway time for the call in milliseconds
X-Gateway-Gateway-Overhead-MsGateway processing time minus the upstream and queue wait, in milliseconds
X-Gateway-Queue-Wait-MsTime spent waiting on the concurrency semaphore before dispatch, in milliseconds
X-Gateway-Connect-MsUpstream connection establishment time in milliseconds
X-Gateway-Context-WindowThe model's context window in tokens, when known
X-Gateway-Context-UtilizationTotal tokens as a fraction of the context window, when known

Dollar costs use the upstream's native cost field when it returns one (X-Gateway-Cost-Native: 1); otherwise they are computed from the per-million prices of the matched model route, falling back to the prices configured on the openai service when no route matches. The denied paths that make no upstream call (embeddings or image generation disabled) return no usage headers.

Request header X-App-Reference

Clients SHOULD send an X-App-Reference header to identify themselves for cost attribution. The value is a free-form slug (max 30 characters, letters, digits, _, ., -). When missing or invalid, the gateway defaults to default. The value is recorded in every usage ledger row and can be queried alongside owner-kind and owner-id to attribute spending per application.

X-App-Reference: devplace-devii-v-1-0-0

Administrators enable and configure this gateway under Background Services (the openai service).

The gateway is exempt from rate limiting, but every other endpoint follows the shared Conventions & Errors; see Authentication for signing DevPlace's own requests.

POST /openai/v1/chat/completions - Chat completions

OpenAI-compatible chat completion. Supports streaming.

Minimal role: Member

Parameters

NameInTypeRequiredDescription
modeljsonstringnoModel id. When it matches a configured model route the gateway forwards to that route's provider and upstream model; otherwise it falls back to the configured default upstream model.
messagesjsonstringyesChat messages array.
streamjsonstringnoSet true for a streamed SSE response.

Returns 503 when the gateway service is not running.

Every response carries the X-Gateway-* token and dollar-cost headers (see Per-call cost and usage headers above), including the streamed SSE response.

If model matches a configured model route it is forwarded to that route's provider, upstream model, and per-model pricing (with an optional vision model); otherwise it falls through to the default upstream (see Model routing and providers above).

POST /openai/v1/embeddings - Embeddings

OpenAI-compatible text embeddings. Request model molodetz~embed.

Minimal role: Member

Parameters

NameInTypeRequiredDescription
modeljsonstringnoEmbedding model id; the gateway maps molodetz~embed to the configured model, or to a matching embed model route's provider and target model.
inputjsonstringyesString or array of strings to embed.
dimensionsjsonstringnoOptional output vector size (Matryoshka, 32-4096).

Returns 503 when the gateway service is not running or embeddings are disabled.

Every response carries the X-Gateway-* token and dollar-cost headers (see Per-call cost and usage headers above).

If model matches a configured embed model route it is forwarded to that route's provider and upstream model; otherwise it falls back to the configured default embedding model.

POST /openai/v1/images/generations - Image generation

OpenAI-compatible image generation. Request model molodetz-img-small.

Minimal role: Member

Parameters

NameInTypeRequiredDescription
modeljsonstringnoImage model id; the gateway maps molodetz-img-small to the configured model, or to a matching image model route's provider and target model.
promptjsonstringyesText prompt describing the image to generate.
sizejsonstringnoOutput dimensions (provider-dependent).
response_formatjsonstringnoReturn format: url or b64_json.

Returns 503 when the gateway service is not running or image generation is disabled.

Every response carries the X-Gateway-* token and dollar-cost headers (see Per-call cost and usage headers above).

If model matches a configured image model route it is forwarded to that route's provider and upstream model; otherwise it falls back to the configured default image model.

POST /openai/v1/{path} - Passthrough

Any other /v1 path is forwarded to the upstream as-is.

Minimal role: Member

Parameters

NameInTypeRequiredDescription
pathpathstringyesUpstream API path after /v1/.