curl --request POST \
--url https://api.tungo.kz/hooks/{token} \
--header 'Content-Type: */*' \
--data '<unknown>'import requests
url = "https://api.tungo.kz/hooks/{token}"
payload = "<unknown>"
headers = {"Content-Type": "*/*"}
response = requests.post(url, data=payload, headers=headers)
print(response.text)const options = {method: 'POST', headers: {'Content-Type': '*/*'}, body: '<unknown>'};
fetch('https://api.tungo.kz/hooks/{token}', options)
.then(res => res.json())
.then(res => console.log(res))
.catch(err => console.error(err));{
"accepted": true,
"event_id": "hev_01jz8x3m4n5p6q7r8s9t0v1w2x",
"duplicate": true,
"run_ids": [
"run_01jz8x3m4n5p6q7r8s9t0v1w2x"
]
}{
"accepted": true,
"event_id": "hev_01jz8x3m4n5p6q7r8s9t0v1w2x",
"duplicate": true,
"run_ids": [
"run_01jz8x3m4n5p6q7r8s9t0v1w2x"
]
}{
"type": "error",
"error": {
"type": "payment_required_error",
"message": "Баланс доп. использования закончился — пополнить его или включить автопополнение могут владелец и админ workspace.",
"code": "balance_exhausted",
"permission": "proposals.approve",
"resets_at": "2026-11-01T19:00:00.000Z",
"allowed_methods": [
"email_otp"
],
"role": "<string>",
"permissions": [
"<string>"
],
"fields": [
{
"path": "bin",
"code": "invalid_format",
"message": "БИН/ИИН — 12 цифр"
}
]
},
"request_id": "req_4f9c2a7e1b3d4c5a8e6f7a9b0c1d2e3f"
}{
"type": "error",
"error": {
"type": "payment_required_error",
"message": "Баланс доп. использования закончился — пополнить его или включить автопополнение могут владелец и админ workspace.",
"code": "balance_exhausted",
"permission": "proposals.approve",
"resets_at": "2026-11-01T19:00:00.000Z",
"allowed_methods": [
"email_otp"
],
"role": "<string>",
"permissions": [
"<string>"
],
"fields": [
{
"path": "bin",
"code": "invalid_format",
"message": "БИН/ИИН — 12 цифр"
}
]
},
"request_id": "req_4f9c2a7e1b3d4c5a8e6f7a9b0c1d2e3f"
}{
"type": "error",
"error": {
"type": "payment_required_error",
"message": "Баланс доп. использования закончился — пополнить его или включить автопополнение могут владелец и админ workspace.",
"code": "balance_exhausted",
"permission": "proposals.approve",
"resets_at": "2026-11-01T19:00:00.000Z",
"allowed_methods": [
"email_otp"
],
"role": "<string>",
"permissions": [
"<string>"
],
"fields": [
{
"path": "bin",
"code": "invalid_format",
"message": "БИН/ИИН — 12 цифр"
}
]
},
"request_id": "req_4f9c2a7e1b3d4c5a8e6f7a9b0c1d2e3f"
}{
"type": "error",
"error": {
"type": "payment_required_error",
"message": "Баланс доп. использования закончился — пополнить его или включить автопополнение могут владелец и админ workspace.",
"code": "balance_exhausted",
"permission": "proposals.approve",
"resets_at": "2026-11-01T19:00:00.000Z",
"allowed_methods": [
"email_otp"
],
"role": "<string>",
"permissions": [
"<string>"
],
"fields": [
{
"path": "bin",
"code": "invalid_format",
"message": "БИН/ИИН — 12 цифр"
}
]
},
"request_id": "req_4f9c2a7e1b3d4c5a8e6f7a9b0c1d2e3f"
}{
"type": "error",
"error": {
"type": "payment_required_error",
"message": "Баланс доп. использования закончился — пополнить его или включить автопополнение могут владелец и админ workspace.",
"code": "balance_exhausted",
"permission": "proposals.approve",
"resets_at": "2026-11-01T19:00:00.000Z",
"allowed_methods": [
"email_otp"
],
"role": "<string>",
"permissions": [
"<string>"
],
"fields": [
{
"path": "bin",
"code": "invalid_format",
"message": "БИН/ИИН — 12 цифр"
}
]
},
"request_id": "req_4f9c2a7e1b3d4c5a8e6f7a9b0c1d2e3f"
}Принять событие по адресу хука
Сюда шлёт события сторонний сервис. Адрес целиком (url) выдаётся при заведении хука и при rotate; токен (th_…, 46 знаков) — и есть доступ: ключ API и сессия не нужны и не принимаются. Токен даёт только приём событий одной компании, ничего не читает.
Тело — любое до предела настройки automations (hook_body_max_bytes, по умолчанию 256 КБ): JSON разбирается и доступен фильтру сценария; не-JSON и двоичное тело тоже принимаются и хранятся как есть.
Подпись: если у хука задан секрет, заголовок (имя — signature_header хука, по умолчанию X-Signature) обязан быть HMAC-SHA256(секрет, сырое тело) в hex, можно с приставкой sha256=. Нет или не сходится — 401.
Повторы: id события берётся по порядку из поля тела по id_path хука (если задан и поле есть — заголовки тогда не важны: повтор с новым Idempotency-Key остаётся тем же событием), заголовка Idempotency-Key, X-Event-Id, иначе — sha256 тела. Тот же id второй раз — 200 и duplicate: true, сценарии не запускаются повторно. Номер операции хук помнит всегда, и после того как тело события стёрто по сроку хранения (automations.limits, retention_days): не используйте один номер для разных операций — вторая будет повтором. Новое событие — 202: сценарии с триггером этого хука запустятся в фоне.
Без id_path то же тело в окне настройки automations.queue (hook_dedupe_minutes, по умолчанию сутки) тоже считается повтором — даже с новым Idempotency-Key.
Неизвестный, выключенный и удалённый хук отвечают одинаково — 404: по ответу не узнать, был ли такой токен. Частота — не больше hook_events_per_minute событий в минуту на хук (по умолчанию 120), сверх — 429; у компании в очереди больше queued_runs_per_company запусков (настройка automations.queue, по умолчанию 50) — тоже 429 с error.code = automation_queue_full; секрет подписи сейчас не открыть — 503, отправителю повторить позже.
Автоматизации компании на паузе (PUT …/automations/state) — событие принимается как обычно, запуски ждут в очереди до снятия паузы.
Пример: curl -X POST <адрес API>/hooks/th_… -H "Content-Type: application/json" -H "X-Signature: sha256=<hex>" -d '{"id":"evt_1","amount":150000}' → 202 {"accepted":true,"event_id":"hev_…","duplicate":false,"run_ids":["run_…"]}.
Без входа: доступ — токен в адресе. Ключ API и сессия не нужны.
curl --request POST \
--url https://api.tungo.kz/hooks/{token} \
--header 'Content-Type: */*' \
--data '<unknown>'import requests
url = "https://api.tungo.kz/hooks/{token}"
payload = "<unknown>"
headers = {"Content-Type": "*/*"}
response = requests.post(url, data=payload, headers=headers)
print(response.text)const options = {method: 'POST', headers: {'Content-Type': '*/*'}, body: '<unknown>'};
fetch('https://api.tungo.kz/hooks/{token}', options)
.then(res => res.json())
.then(res => console.log(res))
.catch(err => console.error(err));{
"accepted": true,
"event_id": "hev_01jz8x3m4n5p6q7r8s9t0v1w2x",
"duplicate": true,
"run_ids": [
"run_01jz8x3m4n5p6q7r8s9t0v1w2x"
]
}{
"accepted": true,
"event_id": "hev_01jz8x3m4n5p6q7r8s9t0v1w2x",
"duplicate": true,
"run_ids": [
"run_01jz8x3m4n5p6q7r8s9t0v1w2x"
]
}{
"type": "error",
"error": {
"type": "payment_required_error",
"message": "Баланс доп. использования закончился — пополнить его или включить автопополнение могут владелец и админ workspace.",
"code": "balance_exhausted",
"permission": "proposals.approve",
"resets_at": "2026-11-01T19:00:00.000Z",
"allowed_methods": [
"email_otp"
],
"role": "<string>",
"permissions": [
"<string>"
],
"fields": [
{
"path": "bin",
"code": "invalid_format",
"message": "БИН/ИИН — 12 цифр"
}
]
},
"request_id": "req_4f9c2a7e1b3d4c5a8e6f7a9b0c1d2e3f"
}{
"type": "error",
"error": {
"type": "payment_required_error",
"message": "Баланс доп. использования закончился — пополнить его или включить автопополнение могут владелец и админ workspace.",
"code": "balance_exhausted",
"permission": "proposals.approve",
"resets_at": "2026-11-01T19:00:00.000Z",
"allowed_methods": [
"email_otp"
],
"role": "<string>",
"permissions": [
"<string>"
],
"fields": [
{
"path": "bin",
"code": "invalid_format",
"message": "БИН/ИИН — 12 цифр"
}
]
},
"request_id": "req_4f9c2a7e1b3d4c5a8e6f7a9b0c1d2e3f"
}{
"type": "error",
"error": {
"type": "payment_required_error",
"message": "Баланс доп. использования закончился — пополнить его или включить автопополнение могут владелец и админ workspace.",
"code": "balance_exhausted",
"permission": "proposals.approve",
"resets_at": "2026-11-01T19:00:00.000Z",
"allowed_methods": [
"email_otp"
],
"role": "<string>",
"permissions": [
"<string>"
],
"fields": [
{
"path": "bin",
"code": "invalid_format",
"message": "БИН/ИИН — 12 цифр"
}
]
},
"request_id": "req_4f9c2a7e1b3d4c5a8e6f7a9b0c1d2e3f"
}{
"type": "error",
"error": {
"type": "payment_required_error",
"message": "Баланс доп. использования закончился — пополнить его или включить автопополнение могут владелец и админ workspace.",
"code": "balance_exhausted",
"permission": "proposals.approve",
"resets_at": "2026-11-01T19:00:00.000Z",
"allowed_methods": [
"email_otp"
],
"role": "<string>",
"permissions": [
"<string>"
],
"fields": [
{
"path": "bin",
"code": "invalid_format",
"message": "БИН/ИИН — 12 цифр"
}
]
},
"request_id": "req_4f9c2a7e1b3d4c5a8e6f7a9b0c1d2e3f"
}{
"type": "error",
"error": {
"type": "payment_required_error",
"message": "Баланс доп. использования закончился — пополнить его или включить автопополнение могут владелец и админ workspace.",
"code": "balance_exhausted",
"permission": "proposals.approve",
"resets_at": "2026-11-01T19:00:00.000Z",
"allowed_methods": [
"email_otp"
],
"role": "<string>",
"permissions": [
"<string>"
],
"fields": [
{
"path": "bin",
"code": "invalid_format",
"message": "БИН/ИИН — 12 цифр"
}
]
},
"request_id": "req_4f9c2a7e1b3d4c5a8e6f7a9b0c1d2e3f"
}Заголовки
Подпись тела, если у хука есть секрет: HMAC-SHA256(секрет, сырое тело) в hex, можно с приставкой sha256= (имя заголовка — signature_header хука)
id события отправителя: повтор с тем же id не запускает сценарии второй раз (если у хука задан id_path и поле есть в теле — главнее оно)
То же, что Idempotency-Key, если отправитель шлёт такой заголовок
Параметры пути
Токен хука (th_…) из адреса, выданного при заведении или rotate
"th_AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA"
Тело
Тело события как есть (обычно JSON)
Тело события как есть (обычно JSON)
Ответ
Повтор уже принятого события (duplicate: true), ничего не запущено
Ответ приёма события.
Всегда true — событие принято
true id события у нас: по нему запуски находятся в журнале — GET …/automations/runs?event_id= (hev_…)
"hev_01jz8x3m4n5p6q7r8s9t0v1w2x"
true — это событие уже принято раньше (тот же id отправителя), второй раз сценарии не запускаются
Запуски, поставленные этим событием (в очереди, ещё не выполнены): статус — GET …/automations/runs/{id}, итог — вебхуки automation.run.completed / automation.run.failed с тем же run_id. У повтора — те же запуски, что поставил первый приём. Пусто — ни один включённый сценарий не слушает этот хук
id запуска (run_…)