Skip to main content

Python Integration

Also available in: PHP · Node.js · Go

The "gateway base URL" is the address of your Observra Gateway (https://gateway.observra.in) - you send requests here instead of directly to OpenAI, Anthropic, or whichever provider you use. The "gateway key" is a per-Application credential you generate in the Observra Dashboard; it authenticates your app to the gateway and is separate from your provider's own API key, which you still keep and send yourself. See Quickstart and Gateway Authentication if you haven't set these up yet. Every example below only changes a base_url/headers - your actual Python code and provider SDKs stay the same.

Try it now

Paste in a gateway URL, your gateway key, and a provider key to send a real request straight from this page - no code required yet.

Loading playground...

Raw HTTP requests

Install:

pip install httpx opentelemetry-api opentelemetry-sdk

Every raw HTTP call follows the same shape: build one headers dict, add X-Gateway-Key, add the provider's own auth header, then POST to the gateway route.

OpenAI

import os
import httpx

headers = {
"Authorization": f"Bearer {os.environ['OPENAI_API_KEY']}",
"X-Gateway-Key": os.environ["OBSERVRA_GATEWAY_KEY"],
}

resp = httpx.post(
"https://gateway.observra.in/openai/v1/chat/completions",
headers=headers,
json={
"model": "gpt-4o-mini",
"messages": [{"role": "user", "content": "Say hello in one line."}],
},
timeout=60,
)

Anthropic

import os
import httpx

headers = {
"x-api-key": os.environ["ANTHROPIC_API_KEY"],
"anthropic-version": "2023-06-01",
"X-Gateway-Key": os.environ["OBSERVRA_GATEWAY_KEY"],
}

resp = httpx.post(
"https://gateway.observra.in/anthropic/v1/messages",
headers=headers,
json={
"model": "claude-sonnet-4-6",
"max_tokens": 256,
"messages": [{"role": "user", "content": "Say hello in one line."}],
},
timeout=60,
)

Gemini

import os
import httpx

headers = {
"x-goog-api-key": os.environ["GEMINI_API_KEY"],
"X-Gateway-Key": os.environ["OBSERVRA_GATEWAY_KEY"],
}

resp = httpx.post(
"https://gateway.observra.in/gemini/v1beta/models/gemini-3.1-flash-lite:generateContent",
headers=headers,
json={
"contents": [
{"role": "user", "parts": [{"text": "Say hello in one line."}]}
],
},
timeout=60,
)

Groq

import os
import httpx

resp = httpx.post(
"https://gateway.observra.in/groq/v1/chat/completions",
headers={
"Authorization": f"Bearer {os.environ['GROQ_API_KEY']}",
"X-Gateway-Key": os.environ["OBSERVRA_GATEWAY_KEY"],
},
json={
"model": "llama-3.3-70b-versatile",
"messages": [{"role": "user", "content": "Say hello in one line."}],
},
timeout=60,
)

Ollama

import os
import httpx

resp = httpx.post(
"https://gateway.observra.in/ollama/api/chat",
headers={
"Authorization": f"Bearer {os.environ['OLLAMA_API_KEY']}",
"X-Gateway-Key": os.environ["OBSERVRA_GATEWAY_KEY"],
},
json={
"model": "gpt-oss:120b-cloud",
"messages": [{"role": "user", "content": "Say hello in one line."}],
},
timeout=60,
)

OpenRouter

import os
import httpx

resp = httpx.post(
"https://gateway.observra.in/openrouter/v1/chat/completions",
headers={
"Authorization": f"Bearer {os.environ['OPENROUTER_API_KEY']}",
"HTTP-Referer": "https://docs.observra.in",
"X-Gateway-Key": os.environ["OBSERVRA_GATEWAY_KEY"],
},
json={
"model": "tencent/hy3:free",
"messages": [{"role": "user", "content": "Say hello in one line."}],
},
timeout=60,
)

Azure OpenAI

import os
import httpx

resp = httpx.post(
"https://gateway.observra.in/azure/v1/chat/completions",
headers={
"api-key": os.environ["AZURE_OPENAI_API_KEY"],
"X-Gateway-Key": os.environ["OBSERVRA_GATEWAY_KEY"],
"X-Azure-Endpoint": os.environ["AZURE_OPENAI_ENDPOINT"],
"X-Azure-Api-Version": os.environ.get("AZURE_OPENAI_API_VERSION", "2024-02-15-preview"),
},
json={
"model": os.environ["AZURE_OPENAI_DEPLOYMENT"],
"messages": [{"role": "user", "content": "Say hello in one line."}],
},
timeout=60,
)

Native SDKs

Point each provider's own SDK at the gateway route as its base_url, use your Observra gateway key as the SDK's api_key field (most SDKs require one, even though the gateway is what checks it), and forward your real provider key with X-Provider-Key.

Install:

pip install openai anthropic google-genai httpx opentelemetry-api opentelemetry-sdk
import os
from opentelemetry import trace
from opentelemetry.propagate import inject

tracer = trace.get_tracer("observra.native-sdk")

OpenAI SDK

import os
from openai import OpenAI

client = OpenAI(
api_key=os.environ["OBSERVRA_GATEWAY_KEY"],
base_url="https://gateway.observra.in/openai",
default_headers={
"X-Provider-Key": os.environ["OPENAI_API_KEY"],
"X-Gateway-Key": os.environ["OBSERVRA_GATEWAY_KEY"],
},
)

response = client.chat.completions.create(
model="gpt-4o-mini",
messages=[{"role": "user", "content": "Say hello in one line."}],
)

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

Anthropic SDK

import os
import anthropic

client = anthropic.Anthropic(
api_key=os.environ["OBSERVRA_GATEWAY_KEY"],
base_url="https://gateway.observra.in/anthropic",
default_headers={
"X-Provider-Key": os.environ["ANTHROPIC_API_KEY"],
"X-Gateway-Key": os.environ["OBSERVRA_GATEWAY_KEY"],
},
)

response = client.messages.create(
model="claude-sonnet-4-6",
max_tokens=256,
messages=[{"role": "user", "content": "Say hello in one line."}],
)

print(response.content[0].text)

Google GenAI SDK

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

client = genai.Client(
api_key=os.environ["OBSERVRA_GATEWAY_KEY"],
http_options=types.HttpOptions(
base_url="https://gateway.observra.in/gemini",
headers={
"X-Provider-Key": os.environ["GEMINI_API_KEY"],
"X-Gateway-Key": os.environ["OBSERVRA_GATEWAY_KEY"],
},
),
)

response = client.models.generate_content(
model="gemini-3.1-flash-lite",
contents="Say hello in one line.",
)

print(response.text)

Groq, Ollama, OpenRouter

These are OpenAI-compatible through the gateway, so reuse the OpenAI SDK with a different base_url and provider key.

import os
from openai import OpenAI

client = OpenAI(
api_key=os.environ["OBSERVRA_GATEWAY_KEY"],
base_url="https://gateway.observra.in/groq",
default_headers={
"X-Provider-Key": os.environ["GROQ_API_KEY"],
"X-Gateway-Key": os.environ["OBSERVRA_GATEWAY_KEY"],
},
)

response = client.chat.completions.create(
model="llama-3.1-8b-instant",
messages=[{"role": "user", "content": "Say hello in one line."}],
)

Azure OpenAI SDK

import os
from openai import AzureOpenAI

client = AzureOpenAI(
api_key=os.environ["AZURE_OPENAI_API_KEY"],
azure_endpoint="https://gateway.observra.in/azure",
api_version=os.environ.get("AZURE_OPENAI_API_VERSION", "2024-02-01"),
default_headers={
"X-Provider-Key": os.environ["AZURE_OPENAI_API_KEY"],
"X-Gateway-Key": os.environ["OBSERVRA_GATEWAY_KEY"],
"X-Azure-Endpoint": os.environ["AZURE_OPENAI_ENDPOINT"],
},
)

response = client.chat.completions.create(
model=os.environ["AZURE_OPENAI_DEPLOYMENT"],
messages=[{"role": "user", "content": "Say hello in one line."}],
)

Agent frameworks & SDKs

More advanced: these frameworks wrap one or more of the SDKs above. Each still points its underlying client at the gateway route and forwards X-Provider-Key/X-Gateway-Key.

Install:

pip install langchain langchain-openai langchain-anthropic langchain-google-genai langchain-groq httpx opentelemetry-api opentelemetry-sdk openinference-instrumentation-langchain python-dotenv
import os
from dotenv import load_dotenv
from opentelemetry import trace
from opentelemetry.propagate import inject

load_dotenv()

proxy_base_url = os.environ.get("PROXY_BASE_URL", "https://gateway.observra.in").rstrip("/")
gateway_key = os.environ["OBSERVRA_GATEWAY_KEY"]
tracer = trace.get_tracer("observra.langchain")

OpenAI model + agent:

from langchain_openai import ChatOpenAI
from langchain.agents import create_agent

provider = "openai"
model_id = "gpt-4o-mini"
base_url = f"{proxy_base_url}/{provider}"

chat_model = ChatOpenAI(
model=model_id,
base_url=base_url,
api_key=gateway_key,
default_headers={
"X-Provider-Key": os.environ["OPENAI_API_KEY"],
"X-Gateway-Key": gateway_key,
},
)

user_prompt = "Say hello in one line."
agent = create_agent(model=chat_model, tools=[])
result = agent.invoke({"messages": [{"role": "user", "content": user_prompt}]})

Anthropic, Gemini, Groq, Ollama, OpenRouter, and Azure use the same pattern with their own LangChain chat classes - see the equivalent raw HTTP sections above for the exact header/URL shape each provider needs. To pass traceparent on every outbound call (LangChain's provider packages issue their own HTTP requests), patch httpx once before your app starts:

import httpx
from opentelemetry.propagate import inject

_original_send = httpx.Client.send

def _traced_send(self, request, **kwargs):
inject(request.headers)
return _original_send(self, request, **kwargs)

httpx.Client.send = _traced_send

_original_asend = httpx.AsyncClient.send

async def _traced_asend(self, request, **kwargs):
inject(request.headers)
return await _original_asend(self, request, **kwargs)

httpx.AsyncClient.send = _traced_asend

Then run the agent inside a span: with tracer.start_as_current_span("langchain-agent-run"): agent.invoke(...).

Next steps