Anthropic Messages API
The /v1/messages endpoint, compatible with the Anthropic SDK and Claude Code
Onysoft also serves the Anthropic Messages API format. Code written with the Anthropic SDK and Claude Code work by changing only the base address and the key; the same sk-ony- key, balance and model catalog are used. Non-Claude models can be called through this endpoint too. For Claude Code setup see the Claude Code section.
/v1/messages
Creates a message (streaming or non-streaming). The response is an Anthropic Message object or Anthropic SSE events.
/v1/messages/count_tokens
Returns the input token count of a request. Free of charge; nothing is deducted from your balance.
/v1/models
Called with the anthropic-version header, returns the model list in the Anthropic format (see Models API).
Base Address and Authentication
In the Anthropic SDK and in Claude Code the base address must be https://api.onysoft.com; the client adds the /v1/messages path itself. The key can be sent two ways: Authorization: Bearer sk-ony-... or x-api-key: sk-ony-.... If both are present, Authorization is used. The SDKs send the anthropic-version header themselves (e.g. 2023-06-01). x-api-key is accepted only on these endpoints; other endpoints such as /v1/chat/completions require Authorization: Bearer.
Do not append /v1. If the base address is set to https://api.onysoft.com/v1, the request goes to /v1/v1/messages and returns 404; Claude Code shows this as "There's an issue with the selected model". The OpenAI SDK, on the other hand, expects https://api.onysoft.com/v1.
Example Request
curl https://api.onysoft.com/v1/messages \
-H "x-api-key: $ONYSOFT_API_KEY" \
-H "anthropic-version: 2023-06-01" \
-H "content-type: application/json" \
-d '{
"model": "anthropic/claude-sonnet-5.5",
"max_tokens": 1024,
"messages": [{"role": "user", "content": "Merhaba!"}]
}'
import os
from anthropic import Anthropic
client = Anthropic(
base_url="https://api.onysoft.com", # do not append /v1
api_key=os.environ["ONYSOFT_API_KEY"],
)
message = client.messages.create(
model="anthropic/claude-sonnet-5.5",
max_tokens=1024,
messages=[{"role": "user", "content": "Merhaba!"}],
)
print(message.content[0].text)
import Anthropic from '@anthropic-ai/sdk';
const client = new Anthropic({
baseURL: 'https://api.onysoft.com', // do not append /v1
apiKey: process.env.ONYSOFT_API_KEY,
});
const message = await client.messages.create({
model: 'anthropic/claude-sonnet-5.5',
max_tokens: 1024,
messages: [{ role: 'user', content: 'Merhaba!' }],
});
console.log(message.content[0].text);
Model Names
In the model field you can use the catalog id (anthropic/claude-sonnet-5.5) or the Anthropic id (claude-sonnet-5-5, claude-haiku-4-5-20251001); Anthropic ids are mapped to their catalog counterpart. Names such as claude-sonnet-latest go to the ~anthropic/claude-sonnet-latest alias. Unprefixed names that match exactly one model in the catalog are resolved too. A model that is not in the catalog, or that your key is not allowed to use, returns 404 not_found_error. Non-Claude models (e.g. openai/gpt-5.5, z-ai/glm-5.3:tr) can be called through this endpoint as well: the request is translated to the chat format and the response still comes back in the Anthropic format.
Supported and Unsupported Fields
- On Claude models
system,tools,tool_choice,thinking,stop_sequencesand streaming are supported in the Anthropic format; the request body (includingcache_controlmarkers) is forwarded to Anthropic unchanged. - Of the server tools, web search (
web_search) and web fetch (web_fetch) work on Claude models; web searches are charged separately. - Not supported (on Claude models 400
invalid_request_error; the error message names the field or tool): Files API file ids (file_id,container_upload),thread, server tools without a defined price (code_execution,tool_searchetc.),containerand the remote MCP connector (mcp_servers). MCP servers running on your own machine (client-side tool calls) are not affected. - Silently removed from the request:
fallbacks,compact_*edits insidecontext_management,speed,service_tieranddiagnostics. The request runs normally without them. - On non-Claude models thinking blocks are not included in the response, Anthropic-specific fields (
cache_control,metadata,context_management) are not passed to the model, and server tools are removed from the request. max_tokensis required; if it exceeds the model's output cap it is lowered to the cap.- Message Batches (
/v1/messages/batches) and Files API endpoints are not available (404).
Token Counting
POST /v1/messages/count_tokens returns the input token count as {"input_tokens": N}; it is free. On Claude models the count is done by Anthropic. On other models (or if counting is not possible) an approximate estimate is returned and the response carries the X-Onysoft-Token-Count: estimate header. Your key's model permissions apply here too, and the request counts toward the per-minute request limit.
// POST /v1/messages/count_tokens
{ "model": "anthropic/claude-sonnet-5.5", "messages": [{ "role": "user", "content": "Merhaba!" }] }
// 200
{ "input_tokens": 10 }
Response and Streaming
A non-streaming request returns an Anthropic Message object (id, type: "message", content, stop_reason, usage). With stream: true you receive Anthropic SSE events: message_start, content_block_start, content_block_delta, content_block_stop, message_delta and message_stop. An error that occurs after the stream has started is reported with an event: error event; for transient conditions the error type is overloaded_error and Claude Code retries the request itself.
Error Format
{
"type": "error",
"error": {
"type": "not_found_error",
"message": "model: claude-example not found"
}
}
Errors on these endpoints use the Anthropic format; there are no success, code or param fields. Types: 400 invalid_request_error, 401 authentication_error, 402 billing_error, 403 permission_error, 404 not_found_error, 413 request_too_large, 429 rate_limit_error, 503 overloaded_error, 504 timeout_error, other 5xx api_error. A model that is not allowed or not in the catalog returns 404 not_found_error. The 402 message states the required and the available amount.
Billing
Charges are taken from actual usage with the same rule and the same model price as Chat Completions. Before the request a balance pre-check is made based on max_tokens (see Balance pre-check). count_tokens is free.