Формат Anthropic
POST /v1/messages принимает запрос в формате Anthropic Messages и работает с моделями группы op (OpenRouter). Можно использовать SDK Anthropic и другие совместимые клиенты, в которых меняются адрес и ключ, с ограничениями, описанными ниже. Группа vn (Venice) в этом формате недоступна: у неё нет родного эндпоинта Anthropic.
Модель называется так же, как во всём API: op/<модель>. Голые имена Anthropic (claude-…) не принимаются — полный список моделей с ценами даёт GET /v1/models.
Запрос
curl https://api.6io.io/v1/messages \
-H "Authorization: Bearer sixio_sk_..." \
-H "anthropic-version: 2023-06-01" \
-H "Content-Type: application/json" \
-d '{
"model": "op/anthropic/claude-haiku-4.5",
"max_tokens": 200,
"messages": [
{"role": "user", "content": "Отвечай коротко: зачем нужен Idempotency-Key?"}
]
}'Ключ можно передать и как у клиентов Anthropic — в заголовке x-api-key: sixio_sk_.... Работают оба способа, передавать оба не нужно. Заголовок anthropic-version передаётся поставщику; anthropic-beta и другие дополнительные заголовки Anthropic не передаются, поэтому функции, которым они нужны, недоступны.
Обязательные поля — model, max_tokens (положительное целое число) и непустой messages. Поддерживаемые параметры Anthropic (system, temperature, tools, metadata и другие) уходят поставщику: что они значат, написано в документации формата. Для выбора провайдера могут добавляться настройки по умолчанию; подробнее — модели OpenRouter. Сообщения с блоками tool_use, tool_result и картинками работают, как у поставщика.
Ответ приходит в формате Anthropic. В model стоит то название, которое вы отправили (op/…), номер запроса — в заголовке X-Sixio-Request-Id.
max_tokens обязателен и у нас не просто так: перед отправкой мы резервируем деньги на самый длинный ответ, который вы разрешили. Спишется только то, что реально потрачено. Подробнее — в разделе Баланс и цены.
Потоковый ответ
С "stream": true ответ приходит по мере генерации, как SSE, в формате Anthropic: message_start, content_block_start, content_block_delta (в том числе дельты вызова инструментов — input_json_delta), content_block_stop, message_delta с итоговым usage, message_stop в конце. Служебные строки event: и ping проходят как есть. Признака [DONE] из формата OpenAI здесь нет — концом потока служит событие message_stop.
from anthropic import Anthropic
client = Anthropic(base_url="https://api.6io.io", api_key="sixio_sk_...", max_retries=0)
with client.messages.stream(
model="op/anthropic/claude-haiku-4.5",
max_tokens=300,
messages=[{"role": "user", "content": "Расскажи короткую сказку"}],
) as stream:
for text in stream.text_stream:
print(text, end="", flush=True)В примере автоматические повторы SDK отключены: при обрыве или неоднозначном ответе повтор может запустить ещё одну платную генерацию. Для повторов используйте один Idempotency-Key на исходный запрос и сначала проверяйте состояние по X-Sixio-Request-Id, если он получен.
- В чанке
message_deltaестьusage. Полеusage.costв нём — стоимость у поставщика в долларах, а не наше списание. Сумму в кредитах покажетGET /v1/requests/{id}. - Если закрыть соединение раньше времени, генерация у поставщика могла уже начаться и её расход будет учтён. Мы продолжаем читать ответ, но если сумма не получена, резерв остаётся на сверке до её подтверждения или решения администратора.
- Если между вами и API стоит промежуточный сервер (nginx и подобные), выключите буферизацию ответа. Мы отправляем заголовок
X-Accel-Buffering: no.
Ошибки
На этом маршруте все наши ошибки приходят в формате Anthropic:
{"type": "error", "error": {"type": "billing_error", "message": "Insufficient credits"}}| Статус | error.type |
Когда бывает |
|---|---|---|
| 400 | invalid_request_error |
неверное тело, нет max_tokens или messages, отвергнутый параметр |
| 401 | authentication_error |
ключ не передан или неверный |
| 402 | billing_error |
на балансе не хватает кредитов (в том числе для бесплатной модели) |
| 403 | permission_error |
аккаунт заблокирован или ограничен |
| 404 | not_found_error |
нет такой модели или страницы |
| 409 | invalid_request_error |
повтор с тем же Idempotency-Key |
| 413 | invalid_request_error |
тело больше PUBLIC_API_MAX_BODY_KB (4 МБ по умолчанию) |
| 422 | invalid_request_error |
тот же Idempotency-Key с другим телом |
| 429 | rate_limit_error |
сработал лимит аккаунта, повторите после Retry-After |
| 500–503 | api_error |
сбой на нашей стороне или у поставщика |
Явные отказы по запросу, в том числе ответ модерации 403, передаются с исходным статусом и телом; резерв освобождается. Другие ошибки мы заменяем своим ответом: например, 429 поставщика превращается в 503 api_error с освобождением резерва, а при 5xx поставщика или обрыве после отправки исход неизвестен и резерв остаётся на сверке. Поэтому по одному статусу 503 нельзя определить, безопасно ли повторять запрос. Проверяйте сообщение и состояние запроса, если известен его номер. Подробнее — в разделах Повторы и сбои и Ошибки и лимиты.
Идемпотентность и бесплатные модели
Заголовок Idempotency-Key работает как в чате: пока запрос сохранён под этим ключом, повтор того же ключа и тела не запускает вторую генерацию — клиент получает 409 с X-Sixio-Request-Id прежнего запроса. Если резерв освобождён после явного отказа или ошибки, при которой запрос не был принят, ключ тоже освобождается: повтор может запустить новую генерацию.
Бесплатные модели (цена 0 в каталоге, у OpenRouter суффикс :free) вызываются как все остальные, списание за них равно нулю. Условие то же: на API-балансе должно быть больше нуля, иначе 402 billing_error.
Что отклоняется до списания
Эти запросы получают 400 invalid_request_error и не доходят до поставщика:
- поля
plugins,web_search_options,models(список запасных моделей) иpreset; - платные серверные инструменты:
toolsс типомopenrouter:…, а также типы Anthropicweb_search_*,computer_*,bash_*,text_editor_*,code_execution_*— их расход резерв по токенам не оценивает.
Суффикс модели :online тоже не поддерживается: если такой модели нет в каталоге, ответ будет 404 not_found_error, иначе — 400 invalid_request_error; до поставщика запрос не дойдёт.
Свои инструменты клиента (tools с типом custom и вызовы через tool_use/tool_result) работают, как у поставщика.