Loading
Skip to content
RedRouterRedRouter
Dashboard ↗

Python SDKs

Use the OpenAI Python SDK for Chat Completions or the Anthropic Python SDK for Messages. This recipe follows the SDK interface; it has not been live-tested against RedRouter.

Install and configure

python3 -m venv .venv
source .venv/bin/activate
python -m pip install openai
export REDROUTER_API_KEY="your-redrouter-api-key"

Save as example.py:

import os
import sys
from openai import OpenAI, APIConnectionError, APIStatusError

with OpenAI(
    api_key=os.environ["REDROUTER_API_KEY"],
    base_url="https://redrouter.org/v1",
    timeout=120.0,
    max_retries=0,
) as client:
    try:
        result = client.chat.completions.create(
            model="red-cyber-1",
            messages=[{"role": "user", "content": "Explain a database index in one sentence."}],
            max_tokens=512,
        )
        if result.choices[0].finish_reason != "stop":
            raise RuntimeError("The request did not finish with a complete text answer.")
        print(result.choices[0].message.content or "")
        if result.usage is not None:
            print(result.usage.model_dump(), file=sys.stderr)
    except APIStatusError as error:
        print(f"RedRouter HTTP {error.status_code}", file=sys.stderr)
        raise
    except APIConnectionError:
        print("Connection failed; the request outcome may be unknown.", file=sys.stderr)
        raise

Run python example.py. A successful request prints a sentence and reported token usage when available. The wording varies. base_url includes /v1; the SDK appends /chat/completions.

Stream or use async

Replace the request inside the same client context with:

stream = client.chat.completions.create(
    model="red-cyber-1",
    messages=[{"role": "user", "content": "Describe three useful code review checks."}],
    max_tokens=1024,
    stream=True,
    stream_options={"include_usage": True},
)
finish_reason = None
try:
    for chunk in stream:
        for choice in chunk.choices:
            print(choice.delta.content or "", end="", flush=True)
            if choice.finish_reason is not None:
                finish_reason = choice.finish_reason
        if chunk.usage is not None:
            print(chunk.usage.model_dump(), file=sys.stderr)
finally:
    stream.close()
if finish_reason != "stop":
    raise RuntimeError(f"Incomplete text stream: {finish_reason!r}")
print()

Usage chunks may have no choices. Read to completion rather than stopping at the first finish reason. The check rejects a stream that ends before a normal text finish reason, but the SDK iterator alone does not prove that the terminal [DONE] arrived. Use the raw SSE reader when exact terminal-event verification is required.

For an async service, use AsyncOpenAI, await client.chat.completions.create(...), and async for for streaming. Reuse one client per service lifetime.

Use the Anthropic SDK

Install anthropic in the same virtual environment:

python -m pip install anthropic

Save this separate example as messages_example.py, then run python messages_example.py:

import os
from anthropic import Anthropic

with Anthropic(
    api_key=os.environ["REDROUTER_API_KEY"],
    base_url="https://redrouter.org",
    max_retries=0,
    timeout=120.0,
) as client:
    response = client.messages.create(
        model="red-cyber-1",
        max_tokens=512,
        messages=[{"role": "user", "content": "Explain a database index in one sentence."}],
    )
    if response.stop_reason != "end_turn":
        raise RuntimeError("The request did not finish with a complete text answer.")
    print("".join(block.text for block in response.content if block.type == "text"))
    print(response.usage)

Use the origin without /v1; the SDK adds /v1/messages. Authentication uses your RedRouter key, and usage is billed by RedRouter. The Messages guide describes content blocks, tool turns, omitted thinking, and compatibility fields. Use the same retry and privacy rules as the OpenAI-shaped examples.

Handle application boundaries

Retries are disabled here so the application chooses when to submit another billable request. A connection failure after dispatch does not prove that generation never started. Apply bounded retry rules and inspect errors rather than retrying every exception.

The example model supports tools and structured output but cannot inspect images. See tool calling, structured output, reasoning, and Responses before enabling SDK helpers that send additional fields. SDK availability is broader than RedRouter's supported API surface.

References: OpenAI Python SDK and Anthropic Python SDK.

↑ ↓ to select · Enter to open · Esc to close