API управления

Ключи

Выпуск ключей песочницы и серверных ключей, области доступа, ротация, отзыв и удаление — и чем отзыв отличается от удаления.

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

Ключи живут внутри песочницы. Видов два: sandbox (stend_sbx_…) — им код интеграции ходит в мок-шлюз, и server (stend_sk_…) — им работают CLI и Management API.

GET /keys

Область: keys:read. Ключи одной песочницы, свежие сверху.

curl -s "$STEND/api/v1/keys?limit=1&kind=server" -H "Authorization: Bearer $STEND_KEY"
{
  "items": [
    {
      "id": "cmtty1zn80000tqm3zy5prwmf",
      "name": "Подрядчик: только логи",
      "subtitle": null,
      "kind": "server",
      "mask": "stend_sk_13ee••••••51d8",
      "services": ["bitrix24", "ozon", "wildberries", "apify"],
      "scopes": ["logs:read", "sandboxes:read"],
      "fullAccess": false,
      "status": "active",
      "rotationDays": 90,
      "requestsPerDay": 0,
      "isCurrent": false,
      "createdAt": "2026-09-09T10:16:56.756Z",
      "lastUsedAt": null,
      "expiresAt": null,
      "revokedAt": null,
      "revokedBy": null
    }
  ],
  "nextCursor": "cmtty1zn80000tqm3zy5prwmf"
}

Фильтры: status (active / expiring / revoked), kind (sandbox / server), плюс общие limit и cursor.

Секрет не отдаётся никогда — только маска: в базе лежит хеш. fullAccess — готовый признак «серверный ключ без ограничений». Ключ со статусом expiring продолжает работать; не работает только revoked.

requestsPerDay считает и вызовы Management API

Счётчик пишется через буфер, а не отдельным UPDATE на каждый вызов, и в него попадают в том числе обращения к /api/v1/*. Это честно: ключ действительно работал.

POST /keys

Область: keys:write. Ответ — 201, и secret приходит ровно в нём.

Тело запроса

ПолеОбязательноеЗначение
nameда2–80 символов
servicesнетпринимается ради совместимости и игнорируется: ключ открывает все сервисы
subtitleнетдо 120 символов
kindнетsandbox (по умолчанию) или server
rotationDaysнет1–365, по умолчанию 90
scopesнеттолько для kind=server; пустой список — полный доступ
curl -s -X POST "$STEND/api/v1/keys" \
  -H "Authorization: Bearer $STEND_KEY" -H 'Content-Type: application/json' \
  -d '{"name":"Подрядчик: только логи","kind":"server","scopes":["logs:read","sandboxes:read"]}'
{
  "id": "cmtty1zn80000tqm3zy5prwmf",
  "name": "Подрядчик: только логи",
  "kind": "server",
  "mask": "stend_sk_13ee••••••51d8",
  "services": ["bitrix24", "ozon", "wildberries", "apify"],
  "scopes": ["logs:read", "sandboxes:read"],
  "fullAccess": false,
  "status": "active",
  "rotationDays": 90,
  "secret": "stend_sk_13eedc3bfddbce93949c2dd70c8551d8",
  "warning": "Сохраните ключ: полностью он показывается только сейчас"
}

rotationDays — срок напоминания о замене, а не срок жизни: сам по себе ключ не протухает. Ключ создаётся в текущей песочнице; для другой укажите ?sandboxId=.

Ограничения на scopes описаны в разделе Области доступа: выдать больше, чем есть у вызывающего, нельзя, а ключу песочницы области не назначаются вовсе (422).

GET и PATCH /keys/{id}

GET (область keys:read) отдаёт тот же объект, что и список. Ключ ищется только в текущей песочнице: ключ из соседней даёт 404, пока не указан её ?sandboxId=.

PATCH (область keys:write) меняет name, subtitle, rotationDays и scopes. Поле services принимается, но не применяется. Секрет остаётся прежним. Пустое тело отвергается:

{ "error": "VALIDATION", "message": "Не указано ни одного поля для изменения" }

POST /keys/{id}/revoke

Область: keys:write. Подтверждение — точное название ключа в confirmName.

Ключ перестаёт работать сразу и навсегда: обратной операции нет, статус active уже не вернуть. Запись остаётся — она видна в списке со статусом revoked, датой и именем отозвавшего, а записи журнала запросов сохраняют ссылку на неё.

Ответ — { id, name, status, revokedAt, revokedBy, self, message }. Отозвать ключ, которым сделан вызов, можно: в ответе это помечено self: true, и следующий запрос с ним получит 401.

POST /keys/{id}/rotate

Область: keys:write. Ответ — 201 с новым secret.

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

Новый ключ наследует название, подпись, вид, сервисы, срок ротации и области доступа, но получает свой идентификатор; старая запись остаётся в списке со статусом revoked и пометкой «ротация». В ответе рядом с обычными полями — replaced с идентификатором, маской и временем отзыва прежнего ключа:

{
  "id": "cmttyhq0z000jtqm3cg2lrxe9",
  "mask": "stend_sk_ee56••••••5a72",
  "secret": "stend_sk_ee56615ed19983ed8194d2a6a77d5a72",
  "replaced": {
    "id": "cmttyhpxh000itqm3asicdcyf",
    "mask": "stend_sk_4561••••••3978",
    "revokedAt": "2026-09-09T10:29:10.785Z"
  },
  "self": false,
  "warning": "Сохраните secret: полностью ключ показывается только сейчас. Старый секрет уже не работает"
}

Отозванный ключ не прокручивается — 409:

{
  "error": "CONFLICT",
  "message": "Ключ отозван 2026-09-09T10:29:10.785Z и прокрутке не подлежит. Выпустите новый через POST /api/v1/keys"
}

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

DELETE /keys/{id}

Область: keys:write. Подтверждение — confirmName.

curl -s -X DELETE "$STEND/api/v1/keys/$KEY_ID" \
  -H "Authorization: Bearer $STEND_KEY" -H 'Content-Type: application/json' \
  -d '{"confirmName":"Подрядчик: только логи"}'
{
  "id": "cmtty1zn80000tqm3zy5prwmf",
  "name": "Подрядчик: только логи",
  "ok": true,
  "logsDetached": 0,
  "tunnelSessionsRemoved": 0,
  "self": false,
  "message": "Ключ удалён вместе с записью. Восстановить его нельзя, для этого пришлось бы знать секрет"
}

Отзыв или удаление

revokedelete
Ключ перестаёт работатьдада
Запись остаётся в спискеда, со статусом revokedнет
Связь записей журнала с ключомсохраняетсяобнуляется (logsDetached)
Сессии туннеля этого ключаостаютсяудаляются каскадом

Удаляйте, когда мешает мусор; отзывайте, когда важен след.

Подводные камни

  • Секрет показывается один раз — при создании и при ротации. Забытый ключ заменяется ротацией, а не восстановлением.
  • services ключа песочницы больше ничего не ограничивают: ключ открывает все сервисы стенда. Поле осталось в ответах, чтобы не ломать клиентов, и всегда содержит полный набор. Области доступа (scopes) — другое: они про Management API и работают как прежде.
  • Отзыв, ротация и правка областей действуют мгновенно: кеш разбора ключей сбрасывается сразу, а не через полминуты.