curl --request POST \
--url https://api.tungo.kz/v1/workspaces/{ws}/webhooks/endpoints \
--header 'Content-Type: application/json' \
--cookie tungo.session_token= \
--data '
{
"url": "https://example.com/tungo/webhooks",
"description": "Учётная система",
"event_types": [
"proposal.written",
"payment.succeeded"
],
"channels": [
"scn_01jz8x3m4n5p6q7r8s9t0v1w2x"
],
"enabled": true
}
'import requests
url = "https://api.tungo.kz/v1/workspaces/{ws}/webhooks/endpoints"
payload = {
"url": "https://example.com/tungo/webhooks",
"description": "Учётная система",
"event_types": ["proposal.written", "payment.succeeded"],
"channels": ["scn_01jz8x3m4n5p6q7r8s9t0v1w2x"],
"enabled": True
}
headers = {
"cookie": "tungo.session_token=",
"Content-Type": "application/json"
}
response = requests.post(url, json=payload, headers=headers)
print(response.text)const options = {
method: 'POST',
headers: {cookie: 'tungo.session_token=', 'Content-Type': 'application/json'},
body: JSON.stringify({
url: 'https://example.com/tungo/webhooks',
description: 'Учётная система',
event_types: ['proposal.written', 'payment.succeeded'],
channels: ['scn_01jz8x3m4n5p6q7r8s9t0v1w2x'],
enabled: true
})
};
fetch('https://api.tungo.kz/v1/workspaces/{ws}/webhooks/endpoints', options)
.then(res => res.json())
.then(res => console.log(res))
.catch(err => console.error(err));{
"id": "ep_2xyzExample",
"url": "https://example.com/tungo/webhooks",
"description": "<string>",
"event_types": [
"<string>"
],
"channels": [
"<string>"
],
"enabled": true,
"created_at": "2026-10-05T09:30:00.000Z",
"updated_at": "2026-10-05T09:30:00.000Z",
"secret": "whsec_…",
"secret_note": "<string>"
}{
"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"
}{
"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"
}Завести адрес
Адрес — только https и не во внутренней сети (localhost, 10.x, 192.168.x, 169.254.x… — и по DNS тоже); сервер доставки ещё раз проверяет это при каждой отправке. event_types — фильтр событий (null или нет — все). channels — id сценариев (scn_…): только их события, например итог сценария в CRM магазина. Сколько адресов можно — настройка платформы webhooks.max_endpoints_per_workspace (сверх — 429, code webhook_endpoints_limit). Одновременные заведения в одной организации идут по очереди; если другой адрес заводится дольше нескольких секунд — 503 (code webhooks_unavailable), повторить позже. Секрет подписи — в ответе.
Idempotency-Key: повтор с тем же ключом и тем же телом отдаёт прежний ответ (статус и тело) с заголовком Idempotent-Replayed: true и ничего не делает второй раз; тот же ключ с другим адресом или телом — 422 (error.code = idempotency_key_reused); первый запрос с этим ключом ещё идёт — 409 (error.code = idempotency_in_progress). Запоминается только удачный ответ (2xx): после отказа повтор с тем же ключом выполнится заново. Ключ живёт сутки (настройка idempotency.keys), область — организация и тот, кто прислал (ключ API или человек).
Доступ: Владелец или админ workspace; ключ API — с правом webhooks.manage.
Доступно по ключу API.
curl --request POST \
--url https://api.tungo.kz/v1/workspaces/{ws}/webhooks/endpoints \
--header 'Content-Type: application/json' \
--cookie tungo.session_token= \
--data '
{
"url": "https://example.com/tungo/webhooks",
"description": "Учётная система",
"event_types": [
"proposal.written",
"payment.succeeded"
],
"channels": [
"scn_01jz8x3m4n5p6q7r8s9t0v1w2x"
],
"enabled": true
}
'import requests
url = "https://api.tungo.kz/v1/workspaces/{ws}/webhooks/endpoints"
payload = {
"url": "https://example.com/tungo/webhooks",
"description": "Учётная система",
"event_types": ["proposal.written", "payment.succeeded"],
"channels": ["scn_01jz8x3m4n5p6q7r8s9t0v1w2x"],
"enabled": True
}
headers = {
"cookie": "tungo.session_token=",
"Content-Type": "application/json"
}
response = requests.post(url, json=payload, headers=headers)
print(response.text)const options = {
method: 'POST',
headers: {cookie: 'tungo.session_token=', 'Content-Type': 'application/json'},
body: JSON.stringify({
url: 'https://example.com/tungo/webhooks',
description: 'Учётная система',
event_types: ['proposal.written', 'payment.succeeded'],
channels: ['scn_01jz8x3m4n5p6q7r8s9t0v1w2x'],
enabled: true
})
};
fetch('https://api.tungo.kz/v1/workspaces/{ws}/webhooks/endpoints', options)
.then(res => res.json())
.then(res => console.log(res))
.catch(err => console.error(err));{
"id": "ep_2xyzExample",
"url": "https://example.com/tungo/webhooks",
"description": "<string>",
"event_types": [
"<string>"
],
"channels": [
"<string>"
],
"enabled": true,
"created_at": "2026-10-05T09:30:00.000Z",
"updated_at": "2026-10-05T09:30:00.000Z",
"secret": "whsec_…",
"secret_note": "<string>"
}{
"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"
}{
"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"
}Авторизации
Сессия кабинета: cookie ставит вход через /v1/auth/* (Better Auth), браузер шлёт её сам — фронтенду кабинета ничего добавлять не нужно (fetch с credentials: 'include'). За HTTPS имя cookie — __Secure-tungo.session_token. Сессия кончилась — 401 authentication_error: отправить на вход.
Заголовки
Ключ повтора (например, UUID): повтор с тем же ключом и тем же телом не выполняет действие второй раз, а отдаёт прежний ответ
255Параметры пути
id организации (workspace), ws_… — из GET /v1/workspaces
Тело
Новый адрес вебхуков.
Адрес приёмника: только https и не во внутренней сети (localhost, 10.x, 192.168.x… — проверяется и по DNS), до 2000 знаков
1 - 2000"https://example.com/tungo/webhooks"
Подпись адреса для людей (до 500 знаков)
500"Учётная система"
Какие события слать на адрес — имена из GET …/webhooks/event-types (до 50). null или не передано при заведении — все события
501 - 100["proposal.written", "payment.succeeded"]
Каналы — id сценариев автоматизаций (scn_…, до 10). Заданы — на адрес приходят только события этих сценариев (automation.run.completed, automation.run.failed, automation.run.notice, automation.write_unknown), и никаких других: так итог конкретного сценария идёт в свою систему. null или не передано при заведении — все события (по event_types)
10^scn_[0-9a-z]{26}$["scn_01jz8x3m4n5p6q7r8s9t0v1w2x"]
false — не слать на адрес, пока не включат снова. При заведении по умолчанию — включён
Ответ
Адрес заведён
Заведённый адрес вебхуков и его секрет подписи.
id адреса (ep_…) — для адресов …/webhooks/endpoints/{id}
"ep_2xyzExample"
Куда слать события (https)
"https://example.com/tungo/webhooks"
Подпись адреса для людей; пустая строка — не задана
Какие события слать (имена из …/webhooks/event-types); null — все
Каналы — id сценариев автоматизаций (scn_…): на адрес идут только события этих сценариев; null — все события
false — на адрес сейчас не шлётся ничего, пока не включат снова (PATCH enabled: true)
Когда заведён, ISO 8601 UTC
"2026-10-05T09:30:00.000Z"
Когда менялся последний раз, ISO 8601 UTC
"2026-10-05T09:30:00.000Z"
Секрет подписи whsec_…: по ключу API его больше негде прочитать, только сменить (POST …/secret/rotate). Хранить как пароль. null — повтор с тем же Idempotency-Key (секрет не запоминается) или Svix не отдал его сразу
"whsec_…"
Только в повторе с тем же Idempotency-Key: где взять секрет