curl --request GET \
--url https://api.tungo.kz/v1/workspaces/{ws}/webhooks/event-types \
--cookie tungo.session_token=import requests
url = "https://api.tungo.kz/v1/workspaces/{ws}/webhooks/event-types"
headers = {"cookie": "tungo.session_token="}
response = requests.get(url, headers=headers)
print(response.text)const options = {method: 'GET', headers: {cookie: 'tungo.session_token='}};
fetch('https://api.tungo.kz/v1/workspaces/{ws}/webhooks/event-types', options)
.then(res => res.json())
.then(res => console.log(res))
.catch(err => console.error(err));{
"data": [
{
"name": "proposal.written",
"description": "<string>",
"schema": {},
"example": {
"id": "<string>",
"created_at": "2023-11-07T05:31:56Z",
"workspace_id": "<string>",
"company_id": "<string>",
"type": "<string>",
"data": {}
}
}
]
}{
"type": "error",
"error": {
"type": "payment_required_error",
"message": "Баланс доп. использования закончился — пополнить его или включить автопополнение могут владелец и админ workspace.",
"code": "balance_exhausted",
"permission": "proposals.approve",
"resets_at": "2026-11-01T19:00:00.000Z",
"retry_after_seconds": 42,
"next_request_at": "2026-11-12T09:30:42.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",
"retry_after_seconds": 42,
"next_request_at": "2026-11-12T09:30:42.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",
"retry_after_seconds": 42,
"next_request_at": "2026-11-12T09:30:42.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",
"retry_after_seconds": 42,
"next_request_at": "2026-11-12T09:30:42.000Z",
"allowed_methods": [
"email_otp"
],
"role": "<string>",
"permissions": [
"<string>"
],
"fields": [
{
"path": "bin",
"code": "invalid_format",
"message": "БИН/ИИН — 12 цифр"
}
]
},
"request_id": "req_4f9c2a7e1b3d4c5a8e6f7a9b0c1d2e3f"
}Какие события бывают
Тело каждого вебхука: { "id": "evt_…", "type": "<событие>", "created_at": "…", "workspace_id": "ws_…", "company_id": "co_…" | null, "data": {…} }. В data — только id, суммы в тиынах, статусы и время; без имён, ИИН/БИН, счетов и текста — подробности читайте через API по id. schema у каждого события — JSON Schema всего тела; те же схемы — в разделе webhooks этого описания.
Подпись: заголовки webhook-id, webhook-timestamp, webhook-signature — Standard Webhooks. Проверка: 1) подписанная строка — «webhook-id.webhook-timestamp.тело», тело — байты запроса как пришли, до разбора JSON; 2) ключ — часть секрета после whsec_, раскодированная из base64; 3) HMAC-SHA256 от строки этим ключом, в base64; 4) в webhook-signature одна или несколько подписей через пробел, каждая вида «v1,base64» (при смене секрета сутки приходят две) — должна совпасть хотя бы одна, сравнивать постоянным по времени сравнением; 5) webhook-timestamp — секунды Unix; расхождение с вашими часами больше 5 минут — отклонить. Готовая проверка: new Webhook(secret).verify(rawBody, headers) из npm standardwebhooks.
Доставка: POST JSON на адрес. Успех — любой ответ 2xx за 30 секунд. Иначе — повторы через 5 с, 5 мин, 30 мин, 2 ч, 5 ч, 10 ч, 10 ч, 10 ч, 10 ч, 10 ч, 10 ч, 5 ч: всего 13 попыток, окно 72 ч 35 мин 5 с от первой до последней. После этого событие можно отправить снова вручную (POST …/webhooks/messages//resend). Адрес, который не принимает ничего 5 суток подряд, отключается (enabled: false) — включите его PATCH …/endpoints/ после починки. Доставка «хотя бы раз»: одно событие может прийти дважды — отбрасывайте повторы по id (evt_…), он у повтора тот же. Порядок не гарантируется: события могут прийти не в той последовательности, в какой случились, — сверяйте created_at и читайте актуальное состояние через API. В месячное число бесплатных событий тарифа считаются только события, которые есть кому получить (включённый адрес с подходящим фильтром); сверх него события не отправляются (не копятся и потом не досылаются): сколько не ушло — over_limit в GET …/webhooks/usage.
proposal.awaiting_approval— Предложение (документ для 1С) готово и ждёт одобрения. blocked — есть блокеры, одобрить пока нельзя.proposal.written— Предложение записано в 1С (документ создан или дополнен). onec_document_number — номер документа в 1С.proposal.failed— Записать предложение в 1С не удалось. Причина — в карточке предложения (GET /v1/companies//proposals/).payment.succeeded— Оплата Tungo картой прошла (подписка, пополнение, подключение компании). Суммы — в тиынах.payment.failed— Оплата Tungo картой не прошла. Суммы — в тиынах.automation.run.completed— Запуск автоматизации закончился успешно. Итог для внешней системы: proposals — что подготовлено и записано в 1С (сумма, номер и дата документа), output — итог в форме сценария (output). Канал сообщения — id сценария (scn_…): адрес вебхука с channels получает только свои сценарии. Ход и ответ — в журнале запусков (GET /v1/companies//automations/runs).automation.run.failed— Запуск автоматизации закончился ошибкой (или его процесс замолчал). Его можно повторить. Сюда же — сбой опроса DirectBank (action: directbank): 1С недоступна, подключение не оплачено, сбой разбора. Каждая попытка — своё событие (attempt).esf.incoming.received— Входящие ЭСФ получены из ИС ЭСФ и разобраны пачкой (POST /v1/companies//batch/esf-purchases): сколько ЭСФ и сколько предложений поступления создано.bank_statement.received— Пришла банковская выписка: загружена файлом (source = upload, разбор идёт пачкой batch_id) или найдены новые документы опросом DirectBank (source = directbank).proposal.rejected— Предложение отклонено человеком — в 1С его не запишут. Кто и почему — в карточке предложения (GET /v1/companies//proposals/).batch.completed— Пачка разобрана до конца: банковская выписка (bank_statement) или входящие ЭСФ (esf_purchases). Счётчики — по строкам пачки; построчно — GET /v1/companies//batch/. stopped — пачку остановили, часть строк не взята (pending).batch.failed— Пачка (банковская выписка или входящие ЭСФ) оборвалась ошибкой и не дошла до конца. Что успели и текст ошибки — GET /v1/companies//batch/.automation.write_unknown— Автоодобрение по правилу сценария писало документ в 1С, а исход записи неизвестен: 1С не ответила или процесс прервался посреди записи (запуск закрыт как брошенный — и тогда, когда сценарий удалили). Сумма остаётся в дневных потолках, повтор запуска ищет документ по метке [AI P-…] и второго не создаст. Проверьте документ в 1С или нажмите «Записать» в карточке предложения.automation.run.notice— Шаг notify цепочки сценария: разработчику — что запуск дошёл до уведомления и почему (reason — условие шага: checks_found_issues — проверки нашли ошибки, previous_created_proposals — прошлый шаг подготовил предложения, previous_failed — прошлый шаг упал, always). Только номера и счётчики; подробности — GET /v1/companies//automations/runs/. Канал сообщения — id сценария (scn_…).chat.turn.completed— Ход чата по ключу API закончился, история записана. Только по факту хода, начатого ключом; ход из кабинета события не шлёт. Текста ответа и персональных данных в теле нет — ответ читайте по dialog_url. Ответ на вопрос ИИ (stop_reason был awaiting_user) — новое событие с тем же turn_no.platform.balance_low— Баланс платформы для разработчиков этим списанием опустился ниже порога (настройка платформы platform.billing). Пополнить — POST /v1/workspaces//platform/purchases.platform.balance_exhausted— Баланс платформы кончился этим списанием: следующие вызовы по ключам и автоматизации получат 402 platform_balance_exhausted.platform.cap_threshold_reached— Траты платформы за месяц дошли до порога месячного потолка (spend.alert_thresholds_pct, по умолчанию 80%). Один раз на порог за месяц.onec.connection.changed— Программа Tungo в офисе (связь с 1С компании) вышла на связь или пропала. reason — почему пропала: device_revoked (устройство отозвали), replaced (подключилась другая копия или привязано другое устройство), key_rotated (сменён ключ — программа сразу переподключится), access_lost (компания отключена, организация заблокирована), no_heartbeat (не отвечала на проверку связи), connection_lost (связь оборвалась: компьютер выключен, сеть), handshake_failed, server_unavailable, server_shutdown (сервер Tungo перезапускается — программа переподключится сама). Пока программы нет на связи, запись в 1С не идёт.api_key.expiring— Срок ключа API скоро кончится: за 14 и за 3 дня (настройка платформы api_keys.expiry_reminder_days), по одному разу на порог. Продлить — PATCH ключа с expires_at или смена секрета (roll). Автору ключа уходит и письмо.api_key.cap_reached— Ключ API упёрся в свой месячный потолок расхода ИИ: вызовы ИИ по нему отклоняются (402 key_cap_reached) до 1-го числа следующего месяца или пока потолок не поднимут (PATCH ключа). Раз в месяц на ключ.
Доступ: Владелец или админ workspace; ключ API — с правом webhooks.manage.
Доступно по ключу API.
curl --request GET \
--url https://api.tungo.kz/v1/workspaces/{ws}/webhooks/event-types \
--cookie tungo.session_token=import requests
url = "https://api.tungo.kz/v1/workspaces/{ws}/webhooks/event-types"
headers = {"cookie": "tungo.session_token="}
response = requests.get(url, headers=headers)
print(response.text)const options = {method: 'GET', headers: {cookie: 'tungo.session_token='}};
fetch('https://api.tungo.kz/v1/workspaces/{ws}/webhooks/event-types', options)
.then(res => res.json())
.then(res => console.log(res))
.catch(err => console.error(err));{
"data": [
{
"name": "proposal.written",
"description": "<string>",
"schema": {},
"example": {
"id": "<string>",
"created_at": "2023-11-07T05:31:56Z",
"workspace_id": "<string>",
"company_id": "<string>",
"type": "<string>",
"data": {}
}
}
]
}{
"type": "error",
"error": {
"type": "payment_required_error",
"message": "Баланс доп. использования закончился — пополнить его или включить автопополнение могут владелец и админ workspace.",
"code": "balance_exhausted",
"permission": "proposals.approve",
"resets_at": "2026-11-01T19:00:00.000Z",
"retry_after_seconds": 42,
"next_request_at": "2026-11-12T09:30:42.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",
"retry_after_seconds": 42,
"next_request_at": "2026-11-12T09:30:42.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",
"retry_after_seconds": 42,
"next_request_at": "2026-11-12T09:30:42.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",
"retry_after_seconds": 42,
"next_request_at": "2026-11-12T09:30:42.000Z",
"allowed_methods": [
"email_otp"
],
"role": "<string>",
"permissions": [
"<string>"
],
"fields": [
{
"path": "bin",
"code": "invalid_format",
"message": "БИН/ИИН — 12 цифр"
}
]
},
"request_id": "req_4f9c2a7e1b3d4c5a8e6f7a9b0c1d2e3f"
}Авторизации
Сессия кабинета: cookie ставит вход через /v1/auth/* (Better Auth), браузер шлёт её сам — фронтенду кабинета ничего добавлять не нужно (fetch с credentials: 'include'). За HTTPS имя cookie — __Secure-tungo.session_token. Сессия кончилась — 401 authentication_error: отправить на вход.