API управления

Обзор и аутентификация

Программный доступ ко всему, что делает кабинет: серверный ключ в заголовке Authorization, cookie-сессия как второй способ и причина, по которой ключ песочницы сюда не пускают.

На этой странице · 6

Management API — тот же самый API, которым работает кабинет. Песочницы, ключи, вебхуки, сценарии, свои моки, журнал и каталог доступны по адресу /api/v1/* и делаются скриптом ровно в том же объёме, что мышкой. Второго набора маршрутов для браузера нет намеренно: две реализации одного и того же расходятся на первой же правке.

Типичные поводы: поднять окружение под прогон тестов в CI, выдать подрядчику ключ с урезанными правами, снести и пересоздать песочницу перед прогоном, выгрузить журнал за период.

Адрес и версия

Префикс — /api/v1. Точка, с которой удобно начинать, — GET /api/v1/meta: она отвечает без авторизации и сообщает всё, что клиенту нужно знать заранее.

curl -s http://localhost:8080/api/v1/meta
{
  "version": "1.0.0",
  "prefix": "/api/v1",
  "routes": 67,
  "auth": {
    "bearer": "Authorization: Bearer stend_sk_…",
    "cookie": "apistend_session",
    "note": "Ключ песочницы (stend_sbx_…) здесь не принимается: им ходит код интеграции, а Management API умеет удалять данные и выпускать ключи."
  },
  "rateLimit": {
    "perMinute": 240,
    "subject": "ключ, а для браузера — сессия кабинета",
    "headers": ["X-RateLimit-Limit", "X-RateLimit-Remaining", "X-RateLimit-Reset", "Retry-After"]
  },
  "pagination": {
    "limitDefault": 25,
    "limitMax": 100,
    "cursor": "идентификатор последней отданной записи, передаётся в ?cursor=",
    "response": "{ items, nextCursor }"
  }
}

Число routes — живое: это количество маршрутов, зарегистрированных в реестре процесса, и с каждым выпуском оно меняется. Полный перечень отдаёт спецификация OpenAPI.

Серверный ключ

Основной способ входа — серверный ключ stend_sk_… в заголовке Authorization.

export STEND=http://localhost:8080
export STEND_KEY=stend_sk_7d21e5a31fa011240aaaf31b136c46f2

curl -s "$STEND/api/v1/account" -H "Authorization: Bearer $STEND_KEY"
{
  "id": "cmtt67iv2000053m3t7mn1qu8",
  "login": "demo",
  "email": "demo@apistend.ru",
  "name": "Игорь Герасимов",
  "initials": "ИГ",
  "planLabel": "Бесплатный доступ",
  "createdAt": "2026-09-08T21:17:25.694Z",
  "sandboxCount": 1,
  "access": {
    "via": "key",
    "apiKeyId": "cmtt67iwi000753m3a3omagx3",
    "scopes": [],
    "defaultSandboxId": "cmtt67ivj000153m3oir9dc6f"
  }
}

Блок access отвечает на три вопроса, без которых скрипт не может начать работу: чем он аутентифицирован, какие области доступа ему выданы (пустой список — полный доступ) и какая песочница подставится там, где sandboxId не указан явно.

Серверный ключ выпускается на экране «Ключи и токены» либо самим Management API — POST /api/v1/keys с kind: "server".

Ключ песочницы сюда не пускают

Ключ stend_sbx_… — тот, которым код интеграции ходит в мок-шлюз. Он лежит в конфигах, в переменных CI и в коде, то есть утекает легче всего. Management API умеет удалять песочницы и выпускать ключи, поэтому принимает только серверный:

curl -s "$STEND/api/v1/account" -H "Authorization: Bearer stend_sbx_0123456789abcdef0123456789abcdef"
{
  "error": "SANDBOX_KEY_NOT_ALLOWED",
  "message": "Ключ песочницы (stend_sbx_…) в Management API не принимается: им ходит код интеграции, и утечь он может вместе с любым конфигом. Нужен серверный ключ stend_sk_… — создайте его на экране «Ключи и токены» или запросом POST /api/v1/keys с kind: \"server\""
}

Код ответа — 401. Отдельный код SANDBOX_KEY_NOT_ALLOWED нужен, чтобы клиент не считал это опечаткой в ключе: перепутанный вид ключа чинится другим действием, чем неверный ключ.

Серверный ключ — секрет уровня всего аккаунта

Ключ с полным доступом позволяет удалить аккаунт, песочницы и все данные, выпустить новые ключи и прочитать журнал запросов целиком. Ему место в секретах CI, а не в репозитории. Ограничить ключ помогают области доступа.

Второй способ — сессия кабинета: cookie apistend_session. Именно ей пользуется браузер, поэтому у сессии полный доступ к аккаунту — урезать её нечем, всё то же самое владелец делает мышкой на соседнем экране.

Из скрипта этот способ обычно не нужен, но он объясняет ряд различий в поведении:

Чем сессия отличается от ключа

ЧтоПо ключуПо сессии
access.viakeysession
Области доступате, что выданы ключувсегда полный доступ
Песочница по умолчаниюпесочница ключапервая созданная песочница аккаунта
Смена паролягасит все сессиигасит все, кроме своей
Удаление аккаунтаподтверждение почтойподтверждение почтой и паролем

Ошибки входа

Все отказы приходят в общем конверте { error, message }.

Ответы 401

errorКогда
UNAUTHORIZEDзаголовка нет, он не вида Bearer …, ключ не опознан, отозван или просрочен
SANDBOX_KEY_NOT_ALLOWEDприслан ключ песочницы stend_sbx_…

Причина «не существует», «отозван» и «просрочен» намеренно не различается в тексте: по разнице ответов перебор понимал бы, какой ключ существует.

Отозванный ключ перестаёт работать сразу, а не после истечения внутреннего кеша: отзыв, ротация и правка областей сбрасывают кеш разбора ключей.

Что дальше