If your app uses the OpenAI Python SDK — or any client that follows the same pattern — the entire integration is a one-parameter change. No new dependency, no wrapper, no restructuring. Here's the exact code, plus the environment variable pattern and framework-specific notes worth knowing.

The Core Change

# Before
from openai import OpenAI

client = OpenAI(api_key="sk-...")

# After — same SDK, same calls, different base URL
from openai import OpenAI

client = OpenAI(
    api_key="sk-...",
    base_url="https://proxy.preto.ai/v1/YOUR-KEY"
)

# Everything below this line is unchanged
response = client.chat.completions.create(
    model="gpt-5-mini",
    messages=[{"role": "user", "content": "Hello"}]
)

Your actual OpenAI API key stays exactly where it is — Preto forwards the request to OpenAI using your key, it doesn't replace or intercept your credentials.

Use an Environment Variable, Not a Hardcoded URL

# .env
OPENAI_BASE_URL=https://proxy.preto.ai/v1/YOUR-KEY

# your app
import os
from openai import OpenAI

client = OpenAI(
    api_key=os.environ["OPENAI_API_KEY"],
    base_url=os.environ.get("OPENAI_BASE_URL"),  # falls back to default if unset
)

This pattern lets you point staging at the proxy while production stays untouched, verify normal behavior, then flip the same variable in production once you're confident — no code deploy required for the actual cutover, just a config change.

Async Clients Work the Same Way

from openai import AsyncOpenAI

client = AsyncOpenAI(
    api_key=os.environ["OPENAI_API_KEY"],
    base_url=os.environ.get("OPENAI_BASE_URL"),
)

response = await client.chat.completions.create(
    model="gpt-5-mini",
    messages=[{"role": "user", "content": "Hello"}]
)

Identical parameter, identical pattern — AsyncOpenAI takes base_url exactly like the synchronous client.

Ready to grab your proxy URL?

Your unique proxy endpoint is waiting in your dashboard.

Copy the Code Snippet

One line. One import change. Your costs appear in Preto immediately.

Framework-Specific Notes

FastAPI. Initialize the client once, outside your request handlers — either at module scope or in a dependency-injected singleton — rather than constructing a new OpenAI client on every request. The base_url is set once at client construction, so there's nothing framework-specific about the proxy integration itself.
Flask. Same pattern — initialize the client at app startup (in your app factory or a module-level singleton) rather than per-request, and pull the base URL from your existing config/environment loading, whatever that already looks like in your app.
Django. Add the proxy URL to your settings module alongside your other environment-driven config, and initialize the client where you'd normally centralize third-party service clients. If you're already using django-environ or similar, the base_url slots into that pattern without anything special.

Verifying It's Working

Trigger one real request through your app after the switch — a normal call your app already makes. Two checks confirm success: your app's response is unchanged (Preto forwards the provider's response exactly as returned), and the request appears in your Preto dashboard within about a minute. If both hold, the integration is complete.

Multi-Provider Apps

If your app calls more than one provider — OpenAI and Anthropic, for example — each client gets its own base_url pointed at the corresponding proxy endpoint. Preto attributes cost per provider automatically, so a multi-provider setup shows up as one unified cost view instead of requiring separate tracking for each.

Running a Node.js service alongside your Python app? The Node.js integration guide covers the equivalent setup. And once data starts flowing in, here's what to look at first.

Frequently Asked Questions

Do I need to change my OpenAI Python SDK code to use Preto?
No — only the base_url parameter changes. Every other call, response handler, and existing pattern stays exactly as it is.
Should I hardcode the proxy URL or use an environment variable?
Use an environment variable. It lets you test staging against the proxy before touching production, and switching between the proxy and direct provider URL becomes a config change rather than a code change.
Does this work with async Python clients?
Yes. AsyncOpenAI takes the same base_url parameter as the synchronous client — the integration pattern is identical.
What if my app uses multiple LLM providers?
Each provider client gets its own base_url pointed at Preto's corresponding proxy endpoint. Preto logs and attributes cost per provider automatically.

Grab your proxy URL and connect in the next few minutes.

Your unique endpoint is ready in your dashboard — copy it, set the environment variable, and your first request will show up within a minute.

Copy the Code Snippet

Questions about your specific setup? Reply to your welcome email.

Gaurav Dagade
Gaurav Dagade

Founder of Preto.ai. 11 years engineering leadership. Previously Engineering Manager at Bynry. Building the cost intelligence layer for AI infrastructure.

LinkedIn · Twitter