Аутентификация

Запросы интеграции проходят аутентификацию API-ключом организации (sk-org-…) в заголовке Authorization: Bearer. Ключ открывает две двери, каждую в пределах своих scope:

ДверьScope
OpenAI-совместимый API: POST /v1/chat/completions, GET /v1/modelschat:write
MCP-сервер по адресу /mcp/: чтениеtools:read
MCP-сервер по адресу /mcp/: вызовы на запись и repl_executetools:write

Ключ передаётся только в Authorization: Bearer; заголовок x-api-key не читается, и запрос только с ним получит 401 AUTH_HEADER_MISSING.

Нативный /api/v1 это внутренний API приложений Сам Решу: он принимает токен вошедшего пользователя, на ключ отвечает 401 AUTH_TOKEN_INVALID и контрактом для интеграций не является. Эндпоинты /v1 устроены наоборот: принимают только ключ, а на токен пользователя отвечают тем же кодом.

Создать ключ и отправить первый запрос

  1. Войдите в Сам Решу и выберите нужную организацию.
  2. Откройте Настройки → API-ключи и нажмите Создать ключ. Создавать ключи могут владелец и администратор организации.
  3. Укажите название, например Моя интеграция. В поле Доступ оставьте Полный доступ: он выбран по умолчанию и включает chat:write. «Только AI-приложения» и «Только просмотр» открывают MCP, но не чат-эндпоинт.
  4. Выберите срок действия и нажмите Создать ключ.
  5. Скопируйте ключ sk-org-… и сохраните его: повторно увидеть полный секрет нельзя.

Если кнопки создания нет, обратитесь к владельцу или администратору организации.

Сохраните ключ в переменной окружения на своём сервере или компьютере:

bash
export SAMRESHUUU_API_KEY="sk-org-your_api_key"

Сначала проверьте ключ запросом списка агентов, с которыми можно говорить, без запуска агента:

bash
curl --fail-with-body https://samreshuuu.ru/v1/models \ -H "Authorization: Bearer $SAMRESHUUU_API_KEY"

При успешной авторизации вернётся JSON со списком агентов. Затем отправьте сообщение одному из них по хэндлу; этот запрос расходует доступную квоту:

bash
curl --fail-with-body https://samreshuuu.ru/v1/chat/completions \ -H "Authorization: Bearer $SAMRESHUUU_API_KEY" \ -H "Content-Type: application/json" \ -d '{"model":"samreshu","messages":[{"role":"user","content":"Ответь одним словом: привет"}]}'

Ответ находится в choices[0].message.content. 401 означает, что ключ не принят; 403 означает, что у ключа нет chat:write; 404 означает, что model не называет доступного вам агента. Примеры для Python и Node.js: OpenAI-совместимый API.

Контекст организации

Ключ привязан к организации, в которой выпущен, и к сотруднику, который его выпустил, и это доступ организации, а не личный. Ему доступны агенты, доступные этому сотруднику там, и общие подключения организации, открытые этому сотруднику. Памяти создателя, его личных подключений и его устройств ключ не видит: агент, отвечающий ключу, начинает без памяти, а подключение, которое видит только создатель, для ключа не подключено.

Ключ работает, только пока его создатель остаётся владельцем или администратором действующей организации. Это проверяется на каждом запросе: если создатель ушёл или удалён из организации, потерял роль или организация удалена, следующий запрос с ключом получит 401 AUTH_INVALID_CREDENTIALS.

Храните ключ на сервере, не в браузерной или мобильной сборке. Ключами управляют в Настройках → API-ключи или токеном вошедшего пользователя (ниже $ADMIN_TOKEN): выпуск и отзыв доступны владельцу и администратору, список видит любой участник.

Формат токенов

API-ключи имеют префикс sk-org-. Полный секрет показывается только один раз, при создании: сохраните его надёжно. Эндпоинты списка и отзыва возвращают только префикс ключа, никогда не секрет. По префиксу sk-org- утёкший ключ находит секрет-сканер: добавьте шаблон в pre-commit и поиск по логам.

Scopes

Ключ несёт список scope, минимум один: tools:read, tools:write, chat:write, sessions:read, sessions:write. Каждый имеет вид ресурс:действие. Запрос, которому нужен отсутствующий у ключа scope, завершается ошибкой 403 AUTH_PERMISSION_DENIED. Ключ, выпущенный через API без scopes, получает tools:write, chat:write, sessions:write; пустой список и любое другое слово (включая write:tools, chat, read:tools, admin) отклоняются с 422.

ScopeДоступ
chat:writePOST /v1/chat/completions и GET /v1/models
tools:readЧтение через MCP: list_services, describe_service, читающие вызовы connector_execute
tools:writeВызовы connector_execute на запись и любой repl_execute через MCP; включает tools:read
sessions:readЗарезервирован: операций с ним пока нет
sessions:writeЗарезервирован: операций с ним пока нет; включает sessions:read

Доступ в настройках соответствует набору scope: Полный доступ означает tools:write, chat:write, sessions:write, тот же набор, что получает ключ, выпущенный через API без scopes; Только AI-приложения означает tools:write, Только просмотр означает tools:read. Чат-эндпоинт открывает только Полный доступ.

Управление ключами

Ключи выпускаются, перечисляются и отзываются в рамках организации. Каждый ключ истекает через expires_in_days: по умолчанию 90, допустимо от 1 до 365; явный null создаёт бессрочный ключ.

bash
# Создать ключ: полный секрет возвращается один раз curl -X POST https://samreshuuu.ru/api/v1/organizations/$ORG_ID/api-keys \ -H "Authorization: Bearer $ADMIN_TOKEN" \ -H "Content-Type: application/json" \ -d '{"name": "production", "scopes": ["chat:write", "tools:write"], "expires_in_days": 90}' # Список ключей без секрета: префикс, scopes, expires_at, last_used_at curl https://samreshuuu.ru/api/v1/organizations/$ORG_ID/api-keys \ -H "Authorization: Bearer $ADMIN_TOKEN" # Отозвать ключ (204) curl -X DELETE https://samreshuuu.ru/api/v1/organizations/$ORG_ID/api-keys/$KEY_ID \ -H "Authorization: Bearer $ADMIN_TOKEN"

Отзыв действует сразу, на HTTP и в MCP. Ключи сотрудника отзываются сами, когда он покидает организацию или теряет роль владельца или администратора, а все ключи организации отзываются при её удалении. Неизвестный, отозванный или истёкший ключ, а также ключ, создатель которого больше не может его держать (см. раздел «Контекст организации»), получает 401 AUTH_INVALID_CREDENTIALS.

Ротация без простоя. Выпустите новый ключ, выкатите его, убедитесь по last_used_at, что старый больше не используется, и отзовите старый. Отметку ставят запросы к /v1/* и к MCP, но не чаще раза в 10 мин: ключ затих, когда его last_used_at старше этого окна и больше не сдвигается. Ключ, попавший в репозиторий, лог или чат, отзывайте сразу, даже если следов использования нет. Для разных сред (разработка, прод) держите разные ключи.

Лимиты частоты и вызовы из браузера

Частота запросов ограничена на каждый ключ, в минуту, по тарифу организации:

ТарифЗапросов в минуту на ключ
Pro180
Max360

Превышение даёт 429 RATE_LIMIT_EXCEEDED с заголовком Retry-After в секундах. Расход модели считается отдельным недельным лимитом, см. Ошибки и лимиты.

Вызовы со страницы в браузере с чужого origin режет CORS: на кросс-доменные запросы с ключом API не отвечает. Ходите через свой сервер, тогда и ключ не попадёт на страницу.

Ошибки аутентификации

Отказ /v1 приходит в публичном объекте ошибки: ветвитесь по error.type и error.code, а не по тексту. Каждый 401 несёт заголовок WWW-Authenticate: Bearer realm="samreshuuu". Статус, код и признак повтора ниже берутся из реестра ошибок сервера; текст отказа по ключу приведён после таблицы.

HTTPКодЗначениеПовтор
401AUTH_HEADER_MISSINGОтсутствует заголовок авторизации.нет
401AUTH_TOKEN_INVALIDНедействительный токен авторизации.нет
401AUTH_TOKEN_EXPIREDСрок действия токена истёк.нет
401AUTH_INVALID_CREDENTIALSНе удалось подтвердить вход. Попробуйте ещё раз.нет
403AUTH_PERMISSION_DENIEDНедостаточно прав для выполнения операции.нет
429RATE_LIMIT_EXCEEDEDСлишком много запросов. Подождите немного.да
  • AUTH_HEADER_MISSING: нет заголовка Authorization. Добавьте Bearer.
  • AUTH_TOKEN_INVALID: не Bearer, повреждённый токен или ключ организации на нативном /api/v1. Используйте /v1 или MCP.
  • AUTH_TOKEN_EXPIRED: истёк токен пользователя. Ключи так не истекают: истёкший ключ получает AUTH_INVALID_CREDENTIALS.
  • AUTH_INVALID_CREDENTIALS: ключ неизвестен, отозван или истёк либо его создатель больше не владелец и не администратор организации. Текст: «Invalid, revoked or expired API key. Create a new key in the organization settings.»
  • AUTH_PERMISSION_DENIED: у ключа нет scope, который требует операция; текст его называет. Не повторяйте: выпустите ключ с этим scope.
  • RATE_LIMIT_EXCEEDED: лимит запросов ключа. Подождите Retry-After секунд.
json
{ "type": "error", "error": { "type": "permission_error", "code": "AUTH_PERMISSION_DENIED", "message": "This API key lacks the chat:write scope. Create a key with this scope.", "param": null }, "request_id": "76a9e461-7848-4159-b90f-5c0d704ac97f" }

MCP отвечает на отказ входа до чтения MCP-сообщения: HTTP 401, тот же заголовок WWW-Authenticate и тело {"detail": {…}} (code, message, message_en); см. MCP. Тем же телом detail отвечает нативный /api/v1 (управление ключами).

Частые вопросы

Как аутентифицировать запрос?

Передайте API-ключ организации в заголовке Authorization: Bearer sk-org-... Он открывает OpenAI-совместимые эндпоинты /v1 и MCP-сервер в пределах своих scope.

В какой организации выполняется запрос?

В той, что выпустила ключ. Ключ является доступом организации, который выпустил один сотрудник: ему открыты общие подключения организации, но не память и не личные подключения создателя, и он работает, пока создатель остаётся там владельцем или администратором. Для работы в другой организации выпустите ключ там.

Что будет, если у ключа нет нужного scope?

Запрос завершится ошибкой 403 AUTH_PERMISSION_DENIED, и текст ошибки назовёт недостающий scope. chat:write открывает /v1/chat/completions и /v1/models, tools:read открывает чтение через MCP, tools:write открывает вызовы на запись и repl_execute через MCP и включает tools:read. sessions:read и sessions:write зарезервированы: операций с ними пока нет. У каждого ключа хотя бы один scope; ключ, выпущенный без scopes, получает tools:write, chat:write и sessions:write.

Можно ли получить секрет ключа после его создания?

Нет. Полный секрет показывается только один раз, при создании. Эндпоинты списка и отзыва возвращают лишь префикс ключа, но не секрет. Ключ истекает через expires_in_days (см. «Управление ключами»), явный null создаёт бессрочный ключ.

Была ли страница полезна?