In this article
A minimal Python request should verify access and response handling before queues, streaming or agent loops are introduced.
You can call OpenRouter from Python with an ordinary HTTP client. A special framework is unnecessary for the first test. Verify the address, credential, permitted model and response structure first; add queues, tools and streaming only after that small request is understood and reproducible.
Build a bounded request
This illustrative example uses Python’s standard library. Supply your own authorized key and a currently permitted model through the server environment; neither is embedded in the source.
import json, os, urllib.request
payload = {
"model": os.environ["OPENROUTER_MODEL"],
"messages": [{"role": "user", "content": "Reply: ready"}],
"max_tokens": 32,
}
request = urllib.request.Request(
"https://openrouter.ai/api/v1/chat/completions",
data=json.dumps(payload).encode("utf-8"),
headers={
"Authorization": "Bearer " + os.environ["OPENROUTER_API_KEY"],
"Content-Type": "application/json",
}, method="POST",
)
with urllib.request.urlopen(request, timeout=60) as response:
result = json.load(response)
print(result.get("id"), result.get("model"))
The example does not select a universally available model or run automatically. Confirm the account, route and applicable charges before executing your own request. The small output limit bounds the experiment rather than establishing production capacity.
Check the actual runtime environment
A variable present in your terminal may not exist inside a container, scheduled job or deployed service. Check that the intended process receives both settings without printing their secret values. Missing local configuration should produce a clear application error before a network call.
Record the Python version, dependency choices and launch method. If the application later moves into a framework, retain this minimal control so that failures can be isolated from higher-level orchestration. The useful comparison is the same authorized request through two paths, not different models and payloads.
Separate HTTP and program failures
The compact example is a starting point, not complete error handling. A production wrapper should distinguish an HTTP rejection, timeout, decoding failure and unexpected response structure. Save the status, safe error details and request identifier when available. Do not log the key or a private source document.
Avoid automatic unlimited retries. A rejected credential or exhausted balance is different from a temporary failure, and retrying after an uncertain completion may add another request. Assign the user task its own identifier so that attempts can be reconciled later.
Confirm useful output before expanding
Inspect the returned content, model identity, finish state and usage. A successful HTTP exchange does not prove the answer satisfies the task. Add a simple expected-result check and test one controlled failure. Then introduce one feature at a time, preserving the baseline script.
For an infrastructure pilot, separate API access from local GPU readiness.
Official references: openrouter.ai — overview, openrouter.ai — authentication.
Related guides: OpenRouter base URL: configuring a compatible client, Calling OpenRouter from Node.js without exposing the key.