События

CLI apistend

Установка, вход, приём событий на localhost и отправка событий из терминала.

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

apistend — небольшой CLI: вход по серверному ключу, приём событий на локальное приложение и отправка событий вручную или серией. Ради него пакет и существует — всё остальное есть и в веб-интерфейсе.

Установка

npx apistend listen --forward localhost:3000/webhooks

Нужен Node.js 20.10 или новее. Скриптов postinstall в пакете нет.

Ключ и конфигурация

CLI авторизуется серверным ключом stend_sk_… — его создают в разделе «Ключи и токены». Ключ песочницы stend_sbx_… предназначен для запросов вашего кода к мок-шлюзу и для CLI не подойдёт:

✗ Это не серверный ключ
  Туннелю нужен ключ вида stend_sk_… — ключ песочницы (stend_sbx_…) им ходит код
  интеграции. Серверный ключ создаётся в разделе «Ключи и токены» или запросом
  POST /api/v1/keys с kind: "server"

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

Источники ключа проверяются в таком порядке: флаг --api-key, переменная APISTEND_API_KEY, сохранённая конфигурация. Конфигурация — обычный JSON в ~/.config/apistend/config.json с правами 0600; каталог можно перенести переменной APISTEND_CONFIG_HOME. Адрес API берётся из --api-base, переменной APISTEND_API_BASE, сохранённой конфигурации — а если не задан нигде, используется https://api.apistend.ru. Для стенда, поднятого у себя, укажите --api-base http://localhost:8080: адрес сохранится в конфигурацию при входе.

Команды

КомандаЧто делает
apistend login --api-key stend_sk_…проверяет ключ и сохраняет его вместе с адресом API
apistend logoutудаляет сохранённый ключ из конфигурации
apistend whoamiаккаунт, песочница, имя ключа и его маска
apistend statusподключён ли агент, куда пересылает, счётчики за час
apistend listenпринимает события и пересылает их в приложение
apistend trigger <событие>отправляет событие вручную или серией

Общие флаги, работающие у любой команды: --api-key <ключ>, --api-base <адрес>, --json. Версия — apistend --version (или -v); отдельной команды version нет.

login, whoami, logout

$ apistend login --api-key stend_sk_84f5…
> Вход выполнен: Интеграция 1С · песочница sandbox-01
> Конфигурация: /Users/you/.config/apistend/config.json

$ apistend whoami
> Аккаунт: Интеграция 1С
> Песочница: sandbox-01
> Ключ: CLI · локальная доставка stend_sk_84f5••••••7de2

login без ключа возьмёт его из APISTEND_API_KEY, а если нет и там — подскажет, где ключ создаётся. logout удаляет только ключ: идентификатор устройства и адрес API в конфигурации остаются.

С флагом --json whoami печатает тот же ответ сервера целиком:

{
  "account": "Интеграция 1С",
  "sandbox": "sandbox-01",
  "keyName": "CLI · локальная доставка",
  "connected": false,
  "agentVersion": null,
  "sessionId": null,
  "forwardUrl": null,
  "latencyMs": null,
  "eventsLastHour": 0,
  "failedDeliveries": 0
}

status

Состояние агента этой песочницы — не обязательно вашего:

$ apistend status
> Локальная доставка не подключена
> Запустите: apistend listen --forward localhost:3000/webhooks

listen

apistend listen --forward localhost:3000/webhooks

Флаги listen

ФлагПо умолчаниюЧто делает
-f, --forward <адрес>localhost:3000/webhooksбаза, к которой добавляется путь подписки; только loopback
-e, --events <список>всефильтр по кодам событий через запятую
--no-replay—влияет только на строку баннера, очередь досылается всё равно
--timeout <мс>таймаут сервисасвой таймаут ответа приложения; 0 отключает его
--concurrency <n>16максимум одновременных вызовов приложения

--timeout 0 полезен ровно в одном случае: когда обработчик стоит на брейкпоинте и отвечать будет через минуту.

Разбор вывода listen

  APIStend CLI 1.5.1
  Аккаунт: Интеграция 1С · песочница sandbox-01

> Готов! Сессия tnl-ef80 · пересылка на http://localhost:3000/webhooks
> Секрет подписи: stend_whsec_98c2fa3750d6e314 (для проверки X-APIStend-Signature)
> События: все · транспорт: websocket · Ctrl+C для выхода
> В очереди 2 события за время простоя, отправляю

2026-09-09 13:15:26   --> stocks_changed [cmtt67ixi000k53m30qwsrlth]
2026-09-09 13:15:26  <--  [200] POST http://localhost:3000/webhooks/wb/stocks  13 мс [cmtt67ixi000k53m30qwsrlth]
2026-09-09 13:15:29   --> ONCRMDEALUPDATE [evt_162c81ddfd68]
2026-09-09 13:15:29  <--  [200] POST http://localhost:3000/webhooks/bitrix/deal  5 мс [evt_162c81ddfd68]
  • tnl-ef80 — идентификатор сессии. Он привязан к устройству и не меняется при переподключении, так что в интерфейсе ничего не мигает.
  • Каждое событие занимает две строки: --> — что пришло с сервера, <-- — чем ответило приложение. В квадратных скобках один и тот же идентификатор доставки, по нему строка находится в журнале доставок.
  • Код ответа подсвечен: зелёный — ниже 300, жёлтый — 3xx и 4xx, красный — 5xx.
  • Строки могут идти не парами: при --concurrency больше единицы приложение обрабатывает несколько событий одновременно.

Про строку «Секрет подписи»

Секрет из этой строки — секрет сессии туннеля, и заголовка X-APIStend-Signature стенд не отправляет. Подпись есть только у Wildberries: заголовок X-Hub-Signature, HMAC-SHA256 от тела ключом самой подписки. Проверять нужно её — см. Вебхуки.

Ошибка вместо ответа печатается третьим видом строки:

2026-09-09 13:18:21  !!!  http://localhost:3000/webhooks/bitrix/deal — соединение отклонено (ECONNREFUSED) [evt_385593ef065b]

Так же выглядит превышение таймаута (превышен таймаут 30 с). При потере связи с APIStend агент переподключается сам, удваивая паузу от 0,5 с до 30 с. Каждая попытка начинается с запроса новой сессии: токен подключения одноразовый и живёт десять минут, поэтому повторить старый нельзя — а события, пришедшие за время обрыва, ждут в очереди и доставляются сразу после восстановления связи:

2026-09-09 13:20:02  ... связь с APIStend потеряна, переподключение (попытка 1)
2026-09-09 13:20:03  >>> переподключено · сессия tnl-ef80 · из очереди доставлено: 4

По Ctrl+C агент печатает итог сессии:

> Сессия tnl-ef80 закрыта · 899 событий · 1 ошибка доставки · медиана 1001 мс

Медиана считается по времени ответа вашего приложения — это его показатель, а не сети.

trigger

Без --count и --rate — одиночная отправка, то же самое, что кнопка «Тест» в строке вебхука:

$ apistend trigger ONCRMDEALUPDATE
> Событие ONCRMDEALUPDATE поставлено в очередь [evt_162c81ddfd68]
> Получатель: /bitrix/deal (local)

Событие ищется среди подписок песочницы. Если такой подписки нет, CLI покажет, какие есть:

✗ Нет вебхука на событие «NOPE_EVENT»
  Доступные события: feedback_updated, ONCRMLEADADD, ONCRMDEALUPDATE, stocks_changed, …

С --count или --rate та же команда запускает серию — про неё отдельная страница: Серии событий.

Что CLI не делает

  • Не создаёт и не удаляет вебхуки — только веб-интерфейс.
  • Не показывает журнал доставок и тела событий.
  • Не пересылает события на публичные адреса: --forward принимает только loopback.
  • Не хранит ключ в системной связке ключей — это осознанный отказ: заблокированная связка и GUI-запрос на CI дают больше проблем, чем файл с правами 0600.

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

  • --json не отменяет журнал listen. Он меняет формат строк ответа, но вместо баннера вы получите поток JSON-объектов — читать его глазами неудобно.
  • apistend <команда> --help печатает справку и завершается с кодом 1, дописывая «Неизвестная команда». Справка при этом верная; на код возврата в скриптах полагаться не стоит.
  • Ключ в --api-key попадает в историю оболочки. Для CI используйте APISTEND_API_KEY.