OhMyGPT

Gemini

Call Gemini, and any other chat model, through the Google Gemini generateContent protocol.

The Gemini endpoints work with the Google Gen AI SDKs and take the model in the URL, as Google's API does. Gemini models and every other chat model in the catalog answer with a GenerateContentResponse.

GeneratePOST https://api.ohmygpt.com/v1/models/{model}:generateContent
StreamPOST https://api.ohmygpt.com/v1/models/{model}:streamGenerateContent
SDK base URLhttps://api.ohmygpt.com, API version v1
Authx-goog-api-key: $OHMYGPT_API_KEY or Authorization: Bearer $OHMYGPT_API_KEY

{model} is a full model ID from GET /v1/models, slash included: /v1/models/google/gemini-3.1-flash-lite:generateContent. Set the SDK's API version to v1, as below.

import os
from google import genai
from google.genai import types

client = genai.Client(
    api_key=os.environ["OHMYGPT_API_KEY"],
    http_options=types.HttpOptions(base_url="https://api.ohmygpt.com", api_version="v1"),
)

response = client.models.generate_content(
    model="google/gemini-3.1-flash-lite",
    contents="Explain QUIC in two sentences.",
)
print(response.text)

for chunk in client.models.generate_content_stream(
    model="google/gemini-3.1-flash-lite",
    contents="Explain QUIC in two sentences.",
):
    print(chunk.text or "", end="")
{
  "candidates": [
    {
      "index": 0,
      "finishReason": "STOP",
      "content": {
        "role": "model",
        "parts": [{ "text": "This is a mock reply from OhMyGPT. Your integration works; switch to a real model when ready." }]
      }
    }
  ],
  "usageMetadata": { "promptTokenCount": 15, "candidatesTokenCount": 17, "totalTokenCount": 32 }
}

Safety settings

When a request has no safetySettings, OhMyGPT sets HARM_CATEGORY_HARASSMENT, HARM_CATEGORY_HATE_SPEECH, HARM_CATEGORY_SEXUALLY_EXPLICIT, and HARM_CATEGORY_DANGEROUS_CONTENT to "threshold": "OFF". To filter, send your own safetySettings; Gemini models receive them unchanged.

{
  "contents": [{ "role": "user", "parts": [{ "text": "ping" }] }],
  "safetySettings": [
    { "category": "HARM_CATEGORY_DANGEROUS_CONTENT", "threshold": "BLOCK_MEDIUM_AND_ABOVE" }
  ]
}

Other models

GPT, Claude, and every other chat model accept the same request. systemInstruction, contents, tools, toolConfig, and thinkingConfig (Thinking) carry over, and so does every generationConfig setting the model has an equivalent for. A setting it has no equivalent for, such as seed on Claude, isn't sent, and the model answers with its own default for it. Other models return one candidate per request, so candidateCount above 1 returns 400 naming generationConfig.candidateCount. safetySettings is not sent to other models. cachedContent is a Gemini feature; use it with Gemini models.

Streaming

:streamGenerateContent answers with server-sent events, with or without ?alt=sse. Each event is a GenerateContentResponse chunk. The chunk with finishReason ends the content, and the last chunk carries usageMetadata:

data: {"candidates":[{"content":{"role":"model","parts":[{"text":" ready."}]},"index":0}]}

data: {"candidates":[{"content":{"role":"model","parts":[]},"finishReason":"STOP","index":0}]}

data: {"usageMetadata":{"promptTokenCount":29,"candidatesTokenCount":17,"totalTokenCount":46},"candidates":[{"content":{"role":"model","parts":[]},"index":0}]}

To see what a Gemini stream cost, look it up with the stream's X-Request-ID header; see Cost of a stream.

Errors

Errors use Google's google.rpc.Status format:

{
  "error": {
    "code": 404,
    "status": "NOT_FOUND",
    "message": "The model `google/gemini-0-nonexistent` does not exist. List available models with `GET /v1/models`.",
    "details": [
      { "@type": "type.googleapis.com/google.rpc.ErrorInfo", "reason": "MODEL_NOT_FOUND", "domain": "ohmygpt.com" }
    ]
  }
}

On this page