You can call Claude with the official OpenAI SDK by pointing the SDK at an OpenAI-compatible gateway instead of at OpenAI. You change two things, the base URL and the API key, then pass a Claude model name. Your existing chat.completions.create code keeps working. This guide shows complete Node.js and Python examples using the NewHost AI gateway, plus how to switch models, handle errors and keep keys safe.
Why use the OpenAI SDK for Claude?
Anthropic has its own SDK and its own Messages API, and if you only ever call Claude, that is a perfectly good choice. The OpenAI SDK route makes sense when:
- Your codebase already uses the OpenAI SDK and you want to try Claude without a rewrite.
- You want to switch between providers (Claude, GPT, Gemini, Mistral and others) by changing one string.
- You use tools and frameworks that expect the OpenAI Chat Completions format.
- You want one bill, in rand, for several providers. See paying for AI APIs in rand.
The trade-off: an OpenAI-compatible layer maps the common features (messages, system prompts, temperature, max tokens). Provider-specific features that don't exist in the OpenAI format may not be available through it. If you depend on one of those, use the provider's native SDK for that part.
What you need
- A NewHost API key with AI access (prepaid AI credits or your own Anthropic key configured). Create it in the dashboard at app.newhost.co.za.
- The gateway base URL:
https://api.newhost.co.za/ai/v1 - A model name in
provider/modelform, for exampleanthropic/claude-opus-5.
Store the key in an environment variable, never in source code:
export NEWHOST_API_KEY="your-key-here"
On NewHost app hosting, add NEWHOST_API_KEY as an encrypted environment variable on the app instead.
Node.js example
Install the official SDK:
npm install openai
Create claude.mjs:
import OpenAI from "openai";
const client = new OpenAI({
baseURL: "https://api.newhost.co.za/ai/v1",
apiKey: process.env.NEWHOST_API_KEY,
});
const completion = await client.chat.completions.create({
model: "anthropic/claude-opus-5",
max_tokens: 500,
messages: [
{ role: "system", content: "You are a concise assistant for a South African small business." },
{ role: "user", content: "Write a two-line out-of-office reply for the December holidays." },
],
});
console.log(completion.choices[0].message.content);
console.log("Tokens used:", completion.usage);
Run it:
node claude.mjs
The .mjs extension lets you use import and top-level await without extra configuration. In a TypeScript or Next.js project the same code works inside an async function or a route handler.
Using it in a Next.js route handler
// app/api/summarise/route.ts
import OpenAI from "openai";
const client = new OpenAI({
baseURL: "https://api.newhost.co.za/ai/v1",
apiKey: process.env.NEWHOST_API_KEY,
});
export async function POST(request: Request) {
const { text } = await request.json();
const completion = await client.chat.completions.create({
model: "anthropic/claude-opus-5",
max_tokens: 300,
messages: [
{ role: "system", content: "Summarise the user's text in three bullet points." },
{ role: "user", content: String(text).slice(0, 20000) },
],
});
return Response.json({ summary: completion.choices[0].message.content });
}
Keep this on the server. Never call the gateway from browser code, because anyone could read the key. Only variables prefixed NEXT_PUBLIC_ reach the browser in Next.js, so a plain NEWHOST_API_KEY stays server-side.
Python example
Install the SDK:
pip install openai
Create claude.py:
import os
from openai import OpenAI
client = OpenAI(
base_url="https://api.newhost.co.za/ai/v1",
api_key=os.environ["NEWHOST_API_KEY"],
)
completion = client.chat.completions.create(
model="anthropic/claude-opus-5",
max_tokens=500,
messages=[
{"role": "system", "content": "You are a concise assistant for a South African small business."},
{"role": "user", "content": "Write a two-line out-of-office reply for the December holidays."},
],
)
print(completion.choices[0].message.content)
print("Tokens used:", completion.usage)
Note the naming difference: Python uses base_url and api_key, Node uses baseURL and apiKey.
Multi-turn conversations
The API is stateless. To continue a conversation, send the earlier messages back with each request:
history = [
{"role": "system", "content": "You help customers track orders."},
{"role": "user", "content": "Where is my order?"},
{"role": "assistant", "content": "Could you share your order number?"},
{"role": "user", "content": "It's 10482."},
]
reply = client.chat.completions.create(
model="anthropic/claude-opus-5",
max_tokens=300,
messages=history,
)
Every message in the history counts as input tokens, so long conversations get more expensive with each turn. Trim or summarise old turns once a conversation grows.
Switching models
Because every model sits behind the same API, switching is a string change. Read the model from configuration so you can change it without a deploy:
const model = process.env.AI_MODEL ?? "anthropic/claude-opus-5";
List the models your key can use:
for m in client.models.list():
print(m.id)
A sensible pattern is to use a large model where quality matters (drafting, reasoning over long documents) and a smaller, cheaper one for classification or extraction. Test both with your real prompts before deciding.
Handling errors
Both SDKs raise typed errors. Handle rate limits and temporary failures with a retry, and treat authentication errors as configuration problems:
import OpenAI from "openai";
try {
const completion = await client.chat.completions.create({ /* ... */ });
} catch (err) {
if (err instanceof OpenAI.APIError) {
console.error(err.status, err.message);
// 401: check NEWHOST_API_KEY. 429: back off and retry. 5xx: retry later.
} else {
throw err;
}
}
The SDKs already retry some failures automatically; you can tune this with the maxRetries option in Node or max_retries in Python.
Personal information and POPIA
Claude runs on Anthropic's infrastructure outside South Africa. If your prompts include personal information, you are transferring it across the border, which POPIA section 72 restricts. Remove what the model doesn't need, disclose AI processing in your privacy policy and read POPIA section 72 and AI APIs before shipping. The NewHost gateway records usage (model, tokens, cost) but does not store prompts or responses.
Frequently asked questions
Can I use the OpenAI SDK with Claude directly, without a gateway?
Anthropic offers its own SDK and API, and the OpenAI SDK needs an OpenAI-compatible endpoint to talk to. A gateway such as NewHost's provides that endpoint for Claude and other providers, so one SDK covers them all.
Which Claude model name should I use?
Use the provider/model name the gateway lists, for example anthropic/claude-opus-5. Call the /models endpoint to see the current list available to your key.
Does streaming work?
Yes. Pass stream: true (Node) or stream=True (Python) and iterate over the chunks exactly as you would with OpenAI directly; the gateway streams the provider's response through. The AI gateway section of the developer docs has a streaming example.
Where should I keep my API key?
In an environment variable on the server, such as NEWHOST_API_KEY. Never commit it to Git or send it to the browser, and use separate keys for development and production.
The full gateway reference is at docs.newhost.co.za. If you're deploying the app that calls it, see Next.js hosting or Node.js hosting.