Anthropic Messages API or OpenAI Chat Completions: which one should I use?
In short: Use whichever format your tool or SDK speaks. On the Wiozen API both work with the same key, the same model names and the same prices: the Anthropic format at /v1/messages, the OpenAI format at /v1/chat/completions. If you're writing code from scratch and want it to work with the most tools, go with the OpenAI format. If you want free input-token counting or Claude's thinking settings, the Anthropic format fits better.
How do the two formats differ?
Both do the same job: you send a list of messages and get the model's answer back. The differences are in the details. In the OpenAI format the system instruction sits inside the messages array as role: "system", the answer comes in choices[0].message.content, and token counts are called prompt_tokens / completion_tokens. In the Anthropic format the system instruction goes in a top-level system field, max_tokens is required, the answer comes as blocks in a content array, and the counts are input_tokens / output_tokens.
| OpenAI format | Anthropic format | |
|---|---|---|
| Path | /v1/chat/completions | /v1/messages |
| Base URL in the SDK | https://api.wiozen.com/v1 | https://api.wiozen.com |
| System instruction | Inside messages | Top-level system |
| Answer | choices[0].message.content | content[0].text |
| Error body | {"error": {"message", "type"}} | {"type": "error", "error": {…}} |
Watch the base URL row: the Anthropic SDK adds /v1/messages to the path itself, while the OpenAI SDK only adds /chat/completions. If /v1 ends up in there twice by mistake, the Wiozen API also accepts /v1/v1/..., so the request still works.
What does the same request look like in each format?
With the Anthropic SDK:
import anthropic
client = anthropic.Anthropic(base_url="https://api.wiozen.com", api_key="sk-gw-...")
msg = client.messages.create(
model="claude-haiku-5-5",
max_tokens=1024,
system="Answer briefly.",
messages=[{"role": "user", "content": "What is HTTP 429?"}],
)
print(msg.content[0].text)
print(msg.usage.input_tokens, msg.usage.output_tokens)With the OpenAI SDK, same model, same question:
from openai import OpenAI
client = OpenAI(base_url="https://api.wiozen.com/v1", api_key="sk-gw-...")
r = client.chat.completions.create(
model="claude-haiku-5-5",
max_tokens=1024,
messages=[
{"role": "system", "content": "Answer briefly."},
{"role": "user", "content": "What is HTTP 429?"},
],
)
print(r.choices[0].message.content)
print(r.usage.prompt_tokens, r.usage.completion_tokens)Both requests go to the same model and are charged the same price. The key header isn't a problem either: the Anthropic SDK sends the key in an x-api-key header and the OpenAI SDK in Authorization: Bearer; the Wiozen API accepts both.
Which models work with which format?
All of them work with both. Every name on the Models page is valid on both endpoints: you can call a Claude model in the OpenAI format, or a DeepSeek or Gemini model in the Anthropic format. The format only decides the shape of the request and response; the model field decides which model runs.
The one exception among tools is Claude Code. It uses the Anthropic format and currently works only with the wiozen-anthropic model; the settings are on its setup page.
What do I get from the Anthropic format?
First, free token counting. /v1/messages/count_tokens tells you how many input tokens a request will use without running the model. The call isn't charged, holds nothing from your balance, and doesn't count toward the per-minute or daily limits. It's handy for checking the cost of a large document before you send it.
count = client.messages.count_tokens(
model="claude-sonnet-5-5",
messages=[{"role": "user", "content": open("report.md").read()}],
)
print(count.input_tokens)Second, the thinking setting. Claude 5.5 models don't accept the older thinking: {"type": "enabled", "budget_tokens": N} form. Instead of rejecting such a request, the Wiozen API turns the budget into a level: under 4,000 becomes low, over 16,000 high, anything between medium. Your old code keeps working unchanged.
What do I get from the OpenAI format?
Compatibility. Most editor extensions, chat interfaces and agent frameworks ask for an "OpenAI-compatible" address and speak only this format. Code you write once in the OpenAI format also runs against other services by changing the base URL. The connection steps are in the connecting an OpenAI-compatible API guide.
OpenAI also has the newer Responses format (/v1/responses). The Wiozen API accepts it too, for tools such as Codex that only use that format. For your own code, Chat Completions is more common and has more examples around.
What should I watch out for when switching formats?
- The system instruction moves. If you use a client that puts
role: "system"insidemessagesin the Anthropic format, the Wiozen API moves those messages into the top-levelsystemfield itself, and the request isn't rejected. - The Anthropic format requires
max_tokens. Don't set it higher than you need; an amount based on it is held from your balance when the request starts. - Write your error handling per format. The error body comes back in the format you sent the request in; an error parser written for the OpenAI format can't read an Anthropic-format error.
- Tool calls (
tools) and streaming (stream) work in both formats, but the field names differ. When you switch, rewrite that part following the SDK's own docs.
Frequently asked questions
Is one format cheaper?
No. A model is charged the same price in both formats; the price depends only on the model.
Can I use Claude models with the OpenAI SDK?
Yes. Write the model name, for example claude-sonnet-5-5, with the base URL https://api.wiozen.com/v1.
Should the Anthropic SDK base URL end with /v1?
No, use https://api.wiozen.com; the SDK adds /v1/messages itself. It works even if you add it, because /v1/v1/ is accepted.
Is token counting charged?
No. /v1/messages/count_tokens is free and doesn't count toward the request limits.
Can I use the same key with both formats?
Yes. Keys aren't tied to a format; the same key works on all four chat endpoints.
The full list of endpoints and parameters is in the docs. Copy model names from the Models page.
More guides: How can you use an AI API from Turkey without a credit card? · How do you connect an OpenAI-compatible API to a tool you already use? · How do you calculate the cost of an AI API? · What should I do if my AI API key has leaked? · How do you generate images with an AI API, and what does one image cost? · Why does my AI API return a 429 error, and how do I fix it? · Why do long AI API requests time out: streaming or non-streaming? · What is a context window, and what is a 1 million token context good for? · Which AI model should I choose: deciding by price, context and quality · Why does a reasoning model return an empty answer, and why are thinking tokens charged? · Why is my API balance running out faster than expected? Tracking spend request by request · How do you convert a web page to Markdown to feed it to an AI model? · How do you get AI to write and publish articles in WordPress automatically? · How do you find blog topics from RSS feeds and Google Trends? · Does AI-written content show up on Google and in AI answers? · How do you get internal links into AI-written WordPress articles? · How do you get AI to generate a different featured image for every WordPress post? · How do you write a content brief when an AI writes your blog posts? · What should you watch for when an AI writes recipes for your food blog? · How do you fix errors when connecting a WordPress plugin to your AI API account? · Why does my AI article bot stop halfway in WordPress? "Run is stuck" and LiteSpeed · Why are my scheduled WordPress posts late? WP-Cron and a real server cron · How do I get an AI article bot to write blog posts in English or another language? · What does "Content Bot cannot generate articles" mean? Reading the bot's log