API ТГИД: v1, v2 для внешних систем и вебхуки
У ТГИД три двери для программ. API v1 — адреса самого веба, описаны в /openapi.json. API v2 — стабильные адреса для ERP, CRM, 1С и шлюзов SCADA с ключом scope: api. Вебхуки — ТГИД сам отправляет события на адрес вашей системы и подписывает их по Standard Webhooks. Урок — о том, какую дверь выбрать, как устроены ключи и почему подпись проверяют именно так.
API ТГИД: v1, v2 для внешних систем и вебхуки
Кратко. У ТГИД три двери для программ. API v1 — адреса самого веба, описаны в
/openapi.json. API v2 — стабильные адреса для ERP, CRM, 1С и шлюзов SCADA с ключомscope: api. Вебхуки — ТГИД сам отправляет события на адрес вашей системы и подписывает их по Standard Webhooks. Урок — о том, какую дверь выбрать, как устроены ключи и почему подпись проверяют именно так.
Зачем это
Внешняя система должна узнавать о новых дефектах, нарядах и отключениях и создавать заявки, не ломаясь при каждом
выпуске веба и не открывая лишнего. Неверный выбор дорого обходится: интеграция на адресах v1 сломается
при обновлении, опрос без seq теряет события, приёмник без проверки подписи примет поддельный запрос.
Три двери
| API v1 | API v2 | Вебхуки | |
|---|---|---|---|
| Для кого | веб ТГИД | внешние системы | внешние системы |
| Кто начинает | клиент | клиент (опрос) | ТГИД (POST на ваш адрес) |
| Вход | токен входа, 8 ч | ключ scope: api, до 730 дн. |
секрет подписки whsec_… |
| Контракт | меняется с вебом | поля только добавляются | состав событий в GET /api/v2 |
| Описание | /openapi.json, /docs |
/api/v2/openapi.json |
страница инструкции |
Обычная связка: вебхук сообщает «случилось событие N», система дочитывает подробности через v2. Без вебхуков —
опрос ленты /api/v2/events раз в минуту.
Токены и назначение
Все токены — JWT, подписанные JWT_SECRET. Различаются назначением (scope) и сроком:
| Токен | Где берут | Срок по умолчанию | Где действует |
|---|---|---|---|
| вход | POST /api/v1/auth/login |
480 мин | везде: v1, v2, OGC, FeatureServer, /mcp |
api |
личный кабинет | 365 дн. | только /api/v2/… |
arcgis |
личный кабинет | 90 дн. | только FeatureServer |
mcp |
личный кабинет | 30 дн. | только /mcp |
Ключ с назначением на чужих адресах получает 401. Права у ключа — того, кто его выдал, и маскирование ПДн
тоже по его праву pii_view. Отозвать один ключ нельзя: на сервере нет их списка, а ключ несёт отпечаток
пароля. Рычаг отзыва — смена пароля или блокировка. Поэтому интеграции дают отдельного пользователя
с минимальными правами.
API v1: что важно клиенту
- У API нескольких городов город — префикс пути
/city/<код>/…; за nginx его подставляет путь города. - Постраничная выдача в v1 своя у каждого семейства адресов (
page/page_size,limit/offset, ссылкаnext). Слишком большойlimit— 422 с границей. - Долгие операции отвечают
{"task_id": …}; ход —GET /api/v1/task/{task_id}(PENDING→PROGRESS→SUCCESSилиFAILURE). - Ошибки —
{"detail": …}: строка, объект сcodeили список ошибок полей. Язык — поAccept-Language.
API v2: контракт
- Списки по возрастанию
id:limitдо 500, ответ{"data": [...], "next_after_id": N}; следующая страница —after_id=N,null— конец. Фильтрupdated_since— время ISO 8601 с поясом. - Лента событий — по номеру
seq:?after=<seq>→{data, next_after, has_more}. События хранятся 30 дней, поэтому последнийseqхраните у себя. - Заявка без дубля —
POST /api/v2/work-ordersсIdempotency-Key: повтор с тем же ключом вернёт тот же наряд (200,Idempotent-Replayed: true). Сеть может оборвать ответ, а не запрос — без ключа повтор создаст второй наряд. - Показания датчиков — пачкой до 10 000; неизвестные коды и время больше чем на сутки вперёд не пишутся, а перечисляются в ответе. Повтор того же времени заменяет значение — пачку можно безопасно отправить ещё раз.
Вебхуки: как устроена подпись
Каждое событие — POST с JSON без пробелов и заголовками webhook-id, webhook-timestamp, webhook-signature:
ключ = base64_decode(секрет без «whsec_»)
подпись = "v1," + base64( HMAC-SHA256(ключ, webhook-id + "." + webhook-timestamp + "." + тело) )
Почему правила проверки именно такие:
- тело как пришло, до разбора JSON — пересборка меняет байты, и подпись не сойдётся;
- время не старше 5 минут — иначе перехваченный запрос можно прислать повторно, и подпись будет верной;
- сравнение постоянного времени — обычное сравнение строк по времени ответа выдаёт, сколько первых символов совпало;
- несколько подписей через пробел — достаточно одной: так переживают смену секрета.
Доставка: ответ 2xx за 10 с. Иначе повторы через 1 мин, 5 мин, 30 мин, 2 ч, 5 ч, 10 ч, 10 ч (8 попыток, около
суток), перенаправления не выполняются. Подписка, не принимающая ничего 3 дня, выключается сама. Один id
может прийти дважды — получатель отбрасывает уже обработанные; порядок не гарантирован. Адрес — только
https:// и публичный; внутренние адреса и http:// — только если разрешено на сервере.

Как сделать в ТГИД
- Вход, OpenAPI, город в адресе, постраничная выдача — API v1 и OpenAPI.
- Ключ v2, адреса, примеры запросов — API v2 для внешних систем.
- Состав событий и готовый код проверки на Python и Node.js — Вебхуки: события и проверка подписи.
- Подписки, «Проверить», «Новый секрет» — окно Вебхуки.
- Формат ошибок и их язык — Устройство кода.
Задания
1. Какой ключ нужен
(а) 1С создаёт заявки на ремонт; (б) ГИС-отдел держит слой участков в QGIS постоянно; (в) инженер подключает Claude Desktop к данным сети; (г) портал акимата показывает карту сети посетителям.
Ответ
(а) Ключ API v2 (scope: api) отдельного пользователя с правом «Журналы». (б) Ключ ArcGIS для FeatureServer
(90 дней); OGC API тоже подходит, но с токеном входа на 8 часов. (в) Токен MCP (scope: mcp).
(г) Ключ встраивания tge_… от администратора — это не JWT, он открывает только встраиваемую карту
(урок 32).
2. Прочитайте ответ и найдите ошибку
CRM выгружает наряды так и получает ответ (данные вымышленные):
GET /api/v2/work-orders?after_id=0&limit=1000
→ 422 {"detail":[{"type":"less_than_equal","loc":["query","limit"],"msg":"…","ctx":{"le":500}}]}
После исправления CRM читает первую страницу и останавливается, решив, что нарядов 500. В чём ошибки?
Ответ
limit в v2 не больше 500 — граница указана в ctx.le. Дальше: страница — не весь список. Нужно повторять
запрос с after_id=<next_after_id>, пока next_after_id не станет null.
3. Проверьте подпись вебхука
Учебный секрет (вымышленный): whsec_Q09VUlNFLURFTU8tTk9ULUEtUkVBTC1TRUNSRVQtMDE=. Заголовки:
webhook-id: evt_demo_101, webhook-timestamp: 1794204000 (09.11.2026 06:00:00 UTC),
webhook-signature: v1,Stv+ivWJBlJZyApcTar+LthNrWCkahfXnE1Nlg/len4=. Тело:
{"id":"evt_demo_101","type":"defect.created","occurred_at":"2026-11-09T06:00:00Z","city":"demo","data":{"defect_id":502}}
Запрос пришёл в 06:12 UTC. Примет ли его функция verify из инструкции? Почему?
Ответ
Нет, по двум причинам. Первая: время. Запрос старше 5 минут (12 мин), verify отклонит его ещё до подсчёта
подписи. Вторая: тело. Подпись Stv+…len4= посчитана для тела с "defect_id":501; для пришедшего тела с 502
верная подпись — v1,stE6BSSA5/xtXpaNkk+OCU6gkk2jPeb26anillB+Acs=. Тело изменили по дороге, и приёмник должен
ответить отказом. Проверьте сами: функция verify со страницы
Вебхуки: события и проверка подписи с параметром tolerance_s побольше.
4. Два наряда вместо одного
Call-центр создаёт заявку POST /api/v2/work-orders. Ответ не пришёл за 30 с, CRM повторила запрос — в ТГИД
два одинаковых наряда. Как исправить на стороне CRM?
Ответ
Передавать Idempotency-Key, например номер обращения в CRM, и повторять с тем же ключом. ТГИД вернёт уже
созданный наряд (200, Idempotent-Replayed: true). Тот же ключ с другим названием заявки — 422: ключ должен
быть привязан к одному обращению.
