POST /v1/messages takes the
Messages request body, answers with the Messages response body, and streams
Anthropic’s own event stream when you ask for one. It is the same key, the same
catalog and the same balance as the OpenAI-shaped endpoints, filed under its own
endpoint family in your usage.
Point the Anthropic SDK at it
Two settings change, as with the OpenAI SDKs: the base URL and the key. The Anthropic SDKs add/v1/messages themselves, so the base URL is the bare
origin.
provider/model, so the provider half is
written out. A bare Anthropic id is refused with the code
model_id_not_pinned like everywhere else. Any model the catalog lists for the
messages family is callable here; ask GET /v1/models for
the exact strings.
Either credential header
Anthropic’s own SDKs send the key asx-api-key. The OpenAI SDKs and most
other clients send Authorization: Bearer. On this one path both are read, so
whichever client you have works unchanged.
Send one of them. A request carrying both with different values is refused
with HTTP 401 rather than served on either:
401
What is identical
- The request body.
model,max_tokens,messages,system,tools,tool_choice,streamand the rest travel as you sent them. - The success body. A non-streamed reply is Anthropic’s message object, with
its
contentarray,stop_reasonandusageofinput_tokensandoutput_tokens, exactly as the provider returned it. - The stream. With
stream: trueyou receive Anthropic’s own server-sent events, so an Anthropic SDK’s streaming helpers work. max_tokens. Anthropic requires it, and we do not fill one in for you. A request without it reaches the provider and is refused there, in the provider’s own words, relayed with its status.
The one departure: refusals wear the OpenAI envelope
A refusal that comes from us rather than from Anthropic, such as an unknown key, an empty balance, a spend cap or a guardrail, is shaped as the OpenAI error envelope documented on Errors: anerror object
with message, type, param, code and request_id. It is not shaped as
Anthropic’s error object.
The reason is that every refusal on this platform is one shape, so a client
that handles one of them handles all of them. An Anthropic SDK still raises on
the status code; what differs is the body it attaches to the exception, and
the code inside it is where the reason lives.
A refusal that comes from Anthropic itself, such as an invalid tool definition,
is relayed with the provider’s own status and a message that quotes the
provider’s sentence.
What we do not forward
Nothing you send as a header reaches the provider. The request we make is built from your body and our own credential with a fresh header set, so ananthropic-version or anthropic-beta header you send is read by nobody. The
version the provider sees is the one we send, and a feature that needs a beta
header is not reachable this way. Send the version header anyway if your SDK
insists; it is harmless.
The same fields we refuse on our own provider credentials elsewhere are refused
here too: store: true, hosted tools that the provider bills for, and the two
container fields container and mcp_servers. Each is a 400 naming the field
in param, and each is forwarded untouched on your own provider key.
Next
Claude Code
Pointing the Claude Code harness at this endpoint.
Errors
The envelope every refusal above is shaped as, and what each code asks of you.
Every response carries the same id on two headers:
x-hopscotch-request-id,
which is ours, and x-request-id, which is the one the official OpenAI SDKs
surface on their error objects. Every error envelope repeats it as
request_id. Quote it when you ask us about a request. Without it we are
guessing at which of your requests you mean.