1. Three settings to move
Compatibility means matching the API format, not the behavior of every model. So migration is replacing three values with verification, not blindly swapping the address. Start with a short text request without tools or large context and record the status, the actual model, and X-Request-Id.
base_url: https://api.normahub.cc/v1
api_key: YOUR_API_KEY # from the dashboard, server-side only
model: MODEL_ID # exact ID from the catalog or /v1/modelsTake the model ID from the current catalog or from GET /v1/models with your key. IDs from third-party READMEs may be renamed, disabled, or closed to your key — no prompt fixes the catalog. Russian version of this guide: OpenAI SDK через NormaHub.
2. Picking the route
One base_url serves several routes, but each route's availability is set by the chosen model. Chat Completions is the messages dialog route. Responses API is a separate input-based route, available where declared. Anthropic-compatible clients use the /v1/messages route — pick it by client format, not by model name.
from openai import OpenAI
client = OpenAI(
api_key="YOUR_API_KEY",
base_url="https://api.normahub.cc/v1",
)
# Chat Completions — the classic dialog route
chat = client.chat.completions.create(
model="MODEL_ID",
messages=[{"role": "user", "content": "Hello"}],
)
# Responses API — where the model declares it
resp = client.responses.create(
model="MODEL_ID",
input="Hello",
)Do not mix protocols blindly: a Claude or GPT entry in the catalog does not mean every model accepts tools, streaming, or the same response shape. Verify each model's endpoint and capabilities before switching — see the API reference for details.
3. Timeouts and retries
A production client differs from a README example in two things: every request has a timeout, and retries are bounded. The SDK retries transient 429s and 5xx itself, but you set the attempt count and the operation deadline. An interactive UI is often better off failing fast with a clear message than holding the user in a retry queue.
from openai import OpenAI
client = OpenAI(
api_key="YOUR_API_KEY",
base_url="https://api.normahub.cc/v1",
timeout=30.0, # seconds per request instead of waiting forever
max_retries=2, # the SDK retries only transient failures
)
response = client.chat.completions.create(
model="MODEL_ID",
messages=[{"role": "user", "content": "Hello"}],
max_tokens=512, # caps both the answer and the bill
)If the connection drops after the request is sent, the outcome is unknown: upstream may already have processed the operation. Do not repeat non-idempotent actions without your own idempotency key. Full rules are in the errors guide.
4. Beyond the OpenAI SDK
The same base_url works with any OpenAI-compatible client: LangChain, LiteLLM, Cline, and CLI agents take the address and key in their own configuration. One rule for all: the key on the server or in the process environment, the model ID from the catalog, the first request small. Tool-specific examples are in the OpenCode guide and the Claude guide.
5. Security
Call NormaHub from a backend or a local AI agent. Never pass the secret key into browser JavaScript, mobile bundles, public logs, CI artifacts, or docker history. Split keys by environment and integration with their own limits: revoking one secret must not stop the whole product. Create and revoke keys in the dashboard.