# Use Claude with the OpenAI SDK: OpenAI-compatible endpoint, streaming, tools and limits Code written for the OpenAI SDK can call Claude without a rewrite: point `base_url` at the gateway's `/v1`, use a gateway key and a Claude model ID. The endpoint accepts Chat Completions requests, streams in the same format and supports function calling. A few Claude features only exist in Anthropic's native format; the last section covers when to switch. ## Endpoint facts | Item | Value | | --- | --- | | Base URL | `https://aiprimetech.io/v1` | | Chat endpoint | `POST https://aiprimetech.io/v1/chat/completions` | | Model list | `GET https://aiprimetech.io/v1/models` | | Auth | `Authorization: Bearer `; `x-api-key` is also accepted | | Models | Claude IDs such as `claude-sonnet-5`; GPT IDs with a key from the Codex group | ## Python ```bash pip install openai ``` ```python import os from openai import OpenAI client = OpenAI(base_url="https://aiprimetech.io/v1", api_key=os.environ["AIPRIME_API_KEY"]) resp = client.chat.completions.create( model="claude-sonnet-5", max_tokens=1024, messages=[ {"role": "system", "content": "You are a concise assistant."}, {"role": "user", "content": "Explain idempotency keys in two sentences."}, ], ) print(resp.choices[0].message.content) print(resp.usage) ``` `base_url` must end in `/v1`: the SDK appends `/chat/completions` to it. Without `/v1` the request lands on the website and returns HTML; with `/v1` twice it returns `404 page not found`. ## Node.js ```js import OpenAI from "openai"; const client = new OpenAI({ baseURL: "https://aiprimetech.io/v1", apiKey: process.env.AIPRIME_API_KEY }); const resp = await client.chat.completions.create({ model: "claude-sonnet-5", max_tokens: 1024, messages: [{ role: "user", content: "Write a haiku about retries." }], }); console.log(resp.choices[0].message.content); ``` ## Streaming ```python stream = client.chat.completions.create( model="claude-sonnet-5", max_tokens=2048, stream=True, stream_options={"include_usage": True}, messages=[{"role": "user", "content": "Outline a zero-downtime migration."}], ) for chunk in stream: if chunk.choices and chunk.choices[0].delta.content: print(chunk.choices[0].delta.content, end="", flush=True) if chunk.usage: print("\n", chunk.usage) ``` Stream long answers: a non-streaming request has to finish inside your client's timeout, a stream does not. `include_usage` adds a final chunk with token counts. More on why it matters in [streaming LLM responses](/blog/streaming-api-guide/). ## Function calling ```python tools = [{ "type": "function", "function": { "name": "get_weather", "description": "Current weather for a city", "parameters": { "type": "object", "properties": {"city": {"type": "string"}}, "required": ["city"], }, }, }] resp = client.chat.completions.create( model="claude-sonnet-5", max_tokens=512, tools=tools, messages=[{"role": "user", "content": "What is the weather in Paris?"}], ) call = resp.choices[0].message.tool_calls[0] print(call.function.name, call.function.arguments) # get_weather {"city": "Paris"} ``` The reply comes back with `finish_reason: "tool_calls"` and OpenAI-style `tool_calls`. Run the function, append a `tool` message with the result and the matching `tool_call_id`, then call again, exactly as with OpenAI models. ## Reasoning and thinking `reasoning_effort` maps to Claude's effort setting and accepts `low`, `medium`, `high`, `xhigh` or `max`. The value `none` is rejected. When the model thinks, its reasoning arrives in a separate `reasoning_content` field next to `content`, so code that reads `message.content` keeps working unchanged. ```python resp = client.chat.completions.create( model="claude-opus-5-5", max_tokens=4096, reasoning_effort="high", messages=[{"role": "user", "content": "Find the bug in this function: ..."}], ) ``` ## Models | Model ID | Use it for | | --- | --- | | `claude-sonnet-5` | Default for coding and agent work: fast, strong, mid-priced. | | `claude-opus-5-5` | Harder reasoning, large refactors, long agent runs. | | `claude-fable-5-1` | Most capable and most expensive; save it for the hardest tasks. | | `claude-haiku-4-5` | Cheap and quick: titles, summaries, classification, small steps. | Use these IDs exactly. Old dated IDs such as `claude-3-5-sonnet-20241022` still appear in some model lists but are not served and return a model-not-supported error. ## When to use the native Anthropic API instead The OpenAI format covers chat, streaming, tools and images. Use Anthropic's own Messages format, at the same gateway, when you need explicit prompt-cache breakpoints, thinking blocks you pass back between turns, PDF documents or citations. The [Anthropic Python SDK guide](/learn/anthropic-python-sdk/) and the [Vercel AI SDK guide](/learn/use-claude-api-with-vercel-ai-sdk/) cover that route. ## Troubleshooting | What you see | Cause | Fix | | --- | --- | --- | | A JSON parse error, response starting with `<` | `base_url` without `/v1` | `https://aiprimetech.io/v1` | | `404 page not found` | `/v1` twice | Exactly one `/v1` | | `401 Invalid API key` | Missing or wrong key in the process | Check the variable; a key belongs to one gateway | | Model not supported | Old dated or misspelled model ID | Use an ID from the table above | | `'none' is not supported` | `reasoning_effort="none"` | Use `low` or higher, or leave it out | | `429 Concurrency limit exceeded for user` | Too many requests in flight | Limit parallelism; see [rate limits and retries](/blog/rate-limits-and-retries/) | | Timeouts on long answers | Long non-streaming request | Stream, or raise the client timeout | ## FAQ ### Can I use Claude with the OpenAI SDK? Yes, through an OpenAI-compatible endpoint: set base_url to the gateway's /v1, use a gateway API key and a Claude model ID such as claude-sonnet-5. Streaming and function calling work in the OpenAI format. ### What base URL do I use for Claude in the OpenAI SDK? The gateway URL ending in /v1, e.g. https://aiprimetech.io/v1. The SDK appends /chat/completions. ### Does function calling work with Claude through the OpenAI format? Yes. Pass tools in the OpenAI format; Claude returns tool_calls with finish_reason tool_calls, and you answer with tool messages as usual. ### When should I use the native Anthropic API instead? When you need explicit prompt caching, thinking blocks across turns, PDF input or citations. Those are part of Anthropic's Messages format. --- Source: https://aiprimetech.io/learn/openai-compatible-claude-api/ Provider: AI Prime Tech — independent Anthropic-compatible API gateway (not affiliated with Anthropic).