← Back to research
Guides13 min readPublished 2026-07-23

Can I Use OpenAI SDK With Gemini? A Practical Python Guide

Can I use OpenAI SDK with Gemini? Keep your Python package, change the base URL, select exact model ids, and test compatibility before production migration.

By LumeAPI Engineering Team

Gemini API hub → Cheap Gemini Api →

Last verified: July 23, 2026

Short path: Start with the Gemini API guide, compare current rates on cheap Gemini API, and check AI API pricing before choosing a model.

If you are asking can I use OpenAI SDK with Gemini, the practical answer is yes—when you call Gemini through an OpenAI-compatible endpoint such as LumeAPI. You can keep the openai Python package, change base_url, provide a LumeAPI key, and set model to a Gemini model id from the catalog.

The catch is that this gives you compatibility at the Chat Completions request layer, not complete parity with every Google Gemini feature. Native Google features, provider-specific parameters, response details, and tool behavior still need separate testing.

Quick Answer

QuestionDirect answer
Can I use OpenAI SDK with Gemini?Yes. Point the OpenAI client at https://api.lumeapi.site/v1 and use a catalog Gemini model id such as gemini-3.5-flash.
What code changes are required?Usually three: change base_url, use a LumeAPI bearer key, and replace the model name.
Can I use the Google API key at LumeAPI?No. Use the LumeAPI credential for the LumeAPI endpoint. Keep Google credentials for direct Google API calls.
Is the OpenAI SDK compatible with every Gemini feature?No. The compatible route exposes an OpenAI-style Chat Completions interface; native Google features may not map one-for-one.
What should I test first?A plain text request, structured output, tool calling if needed, token usage, error handling, and your real prompts.

In short

You do not need to rewrite an application just to try Gemini through an OpenAI-shaped interface. Change the endpoint and model id, then run a compatibility test suite before switching production traffic. The important boundary is this: an OpenAI-compatible gateway preserves much of your client code, but it does not promise identical semantics to the native Gemini API.

What most guides get wrong

The common myth is that “OpenAI-compatible” means “every OpenAI feature works identically with every model.”

It does not.

Compatibility normally means your client can send an OpenAI-style request to an endpoint that accepts familiar fields such as model, messages, temperature, and possibly tools. It does not guarantee that Gemini will interpret every parameter the same way, return the same metadata, or support every native Google capability through that route.

A migration can appear successful because the first client.chat.completions.create() call returns text. The failure often arrives later:

  • A tool call has a different argument shape than your agent loop expects.
  • A response parser assumes OpenAI-specific metadata.
  • A retry handler retries a non-idempotent action.
  • A parameter accepted by one model is ignored or rejected by another.
  • A native Gemini feature is unavailable through the compatible endpoint.

The right mental model is “same client transport, different model behavior.” Keep the SDK to reduce migration work, but keep model-specific tests.

A realistic production scenario

Maya’s six-person Python team has a support-triage worker built with the OpenAI package, Pydantic validation, and a Redis-backed retry queue. The worker currently points directly at an OpenAI endpoint. It sends roughly 10 million input tokens and 1 million output tokens each month.

The team wants to evaluate Gemini without changing every import, dependency, and environment variable in the worker. Maya first changes only the endpoint and model:

python
client = OpenAI(
    api_key=os.environ["LUMEAPI_KEY"],
    base_url="https://api.lumeapi.site/v1",
)

response = client.chat.completions.create(
    model="gemini-3.5-flash",
    messages=messages,
)

The first smoke test passes. The second test exposes the real problem: the worker’s parser assumes every assistant turn contains a normal text string, while one evaluation path expects a tool call. Maya does not roll back the whole migration. She separates the text-only route from the tool route, adds a fixture for the returned response shape, and sends only the safe classification workload to Gemini first.

The endpoint change was easy. The contract testing was the migration.

Expert take

The OpenAI Python SDK is useful here because it keeps the application’s transport code stable. Your application still creates a client, supplies a model, sends messages, and reads a completion. That is valuable when the expensive part of a migration is not the API call itself but the surrounding code: dependency injection, tracing, queues, secrets, test fixtures, and billing logs.

The boundary is semantic, not syntactic.

A compatible endpoint can translate an OpenAI-style request into a provider-specific request. That translation has to make choices about message roles, tool definitions, generation controls, usage accounting, and error mapping. Some choices are straightforward. Others are lossy. A field that exists in the OpenAI client may not have an equivalent Gemini behavior, and a Gemini-native capability may not be expressible through the OpenAI request schema.

That is why the safe migration pattern is:

  1. Keep the SDK and isolate the provider configuration.
  2. Change one model id at a time.
  3. Record the exact request and response shape in tests, with secrets removed.
  4. Compare task quality and token usage, not just HTTP status codes.
  5. Promote traffic by workload rather than changing every agent at once.

Do not follow this advice when you need provider-native capabilities that are not exposed through the compatible interface. In that case, use Google’s native Gemini API for that code path and keep the OpenAI-shaped client for the simpler workloads. A split integration is less elegant than one client, but it is safer than pretending the interfaces are identical.

LumeAPI is an independent third-party gateway, not OpenAI, Google, or Anthropic. It can reduce endpoint migration work, but you should verify its supported request fields and operational behavior for the models you plan to use. Do not assume native Google Batch behavior, prompt caching, quotas, or every multimodal feature is available through the gateway unless the relevant documentation says so.

The minimum change: endpoint, key, and model

The smallest working migration has three configuration differences:

  • Endpoint: https://api.lumeapi.site/v1
  • Credential: a LumeAPI API key sent as a bearer credential by the SDK
  • Model: an exact Gemini id from the live catalog, such as gemini-3-flash

The rest of your application can often remain unchanged for a basic text request.

Install the official OpenAI Python package according to its official documentation. Then use an explicit client rather than changing a global default:

bash
pip install openai

Set the credential:

bash
export LUMEAPI_KEY="your_lumeapi_key"

Create a request:

python
import os
from openai import OpenAI

client = OpenAI(
    api_key=os.environ["LUMEAPI_KEY"],
    base_url="https://api.lumeapi.site/v1",
)

response = client.chat.completions.create(
    model="gemini-3.5-flash",
    messages=[
        {
            "role": "system",
            "content": "You classify support tickets. Return a concise category.",
        },
        {
            "role": "user",
            "content": "The customer cannot reset their password.",
        },
    ],
)

print(response.choices[0].message.content)

The base_url ends in /v1. The SDK appends the path needed for the Chat Completions call. Do not accidentally use the website URL or a provider-native URL while supplying a LumeAPI key.

You can select another catalog model by changing only the model value:

python
model = "gemini-3-flash"

The model id is not a display name. Copy it exactly. gemini-3-flash, gemini-3.5-flash, and gemini-3.1-pro-preview are separate catalog entries.

Use environment-based configuration

Hard-coding the endpoint and key in application modules makes testing harder. Put the provider settings behind a small factory:

python
import os
from openai import OpenAI

def create_lume_client() -> OpenAI:
    api_key = os.environ.get("LUMEAPI_KEY")
    if not api_key:
        raise RuntimeError("LUMEAPI_KEY is not set")

    return OpenAI(
        api_key=api_key,
        base_url=os.environ.get(
            "LUMEAPI_BASE_URL",
            "https://api.lumeapi.site/v1",
        ),
    )

client = create_lume_client()

response = client.chat.completions.create(
    model=os.environ.get("GEMINI_MODEL", "gemini-3.5-flash"),
    messages=[
        {"role": "user", "content": "Summarize this ticket in one sentence."},
    ],
)

print(response.choices[0].message.content)

This gives you a controlled switch:

bash
export LUMEAPI_BASE_URL="https://api.lumeapi.site/v1"
export GEMINI_MODEL="gemini-3-flash"

For a direct Google integration, do not reuse this configuration blindly. The native Google endpoint, authentication method, model naming, and request surface are separate concerns. Google documents its OpenAI compatibility approach in the Gemini API OpenAI compatibility guide. Read that documentation when deciding whether a native or compatible integration fits your workload.

What changes when the model is Gemini?

The Python call may look familiar, but your assumptions about the model should change.

Messages are still application data

Keep system instructions and user content explicit. Do not rely on a provider-specific default persona or hidden instruction. A useful migration test stores representative message arrays and compares:

  • Whether the answer follows the instruction
  • Whether it stays within the expected length
  • Whether it preserves required JSON or delimiter rules
  • Whether it refuses or asks for clarification in the same cases
  • Whether the response parser receives the expected content type

Do not compare only one happy-path prompt. A classification worker, a retrieval worker, and an agent planner stress different parts of the interface.

Generation parameters need verification

Parameters such as temperature, token limits, stop sequences, and response-format controls can differ in name, support, or effect across providers and models. Start with the smallest documented request. Add optional parameters one by one.

For example:

python
response = client.chat.completions.create(
    model="gemini-3.5-flash",
    messages=[
        {"role": "user", "content": "Return exactly three short bullet points."},
    ],
    temperature=0.2,
)

If you add a parameter and receive a validation error, remove it and check the compatible endpoint’s documentation. Do not “fix” a migration by silently dropping parameters that your application depends on. Make the loss visible in a test or configuration warning.

Response parsing should be defensive

A basic text response is commonly read like this:

python
text = response.choices[0].message.content or ""

That is fine for a text-only path, but production code should validate the response before using it:

python
def get_text(response) -> str:
    if not response.choices:
        raise ValueError("Model response contained no choices")

    message = response.choices[0].message
    content = message.content

    if not isinstance(content, str) or not content.strip():
        raise ValueError("Model response contained no usable text")

    return content.strip()

If your code supports tools, structured output, or multimodal content, write a separate parser for that path. Do not assume the text accessor is the complete response.

Gemini OpenAI-compatible Python smoke test

Before moving an agent or customer-facing workflow, run a small test suite. This is a practical Gemini OpenAI-compatible Python check:

python
import os
from openai import OpenAI

client = OpenAI(
    api_key=os.environ["LUMEAPI_KEY"],
    base_url="https://api.lumeapi.site/v1",
)

def run_smoke_test(model: str) -> None:
    response = client.chat.completions.create(
        model=model,
        messages=[
            {
                "role": "system",
                "content": "Answer with one sentence and no markdown.",
            },
            {
                "role": "user",
                "content": "Why should an API client use timeouts?",
            },
        ],
    )

    if not response.choices:
        raise AssertionError("No choices returned")

    content = response.choices[0].message.content
    if not content:
        raise AssertionError("No message content returned")

    print(f"{model}: {content}")
    print("usage:", getattr(response, "usage", None))

for model_id in (
    "gemini-3-flash",
    "gemini-3.5-flash",
    "gemini-3.1-pro-preview",
):
    run_smoke_test(model_id)

This does not prove production compatibility. It verifies that:

  • Your key is accepted.
  • The base URL is correct.
  • The model ids are spelled correctly.
  • The client can send a basic Chat Completions request.
  • Your response access path works.
  • Usage data is available in the returned object, if the endpoint supplies it.

Run this test in CI with a controlled credential if your deployment process allows it. Otherwise, keep a local smoke test and a mocked response fixture in the repository.

Tool calls, structured output, and multimodal requests

This is where the phrase “use the OpenAI package with Google Gemini” becomes less precise.

A plain text migration is not the same as an agent migration. Before switching a tool-using worker, test each of these independently:

  1. The model receives the tool schema.
  2. The response indicates a tool call in the shape your code expects.
  3. Tool arguments can be parsed and validated.
  4. Your executor sends the tool result back in an accepted message format.
  5. A failed tool call does not trigger duplicate side effects.
  6. The final assistant response remains parseable after one or more tool turns.

A retry loop deserves special attention. If your code retries after a network timeout, you may not know whether the model request completed. If the request caused a downstream action, blindly retrying can duplicate work. Use idempotency at the application layer where possible: attach a request or job identifier to your own tool execution record, and do not perform the same side effect twice merely because the model call was retried.

Structured output has a similar trap. “The model returned valid JSON once” is not a contract. Validate the output with your schema, record failures, and decide whether to repair, retry, or escalate. If a native Gemini feature is required to enforce a schema, verify that the compatible route exposes it before committing to this integration style.

For images, audio, files, and other non-text content, check the endpoint’s documented content format. Do not copy a native Google example into an OpenAI-compatible request and expect the gateway to translate every part automatically.

Pricing: what the endpoint change can save

The catalog pricing supplied for this article is updated July 22, 2026. Rates below are USD per 1 million tokens, shown as input / output. “Official” is the reference rate in the catalog; LumeAPI is the corresponding gateway rate.

ModelOfficial input / outputLumeAPI input / outputCatalog discount
gemini-3.1-pro-preview$2.00 / $12.00$1.00 / $6.0050%
gemini-3.5-flash$1.50 / $9.00$0.75 / $4.5050%
gemini-3-flash$0.50 / $3.00$0.25 / $1.5050%

Assume a workload uses 10 million input tokens and 1 million output tokens per month:

ModelOfficial monthly mathLumeAPI monthly mathDifference
gemini-3.1-pro-preview(10 × $2) + (1 × $12) = $32(10 × $1) + (1 × $6) = $16$16
gemini-3.5-flash(10 × $1.50) + (1 × $9) = $24(10 × $0.75) + (1 × $4.50) = $12$12
gemini-3-flash(10 × $0.50) + (1 × $3) = $8(10 × $0.25) + (1 × $1.50) = $4$4

The arithmetic is simple. The choice is not. A cheaper input rate does not fix a prompt that resends a 30,000-token conversation on every agent hop. Nor does a compatible gateway automatically make retries free. Log input and output tokens per route, count attempts rather than only successful jobs, and include failed requests in your cost review.

The gateway also is not a substitute for provider-native pricing programs or features. If a provider’s native Batch or caching option is materially better for your workload, compare that path directly. Verify the current terms before making a cost decision.

A migration checklist that catches the expensive failures

Use this checklist before changing a production model:

Configuration

  • [ ] base_url is exactly https://api.lumeapi.site/v1
  • [ ] The application sends a LumeAPI key, not a Google credential
  • [ ] The model id is copied exactly from the live catalog
  • [ ] Secrets are injected through the deployment environment
  • [ ] Logs redact authorization headers and prompt content where required

Request compatibility

  • [ ] Plain text completion succeeds
  • [ ] System and user messages preserve their intended order
  • [ ] Optional generation parameters are supported or intentionally removed
  • [ ] Your timeout is set at the client or request layer
  • [ ] Your retry policy distinguishes connection failures from invalid requests

Response compatibility

  • [ ] Empty choices are handled
  • [ ] Missing or non-string content is handled
  • [ ] Usage fields are recorded when present
  • [ ] Tool calls have a tested parser
  • [ ] Structured responses are validated before use

Quality and operations

  • [ ] Representative prompts are evaluated, not just a smoke-test question
  • [ ] Token counts are compared by task
  • [ ] Latency and error rates are measured in your own environment
  • [ ] A rollback model and endpoint are configured
  • [ ] One workload is migrated before the entire agent fleet

A useful rollout is intentionally boring: send a small, reversible route to the new model, watch failures and output quality, then expand. Changing the model, prompt, parser, and retry policy at the same time makes every incident ambiguous.

When to use the native Gemini API instead

The compatible route is a good fit when your priority is preserving an existing OpenAI-client integration. It is a weaker fit when your application depends on provider-specific capabilities or needs the newest native feature immediately.

Use the native Google integration when:

  • Your request requires a Gemini-specific feature unavailable through the compatible endpoint.
  • You need the exact native request and response schema.
  • Your team already has Google credential, quota, and observability handling in place.
  • You need provider-native operational features that the gateway does not claim to reproduce.
  • A compatibility translation would make debugging harder than maintaining two clients.

Use the OpenAI SDK through LumeAPI when:

  • Your application already has a stable OpenAI-style abstraction.
  • You want to evaluate several catalog models with minimal client changes.
  • Your workload is primarily text Chat Completions.
  • You want one credential and endpoint for the models exposed in the LumeAPI catalog.
  • You have tests that protect your parser and agent loop.

The decision is not ideological. Keep the compatible path where it removes real migration work. Use a native path where translation would hide an important provider capability.

FAQ

Can I use OpenAI SDK with Gemini without rewriting my Python application?

Yes, for a compatible Chat Completions workflow you can usually keep the OpenAI client code and change the endpoint, credential, and model id. You still need to test parameters and response parsing.

Can I use the Google Gemini API key with the OpenAI package?

Not automatically through LumeAPI. The OpenAI package sends the credential you provide to the configured endpoint, so use a LumeAPI key with https://api.lumeapi.site/v1. Direct Google calls have their own authentication and endpoint configuration.

Which Gemini model id should I use in the OpenAI SDK?

Use an exact id from the available catalog, such as gemini-3-flash, gemini-3.5-flash, or gemini-3.1-pro-preview. Do not substitute a marketing label or a model name copied from a different provider.

Does the OpenAI SDK support Gemini tool calling through a compatible gateway?

It may support a compatible tool-calling request, but you must verify the endpoint’s supported schema and test the returned tool-call shape. A successful text request does not prove that an agent loop will work.

Is the OpenAI SDK Gemini API route cheaper than calling Google directly?

The supplied LumeAPI catalog lists Gemini rates at 50% below its listed official reference rates, but your real bill also depends on token volume, retries, and model selection. Compare native provider features such as Batch or caching separately when they matter.

Should I use gemini-3-flash or gemini-3.5-flash first?

Start with the lower-cost model for a representative evaluation, then move up if it fails your quality or tool-use criteria. Do not choose solely by name; measure the task that produces your bill.

Next steps

  1. Run the plain-text smoke test with gemini-3-flash, then repeat it with the model you are considering for production.
  2. Add fixtures for your real structured-output or tool-calling responses before changing the agent loop.
  3. Compare token usage and failure costs on one reversible workload, then review the Gemini API options before expanding traffic.

The core rule is simple: keep the OpenAI SDK when the compatible interface saves migration effort, but do not confuse a familiar client with identical model behavior. Change the endpoint and model id first; earn the production cutover with tests.