Models & keys
By default the upstream account chooses the model. You can override that per API key, so a given key always runs on the model you want — no matter what the client requests.
The default: auto
Send "model": "auto" (or omit it) and ChatGPT picks the model for the account. This is the simplest setup and needs no configuration.
OpenCode Muse Spark
Use "model": "opencode/muse-spark-1.3-contributor-free" on POST /v1/chat/completions to call the local OpenCode CLI. Install OpenCode under the gateway's OS account and verify the command works there. This route needs no captured ChatGPT session; auto still uses ChatGPT.
Omit X-Conversation-Id to start a new chat; the response returns its ID in that header. Reuse the header to continue and send only the new messages. Alternatively, choose different IDs for different chats. Sessions are scoped to each API key, and conversation mappings survive gateway restarts. OpenCode stores the actual history locally; its data directory must also persist.
The bridge accepts text and inline base64 image attachments and rejects tool execution permissions. Remote image URLs and tool-role messages are rejected. With stream: true, SSE output is buffered until the command finishes. Token usage, sampling controls, and tool calling are not supported. The model listing does not guarantee upstream availability.
Pinning a model to a key
To force a model regardless of what the client sends, pin it to the key:
- Open the dashboard and find the key under API keys.
- Pick a model from that key's dropdown. The list includes models your pooled accounts expose and the OpenCode Muse Spark bridge.
- Every request on that key now uses the pinned model; the client's
modelfield is ignored.
This is how you give one client GPT-5.x while leaving another on auto — the choice rides on the key, not the request.
Leaving a key's model empty means "honour the client's request" — the client's model field (or auto) is used as-is.
Why a model may misname itself
If you ask a pinned model "which model are you?", it may answer with a different name than the one you pinned — for example reporting "mini" when you pinned the full model. That is the model describing itself from its training, not the gateway ignoring your pin.
What actually ran is reported in the upstream metadata (the model field on the response), and it reflects the pin. In short: trust the pin and the response metadata, not the model's self-description.
Seeing available models
Clients that probe GET /v1/models receive the logical ChatGPT entry msemax and opencode/muse-spark-1.3-contributor-free. A model pinned to a client key overrides the requested model.
curl __BASE__/v1/models \ -H "Authorization: Bearer YOUR_API_KEY"
Client keys vs. the master key
| Capability | Client key (msk-…) | Master key |
|---|---|---|
| Call the chat endpoint | Yes | Yes |
| Be pinned to a model | Yes | — |
| Manage sessions | No | Yes |
| Create / revoke keys | No | Yes |
| Open the dashboard | No | Yes |
Generate a client key per consumer so you can revoke one without disturbing the rest. Revoking is instant and reversible from the dashboard.