BETA
Documentation
Create a message
POST/v1/messages
Native Anthropic Messages API — for Anthropic-protocol clients (Claude Code and other Anthropic SDKs) that connect via ANTHROPIC_BASE_URL/ANTHROPIC_API_KEY instead of an OpenAI-compatible provider block.
Request body
model
required, string — a catalog id from GET /v1/models
max_tokens
required, number — the Anthropic API requires it, unlike OpenAI's chat/completions
messages
required, array — role: "user"/"assistant", content as a string or content blocks (text, tool_use, tool_result)
system
optional, string or array of text blocks
tools
optional, array — Anthropic tool-definition shape (name, description, input_schema)
tool_choice
optional — auto / any / none / a named tool
stop_sequences
optional, array of strings
stream
optional, boolean — Anthropic-style SSE events when true
temperature / top_p
optional, forwarded unmodified
cURL example
terminal
curl https://apily.pro/v1/messages \
-H "x-api-key: apily_your-api-key" \
-H "Content-Type: application/json" \
-d '{"model":"claude-opus-5","max_tokens":1024,"messages":[{"role":"user","content":"ping"}]}'Response
An Anthropic Message object — content (an array of text/tool_use blocks), stop_reason, and usage (input_tokens/output_tokens) with the real token counts for the request, not an upfront estimate. Streaming requests get the standard Anthropic SSE sequence — message_start → content_block_start/delta/stop → message_delta → message_stop.
Not supported
imagecontent blocks, and any unrecognized content-block type, return a400 invalid_request_errorinstead of being silently dropped.- The
thinkingrequest field andthinking/redacted_thinkinghistory blocks are silently ignored — most Anthropic clients sendthinkingby default, so this keeps the endpoint usable rather than rejecting every request. cache_control(prompt caching) is not proxied to the upstream model.- The Anthropic Batches and Token Counting APIs (
/v1/messages/batches,/v1/messages/count_tokens) are not implemented.
Error responses
Errors use the Anthropic error envelope ({ type: "error", error: { type, message } }), not the { error: string } shape used by the OpenAI-compatible routes.
| Symptom | Cause | Fix |
|---|---|---|
401 Missing API key | No auth header was sent. | Apily accepts Authorization: Bearer … and x-api-key: …. |
401 Invalid API key | Key copied with stray spaces, truncated, or revoked. | Copy the key whole from the API page in your Apily account, the apily_ prefix included. |
403 Email not verified | Your Apily account's email address isn't verified yet. | Verify your email from the banner in the Apily app, then retry. |
404 Model not found | The model ID isn't in the Apily catalog. | Copy the exact ID from GET /v1/models or the Models page in your account. |
503 Model temporarily unavailable | The model exists, but no upstream provider is reachable right now. | Retry in a moment — it usually recovers within a minute. Switch models if it keeps happening. |
402 Insufficient balance | Your token balance can't cover the request's estimated cost. | Top up your balance on the Billing page in your Apily account. |
429 Too many requests | Your account sent more than 600 /v1/* requests in a minute — all of your API keys share one budget. The body is { error: { message, type: "rate_limit_error", code: "rate_limit_exceeded" }, retryAfterSeconds }. | Wait the Retry-After header (or retryAfterSeconds) before retrying, and lower request concurrency. |
502 Upstream error | The upstream provider returned an unexpected error. | Retry the request; try a different model if it persists. |