OhMyGPT

Protocols

Call any chat model through the OpenAI, Anthropic, or Gemini protocol, and what you get back on each.

Any chat model can be called through any of the four chat protocols, so you can call Claude from the OpenAI SDK, or GPT from the Google Gen AI SDK, by changing only the model ID. Pick the protocol your SDK or tool already speaks:

You useCallPage
OpenAI SDK, Vercel AI SDK, LangChain, opencode, CursorPOST /v1/chat/completionsChat Completions
Codex, OpenAI SDK client.responsesPOST /v1/responsesResponses
Anthropic SDK, Claude CodePOST /v1/messagesMessages
Google Gen AI SDKPOST /v1/models/{model}:generateContentGemini

The same model on two protocols:

curl https://api.ohmygpt.com/v1/chat/completions \
  -H "Authorization: Bearer $OHMYGPT_API_KEY" \
  -H "Content-Type: application/json" \
  -d '{"model": "anthropic/claude-haiku-4-5", "max_tokens": 256,
       "messages": [{"role": "user", "content": "Explain QUIC in two sentences."}]}'

curl https://api.ohmygpt.com/v1/messages \
  -H "x-api-key: $OHMYGPT_API_KEY" \
  -H "Content-Type: application/json" \
  -d '{"model": "anthropic/claude-haiku-4-5", "max_tokens": 256,
       "messages": [{"role": "user", "content": "Explain QUIC in two sentences."}]}'

The first answers with a chat.completion object, the second with an Anthropic message.

Native protocol

Each model has a native protocol: Messages for Claude, Gemini for Gemini models, Chat Completions for GPT, DeepSeek, Qwen, and most others. GET /v1/models marks it with "native": true:

curl -s https://api.ohmygpt.com/v1/models \
  | jq -r '.data[] | select(.id == "anthropic/claude-haiku-4-5") | .protocols[] | [.path, (.native // false)] | @tsv'
/v1/chat/completions	false
/v1/responses	false
/v1/messages	true
/v1/models/{id}:generateContent	false

On its native protocol, a model receives your request body as you sent it, so vendor-specific fields and beta features work as the vendor documents them. OhMyGPT sets only these:

FieldWhat OhMyGPT does
modelResolves your model ID to the vendor's
streamKeeps your choice
stream_optionsChat Completions streams always end with a usage chunk
providerReads your routing preferences on Chat Completions and Responses
safetySettingsGemini requests without one get the four adjustable categories set to OFF; see Gemini
anthropic-versionSet to 2023-06-01 on Messages if you send none; other anthropic-* headers, such as anthropic-beta, are passed on

Other protocols

On any other protocol, OhMyGPT converts your request to the model's native protocol and converts the answer back. Messages, system prompts, images, tools, tool choice, token limits, structured output, and reasoning controls all carry over, and so does every sampling and output parameter the model has an equivalent for. The response comes back in your protocol's shape, with the finish reason in its vocabulary.

A sampling or output parameter the model has no equivalent for, such as seed or logprobs on Claude, isn't sent, and the model answers with its own default for that setting. Parameters shows which parameters apply to each model family. The same goes for enable_thinking and thinking_budget on Chat Completions (use the reasoning controls instead), and max_tool_calls, truncation, and top_logprobs on Responses.

A few fields carry input that only the model's native protocol can deliver, such as stored context, server-side tools, or prompt templates. Send them there:

ProtocolFields to send on the native protocol
Chat Completionsfunctions and function_call (or use tools and tool_choice on any model)
Responsesbackground, conversation, prompt
Messagescontainer, mcp_servers, and server tools such as web_search_20250305
GeminicachedContent

If one of these reaches a model on another protocol, the request returns 400 before it reaches the model, so nothing is charged and you never get an answer that silently skipped part of your input:

{
  "error": {
    "type": "invalid_request_error",
    "code": "unsupported_parameter",
    "param": "background",
    "message": "The model `mock` does not support the `background` parameter."
  }
}

Fields set to null, false, "", [], or {} count as unset, so SDK defaults never trigger this.

Errors

Errors come back in the format of the protocol you called, so your SDK's error types work unchanged.

{
  "error": {
    "type": "invalid_request_error",
    "code": "unsupported_endpoint",
    "param": "model",
    "message": "The model `ohmygpt/mock` does not support this endpoint. `GET /v1/models` lists the endpoints each model supports."
  }
}

On OpenAI-format errors, code is a stable value to branch on. Errors lists the codes and what to do for each status.

On this page