Claude API: полный гайд для разработчиков

Автор: Обновлено

Что такое Claude API?

Claude API - программный интерфейс Anthropic для интеграции моделей Claude в приложения. Работает через Messages API: вы отправляете массив сообщений (user/assistant), получаете ответ модели. Поддерживает text, vision, tool use, streaming, adaptive thinking и prompt caching. Доступен через REST API, Python SDK и TypeScript SDK.

TL;DR

  • -Claude API работает через Messages API - единый endpoint для текста, изображений, tool use, streaming и thinking
  • -Четыре актуальные модели: Opus 5.5 ($4/$20 за MTok) для агентов и сложных задач, Sonnet 5.5 ($2/$10) - баланс скорости и качества, Haiku 5.5 (от $0.10/$0.50) для массовых операций, Fable 5.1 ($10/$50) для самых тяжёлых рассуждений
  • -Tool use превращает Claude в исполнителя: модель генерирует JSON-вызовы ваших функций, вы возвращаете результат - цикл повторяется до завершения задачи
  • -Чтение из prompt cache стоит 10% от базовой цены input (5% на Opus 5.5 и Sonnet 5.5, 2.5% на Fable 5.1), Batches API даёт 50% скидку на некритичные задачи
  • -На актуальных моделях thinking включён по умолчанию, глубину задаёт `output_config.effort` (low/medium/high/xhigh/max); `budget_tokens`, `temperature`/`top_p`/`top_k` и prefill возвращают 400

Claude API - программный интерфейс для работы с моделями Anthropic. Один endpoint - Messages API - покрывает текст, изображения, tool use, streaming и thinking. Python SDK, TypeScript SDK, REST - три способа интеграции.

Эта статья - полный справочник. От первого запроса до продвинутых техник: prompt caching, batches, vision. Каждый пример - рабочий код, который можно скопировать и запустить.

Если Claude скрыт за endpoint вашего продукта, публичный контракт стоит описать отдельно. Гайд по REST API design разбирает naming, ошибки, версионирование и генерацию OpenAPI для слоя, к которому обращаются клиенты.

Что такое Claude API

Messages API - единый endpoint

Вся работа с Claude проходит через один endpoint: POST https://api.anthropic.com/v1/messages. Вы отправляете массив сообщений с ролями user и assistant, модель генерирует следующее сообщение в диалоге.

Это не completions API в стиле GPT-3 - Messages API построен вокруг диалоговой структуры. Каждый запрос содержит полную историю разговора. Состояние между вызовами не хранится.

Модели

Четыре актуальные модели (на ноябрь 2026):

МодельAPI IDКонтекстMax outputЦена (input/output за MTok)
Fable 5.1claude-fable-5-11M128k$10 / $50
Opus 5.5claude-opus-5-51M128k$4 / $20
Sonnet 5.5claude-sonnet-5-51M128k$2 / $10
Haiku 5.5claude-haiku-5-51M128k$0.10 / $0.50 для промптов до 100K токенов, $0.50 / $2.50 сверх

Opus 5.5 - основной флагман для долгих агентных задач в коде и работе со знаниями. Документация Anthropic советует начинать именно с него. Дефолтный effort у него medium, поэтому для задач, где нужна глубина, задавайте уровень явно.

Sonnet 5.5 - рабочая лошадка: лучшее сочетание скорости и интеллекта для повседневного кода, агентов и корпоративных задач. Вдвое дешевле Opus 5.5 и по input, и по output ($2/$10 против $4/$20).

Haiku 5.5 - скорость и экономия. Классификация, извлечение данных, роутинг, задачи субагентов. На промптах до 100K токенов в 20 раз дешевле Sonnet 5.5; выше этого порога все цены запроса растут в 5 раз.

Fable 5.1 - самая сильная модель линейки, для тяжёлых рассуждений и долгих агентных задач. Самая медленная и дорогая: берите её, когда Opus 5.5 на высоком effort всё ещё не дотягивает на ваших eval’ах.

Opus 5, Sonnet 5, Haiku 4.5, Fable 5 и модели Opus/Sonnet 4.x теперь в статусе legacy: они доступны, сроки отключения - на странице model deprecations. Если переходите с Sonnet 4.6, Haiku 4.5 или более старых моделей, пересчитайте токены: у Claude 4.7 и новее другой токенайзер, на тот же текст он даёт примерно в 1–1.35 раза больше токенов (в среднем около 30%, по данным страницы цен).

Отличие от Claude.ai

Claude.ai - чат-интерфейс. API дает то, чего в чате нет:

  • System prompts - точная настройка поведения модели
  • Tool use - модель вызывает ваши функции
  • Streaming - потоковый вывод токен за токеном
  • Thinking - сводка рассуждений модели и управление их глубиной через effort
  • Prompt caching - кэширование повторяющегося контекста
  • Batches - асинхронная пакетная обработка со скидкой 50%
  • Полный контроль - effort, stop sequences, metadata

Быстрый старт

Получение API-ключа

  1. Зарегистрируйтесь в Claude Console на platform.claude.com
  2. Перейдите в Settings → API Keys
  3. Создайте ключ
  4. Пополните баланс в Billing

Ключ привязан к workspace. Один workspace - один набор ключей, лимитов, биллинга.

Для локальной разработки ключ можно не заводить: поставьте CLI ant и выполните ant auth login - SDK подхватят эти учётные данные сами.

Установка SDK

Python:

pip install anthropic

TypeScript:

npm install @anthropic-ai/sdk

Примеры рассчитаны на текущие мажорные версии (anthropic 2.x для Python, @anthropic-ai/sdk 1.x для TypeScript). По умолчанию они отправляют версию API 2026-10-21.

SDK берёт ключ из переменной окружения ANTHROPIC_API_KEY:

export ANTHROPIC_API_KEY="your-api-key"

Первый запрос

Python:

import anthropic

client = anthropic.Anthropic()

message = client.messages.create(
    model="claude-sonnet-5-5",
    max_tokens=4096,
    messages=[
        {"role": "user", "content": "Объясни разницу между REST и GraphQL в трех предложениях."}
    ]
)

for block in message.content:
    if block.type == "text":
        print(block.text)

TypeScript:

import Anthropic from "@anthropic-ai/sdk";

const client = new Anthropic();

const message = await client.messages.create({
  model: "claude-sonnet-5-5",
  max_tokens: 4096,
  messages: [
    { role: "user", content: "Объясни разницу между REST и GraphQL в трех предложениях." }
  ]
});

for (const block of message.content) {
  if (block.type === "text") {
    console.log(block.text);
  }
}

Ответ в message.content - массив контент-блоков. На актуальных моделях thinking включён по умолчанию, поэтому перед блоком text может идти один или несколько блоков thinking. Выбирайте блоки по type, а не по позиции: код вида content[0].text на таких ответах ломается.

Streaming - потоковый ответ

Streaming отдаёт токены по мере генерации - пользователь видит ответ сразу.

Python:

import anthropic

client = anthropic.Anthropic()

with client.messages.stream(
    model="claude-sonnet-5-5",
    max_tokens=4096,
    messages=[
        {"role": "user", "content": "Напиши функцию бинарного поиска на Python."}
    ]
) as stream:
    for text in stream.text_stream:
        print(text, end="", flush=True)

TypeScript:

import Anthropic from "@anthropic-ai/sdk";

const client = new Anthropic();

const stream = client.messages.stream({
  model: "claude-sonnet-5-5",
  max_tokens: 4096,
  messages: [
    { role: "user", content: "Напиши функцию бинарного поиска на Python." }
  ]
});

for await (const event of stream) {
  if (event.type === "content_block_delta" && event.delta.type === "text_delta") {
    process.stdout.write(event.delta.text);
  }
}

Messages API: полный разбор

Параметры запроса

ПараметрТипОбязательныйОписание
modelstringДаID модели: claude-opus-5-5, claude-sonnet-5-5, claude-haiku-5-5, claude-fable-5-1
messagesarrayДаМассив сообщений с ролями user и assistant
max_tokensintegerДаЖёсткий потолок output вместе с thinking (актуальные модели: до 128k; выше 21 333 SDK требует streaming)
systemstring/arrayНетSystem prompt - инструкции для модели
thinkingobjectНетРежим thinking: на актуальных моделях по умолчанию {"type": "adaptive"}; display определяет, что попадёт в thinking-блоки
output_configobjectНетeffort (глубина рассуждений и расход токенов) и format (structured outputs)
temperature, top_p, top_k--Не передавайте: на моделях 5.5 и Fable 5.1 недефолтные значения дают 400, а с версии API 2026-10-21 любое значение даёт 400 на всех моделях. В текущих мажорных версиях SDK этих параметров уже нет
stop_sequencesarrayНетСтроки, при генерации которых модель останавливается
streambooleanНетПотоковый вывод через Server-Sent Events
metadataobjectНетuser_id для отслеживания и abuse detection

System prompt

System prompt задаёт роль и правила поведения. Передаётся отдельным параметром, не через messages.

Python:

message = client.messages.create(
    model="claude-sonnet-5-5",
    max_tokens=4096,
    system="Ты — senior Python-разработчик. Отвечай кратко. Код — с типами и docstrings.",
    messages=[
        {"role": "user", "content": "Напиши декоратор для retry с exponential backoff."}
    ]
)

System prompt - строка или массив контент-блоков. Массив нужен для prompt caching:

system=[
    {
        "type": "text",
        "text": "Ты — senior Python-разработчик. Отвечай кратко.",
        "cache_control": {"type": "ephemeral"}
    }
]

Multi-turn conversations

Claude не хранит состояние между запросами. Для продолжения диалога отправляйте всю историю:

Python:

messages = [
    {"role": "user", "content": "Что такое dependency injection?"},
    {"role": "assistant", "content": "Dependency injection — паттерн, при котором зависимости объекта передаются извне, а не создаются внутри..."},
    {"role": "user", "content": "Покажи пример на Python с dataclass."}
]

message = client.messages.create(
    model="claude-sonnet-5-5",
    max_tokens=4096,
    messages=messages
)

Каждое сообщение - объект с role (user или assistant) и content. Роли чередуются. Два подряд от одной роли - API объединит их. Последним не должно быть сообщение assistant: Claude 4.6 и новее отклоняют заготовленное начало ответа (prefill) с ошибкой 400.

Stop sequences

Кастомные строки, при генерации которых модель останавливается:

message = client.messages.create(
    model="claude-sonnet-5-5",
    max_tokens=4096,
    stop_sequences=["```", "END"],
    messages=[
        {"role": "user", "content": "Напиши JSON-конфигурацию для nginx."}
    ]
)

# message.stop_reason == "stop_sequence"
# message.stop_sequence == "```"

Полезно для structured output: модель генерирует до определенного маркера, вы парсите результат.

Metadata

user_id в metadata нужен для отслеживания abuse. Добавляйте в production:

message = client.messages.create(
    model="claude-sonnet-5-5",
    max_tokens=4096,
    metadata={"user_id": "user_abc123"},
    messages=[
        {"role": "user", "content": "Привет!"}
    ]
)

Используйте хеши или UUID, не передавайте email или реальные имена.

Tool Use (Function Calling)

Tool use - способ вызывать ваши функции из Claude. Вы описываете инструменты через JSON Schema. Модель решает, когда и какой вызвать, формирует параметры. Вы исполняете вызов и возвращаете результат.

Определение инструментов

Инструмент - это имя, описание и JSON Schema для входных параметров:

tools = [
    {
        "name": "get_weather",
        "description": "Получить текущую погоду в указанном городе.",
        "input_schema": {
            "type": "object",
            "properties": {
                "city": {
                    "type": "string",
                    "description": "Название города, например: Москва"
                },
                "units": {
                    "type": "string",
                    "enum": ["celsius", "fahrenheit"],
                    "description": "Единицы измерения температуры"
                }
            },
            "required": ["city"]
        }
    }
]

Описания критичны. Claude читает их, чтобы решить - вызывать инструмент или нет. Чем точнее описание, тем правильнее выбор.

Цикл tool_use → tool_result

Цикл выглядит так:

  1. Вы отправляете запрос с tools
  2. Claude возвращает блок tool_use с именем инструмента и параметрами
  3. Вы исполняете вызов
  4. Отправляете обратно сообщение assistant без изменений (вместе с блоками thinking) и результат как tool_result
  5. Claude формирует финальный ответ (или вызывает следующий инструмент)

Шаг 4 на актуальных моделях важен: API отклоняет изменённые, переставленные или частично выкинутые thinking-блоки с ошибкой 400. Добавляйте response.content как есть, не фильтруя блоки по типу.

Полный пример: погодный бот

Python:

import anthropic
import json

client = anthropic.Anthropic()

tools = [
    {
        "name": "get_weather",
        "description": "Получить текущую погоду в указанном городе.",
        "input_schema": {
            "type": "object",
            "properties": {
                "city": {"type": "string", "description": "Город"},
                "units": {"type": "string", "enum": ["celsius", "fahrenheit"]}
            },
            "required": ["city"]
        }
    }
]

def get_weather(city: str, units: str = "celsius") -> dict:
    """Заглушка — в production здесь вызов реального API."""
    return {"city": city, "temperature": 22, "units": units, "condition": "облачно"}

# Шаг 1: отправляем запрос
messages = [{"role": "user", "content": "Какая погода в Москве?"}]

response = client.messages.create(
    model="claude-sonnet-5-5",
    max_tokens=4096,
    tools=tools,
    messages=messages
)

# Шаг 2: обрабатываем tool_use
if response.stop_reason == "tool_use":
    # Находим блок tool_use в ответе
    tool_block = next(b for b in response.content if b.type == "tool_use")

    # Исполняем вызов
    result = get_weather(**tool_block.input)

    # Шаг 3: возвращаем результат (сообщение assistant — без изменений, вместе с thinking-блоками)
    messages.append({"role": "assistant", "content": response.content})
    messages.append({
        "role": "user",
        "content": [
            {
                "type": "tool_result",
                "tool_use_id": tool_block.id,
                "content": json.dumps(result)
            }
        ]
    })

    # Шаг 4: получаем финальный ответ
    final_response = client.messages.create(
        model="claude-sonnet-5-5",
        max_tokens=4096,
        tools=tools,
        messages=messages
    )

    for block in final_response.content:
        if block.type == "text":
            print(block.text)

TypeScript:

import Anthropic from "@anthropic-ai/sdk";

const client = new Anthropic();

const tools: Anthropic.Tool[] = [
  {
    name: "get_weather",
    description: "Получить текущую погоду в указанном городе.",
    input_schema: {
      type: "object" as const,
      properties: {
        city: { type: "string", description: "Город" },
        units: { type: "string", enum: ["celsius", "fahrenheit"] }
      },
      required: ["city"]
    }
  }
];

function getWeather(city: string, units = "celsius") {
  return { city, temperature: 22, units, condition: "облачно" };
}

const messages: Anthropic.MessageParam[] = [
  { role: "user", content: "Какая погода в Москве?" }
];

const response = await client.messages.create({
  model: "claude-sonnet-5-5",
  max_tokens: 4096,
  tools,
  messages
});

if (response.stop_reason === "tool_use") {
  const toolBlock = response.content.find(
    (b): b is Anthropic.ToolUseBlock => b.type === "tool_use"
  )!;

  const result = getWeather(
    (toolBlock.input as any).city,
    (toolBlock.input as any).units
  );

  messages.push({ role: "assistant", content: response.content });
  messages.push({
    role: "user",
    content: [
      {
        type: "tool_result",
        tool_use_id: toolBlock.id,
        content: JSON.stringify(result)
      }
    ]
  });

  const finalResponse = await client.messages.create({
    model: "claude-sonnet-5-5",
    max_tokens: 4096,
    tools,
    messages
  });

  for (const block of finalResponse.content) {
    if (block.type === "text") {
      console.log(block.text);
    }
  }
}

На Opus 5.5 и Sonnet 5.5 короткие заметки, которые модель пишет между вызовами инструментов, приходят не в text, а в блоках thinking - и по умолчанию пустыми. Если интерфейс показывает этот прогресс, задайте thinking: {"type": "adaptive", "display": "summarized"} (или display: "updates" с beta-заголовком thinking-display-updates-2026-08-18).

tool_choice - контроль вызова инструментов

ЗначениеПоведение
{"type": "auto"}Модель сама решает - вызывать или нет (default)
{"type": "any"}Модель обязана вызвать хотя бы один инструмент. На Opus 5.5, Sonnet 5.5 и Fable 5.1 - ошибка 400
{"type": "tool", "name": "get_weather"}Модель обязана вызвать конкретный инструмент. На Opus 5.5, Sonnet 5.5 и Fable 5.1 - ошибка 400
{"type": "none"}Инструменты отключены

Принудительный вызов по-прежнему работает на Haiku 5.5 и legacy-моделях:

# Принудительный вызов конкретного инструмента (Haiku 5.5)
response = client.messages.create(
    model="claude-haiku-5-5",
    max_tokens=4096,
    tools=tools,
    tool_choice={"type": "tool", "name": "get_weather"},
    messages=[{"role": "user", "content": "Расскажи о Москве."}]
)

На Opus 5.5, Sonnet 5.5 и Fable 5.1 используйте tool_choice: {"type": "auto"}, назовите инструмент в промпте и поставьте инструменту strict: true, чтобы аргументы всегда совпадали со схемой. Если нужен только JSON заданной структуры, берите structured outputs.

Параллельные вызовы инструментов

Claude вызывает несколько инструментов за один ход. Ответ содержит несколько блоков tool_use - обработайте все и верните результаты:

# Если Claude вызвал 3 инструмента — возвращаем 3 результата
tool_results = []
for block in response.content:
    if block.type == "tool_use":
        result = execute_tool(block.name, block.input)
        tool_results.append({
            "type": "tool_result",
            "tool_use_id": block.id,
            "content": json.dumps(result)
        })

messages.append({"role": "assistant", "content": response.content})
messages.append({"role": "user", "content": tool_results})

Отключить параллельные вызовы: tool_choice: {"type": "auto", "disable_parallel_tool_use": true}.

Extended Thinking

Thinking даёт Claude порассуждать перед ответом. Модель разбирает задачу по шагам, проверяет гипотезы, выявляет ошибки - и только потом отвечает. Сырую цепочку рассуждений API не отдаёт никогда: максимум - её сводку.

Когда включать

  • Сложная математика и логические задачи
  • Многошаговый анализ кода
  • Задачи с неочевидным решением
  • Любая ситуация, где «подумать дольше» = «ответить лучше»

На актуальной линейке вопрос скорее не «включать ли», а «насколько глубоко»: thinking включён по умолчанию, а глубину регулирует effort.

Параметры

С выходом Claude 4.6 Anthropic перешла на adaptive thinking - модель сама решает, сколько думать. Ручной режим thinking: {type: "enabled", budget_tokens: N} на всех актуальных моделях возвращает 400 Bad Request.

Как актуальные модели обрабатывают поле thinking:

МодельБез thinkingВыключить thinkingeffort по умолчанию
Opus 5.5adaptiveНельзя: {"type": "disabled"} даёт 400medium
Fable 5.1adaptiveНельзя: {"type": "disabled"} даёт 400high
Sonnet 5.5adaptivedisabled даёт 400; {"type": "between_tools"} отключает предварительное thinking при effort high и нижеhigh
Haiku 5.5adaptive{"type": "disabled"} при effort high и нижеmedium

Все четыре принимают все пять уровней effort: low, medium, high, xhigh, max. Глубина задаётся через output_config.effort:

response = client.messages.create(
    model="claude-sonnet-5-5",
    max_tokens=16000,
    thinking={"type": "adaptive", "display": "summarized"},
    output_config={"effort": "high"},  # low | medium | high | xhigh | max
    messages=[
        {"role": "user", "content": "Докажи, что существует бесконечно много простых чисел p, где p mod 4 == 3."}
    ]
)

effort - мягкий сигнал, не жёсткий лимит токенов. Жёсткая граница - max_tokens, и она покрывает thinking вместе с текстом ответа. Чтобы снизить стоимость или latency, сначала понижайте effort; чтобы дать модели больше глубины - повышайте. На простых запросах Claude может вовсе не думать - тогда thinking-блока в ответе не будет.

Чтение thinking-блоков

Ответ содержит thinking и text блоки:

for block in response.content:
    if block.type == "thinking":
        print(f"Размышления: {block.thinking}")
    elif block.type == "text":
        print(f"Ответ: {block.text}")

На всех актуальных моделях (Fable 5.1, Opus 5.5, Sonnet 5.5, Haiku 5.5) по умолчанию display: "omitted": блок приходит с пустым полем thinking и только с signature. На Opus 4.6, Sonnet 4.6 и более ранних моделях дефолтом был display: "summarized". Чтобы видеть суть рассуждений, задайте thinking: {type: "adaptive", display: "summarized"}, как в примере выше. display: "omitted" ускоряет первый токен текста при streaming. Биллинг - за полные thinking-токены независимо от значения display.

Streaming с extended thinking

Python:

with client.messages.stream(
    model="claude-sonnet-5-5",
    max_tokens=16000,
    thinking={"type": "adaptive", "display": "summarized"},
    output_config={"effort": "high"},
    messages=[{"role": "user", "content": "Реализуй красно-черное дерево на Python."}],
) as stream:
    for event in stream:
        if event.type == "content_block_delta":
            if event.delta.type == "thinking_delta":
                print(event.delta.thinking, end="", flush=True)
            elif event.delta.type == "text_delta":
                print(event.delta.text, end="", flush=True)

Без display: "summarized" события thinking_delta приходят с пустой строкой, и пользователь видит паузу перед ответом.

Ограничения и совместимость

  • Не передавайте temperature, top_p и top_k: на Fable 5.1 и моделях 5.5 недефолтные значения дают 400, а с версии API 2026-10-21 - любые
  • Нельзя prefill: Claude 4.6 и новее отклоняют заготовленное последнее сообщение assistant с ошибкой 400
  • Принудительный вызов инструмента (tool_choice any/tool) на Opus 5.5, Sonnet 5.5 и Fable 5.1 даёт 400
  • max_tokens покрывает thinking и ответ; при effort: xhigh или max начинайте с 64k
  • При max_tokens больше 21 333 SDK требует streaming: используйте .stream() и .get_final_message()
  • Для очень длинного output у Batches API есть режим до 300k токенов (см. ниже)

Стоимость

Thinking-токены тарифицируются как output-токены, даже если текст рассуждений вам не возвращается. Стоимость зависит от реально израсходованного объёма (effort его направляет, но не ограничивает). usage.output_tokens - это оплачиваемое число, и thinking в него входит, поэтому оно не совпадёт с длиной видимого текста.

Опция display: "omitted" скрывает thinking-блоки в ответе и снижает latency, но не стоимость - токены всё равно биллятся.

Prompt Caching

Prompt caching сохраняет обработанные токены между запросами. Чтение из кэша стоит 10% от базовой цены input на большинстве моделей, 5% на Opus 5.5 и Sonnet 5.5 и 2.5% на Fable 5.1. Сравнение с OpenAI, Gemini и DeepSeek и формула окупаемости собраны в разборе prompt caching у разных вендоров.

Как работает

Помечаете блоки маркером cache_control. Anthropic кэширует результат. Следующий запрос с тем же контентом - cache hit, токены не перечитываются.

Кэш иерархический: tools → system → messages. Изменение на любом уровне инвалидирует его и все последующие. Смена настроек thinking или уровня effort тоже начинает новый префикс кэша.

TTL: два варианта

TTLCache writeCache readКогда использовать
5 минут (default)1.25x от базовой цены0.1x от базовой цены (0.05x на Opus 5.5 и Sonnet 5.5, 0.025x на Fable 5.1)Частые запросы (чаще раза в 5 минут)
1 час2x от базовой ценыКак вышеАгентные задачи, длинные сессии

Минимальный размер для кэширования

МодельМинимум токенов
Fable 5.1, Opus 5.5, Sonnet 5.5, Haiku 5.5, Opus 5512
Sonnet 5, Opus 4.8, Sonnet 4.61024
Haiku 4.54096

Контент короче минимума не кэшируется - запрос обработается без ошибок, просто без кэша.

Пример: кэширование большого документа

Python:

import anthropic

client = anthropic.Anthropic()

# Большой документ — кэшируем в system prompt
long_document = open("technical_spec.md").read()

response = client.messages.create(
    model="claude-sonnet-5-5",
    max_tokens=4096,
    system=[
        {
            "type": "text",
            "text": "Ты — технический аналитик. Отвечай на вопросы по документу ниже.",
        },
        {
            "type": "text",
            "text": long_document,
            "cache_control": {"type": "ephemeral"}  # 5-минутный кэш
        }
    ],
    messages=[
        {"role": "user", "content": "Какие нефункциональные требования описаны в документе?"}
    ]
)

# Проверяем кэш
usage = response.usage
print(f"Cache write: {usage.cache_creation_input_tokens}")
print(f"Cache read: {usage.cache_read_input_tokens}")
print(f"Uncached: {usage.input_tokens}")

Второй запрос с тем же system prompt - cache hit. cache_read_input_tokens будет ненулевым.

1-часовой кэш

system=[
    {
        "type": "text",
        "text": long_document,
        "cache_control": {"type": "ephemeral", "ttl": "1h"}
    }
]

Используйте 1-часовой кэш в агентных сценариях, где между запросами больше 5 минут.

Автоматическое кэширование

По умолчанию кэширования нет - без cache_control ничего не кэшируется. Самый простой вариант, с которого документация Anthropic и советует начинать, - один cache_control верхнего уровня в запросе: API сам ставит breakpoint на последний кэшируемый блок и сдвигает его по мере роста истории. Он занимает один из 4 доступных слотов для breakpoint.

Vision (мультимодальность)

Claude принимает изображения в сообщениях. Два способа: base64 и URL.

Поддерживаемые форматы

JPEG, PNG, GIF, WebP (у анимации берётся только первый кадр). Максимальный размер - 10 МБ на изображение (в base64) через Claude API, 5 МБ на Amazon Bedrock. Максимальные размеры - 8000x8000 px.

Base64

Python:

import anthropic
import base64

client = anthropic.Anthropic()

with open("screenshot.png", "rb") as f:
    image_data = base64.standard_b64encode(f.read()).decode("utf-8")

message = client.messages.create(
    model="claude-sonnet-5-5",
    max_tokens=4096,
    messages=[
        {
            "role": "user",
            "content": [
                {
                    "type": "image",
                    "source": {
                        "type": "base64",
                        "media_type": "image/png",
                        "data": image_data
                    }
                },
                {
                    "type": "text",
                    "text": "Проанализируй этот UI-скриншот. Найди проблемы с UX."
                }
            ]
        }
    ]
)

for block in message.content:
    if block.type == "text":
        print(block.text)

URL

message = client.messages.create(
    model="claude-sonnet-5-5",
    max_tokens=4096,
    messages=[
        {
            "role": "user",
            "content": [
                {
                    "type": "image",
                    "source": {
                        "type": "url",
                        "url": "https://example.com/diagram.png"
                    }
                },
                {
                    "type": "text",
                    "text": "Опиши эту архитектурную диаграмму."
                }
            ]
        }
    ]
)

Подсчет токенов для изображений

Claude обрабатывает изображение патчами 28×28 пикселей: оно стоит ⌈width / 28⌉ × ⌈height / 28⌉ токенов. Крупные изображения сначала уменьшаются. Все актуальные модели относятся к high-resolution tier (Claude 4.7 и новее): до 2576 px по длинной стороне и до 4 784 токенов на изображение; у старых моделей предел - 1568 px и 1 568 токенов. Примеры для актуальных моделей:

  • 200x200 px: 64 токена
  • 1000x1000 px: 1 296 токенов
  • 1920x1080 px: 2 691 токен
  • 3840x2160 px: уменьшается до 2576x1449, 4 784 токена

То же изображение может стоить примерно до трёх раз больше токенов, чем на модели standard tier. Если детали не нужны, уменьшайте картинку до отправки. Для точного подсчёта используйте Token Counting API - отдельный endpoint, который считает токены без генерации ответа.

TypeScript-пример: анализ скриншота

import Anthropic from "@anthropic-ai/sdk";
import { readFileSync } from "fs";

const client = new Anthropic();

const imageData = readFileSync("screenshot.png").toString("base64");

const message = await client.messages.create({
  model: "claude-sonnet-5-5",
  max_tokens: 4096,
  messages: [
    {
      role: "user",
      content: [
        {
          type: "image",
          source: {
            type: "base64",
            media_type: "image/png",
            data: imageData
          }
        },
        {
          type: "text",
          text: "Что изображено на скриншоте? Перечисли все UI-элементы."
        }
      ]
    }
  ]
});

for (const block of message.content) {
  if (block.type === "text") {
    console.log(block.text);
  }
}

Streaming

Server-Sent Events

При stream: true ответ приходит как поток SSE-событий. Основные типы:

СобытиеОписание
message_startНачало сообщения, содержит метаданные
content_block_startНачало контент-блока (text, tool_use, thinking)
content_block_deltaДельта контента: text_delta, thinking_delta, signature_delta, input_json_delta
content_block_stopКонец контент-блока
message_deltaФинальные данные: stop_reason, usage
message_stopКонец сообщения

На актуальных моделях поток обычно начинается с блока thinking, поэтому не считайте первый content_block_start текстом - ветвитесь по типу блока.

Python SDK - stream helper

import anthropic

client = anthropic.Anthropic()

with client.messages.stream(
    model="claude-sonnet-5-5",
    max_tokens=4096,
    messages=[{"role": "user", "content": "Напиши async HTTP-клиент на Python."}]
) as stream:
    for text in stream.text_stream:
        print(text, end="", flush=True)

# После завершения — доступ к полному сообщению
final_message = stream.get_final_message()
print(f"\nТокены: {final_message.usage.input_tokens} in / {final_message.usage.output_tokens} out")

stream.text_stream отдаёт только текст. Для низкоуровневого доступа к событиям итерируйтесь по самому объекту stream.

TypeScript SDK - stream

import Anthropic from "@anthropic-ai/sdk";

const client = new Anthropic();

const stream = client.messages.stream({
  model: "claude-sonnet-5-5",
  max_tokens: 4096,
  messages: [{ role: "user", content: "Напиши async HTTP-клиент на TypeScript." }]
});

for await (const event of stream) {
  if (event.type === "content_block_delta" && event.delta.type === "text_delta") {
    process.stdout.write(event.delta.text);
  }
}

const finalMessage = await stream.finalMessage();
console.log(`\nТокены: ${finalMessage.usage.input_tokens} in / ${finalMessage.usage.output_tokens} out`);

Streaming с tool use

При streaming параметры инструмента приходят как input_json_delta - фрагменты JSON:

with client.messages.stream(
    model="claude-sonnet-5-5",
    max_tokens=4096,
    tools=tools,
    messages=[{"role": "user", "content": "Какая погода в Москве?"}]
) as stream:
    for event in stream:
        if event.type == "content_block_start" and event.content_block.type == "tool_use":
            print(f"Вызов инструмента: {event.content_block.name}")
        elif event.type == "content_block_delta":
            if event.delta.type == "input_json_delta":
                print(f"  параметры: {event.delta.partial_json}", end="")
            elif event.delta.type == "text_delta":
                print(event.delta.text, end="", flush=True)

Собирайте partial_json до content_block_stop, затем парсите полный JSON.

Batches API

Batches API - асинхронная пакетная обработка со скидкой 50%. Запросы не держат HTTP-соединение: отправили пакет, забрали результаты когда готово. В пакет помещается до 100 000 запросов или 256 МБ; большинство пакетов обрабатывается меньше чем за час, результаты хранятся 29 дней.

Когда использовать

  • Массовая обработка: классификация тысяч документов
  • Eval-пайплайны: прогон тестов по бенчмарку
  • Генерация контента: пакетное создание описаний
  • Любые задачи, не критичные по latency

Создание batch-запроса

Python:

import anthropic

client = anthropic.Anthropic()

batch = client.messages.batches.create(
    requests=[
        {
            "custom_id": "request-1",
            "params": {
                "model": "claude-sonnet-5-5",
                "max_tokens": 4096,
                "messages": [
                    {"role": "user", "content": "Классифицируй тикет: 'Не работает оплата картой'. Категории: billing, technical, feature_request."}
                ]
            }
        },
        {
            "custom_id": "request-2",
            "params": {
                "model": "claude-sonnet-5-5",
                "max_tokens": 4096,
                "messages": [
                    {"role": "user", "content": "Классифицируй тикет: 'Хочу экспорт в PDF'. Категории: billing, technical, feature_request."}
                ]
            }
        }
    ]
)

print(f"Batch ID: {batch.id}")
print(f"Статус: {batch.processing_status}")

Получение результатов

# Проверяем статус
batch = client.messages.batches.retrieve(batch.id)

if batch.processing_status == "ended":
    # Читаем результаты
    for entry in client.messages.batches.results(batch.id):
        if entry.result.type == "succeeded":
            text = "".join(b.text for b in entry.result.message.content if b.type == "text")
            print(f"{entry.custom_id}: {text}")
        else:
            print(f"{entry.custom_id}: ошибка — {entry.result.type}")

TypeScript

import Anthropic from "@anthropic-ai/sdk";

const client = new Anthropic();

const batch = await client.messages.batches.create({
  requests: [
    {
      custom_id: "request-1",
      params: {
        model: "claude-sonnet-5-5",
        max_tokens: 4096,
        messages: [
          { role: "user", content: "Суммаризируй: 'Claude API поддерживает streaming, tool use и prompt caching.'" }
        ]
      }
    }
  ]
});

console.log(`Batch ID: ${batch.id}`);

// Позже — получение результатов
const results = await client.messages.batches.results(batch.id);
for await (const entry of results) {
  if (entry.result.type === "succeeded") {
    const text = entry.result.message.content
      .filter((b): b is Anthropic.TextBlock => b.type === "text")
      .map((b) => b.text)
      .join("");
    console.log(`${entry.custom_id}: ${text}`);
  }
}

Extended output в Batches

Batches API поддерживает увеличенный output: до 300k токенов для Opus 5.5, Sonnet 5.5, Haiku 5.5, Opus 5, Sonnet 5, Opus 4.8, Opus 4.7, Opus 4.6 и Sonnet 4.6 с beta-заголовком output-300k-2026-03-24 (через client.beta.messages.batches.create). Для генерации длинных документов, книг, отчётов. Одна генерация на 300k токенов может идти больше часа - учитывайте 24-часовое окно обработки пакета.

Цены и оптимизация

Как выбрать между Opus и Sonnet под задачу и бюджет - в отдельном сравнении.

Таблица цен

МодельInputOutputCache write (5m)Cache readCache write (1h)
Fable 5.1$10$50$12.50 (1.25x)$0.25 (0.025x)$20 (2x)
Opus 5.5$4$20$5 (1.25x)$0.20 (0.05x)$8 (2x)
Sonnet 5.5$2$10$2.50 (1.25x)$0.10 (0.05x)$4 (2x)
Haiku 5.5 (промпт до 100K токенов)$0.10$0.50$0.125 (1.25x)$0.01 (0.1x)$0.20 (2x)
Haiku 5.5 (промпт больше 100K токенов)$0.50$2.50$0.625 (1.25x)$0.05 (0.1x)$1 (2x)
Opus 5 (legacy)$5$25$6.25 (1.25x)$0.50 (0.1x)$10 (2x)
Sonnet 5 (legacy)$2$10$2.50 (1.25x)$0.20 (0.1x)$4 (2x)
Haiku 4.5 (legacy)$1$5$1.25 (1.25x)$0.10 (0.1x)$2 (2x)

Batches API - 50% скидка на все модели.

У Haiku 5.5 в длину промпта входят все input-токены, включая чтение и запись кэша; запрос сверх порога платит повышенные цены за всё, в том числе за output. Остальные актуальные модели берут одну и ту же цену за токен на всём контексте в 1M.

Fast mode на Opus 5.5 (speed: "fast", Claude API) стоит $8 / $40 и не работает с Batches API.

Все цены за миллион токенов (MTok). Источник - страница цен Anthropic.

Стратегии оптимизации

1. Выбирайте модель под задачу

Не гоняйте Opus 5.5 на классификации - Haiku 5.5 справится за 1/40 цены (на промптах до 100K токенов). Sonnet 5.5 закрывает повседневные задачи вдвое дешевле Opus. Opus 5.5 берите, когда ошибка дорого стоит, а Fable 5.1 - только если Opus 5.5 на высоком effort не справляется.

2. Prompt caching для повторяющегося контекста

Если system prompt и контекстные документы одинаковы - кэшируйте. На Sonnet 5.5 чтение из кэша стоит 5% от базовой цены. При 100k токенов кэшированного контекста:

  • Без кэша: 100k × $2/MTok = $0.20 за запрос (Sonnet 5.5)
  • С кэшем: 100k × $0.10/MTok = $0.01 за запрос
  • Экономия: 95% на input-токенах

3. Batches для некритичных задач

Eval-пайплайны, массовая классификация, генерация датасетов - latency не критична. Batches API даёт 50% скидку.

4. Streaming для UX

Streaming на токенах не экономит, но первый символ появляется через секунды - пользователь не ждёт. Для чат-интерфейсов - обязательно.

5. Контролируйте max_tokens и effort

max_tokens - жёсткий потолок для thinking и ответа вместе: поставите слишком мало - ответ обрежется. Чтобы тратить меньше токенов, понижайте effort: он уменьшает весь ответ, включая thinking. При смене модели прогоните подбор effort заново: у Opus 5.5 дефолт medium, у Sonnet 5.5 - high.

6. Мониторинг usage

Каждый ответ содержит usage:

{
  "input_tokens": 2095,
  "output_tokens": 503,
  "cache_creation_input_tokens": 0,
  "cache_read_input_tokens": 2000
}

Логируйте. Считайте стоимость по формуле:

cost = (input_tokens * input_price + output_tokens * output_price
        + cache_creation * write_price + cache_read * read_price) / 1_000_000

Structured Outputs

Нативный JSON mode доступен через output_config.format - GA без beta-заголовков, работает на всех актуальных моделях. API гарантирует валидный JSON по заданной схеме.

import anthropic
import json

client = anthropic.Anthropic()

response = client.messages.create(
    model="claude-sonnet-5-5",
    max_tokens=4096,
    output_config={
        "format": {
            "type": "json_schema",
            "schema": {
                "type": "object",
                "properties": {
                    "name": {"type": "string"},
                    "age": {"type": "integer"},
                    "role": {"type": "string"}
                },
                "required": ["name", "age", "role"],
                "additionalProperties": False
            }
        }
    },
    messages=[
        {"role": "user", "content": "Иван Петров, 35 лет, senior developer"}
    ]
)

text = next(b.text for b in response.content if b.type == "text")
data = json.loads(text)
# {"name": "Иван Петров", "age": 35, "role": "senior developer"}

В Python ещё проще client.messages.parse() с Pydantic-моделью: SDK сам строит схему, валидирует ответ и кладёт объект в parsed_output (пример - в разделе про JSON mode ниже).

Когда что выбирать:

  • output_config.format - проще, не требует инструментального контекста, подходит для большинства случаев
  • Strict tool use (strict: true у инструмента) - если в том же запросе уже есть инструменты и нужны аргументы строго по схеме. Принудительный tool_choice на Opus 5.5, Sonnet 5.5 и Fable 5.1 даёт 400, поэтому на этих моделях инструмент вызывают через auto и указание в промпте

MCP Connector

MCP Connector позволяет подключать remote MCP серверы прямо из Messages API - без отдельного MCP-клиента. Полезно для агентных сценариев: модель сама вызывает инструменты из ваших MCP-сервисов.

Требует beta-заголовок mcp-client-2025-11-20. На Claude API есть и более новый mcp-client-2026-09-15: он умеет всё то же и добавляет фиксацию списка инструментов сервера.

import anthropic

client = anthropic.Anthropic()

response = client.beta.messages.create(
    model="claude-sonnet-5-5",
    max_tokens=4096,
    mcp_servers=[
        {
            "type": "url",
            "url": "https://your-mcp-server.example.com/mcp",
            "name": "my-tools",
            "authorization_token": "YOUR_TOKEN"  # опционально
        }
    ],
    tools=[
        {
            "type": "mcp_toolset",
            "mcp_server_name": "my-tools"  # имя сервера из mcp_servers
        }
    ],
    messages=[
        {"role": "user", "content": "Выполни задачу, используя доступные инструменты."}
    ],
    betas=["mcp-client-2025-11-20"]
)

Конфигурация инструментов находится в массиве tools в виде объекта mcp_toolset. Можно ограничить набор инструментов через allowlist/denylist:

tools=[
    {
        "type": "mcp_toolset",
        "mcp_server_name": "my-tools",
        "default_config": {"enabled": False},   # allowlist: отключаем всё по умолчанию
        "configs": {
            "tool1": {"enabled": True},          # включаем только нужные
            "tool2": {"enabled": True}
        }
    }
]

Важные ограничения:

  • Поддерживаются только MCP tool calls - prompts и resources не поддерживаются
  • Сервер должен быть доступен публично по HTTP (Streamable HTTP или SSE); локальные STDIO-серверы напрямую не подключить
  • Доступен в beta на Claude API, Claude Platform on AWS, Claude Models on Google Cloud (Anthropic managed) и Microsoft Foundry; на Amazon Bedrock не поддерживается
  • Результаты инструментов приходят из внешней системы - применяйте те же меры доверия, что и к user input (риск indirect prompt injection)

Best Practices

Error handling и retries

Стандартные HTTP-коды. Основные ошибки:

КодПричинаДействие
400Невалидный запросПроверьте параметры
401Неверный API-ключПроверьте ANTHROPIC_API_KEY
429Rate limitRetry с exponential backoff
529API перегруженRetry через 30-60 секунд
500Серверная ошибкаRetry с backoff

Python SDK делает retry автоматически:

# SDK автоматически ретраит 429 и 5xx
client = anthropic.Anthropic(
    max_retries=3,  # default: 2
    timeout=60.0     # секунды
)

Для кастомной логики:

import time
from anthropic import RateLimitError, APIStatusError

def call_with_retry(client, max_retries=3, **kwargs):
    for attempt in range(max_retries):
        try:
            return client.messages.create(**kwargs)
        except RateLimitError:
            wait = 2 ** attempt  # 1s, 2s, 4s
            print(f"Rate limit, жду {wait}s...")
            time.sleep(wait)
        except APIStatusError as e:
            if e.status_code >= 500:
                time.sleep(2 ** attempt)
                continue
            raise
    raise Exception("Все попытки исчерпаны")

Безопасность API-ключей

  • Храните ключ в переменных окружения, не в коде
  • Используйте разные ключи для dev/staging/production
  • Ротируйте ключи регулярно
  • Один workspace - один проект (изоляция биллинга и лимитов)
  • В CI/CD - через секреты (GitHub Secrets, Vault)
# Правильно
client = anthropic.Anthropic()  # берёт из ANTHROPIC_API_KEY

# Неправильно
client = anthropic.Anthropic(api_key="your-api-key")  # ключ в коде

Structured output (JSON mode)

Рекомендуемый способ - output_config.format (описан в отдельной секции выше). Старый приём с prefill (закончить messages сообщением assistant {) больше не работает: Claude 4.6 и новее отклоняют его с ошибкой 400. Два других подхода:

Подход 1: client.messages.parse() с Pydantic-моделью

from pydantic import BaseModel

class Person(BaseModel):
    name: str
    age: int
    role: str

response = client.messages.parse(
    model="claude-sonnet-5-5",
    max_tokens=4096,
    messages=[
        {"role": "user", "content": "Извлеки данные из текста: 'Иван Петров, 35 лет, senior developer'."}
    ],
    output_format=Person,
)

person = response.parsed_output  # Person(name='Иван Петров', age=35, role='senior developer')

SDK превращает модель в JSON Schema, отправляет её как output_config.format и валидирует ответ.

Подход 2: Strict tool use

tools = [{
    "name": "extract_person",
    "description": "Извлечь данные о человеке.",
    "strict": True,
    "input_schema": {
        "type": "object",
        "properties": {
            "name": {"type": "string"},
            "age": {"type": "integer"},
            "role": {"type": "string"}
        },
        "required": ["name", "age", "role"],
        "additionalProperties": False
    }
}]

message = client.messages.create(
    model="claude-sonnet-5-5",
    max_tokens=4096,
    tools=tools,
    messages=[
        {"role": "user", "content": "Вызови extract_person для текста: Иван Петров, 35 лет, senior developer"}
    ]
)

# При strict: true tool_use.input всегда соответствует схеме
tool_block = next((b for b in message.content if b.type == "tool_use"), None)
if tool_block:
    person = tool_block.input  # {"name": "Иван Петров", "age": 35, "role": "senior developer"}

strict: true гарантирует аргументы по схеме, но при tool_choice: auto вызывать ли инструмент, решает модель - поэтому назовите его в промпте и проверьте, что блок пришёл. На Haiku 5.5 и legacy-моделях вызов по-прежнему можно форсировать через tool_choice: {"type": "tool", "name": "extract_person"}.

Rate limits

Лимиты зависят от модели и usage tier организации. Основные метрики:

  • Requests per minute (RPM) - количество запросов в минуту
  • Input tokens per minute (ITPM) - считается только некэшированный input: cache_read_input_tokens в лимит не входят
  • Output tokens per minute (OTPM) - сгенерированные токены; max_tokens на лимит не влияет

Заголовки ответа содержат текущие лимиты:

anthropic-ratelimit-requests-limit: 1000
anthropic-ratelimit-requests-remaining: 999
anthropic-ratelimit-requests-reset: 2026-04-09T12:00:00Z
anthropic-ratelimit-tokens-limit: 80000
anthropic-ratelimit-tokens-remaining: 79500

Стратегии:

  1. Exponential backoff при 429 - SDK делает это автоматически; если в ответе есть заголовок retry-after, подождите указанное число секунд
  2. Пакетная обработка через Batches API - у него свои лимиты, и на rate limits Messages API он не влияет
  3. Несколько workspace’ов для изоляции лимитов между проектами
  4. Чтение из кэша не считается в ITPM - ещё один повод кэшировать

Logging и monitoring

Каждый ответ содержит id (msg_...) и usage. Логируйте оба значения:

import logging

logger = logging.getLogger("claude_api")

response = client.messages.create(
    model="claude-sonnet-5-5",
    max_tokens=4096,
    messages=[{"role": "user", "content": "Привет"}]
)

logger.info(
    "API call",
    extra={
        "message_id": response.id,
        "model": response.model,
        "input_tokens": response.usage.input_tokens,
        "output_tokens": response.usage.output_tokens,
        "stop_reason": response.stop_reason,
    }
)

В production подключайте observability: Langfuse, LangSmith или собственный pipeline. Трекайте latency, стоимость на запрос, распределение по моделям.

Итого

Claude API - один endpoint, четыре актуальные модели, набор мощных фичей.

Для старта: установите SDK, получите ключ, отправьте первый запрос. Anthropic советует начинать с Opus 5.5; Sonnet 5.5 вдвое дешевле и быстрее.

Для production: prompt caching на повторяющемся контексте, streaming для UX, Haiku 5.5 для массовых операций, Batches для eval-пайплайнов. Читайте блоки ответа по type и уберите из старого кода temperature, prefill и принудительный tool_choice.

Для сложных задач: adaptive thinking с output_config.effort для reasoning, tool use для интеграции с внешними системами, MCP Connector для подключения к remote MCP-серверам напрямую из API, Opus 5.5 когда точность критична, Fable 5.1 - когда не хватает и его.

Structured outputs: output_config.format - нативный JSON mode без beta-заголовков.

Вся документация - platform.claude.com/docs. SDK: anthropic-sdk-python, anthropic-sdk-typescript. Примеры и рецепты - anthropic-cookbook.

Часто задаваемые вопросы

Как получить API-ключ Claude?
Зарегистрируйтесь в Claude Console на platform.claude.com и создайте ключ в Settings → API Keys. Ключ привязан к workspace. Пополните баланс в Billing. Для локальной разработки ключ можно не заводить: после `ant auth login` SDK сами подхватывают учётные данные CLI.
Сколько стоит Claude API?
Цены за миллион токенов (MTok): Opus 5.5 - $4 input / $20 output, Sonnet 5.5 - $2 / $10, Haiku 5.5 - $0.10 / $0.50 для промптов до 100K токенов и $0.50 / $2.50 сверх этого, Fable 5.1 - $10 / $50. Чтение из prompt cache стоит 10% от базовой цены input на большинстве моделей (5% на Opus 5.5 и Sonnet 5.5, 2.5% на Fable 5.1). Batches API даёт 50% скидку.
Чем Claude API отличается от Claude.ai?
Claude.ai - чат-интерфейс для конечных пользователей. API дает полный контроль: system prompts, tool use (function calling), streaming, настройки thinking и effort, prompt caching, batches. Можно встроить Claude в любое приложение, автоматизировать обработку и масштабировать.
Какую модель Claude выбрать?
Opus 5.5 (`claude-opus-5-5`) - для долгих агентных задач в коде и работе со знаниями; Anthropic советует начинать с неё для большинства нагрузок. Sonnet 5.5 (`claude-sonnet-5-5`) - лучшее сочетание скорости и интеллекта, вдвое дешевле Opus. Haiku 5.5 (`claude-haiku-5-5`) - для классификации, извлечения данных, роутинга и других массовых задач. Fable 5.1 (`claude-fable-5-1`) - для самых сложных рассуждений и долгих агентных задач, когда Opus 5.5 не справляется. У всех четырёх контекст 1M токенов и до 128k output.