# Messages API > Point an Anthropic client or Claude Code at Katara and send Messages requests, tools, images and documents included. Section: Developers. Web page: https://docs.katara.com/developers/messages/ Send Messages requests to `https://api.katara.com/v1/messages`, with your Katara key in `x-api-key` or `Authorization: Bearer`. If you send both, they must carry the same key. The `anthropic-version` header is optional; `2023-06-01` and `2026-10-21` are accepted, any other value is refused. ```bash curl 'https://api.katara.com/v1/messages' \ -H "x-api-key: $KATARA_API_KEY" \ -H 'anthropic-version: 2023-06-01' \ -H 'Content-Type: application/json' \ -d '{ "model": "katara/cortex", "max_tokens": 2048, "messages": [{"role": "user", "content": "Explain this project layout."}] }' ``` An Anthropic SDK takes the address without `/v1`: `Anthropic(base_url="https://api.katara.com", api_key=...)`. Claude Code runs against Katara with `ANTHROPIC_BASE_URL=https://api.katara.com` and your key in `ANTHROPIC_API_KEY`; edits, client tools and MCP servers, resumed sessions, prompt caching and web search all work. Messages uses the same account, payment method and Katara Community setting as [Chat Completions](https://docs.katara.com/start/api.txt). A request never switches payment methods. Payment challenges and receipt headers reach wallet clients unchanged. ## Model names Any `model` is accepted, including the Claude names Anthropic clients send by default, and Katara Cortex serves it ([Model names in requests](https://docs.katara.com/concepts/models.txt#model-names-in-requests)). The reply's `model` is `katara/cortex`. A request paid with [x402](https://docs.katara.com/developers/x402.txt#choosing-a-model) may name `katara/cortex-genius` or `katara/cortex-smart` to fix the model; its reply still names `katara/cortex`, and a key that names either is refused. `GET /v1/models` with an `anthropic-version` header, and `GET /v1/models/{id}`, answer in the Anthropic shape with that one model. ## Content `system` takes a string or text blocks. A message's content takes: - text; - images (`image/jpeg`, `image/png`, `image/gif`, `image/webp`) as base64, an `https` `url`, or a `file` source naming a `file_id` uploaded through [`/v1/files`](https://docs.katara.com/developers/media.txt); - documents: a base64 PDF, plain `text`, `content` blocks, or a `file_id`, each with an optional title and context. A document given by `url` is refused, because Katara does not fetch it; - `search_result` blocks; - assistant `tool_use` and `thinking` blocks, and user `tool_result` blocks. A request ending on an assistant message (prefill) is refused. `max_tokens: 0` answers an empty message with `stop_reason: "max_tokens"` and an input estimate in `usage`, without running a model or charging anything. ## Tools Each tool has a `name` of up to 128 letters, digits, `_` or `-`, an object `input_schema`, and optionally `description`, `strict`, `input_examples`, `eager_input_streaming`, `allowed_callers` and `cache_control`. `defer_loading: true` is refused. `tool_choice` takes `auto`, `none`, `any`, or `tool` with a declared name; `disable_parallel_tool_use: true` gets at most one call per reply. A forced choice that the model ignores is not delivered: Cortex tries the next model. Return each tool's id unchanged. All results belong at the start of the next user message, before any text; duplicate, missing and unknown ids are refused. A result can carry text, images, documents and search results. An error result reaches the model with `is_error: true` and its text. Anthropic's versioned client tools become ordinary tools with their published names and schemas, so your client runs them as it would anyway: `bash_20241022` and `bash_20250124`, the `text_editor_` tools from `20241022` to `20250728`, and `memory_20250818`. Server tools that Katara does not run are refused with a message naming the feature: web fetch, code execution, computer use, browser control, tool search, the advisor and the MCP connector (`mcp_toolset` tools, or a non-empty `mcp_servers`). A top-level `container` is refused too. Run an MCP server in your client and declare its tools in `tools`. ## Web search Declare a `web_search_` tool (`web_search_20250305`, `web_search_20260209` or `web_search_20260318`, named `web_search`) and Katara runs the searches the model asks for. `max_uses` lowers the cap of five searches per request, `allowed_domains` or `blocked_domains` (not both) narrows the results, and `user_location` is accepted. Each search the model makes appears as a `server_tool_use` block followed by a `web_search_tool_result` block before the text that uses it. In a stream the `server_tool_use` block opens when the search starts, and its result follows once the search has run. A failed search comes back as a result with an error code (`invalid_tool_input`, `query_too_long`, `too_many_requests`, `max_uses_exceeded` or `unavailable`); the model answers without it and the search is not charged. Once the model asks to search, the rest of the request is served by Katara's managed models only. If it then ends without an answer, the searches and the model calls after the first are not charged. [Web search](https://docs.katara.com/developers/tools.txt#web-search) has the price and when it is offered. Send earlier `server_tool_use` and `web_search_tool_result` blocks back unchanged in assistant history; they keep the page text the model read. ## Thinking and caching `thinking`, `output_config.effort` and `task_budget` are accepted in every form, budgets included, and change nothing: Katara Cortex decides how much the model reasons. Reasoning arrives as `thinking` blocks with an empty `signature`. Send thinking blocks back as you received them; thinking with another service's signature is read as plain reasoning, and `redacted_thinking` is dropped. `cache_control` on the system prompt, tools, messages or the request (`ttl` `5m` or `1h`) is served by Katara's own [prompt caching](https://docs.katara.com/concepts/cortex.txt#caching). `context_management` (`clear_tool_uses_20250919`, `clear_thinking_20251015`, `compact_20260112`) and a top-level `compaction` are served by Katara's [context management](https://docs.katara.com/developers/context.txt). `output_config.format` and `output_format` with a JSON schema ask for structured output. Any `anthropic-beta` header is accepted. `temperature` and `top_p` take 0 to 1. `metadata.user_id`, `top_k`, `service_tier`, `speed`, `inference_geo`, `diagnostics`, `fallbacks` and `fallback_credit_token` are accepted and not sent to a model. `thread` is refused: send the whole conversation in `messages`. Other unknown fields are refused with a clear error. Keep `katara.session` from the last successful reply and send it back on the next request for that conversation. `katara.reset_session: true` starts a new session. A session token does not replace authentication or authorize payment. ## Stop sequences `stop_sequences` takes any number of strings. Katara applies them itself: the reply ends before the first match and nothing after it is sent. `stop_reason` is then `stop_sequence` and `stop_sequence` holds the matched string. Text the model wrote past the match is still paid for. ## Streaming and usage Set `stream: true` for named server-sent events. The sequence starts with `message_start`; each content block has a start, deltas and a stop. Tool arguments arrive as `input_json_delta` fragments; accumulate them by block index and parse the JSON when that block stops. A reply that has not begun after ten seconds starts its stream early, and a `ping` follows every ten seconds of silence, so a client that waits on a long first token does not time out. Streams paid with x402 never start early, so their payment headers come first. The final `message_delta` carries the authoritative `usage`, followed by `message_stop`. `input_tokens` excludes cached input: add `cache_read_input_tokens` and `cache_creation_input_tokens` to obtain total input. `server_tool_use.web_search_requests` counts the charged searches. The final delta, and a non-streamed reply beside `usage`, also carry the `katara` object with the charge; read the decimal `cost_usd` or `cost_usdc` as a string ([Usage and cost](https://docs.katara.com/developers/usage.txt)). `stop_reason` is `end_turn`, `max_tokens`, `tool_use`, `stop_sequence` or `refusal` (with `stop_details`). An interrupted stream emits an `error` event without `message_stop`. Wait for `message_stop` before treating the turn as complete, and check your usage before retrying an interrupted request. ## Errors Errors use the Anthropic envelope, with `request_id` in the body and a `request-id` header on every reply. | HTTP | `error.type` | When | |---|---|---| | 400 | `invalid_request_error` | The body is malformed or uses a refused feature. Not retried (`x-should-retry: false`). | | 401 | `authentication_error` | Missing or unknown key. | | 402 | `billing_error` | The funds behind the key cannot cover the request. Not retried. | | 403 | `permission_error` | The account or the key's environment refuses the request, for example a suspended account or Katara Community turned off. | | 404 | `not_found_error` | No API route at that path. | | 413 | `request_too_large` | The body is over 32 MB. | | 429 | `rate_limit_error` | Every vendor that could serve the request is rate limiting. `Retry-After` says when to retry. | | 500 | `api_error` | Something failed behind Katara. | | 529 | `overloaded_error` | No candidate could serve the request in time. `Retry-After` says when to retry. | `/v1/messages/batches` and its sub-paths answer `400 invalid_request_error`: Katara does not run message batches. Send each request to `/v1/messages`. ## Token counting `POST https://api.katara.com/v1/messages/count_tokens` takes the same body as `/v1/messages` and returns an estimate of its input. It needs a key, never runs a model and never reserves payment. Generation controls such as `max_tokens` are accepted and ignored. ```json {"input_tokens": 293, "katara": {"estimated": true, "estimation_method": "conservative-v2", "bytes_per_token": 3}} ``` Use it for context management, never to predict a bill. Text, tool calls and tool definitions count one token per three bytes, plus 16 for the request, 4 per message and 16 per tool definition. Each image counts 2,240 tokens, each PDF page 1,120 and a stored file 4,480. The estimate runs above the real count, so a client compacts a little early rather than overflowing. Billed usage comes only from inference.