# Читаем ответ: content, usage, stop_reason

Курс: Claude API для разработчиков — https://zero2claude.ru/learn/api
Канонический URL: https://zero2claude.ru/learn/api/0-4-chitaem-otvet

Текст ответа лежит в массиве content — доставай его по type == "text", а не из content[0] вслепую. Что значат usage и stop_reason.

## Как выглядит ответ

На успешный запрос сервер возвращает JSON примерно такой формы:

```
{
  "content": [
    {"type": "text", "text": "Здравствуйте! Ваш заказ №1542 уже в пути."}
  ],
  "stop_reason": "end_turn",
  "usage": {
    "input_tokens": 24,
    "output_tokens": 17,
    "cache_read_input_tokens": 0,
    "cache_creation_input_tokens": 0
  },
  "model": "claude-opus-4-8"
}
```

## content — это массив, не строка

Главная ловушка новичка: `content` — это **массив блоков**, а не одна строка. Блоки бывают разных типов (`text`, позже — `tool_use`). Текст надо брать из блоков с `type == "text"`, а не хватать `content[0]` вслепую — там может оказаться, например, блок инструмента.

Правильно в Python:

```
resp = client.messages.create(
    model="claude-opus-4-8",
    max_tokens=1024,
    messages=[{"role": "user", "content": "Привет!"}],
)
text = "".join(b.text for b in resp.content if b.type == "text")
```

Код вида `resp.content[0].text` сломается, как только в начале ответа окажется не текстовый блок. Всегда фильтруй по `type == "text"`.

## stop_reason и usage

- **`stop_reason`** — почему модель остановилась: `end_turn` (закончила сама), `max_tokens` (упёрлась в лимит — ответ неполный), `tool_use` (хочет вызвать инструмент), `refusal` (отказ по правилам безопасности).
- **`usage`** — счётчики токенов. `input_tokens` и `output_tokens` — это то, за что ты платишь. Поля `cache_read_input_tokens` и `cache_creation_input_tokens` понадобятся позже, в теме про кэширование.

Если `stop_reason` равен `max_tokens` — ответ обрезан. Это сигнал поднять `max_tokens`, а не баг модели.
