6ioAPI

Формат 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:…, а также типы Anthropic web_search_*, computer_*, bash_*, text_editor_*, code_execution_* — их расход резерв по токенам не оценивает.

Суффикс модели :online тоже не поддерживается: если такой модели нет в каталоге, ответ будет 404 not_found_error, иначе — 400 invalid_request_error; до поставщика запрос не дойдёт.

Свои инструменты клиента (tools с типом custom и вызовы через tool_use/tool_result) работают, как у поставщика.