API управления

Рецепты

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

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

Четыре задачи, ради которых Management API обычно и берут. Скрипты не псевдокод — они выполнены на стенде целиком.

Во всех примерах:

export STEND=http://localhost:8080
export STEND_KEY=stend_sk_…   # серверный ключ

Окружение под CI одним скриптом

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

#!/usr/bin/env bash
set -euo pipefail

API="$STEND/api/v1"
NAME="ci-${GITHUB_RUN_ID:-local}"

api() {
  local method=$1 path=$2
  shift 2
  curl -sS -X "$method" "$API$path" \
    -H "Authorization: Bearer $STEND_KEY" \
    -H 'Content-Type: application/json' "$@"
}

# Песочница под прогон: без задержки и без случайных ошибок,
# иначе тесты падают на ровном месте.
SANDBOX=$(api POST /sandboxes \
  -d "{\"name\":\"$NAME\",\"project\":\"CI\",\"dataVolume\":\"min\",\"latencyMs\":0,\"errorRate\":0}")
SANDBOX_ID=$(printf '%s' "$SANDBOX" | node -pe 'JSON.parse(require("fs").readFileSync(0,"utf8")).id')

# Ключ песочницы — им ходит код интеграции.
KEY=$(api POST "/keys?sandboxId=$SANDBOX_ID" \
  -d '{"name":"CI","services":["bitrix24","ozon","wildberries"]}')

echo "APISTEND_SANDBOX_ID=$SANDBOX_ID"
printf '%s' "$KEY" | node -pe '"APISTEND_KEY=" + JSON.parse(require("fs").readFileSync(0,"utf8")).secret'
APISTEND_SANDBOX_ID=cmttys5y5000ntqm3y097rtwh
APISTEND_KEY=stend_sbx_950e2eba9ca74a46f41b18545e276260

Полученный ключ сразу работает на шлюзе:

curl -s -o /dev/null -w '%{http_code}\n' -X POST "$STEND/oz/v3/posting/fbs/list" \
  -H 'Client-Id: 1' -H "Api-Key: $APISTEND_KEY" \
  -H 'Content-Type: application/json' -d '{"limit":1}'
# 200

Уборка после прогона — одним запросом, вместе с ключом:

curl -sS -X DELETE "$STEND/api/v1/sandboxes/$APISTEND_SANDBOX_ID" \
  -H "Authorization: Bearer $STEND_KEY" -H 'Content-Type: application/json' \
  -d "{\"confirmName\":\"$NAME\"}"
{
  "ok": true,
  "id": "cmttys5y5000ntqm3y097rtwh",
  "name": "ci-local",
  "removed": { "keys": 1, "webhooks": 0, "mocks": 0, "scenarios": 0, "bursts": 0, "requestLogs": 0, "b24Apps": 0, "overlay": 0 }
}

Держите серверный ключ CI не в той песочнице, которую сносите

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

Ключ подрядчику с ограниченными правами

Подрядчику, который разбирает падения, нужен журнал — и больше ничего.

curl -sS -X POST "$STEND/api/v1/keys" \
  -H "Authorization: Bearer $STEND_KEY" -H 'Content-Type: application/json' \
  -d '{
    "name": "Подрядчик: только логи",
    "kind": "server",
    "services": ["bitrix24"],
    "scopes": ["logs:read", "sandboxes:read"]
  }'
{
  "id": "cmtty1zn80000tqm3zy5prwmf",
  "kind": "server",
  "mask": "stend_sk_13ee••••••51d8",
  "scopes": ["logs:read", "sandboxes:read"],
  "fullAccess": false,
  "secret": "stend_sk_13eedc3bfddbce93949c2dd70c8551d8",
  "warning": "Сохраните ключ: полностью он показывается только сейчас"
}

Проверьте границы сразу, не дожидаясь вопросов:

curl -s "$STEND/api/v1/logs?limit=1" -H "Authorization: Bearer $CONTRACTOR_KEY" | head -c 80
# {"items":[{"id":"cmtty1cj7003o7am3ecx44grz","publicId":"req_5b2248c388", …

curl -s "$STEND/api/v1/keys" -H "Authorization: Bearer $CONTRACTOR_KEY"
{
  "error": "FORBIDDEN",
  "message": "Ключу не выдана область доступа «keys:read» (список ключей). Выданы: logs:read, sandboxes:read"
}

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

curl -sS -X DELETE "$STEND/api/v1/keys/$CONTRACTOR_KEY_ID" \
  -H "Authorization: Bearer $STEND_KEY" -H 'Content-Type: application/json' \
  -d '{"confirmName":"Подрядчик: только логи"}'

Отзыв (POST /keys/{id}/revoke) вместо удаления оставит запись в списке и связь с записями журнала — так видно, кто и когда ключом ходил.

Пересоздать песочницу перед прогоном

Два способа, и они разные.

Быстро и без потерь: удаляет только личные изменения поверх демо-данных и переставляет lastResetAt. Ключи, вебхуки, моки, сценарии и журнал остаются на месте.

curl -sS -X POST "$STEND/api/v1/sandboxes/$SANDBOX_ID/reset" \
  -H "Authorization: Bearer $STEND_KEY"
{
  "sandboxId": "cmtty4eoh0006tqm356k1tp23",
  "removed": 0,
  "lastResetAt": "2026-09-09T10:18:49.795Z"
}

Порядок именно такой: имя песочницы уникально в пределах аккаунта, и создать одноимённую до удаления старой нельзя — придёт 409. Удалить последнюю песочницу аккаунта тоже нельзя — 422; в этом случае создайте новую, перенесите работу и удалите старую.

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

curl -sS -X POST "$STEND/api/v1/logs/clear" \
  -H "Authorization: Bearer $STEND_KEY" -H 'Content-Type: application/json' \
  -d '{"confirm":true}'

Выгрузить журнал за период

Выгрузка отдаёт до limit записей за раз и честно сообщает, что упёрлась в потолок.

curl -sS "$STEND/api/v1/logs/export?from=2026-09-01T00:00:00%2B03:00&to=2026-09-08T00:00:00%2B03:00&limit=10000" \
  -H "Authorization: Bearer $STEND_KEY" -o logs.json
{
  "format": "json",
  "generatedAt": "2026-09-09T10:18:03.489Z",
  "count": 2,
  "truncated": true,
  "rows": ["…"]
}

truncated: true означает, что записей больше, чем вошло. Забирайте период по кускам — по суткам или по часам:

for day in 01 02 03 04 05 06 07; do
  curl -sS "$STEND/api/v1/logs/export?from=2026-09-${day}T00:00:00Z&to=2026-09-${day}T23:59:59Z&format=csv" \
    -H "Authorization: Bearer $STEND_KEY" -o "logs-2026-09-$day.csv"
  sleep 10
done

Шесть выгрузок в минуту

У logs/export своё ограничение частоты, не связанное с общей нормой. Без паузы цикл упрётся в 429 на седьмом шаге:

{
  "error": "RATE_LIMITED",
  "message": "Выгрузок журнала не больше 6 в минуту. Повторите через 10 с или сузьте период полями from и to"
}

Формат csv отдаётся с BOM и разделителем «;» — файл открывается в Excel с русской локалью без плясок. Заголовок первой строки:

Время;Сервис;Метод;Эндпоинт;Код;Задержка, мс;Размер, байт;Сценарий;Ключ;ID запроса

Если нужны тела запросов и ответов, выгрузка их не отдаёт: они доступны только поштучно в GET /logs/{id}.