Model discovery
GET /oss/v1/models is one path with two response shapes,
chosen by request headers. That's what lets OpenAI clients (Cursor) and
Anthropic clients (Claude Code CLI, IDE, Desktop) both discover models from one endpoint.
Header discrimination
- If
anthropic-versionorx-api-keyis present → the Anthropic list shape. - Otherwise → the OpenAI list shape.
OpenAI shape
{
"object": "list",
"data": [
{
"id": "claude-turbo-hub-glm-5-2",
"object": "model",
"created": 1730000000,
"owned_by": "opengateway"
}
]
}
Anthropic shape
{
"data": [
{
"type": "model",
"id": "claude-turbo-hub-glm-5-2",
"display_name": "GLM 5.2",
"created_at": "2026-01-01T00:00:00Z"
}
],
"has_more": false
}
What each client needs
| Client | Needs models? | Shape | Note |
|---|---|---|---|
| Cursor | Required | OpenAI | Must return 200 to verify the key. |
| Claude Code (CLI/IDE/Desktop) | Optional (gated) | Anthropic | Picker only shows claude*/anthropic* ids; display_name shows the real open model (e.g. GLM 5.2). |
| OpenAI SDK | On demand | OpenAI | client.models.list() |
| Anthropic SDK | On demand | Anthropic | client.models.list() |
| Codex | Avoid | — | Set model explicitly; don't rely on the list refresh. |
Codex's background catalog refresh expects {"models":[…]}, not {"data":[…]}. Don't satisfy Codex via the models list — set model (and, if needed, model_catalog_json) in its config. See Codex setup.
The usable-model contract
Beyond id/object, OpenGateway emits the Claude Code
"usable-model" fields (owned_by, capabilities,
category, endpoint, metadata.api_shape
and the context-window trio). Without these, Claude
Desktop reports "Gateway returned no usable models" — the curated
claude-* aliases ensure the picker is populated.
Discovery call
curl "https://api.opengateway.one/oss/v1/models" \ -H "Authorization: Bearer $OPENGATEWAY_API_KEY"
Results reflect live provider telemetry refreshed by the gateway cron — the same data that powers the models catalog.