- Messages API Endpoint and Required Headers
- The Request and Response Structure
- A Minimal curl Request
- Python Usage With the Anthropic SDK
- Multi-Turn Conversations and System Prompts
- Streaming Responses
- Claude Vision API Requests
- Anthropic Files API Usage
- Tool Use for Agent Backends
- Anthropic-Native vs OpenAI-Compatible Requests
- Building a Provider-Neutral Agent Backend
- Common Errors and Debugging
- Implementation Checklist
- FAQ
The Anthropic Messages API is the main HTTP interface for sending prompts to Claude. The core endpoint is POST /v1/messages: you provide a model, a list of typed message content blocks, and a token limit, then receive an assistant message containing one or more output blocks.
This guide turns the Anthropic API documentation into an implementation checklist. It covers the request contract, multi-turn state, streaming, vision, the Files API, tool use, and the choices involved when an agent backend needs to support both Anthropic-native and OpenAI-compatible model providers.
Messages API Endpoint and Required Headers
Anthropic’s native Messages API uses this endpoint:
POST https://api.anthropic.com/v1/messages
Direct HTTP requests normally include these headers:
| Header | Purpose |
|---|---|
x-api-key | Authenticates the Anthropic account |
anthropic-version | Selects the documented API version contract |
content-type: application/json | Declares a JSON request body |
The API version header is not a model version. It controls the HTTP API behavior, while the model field selects the Claude model used for inference. Keep both values in configuration instead of scattering them through application code.
The Request and Response Structure
A basic request contains three fields:
{
"model": "YOUR_CLAUDE_MODEL_ID",
"max_tokens": 1024,
"messages": [
{
"role": "user",
"content": "Explain idempotency keys in two paragraphs."
}
]
}
The response is an assistant message rather than a bare string. Its content property is an array of typed blocks, so production code should inspect each block’s type before reading its fields.
{
"type": "message",
"role": "assistant",
"content": [
{
"type": "text",
"text": "An idempotency key..."
}
],
"stop_reason": "end_turn",
"usage": {
"input_tokens": 18,
"output_tokens": 126
}
}
This block-based design matters once you add images or tools. A single assistant turn can contain text and a tool request, and a user turn can contain text alongside image or document blocks.
A Minimal curl Request
Store credentials in an environment variable and use a model ID currently available to your Anthropic account:
export ANTHROPIC_API_KEY="your-api-key"
export ANTHROPIC_MODEL="your-claude-model-id"
curl https://api.anthropic.com/v1/messages \
--header "x-api-key: $ANTHROPIC_API_KEY" \
--header "anthropic-version: 2023-06-01" \
--header "content-type: application/json" \
--data '{
"model": "'"$ANTHROPIC_MODEL"'",
"max_tokens": 512,
"messages": [
{
"role": "user",
"content": "Return three practical ways to reduce API latency."
}
]
}'
Do not hard-code a model name copied from an old tutorial. Model availability and aliases can change, so deployment configuration should use a model ID verified in the provider’s current model documentation or console.
Python Usage With the Anthropic SDK
The official Python SDK handles authentication headers and converts the response into typed objects:
import os
from anthropic import Anthropic
client = Anthropic(api_key=os.environ["ANTHROPIC_API_KEY"])
message = client.messages.create(
model=os.environ["ANTHROPIC_MODEL"],
max_tokens=512,
messages=[
{
"role": "user",
"content": "Write a Python function that validates a UUID string.",
}
],
)
for block in message.content:
if block.type == "text":
print(block.text)
Iterating over content blocks is safer than assuming message.content[0] is always text. Agent applications may receive tool-use blocks, and multimodal features can add other block types to the conversation.
Multi-Turn Conversations and System Prompts
The Messages API is stateless. Your application sends the relevant conversation history again with each request:
{
"model": "YOUR_CLAUDE_MODEL_ID",
"max_tokens": 512,
"system": "You are a concise API documentation assistant.",
"messages": [
{"role": "user", "content": "What does HTTP 429 mean?"},
{"role": "assistant", "content": "It indicates rate limiting."},
{"role": "user", "content": "How should my client retry?"}
]
}
Anthropic places the system instruction in the top-level system field rather than in a message with role: "system". That is one of the important differences to account for when translating requests from OpenAI-compatible schemas.
For long-running sessions, do not resend an unlimited transcript. Keep the latest turns, preserve decisions and tool results that still affect the task, and summarize older context before the prompt approaches the selected model’s context limit.
Streaming Responses
Set stream: true when the interface should display output incrementally:
import os
from anthropic import Anthropic
client = Anthropic(api_key=os.environ["ANTHROPIC_API_KEY"])
with client.messages.stream(
model=os.environ["ANTHROPIC_MODEL"],
max_tokens=1024,
messages=[
{"role": "user", "content": "Explain database connection pooling."}
],
) as stream:
for text in stream.text_stream:
print(text, end="", flush=True)
Streaming improves perceived latency, but it adds state-management work. Your application must handle a connection that closes early, partial text, event ordering, and final usage metadata. For tool-using agents, buffer the complete tool-input block before parsing or executing it.
Claude Vision API Requests
The Claude Vision API uses the same Messages endpoint. Add an image content block before the related text question. Images can be provided as supported base64 data or through an allowed source type described in the current vision documentation.
import base64
import os
from anthropic import Anthropic
client = Anthropic(api_key=os.environ["ANTHROPIC_API_KEY"])
with open("architecture.png", "rb") as image_file:
image_data = base64.b64encode(image_file.read()).decode("utf-8")
message = client.messages.create(
model=os.environ["ANTHROPIC_VISION_MODEL"],
max_tokens=700,
messages=[
{
"role": "user",
"content": [
{
"type": "image",
"source": {
"type": "base64",
"media_type": "image/png",
"data": image_data,
},
},
{
"type": "text",
"text": "Identify two reliability risks in this architecture diagram.",
},
],
}
],
)
Resize oversized images before sending them. Large images increase transfer time and token usage without necessarily improving the answer. Also validate the MIME type; declaring JPEG data as PNG is a common cause of rejected requests.
Anthropic Files API Usage
The Anthropic Files API is useful when a file should be uploaded once and referenced by later Messages API calls instead of being encoded and transmitted repeatedly. The exact availability, supported file types, and request fields can differ by feature status, so check the current Files API documentation before relying on it in production.
A typical integration has two stages:
- Upload the file and persist the returned file identifier with your application’s document record.
- Reference that identifier in a supported content block when creating a message.
Treat file IDs as provider-specific resources. Record which provider and account created each ID, apply your own access controls, and define a deletion policy. A file identifier should not be accepted directly from an untrusted user without authorization checks.
For occasional small images, base64 is straightforward. For documents used across many requests, a provider file resource can reduce repeated uploads. If your application must work across multiple providers, keep the original object in your own storage and create provider-specific file IDs as a cache.
Tool Use for Agent Backends
Tools allow Claude to request an application-defined function. Your backend describes each tool with a name, a purpose, and a JSON Schema input contract. The model can then return a tool_use block rather than pretending it executed the operation.
{
"name": "get_order_status",
"description": "Look up the current status of a customer order.",
"input_schema": {
"type": "object",
"properties": {
"order_id": {
"type": "string",
"description": "The order identifier shown to the customer."
}
},
"required": ["order_id"]
}
}
The safe execution loop is:
- Send messages and tool definitions to the model.
- Detect a
tool_usecontent block. - Validate its input against the schema and your authorization rules.
- Execute the tool in a controlled environment.
- Return a matching
tool_resultblock in the next user turn. - Continue until the model produces a normal answer or reaches your loop limit.
Never execute tool arguments as trusted shell, SQL, or file paths. For coding agents, run generated commands inside an isolated environment such as Novita Agent Sandbox, with explicit time, network, filesystem, and resource limits.
Anthropic-Native vs OpenAI-Compatible Requests
Anthropic-native and OpenAI-compatible APIs solve the same general problem, but their wire formats are not identical.
| Concern | Anthropic Messages API | OpenAI-compatible chat API |
|---|---|---|
| Common endpoint | /v1/messages | /v1/chat/completions |
| System instruction | Top-level system field | Commonly a system or developer message |
| Output representation | Typed content blocks | Commonly choices[].message |
| Tool request | tool_use block | Commonly tool_calls |
| Tool result | tool_result content block | Commonly a tool role message |
An OpenAI-compatible endpoint is valuable when your application already uses the OpenAI SDK or needs to switch among open-source models with minimal transport changes. Novita AI exposes an OpenAI-compatible LLM API, so the same client structure can target multiple available models by changing the base URL and model configuration.
import os
from openai import OpenAI
client = OpenAI(
api_key=os.environ["NOVITA_API_KEY"],
base_url="https://api.novita.ai/v3/openai",
)
response = client.chat.completions.create(
model=os.environ["NOVITA_MODEL"],
messages=[
{
"role": "user",
"content": "Review this retry strategy for failure modes.",
}
],
)
print(response.choices[0].message.content)
This is not a drop-in translation of every Anthropic feature. If your application depends on Anthropic-specific content blocks, tool semantics, citations, or beta features, keep an Anthropic-native adapter. Use the shared OpenAI-compatible path for workloads that fit its common request model.
Building a Provider-Neutral Agent Backend
A provider-neutral backend should normalize application concepts without pretending all providers are identical. A practical design has four layers:
- Conversation model: store roles, text, images, tool calls, and tool results in an internal schema.
- Provider adapter: translate the internal schema into Anthropic Messages or OpenAI-compatible payloads.
- Capability registry: track whether the selected model supports vision, tools, structured output, or other required behavior.
- Execution layer: run tools and code separately from the inference provider.
This separation lets a team use Claude where Anthropic-native behavior is important while routing compatible workloads to an open-source model through Novita AI. The open-source path can be useful for cost control, model experimentation, data-location requirements, or avoiding a single-provider dependency. Test output quality and tool reliability on your own tasks rather than assuming two models are interchangeable because both accept chat messages.
For agent workloads, the execution layer deserves equal attention. Model switching does not protect your infrastructure from unsafe commands. Use an isolated sandbox, enforce tool allowlists, cap iterations, and log each model decision and tool result with secrets removed.
Common Errors and Debugging
400 Bad Request
Check the JSON shape, content-block types, required fields, and whether the selected model supports the requested feature. Log the provider’s request ID and structured error body, but redact credentials and base64 file data.
401 Authentication Error
Confirm the API key is present in the runtime environment and belongs to the intended provider. Anthropic uses x-api-key for direct HTTP requests; an OpenAI-compatible client usually sends a bearer token automatically.
404 Model or Resource Not Found
Verify the model ID against the current provider documentation or console. For Files API resources, also verify that the file belongs to the same account and environment used by the request.
429 Rate Limit
Retry with exponential backoff and jitter, but cap the number of attempts. Queue background work, limit concurrency per provider, and avoid immediately retrying every failed request at the same interval.
Context or Token Limit Errors
Reduce conversation history, image size, file content, or requested output length. Count the entire request, including system instructions, tool schemas, prior tool results, and multimodal content.
Recommended Articles
- What Are Coding Agents? Architecture, Tools, and Execution Loops
- What Is MCP? A Developer’s Guide to Model Context Protocol
- Open-Source LLM Guide 2026: Models, Tradeoffs, and Deployment
Implementation Checklist
- Keep API keys, model IDs, base URLs, and API versions in runtime configuration.
- Parse typed content blocks instead of assuming a single text string.
- Store enough conversation state to reconstruct each stateless request.
- Validate tool inputs and execute them outside the model process.
- Add timeouts, retry limits, request IDs, and redacted observability.
- Gate provider routing by model capability, not just price or name.
- Recheck model IDs, feature status, limits, and pricing before deployment.
The Messages API is straightforward at the HTTP layer. The harder engineering work appears when an application adds streaming, multimodal input, tools, persistent files, or multiple model providers. Keep those concerns behind explicit adapters, and your agent backend can evolve without tying business logic to one request format.
FAQ
What is the Anthropic Messages API endpoint?
The native endpoint is POST https://api.anthropic.com/v1/messages. Requests require authentication, an Anthropic API version header, a model ID, a token limit, and a messages array.
Is the Anthropic Messages API OpenAI-compatible?
No. The concepts overlap, but system prompts, content blocks, response objects, and tool-use messages differ. Use a provider adapter if one application needs to support both formats.
Does the Claude Vision API use a separate endpoint?
No. Vision requests use the Messages API with image and text content blocks. The selected Claude model must support image input.
When should I use the Anthropic Files API?
Use it when supported files need to be referenced across requests and repeated base64 uploads would be wasteful. Keep your own source file and authorization record because provider file IDs are account-specific resources.
Can Claude Code use a custom API backend?
Claude Code integration depends on the authentication and provider configuration supported by the current Claude Code release. Do not assume an OpenAI-compatible endpoint implements Anthropic’s Messages API. For a custom agent, a provider-neutral adapter is usually clearer than attempting to make different protocols appear identical.
When should I choose an open-source model through Novita AI?
Consider it when you want OpenAI-compatible model switching, open-model experimentation, or a second provider for compatible workloads. Keep Anthropic-native requests for features that require Claude-specific API behavior, and evaluate both paths on your own prompts and tools.
