What you will be able to do
- Name the main Claude API endpoints and the HTTP method each one uses
- List the headers a raw HTTP request to the Claude API must carry, and say which of them the client SDKs send for you
- Read the HTTP contract on the way back: the request-id header, the error JSON shape and the request size limits
- Map an SDK method to the REST endpoint it wraps, and configure its built-in retries and pagination instead of rewriting them
Key concept
The Claude API is plain REST — Every Claude API feature is an HTTPS request to a path under api.anthropic.com, sent with a fixed set of headers and a JSON body. The client SDKs don't replace that contract. They build those requests for you and parse the responses.
1.Endpoints under one base URL
Every Claude API feature sits at a path under https://api.anthropic.com, and each path is named after what it does. Most of your traffic goes to POST /v1/messages. Other jobs have their own endpoints: counting tokens before you send a prompt, submitting a large asynchronous batch, listing the models you can call, or uploading a file once so later requests can refer to it. In a raw integration the URL and the HTTP method pick the operation, and the JSON body carries the parameters.
| API | Method and path | Purpose |
|---|---|---|
| Messages API | POST /v1/messages | Send messages to Claude for conversational interactions |
| Message Batches API | POST /v1/messages/batches | Process large volumes of Messages requests asynchronously |
| Token Counting API | POST /v1/messages/count_tokens | Count tokens in a message before sending it |
| Models API | GET /v1/models | List available Claude models and their details |
| Files API | POST /v1/files, GET /v1/files | Upload and manage files used across multiple API calls |
| Skills API | POST /v1/skills, GET /v1/skills | Create and manage custom agent skills |
The Agents, Sessions and Environments APIs, which power Claude Managed Agents, are in beta and sit alongside these. List endpoints such as GET /v1/models return results in pages. You pass a limit and a page cursor, and each response carries a data array plus a next_page cursor that is null once you reach the end.
Checkpoint 1 of 6· Check yourself
Before running an expensive prompt, a service wants to know how many input tokens it will use without generating a response. Which request does that?
The Token Counting API has its own endpoint, and it counts a message's tokens before the message is sent for generation. The other endpoints generate responses, list models or queue batches.
“Token Counting API: Count tokens in a message before sending to manage costs and rate limits (POST /v1/messages/count_tokens)”Source: platform.claude.com
Sources1
2.The headers a raw HTTP call must carry
Without the right headers, a request with a valid body is still rejected. A direct integration, such as a curl script, a language with no official SDK, or an HTTP client you wrote yourself, has to send three things on every call. First, a credential, normally your Console API key in x-api-key. Second, anthropic-version with a dated value such as 2023-06-01. Third, content-type: application/json. Leave out anthropic-version and the request fails even though the key is fine. That header pins the API behaviour your code was written against, as explained in [API versions and feature classifications (beta vs GA)](lesson:2.2).
| Header | Value | Required |
|---|---|---|
| x-api-key | Your API key from Console | Yes, unless Authorization is set |
| Authorization | Bearer <token>: an API key or a Workload Identity Federation access token | Yes, unless x-api-key is set |
| anthropic-version | API version, for example 2023-06-01 | Yes |
| content-type | application/json | Yes |
| anthropic-workspace-id | ID of the workspace the request runs in | Required with a multi-workspace API key |
You can send the credential as Authorization: Bearer <token> instead of x-api-key. The Bearer form is also how short-lived Workload Identity Federation tokens are sent, while x-api-key remains supported as the legacy fallback. Exam scenarios still use the classic set: x-api-key, anthropic-version and content-type.
Moving a raw call into an SDK turns those headers from per-request code into client configuration. You hand the credential to the client once, delete the three header lines from every call site, and keep only anthropic-workspace-id when your key spans several workspaces. A migrated script that still sets anthropic-version by hand is carrying a line the client already owns.
Checkpoint 2 of 6· Check yourself
A developer posts to https://api.anthropic.com/v1/messages with plain HTTP. The body is valid and the key works in the Console playground. Which set of headers must the request include?
anthropic-version and content-type are always required, and the key goes in x-api-key (or Authorization). anthropic-beta is only needed for beta features, and anthropic-workspace-id only for multi-workspace keys.
“If you are using the Client SDKs, the SDK sends the authentication, version, and content-type headers automatically”Source: platform.claude.com
Checkpoint 3 of 6· Exam question
A frontend engineer building a custom SSE parser for streaming Messages API responses needs to know when it is safe to treat one content block as fully received and move on to parsing the next one. Which event signals that a specific content block, identified by its index, will receive no further delta events?
Correct answer: A — content_block_stop
- A. Correct — content_block_stop is emitted once a content block at a given index has received all of its delta events and will not change further.
- B. message_delta communicates top-level changes to the Message object, such as stop_reason and cumulative usage, not the completion of an individual content block.
- C. content_block_start marks the beginning of a new content block and precedes its delta events, not the end.
- D. message_stop signals the end of the entire stream, after all content blocks have already closed with their own content_block_stop events.
Sources1
3.What the client SDKs add on top of REST
The official SDKs make the same REST calls as a raw integration and handle the repetitive parts. Anthropic publishes client SDKs for Python, TypeScript, C#, Go, Java, PHP and Ruby. Each one does the following:
- sends the authentication, anthropic-version and content-type headers automatically
- gives you typed request and response objects instead of raw dictionaries
- retries transient failures with built-in logic and raises typed exceptions
- supports streaming
- manages request timeouts and connections
Some defaults matter in practice. The Python client reads ANTHROPIC_API_KEY from the environment if you don't pass a key, and it has both sync (Anthropic) and async (AsyncAnthropic) clients. The TypeScript SDK runs on Node.js, Deno, Bun and edge runtimes, but it refuses to run in a web browser unless you set dangerouslyAllowBrowser. That default protects your secret key from being shipped to end users.
Each SDK method is a thin wrapper over one endpoint, so what you know about the REST surface carries over directly. client.messages.create is POST /v1/messages, client.messages.batches.create is POST /v1/messages/batches, and token counting is a method on the same messages object that maps to POST /v1/messages/count_tokens. The parameters keep their REST names, so a JSON body from a curl script translates almost field for field into keyword arguments.
count = client.messages.count_tokens(
model="claude-opus-5-5",
messages=[{"role": "user", "content": "Hello, world"}],
)
print(count.input_tokens) # 10Retries and pagination are the two chores an SDK takes off your hands, and each is a setting to tune rather than code to write. The client retries connection errors, rate limits and 5xx responses twice by default, with exponential backoff, and it honors a retry-after header when the API sends one. max_retries on the client changes or disables that. A hand-written retry loop around an SDK call multiplies attempts with the built-in ones, so set max_retries to match whichever layer you want in charge.
For list endpoints, the SDK's auto-paginating iterator follows next_page for you, so a for loop walks every result without you touching a cursor. It only moves forward. Going back a page is the case where you read prev_page from the response and pass it back as page yourself.
Checkpoint 4 of 6· Fill the gap
Which environment variable does the Python client read by default, so this argument can be omitted?
import os
from anthropic import Anthropic
client = Anthropic(
# This is the default and can be omitted
api_key=os.environ.get(" ? "),
)The SDK picks up ANTHROPIC_API_KEY from the environment and sends it as the authentication header, so most code never passes api_key explicitly.
Source: platform.claude.comCheckpoint 5 of 6· Check yourself
A service uses the Python SDK and also wraps each call in its own three-attempt retry loop. A 503 comes back from the API. What is true?
Transient failures such as 5xx errors are retried inside the client by default, so an outer loop multiplies the attempts. Setting max_retries decides which layer owns retrying.
“with exponential backoff, twice by default, honoring the retry-after header when present”Source: platform.claude.com
4.The response side of the contract: request IDs, errors and size limits
The HTTP contract also covers what comes back. Every response carries a request-id header with a value like req_018EeWyXxfu5pfWkrYcMdjWG, and that is the identifier support will ask for. Responses also report which organization and workspace the credential resolved to, in anthropic-organization-id and anthropic-workspace-id. The Python and TypeScript SDKs expose the ID as _request_id on the response object. To read other headers, use with_raw_response.
Failures come back as JSON in a single, fixed shape. The top-level type is error, and the error object holds a machine-readable type and a human-readable message. The same request ID is repeated in the body as request_id, so a logged error body is enough to trace the call. Which status codes are worth retrying is covered in [API error types and recovery](lesson:4.1). On this page, the point is that every failure has this shape, and that the SDKs turn it into typed exceptions such as anthropic.NotFoundError rather than handing you raw JSON.
{
"type": "error",
"error": {
"type": "not_found_error",
"message": "The requested resource could not be found."
},
"request_id": "req_011CSHoEeqs5C35K2UUqR7Fy"
}Request bodies have a size limit that depends on the endpoint. Messages and Token Counting accept up to 32 MB, Message Batches up to 256 MB and the Files API up to 500 MB. A request over its limit fails with 413 request_too_large before it reaches the API servers. If an application embeds large documents directly in a Messages request, it can hit this limit, which is a reason to upload those documents through the Files API instead.
Checkpoint 6 of 6· Check yourself
A user reports one failed call. Your logs kept the error body but not the response headers. What can you give Anthropic support to identify the request?
The identifier from the request-id header is repeated as request_id in error bodies. error.type is a category such as not_found_error, not an identifier.
“The same identifier appears as the request_id field in error response bodies.”Source: platform.claude.com
Sources5
Exam traps
Each one states something that sounds right. Open it to see what is actually true.
1.A raw HTTP call only needs an API key and a JSON content type, and the API version is implied by the model.Why is that wrong?
anthropic-version is required on every request. The SDKs hide this because they add it automatically, along with the authentication and content-type headers.
Covered in The headers a raw HTTP call must carry
2.Once you use an SDK, no header is your responsibility any more.Why is that wrong?
The SDK sends the authentication, version and content-type headers, but anthropic-workspace-id depends on your key, so you pass it yourself when the key needs it.
Covered in What the client SDKs add on top of REST
3.Error responses differ by endpoint, so clients have to string-match the message to tell failures apart.Why is that wrong?
Every error uses the same JSON shape with a typed error object. The SDKs raise typed exceptions, which you should catch instead of matching message strings.
Covered in The response side of the contract: request IDs, errors and size limits
Sources
Every claim above is drawn from one of these pages, quoted as it was written on the date shown.
- 1.https://platform.claude.com/docs/en/api/overviewOfficial docs
“Messages API: Send messages to Claude for conversational interactions (POST /v1/messages)”
↩︎ Endpoints under one base URL“Cursor for the next page, or null if there are no more results.”
↩︎ Endpoints under one base URL“Legacy fallback for Authorization, still supported”
↩︎ The headers a raw HTTP call must carry“anthropic-version | API version (for example, 2023-06-01) | Yes”
↩︎ The headers a raw HTTP call must carry“you pass anthropic-workspace-id yourself when your key needs it”
↩︎ The headers a raw HTTP call must carry“Automatic header management (authentication, anthropic-version, content-type)”
↩︎ What the client SDKs add on top of REST“The SDK provides an auto-paginating iterator that follows next_page for you.”
↩︎ What the client SDKs add on top of REST“The Claude API is a RESTful API at https://api.anthropic.com that provides programmatic access to Claude models and Claude Managed Agents.”
↩︎ Key concept“If you are using the Client SDKs, the SDK sends the authentication, version, and content-type headers automatically”
↩︎ Exam trap 1“you pass anthropic-workspace-id yourself when your key needs it”
↩︎ Exam trap 2“Token Counting API: Count tokens in a message before sending to manage costs and rate limits (POST /v1/messages/count_tokens)”
↩︎ Checkpoint“If you are using the Client SDKs, the SDK sends the authentication, version, and content-type headers automatically”
↩︎ Checkpoint“you pass anthropic-workspace-id yourself when your key needs it”
↩︎ Prediction - 2.
“Web browsers: disabled by default to avoid exposing your secret API credentials”
↩︎ What the client SDKs add on top of REST - 3.
“The CLI, client SDKs, and libraries are for calling the Claude API yourself: you send each request and handle each response.”
↩︎ What the client SDKs add on top of REST - 4.
“You can also count tokens before making a request:”
↩︎ What the client SDKs add on top of REST - 5.https://platform.claude.com/docs/en/api/errorsOfficial docs
“The SDK client accepts max_retries to configure or disable this behavior.”
↩︎ What the client SDKs add on top of REST“Every API response includes a unique request-id header.”
↩︎ The response side of the contract: request IDs, errors and size limits“The official SDK raises typed exceptions for these errors instead of returning raw JSON.”
↩︎ The response side of the contract: request IDs, errors and size limits“On the direct Claude API, Cloudflare returns this error before the request reaches the API servers.”
↩︎ The response side of the contract: request IDs, errors and size limits“The API always returns errors as JSON, with a top-level error object that always includes a type and message value.”
↩︎ Exam trap 3“with exponential backoff, twice by default, honoring the retry-after header when present”
↩︎ Checkpoint“The same identifier appears as the request_id field in error response bodies.”
↩︎ Checkpoint