Chat Completions
Call any chat model through the OpenAI Chat Completions protocol.
POST /v1/chat/completions speaks the OpenAI Chat Completions protocol and serves every chat model: GPT, Claude, Gemini, DeepSeek, Qwen, and the rest. Point an OpenAI SDK at https://api.ohmygpt.com/v1 and change model to switch between them. The full request and response schema is in the endpoint reference.
| Endpoint | POST https://api.ohmygpt.com/v1/chat/completions |
| SDK base URL | https://api.ohmygpt.com/v1 |
| Auth | Authorization: Bearer $OHMYGPT_API_KEY |
| Content type | application/json |
import os
from openai import OpenAI
client = OpenAI(
base_url="https://api.ohmygpt.com/v1",
api_key=os.environ["OHMYGPT_API_KEY"],
)
completion = client.chat.completions.create(
model="anthropic/claude-haiku-4-5",
messages=[{"role": "user", "content": "Explain QUIC in two sentences."}],
)
print(completion.choices[0].message.content)Native and other models
For models whose native protocol is Chat Completions, such as GPT, DeepSeek, Qwen, Kimi, and GLM, the vendor receives your body as sent, and vendor-specific fields work as the vendor documents them. Claude and Gemini models answer in the same chat.completion shape; Protocols covers what carries over.
Claude and Gemini responses
Finish reasons
For Claude and Gemini models, finish_reason uses the OpenAI values and native_finish_reason keeps the model's original reason:
"choices": [
{
"index": 0,
"finish_reason": "length",
"native_finish_reason": "max_tokens",
"message": { "role": "assistant", "content": "Pong! " }
}
]| Model's reason | finish_reason |
|---|---|
Claude end_turn, stop_sequence, pause_turn; Gemini STOP | stop |
Claude max_tokens; Gemini MAX_TOKENS | length |
Claude tool_use; Gemini function call | tool_calls |
Claude refusal; Gemini safety and recitation blocks | content_filter |
Reasoning in the response
For Claude and Gemini models, the model's visible reasoning arrives in message.reasoning, with structured entries in message.reasoning_details. Claude entries carry a signature:
"message": {
"role": "assistant",
"content": "391",
"reasoning": "17 * 23 = ?\n\nLet me calculate this:\n17 * 23 = 17 * 20 + 17 * 3\n= 340 + 51\n= 391",
"reasoning_details": [
{
"type": "reasoning.text",
"text": "17 * 23 = ?\n\nLet me calculate this:\n17 * 23 = 17 * 20 + 17 * 3\n= 340 + 51\n= 391",
"signature": "EuoCCrgBCBMYAipATvOr...",
"index": 0
}
]
}Models whose native protocol is Chat Completions return reasoning in the vendor's own field, for example reasoning_content on DeepSeek and Qwen. Streams carry the same data as delta.reasoning and delta.reasoning_details. Thinking covers the request parameters that turn reasoning on, off, or down.
For multi-turn Claude conversations that combine extended thinking with tool use, use Messages, which keeps thinking blocks and their signatures from turn to turn. Gemini tool calls carry their thought signature in tool_calls[].extra_content; send assistant messages back unchanged to keep it.
Routing
A top-level provider object chooses which provider serves the model (order, only, ignore, sort). The OpenAI Python SDK takes it in extra_body:
completion = client.chat.completions.create(
model="openai/gpt-5.4-nano",
messages=[{"role": "user", "content": "ping"}],
extra_body={"provider": {"sort": "price"}},
)See Provider routing for the fields and their rules.
Streaming
Set stream: true to receive chat.completion.chunk events ending with data: [DONE]. The last chunk before [DONE] carries usage whether or not you set stream_options, and a : x-cost-credits comment line reports the charge. See Streaming.
Errors
Errors use the OpenAI format. error.code is a stable value, for example unsupported_parameter with the field named in param:
{
"error": {
"type": "invalid_request_error",
"code": "unsupported_parameter",
"param": "functions",
"message": "The model `anthropic/claude-haiku-4-5` does not support the `functions` parameter."
}
}Errors lists the codes and status handling.