Вебхуки
Узнавайте о событиях сразу, вместо того чтобы опрашивать API.
Зарегистрируйте эндпоинт в разделе Разработчик → Вебхуки (или POST /api/v1/webhooks), выберите события и проверяйте заголовок X-ChatVendor-Signature при каждой доставке. Неудачные доставки повторяются с задержкой.
Webhook'и
Узнавайте о событиях: события, payload, подпись, повторы.
Base URL: https://chatvendor.net/api/v1 · каждый ответ {"success": true, "data": …}
GET
/webhooks
List webhook endpoints
webhooks:manage
Право: webhooks:manage
Ответ 200 · Webhook[]
id stringurl stringevents string: message.queued | message.sent | message.delivered | message.failed | device.online | device.offline | chat.message | chat.message.edited | chat.message.deleted | chat.action | chat.reaction | chat.operator_requested | lead.new | lead.updated | scenario.done | scenario.failed | scenario.cancelled | channel.connected | channel.disconnected | channel.revoked | bot.callback | bot.inline_query | bot.inline_chosen | bot.precheckout | bot.shipping | bot.join_request | bot.stopped | bot.reaction | bot.business_message | bot.paid_media | bot.payment | call.incoming | call.ended | call.group | secret.chat | contact.referral | contact.link_click | contact.updated | comment.new | order.created | order.paid | order.expired | order.updated | booking.created | booking.confirmed | booking.cancelled[]enabled boolean
curl https://chatvendor.net/api/v1/webhooks \
-H "Authorization: Bearer cv_live_xxxxxxxxxxxx"
POST
/webhooks
Create a webhook endpoint
webhooks:manage
Право: webhooks:manage
Тело запроса (application/json)
urlstring (uri)обязательноeventsstring: message.queued | message.sent | message.delivered | message.failed | device.online | device.offline | chat.message | chat.message.edited | chat.message.deleted | chat.action | chat.reaction | chat.operator_requested | lead.new | lead.updated | scenario.done | scenario.failed | scenario.cancelled | channel.connected | channel.disconnected | channel.revoked | bot.callback | bot.inline_query | bot.inline_chosen | bot.precheckout | bot.shipping | bot.join_request | bot.stopped | bot.reaction | bot.business_message | bot.paid_media | bot.payment | call.incoming | call.ended | call.group | secret.chat | contact.referral | contact.link_click | contact.updated | comment.new | order.created | order.paid | order.expired | order.updated | booking.created | booking.confirmed | booking.cancelled[]обязательноОтвет 201 · Webhook
id stringurl stringevents string: message.queued | message.sent | message.delivered | message.failed | device.online | device.offline | chat.message | chat.message.edited | chat.message.deleted | chat.action | chat.reaction | chat.operator_requested | lead.new | lead.updated | scenario.done | scenario.failed | scenario.cancelled | channel.connected | channel.disconnected | channel.revoked | bot.callback | bot.inline_query | bot.inline_chosen | bot.precheckout | bot.shipping | bot.join_request | bot.stopped | bot.reaction | bot.business_message | bot.paid_media | bot.payment | call.incoming | call.ended | call.group | secret.chat | contact.referral | contact.link_click | contact.updated | comment.new | order.created | order.paid | order.expired | order.updated | booking.created | booking.confirmed | booking.cancelled[]enabled boolean
curl -X POST https://chatvendor.net/api/v1/webhooks \
-H "Authorization: Bearer cv_live_xxxxxxxxxxxx"
-H "Content-Type: application/json" \
-d '{"url":"…","events":[]}'
PATCH
/webhooks/{webhook}
Update a webhook endpoint
webhooks:manage
Право: webhooks:manage
Параметры
webhookpath · stringобязательноWebhook public id
Ответ 200 · Webhook
id stringurl stringevents string: message.queued | message.sent | message.delivered | message.failed | device.online | device.offline | chat.message | chat.message.edited | chat.message.deleted | chat.action | chat.reaction | chat.operator_requested | lead.new | lead.updated | scenario.done | scenario.failed | scenario.cancelled | channel.connected | channel.disconnected | channel.revoked | bot.callback | bot.inline_query | bot.inline_chosen | bot.precheckout | bot.shipping | bot.join_request | bot.stopped | bot.reaction | bot.business_message | bot.paid_media | bot.payment | call.incoming | call.ended | call.group | secret.chat | contact.referral | contact.link_click | contact.updated | comment.new | order.created | order.paid | order.expired | order.updated | booking.created | booking.confirmed | booking.cancelled[]enabled boolean
curl -X PATCH https://chatvendor.net/api/v1/webhooks/{webhook} \
-H "Authorization: Bearer cv_live_xxxxxxxxxxxx"
DELETE
/webhooks/{webhook}
Delete a webhook endpoint
webhooks:manage
Право: webhooks:manage
Параметры
webhookpath · stringобязательноWebhook public id
Ответ 204
Deleted
curl -X DELETE https://chatvendor.net/api/v1/webhooks/{webhook} \
-H "Authorization: Bearer cv_live_xxxxxxxxxxxx"Узнавайте о событиях вместо опроса. Добавьте endpoint в Developer → Webhooks или через API выше с ключом webhooks:manage. У каждого endpoint есть секрет; каждая доставка подписана.
События
События мессенджера: chat.message, chat.message.edited, chat.message.deleted, chat.action, chat.operator_requested, lead.new, lead.updated, scenario.done|failed|cancelled, channel.connected|disconnected|revoked. В payload — channel_id и данные события.
message.queuedСообщение в очередиmessage.sentСообщение отправленоmessage.deliveredСообщение доставленоmessage.failedОшибка отправкиdevice.onlineУстройство вышло на связьdevice.offlineУстройство пропало со связиchat.messageЧат: новое сообщениеchat.message.editedЧат: сообщение измененоchat.message.deletedЧат: сообщение удаленоchat.actionЧат: событие группыchat.reactionЧат: изменились реакцииchat.operator_requestedЧат: запрошен операторlead.newЛид: новыйlead.updatedЛид: обновлёнscenario.doneСценарий: завершёнscenario.failedСценарий: ошибкаscenario.cancelledСценарий: отменёнchannel.connectedСеть подключенаchannel.disconnectedСеть отключенаchannel.revokedСессия сети отозванаbot.callbackБот: нажата кнопкаbot.inline_queryБот: inline-запросbot.inline_chosenБот: выбран inline-результатbot.precheckoutБот: pre-checkout запросbot.shippingБот: запрос доставкиbot.join_requestБот: заявка на вступлениеbot.stoppedБот: пользователь заблокировал/разблокировал ботаbot.reactionБот: реакцияbot.business_messageБот: бизнес-сообщениеbot.paid_mediaБот: куплено платное медиаbot.paymentБот: инвойс оплаченcall.incomingЗвонок: входящийcall.endedЗвонок: завершёнcall.groupЗвонок: изменился голосовой чатsecret.chatСекретный чат: запрошен / принят / отклонёнcontact.referralКонтакт: новый рефералcontact.link_clickКонтакт: клик по ссылкеcontact.updatedКонтакт: изменились теги/переменныеcomment.newInstagram: новый комментарийorder.createdЗаказ: созданorder.paidЗаказ: оплаченorder.expiredЗаказ: подписка истеклаorder.updatedЗаказ: статус доставки изменилсяbooking.createdЗапись: созданаbooking.confirmedЗапись: подтвержденаbooking.cancelledЗапись: отмененаPayload
POST https://example.com/webhooks/sms
Content-Type: application/json
X-SMS-Event: message.delivered
X-SMS-Event-Id: evt_01k…
X-SMS-Delivery-Attempt: 1
X-SMS-Signature: t=1754825400,v1=8f3a…
{
"event_id": "evt_01k…",
"event": "message.delivered",
"timestamp": "2026-08-11T09:30:00+00:00",
"data": {
"id": "msg_01k…",
"status": "delivered",
"to": "+998901234567",
"segments": 1,
"client_reference": "order_4389",
"delivered_at": "2026-08-11T09:29:58+00:00"
}
}
Проверка подписи
Compute HMAC SHA-256 over "{timestamp}.{raw body}" with your
endpoint's secret. Sign the raw body — re-encoding the JSON first will
change the bytes and the signature will not match. The timestamp is inside the signed
string, which is what stops a captured payload being replayed later.
// PHP
$raw = file_get_contents('php://input');
$header = $_SERVER['HTTP_X_SMS_SIGNATURE'] ?? '';
parse_str(strtr($header, ',', '&'), $parts);
if (abs(time() - (int) $parts['t']) > 300) {
http_response_code(400); // too old, treat as replay
exit;
}
$expected = hash_hmac('sha256', $parts['t'] . '.' . $raw, $secret);
if (! hash_equals($expected, $parts['v1'])) {
http_response_code(401);
exit;
}
// Node.js (express, raw body required)
app.post('/webhooks/sms', express.raw({ type: 'application/json' }), (req, res) => {
const parts = Object.fromEntries(
req.get('X-SMS-Signature').split(',').map((p) => p.split('=')),
);
const expected = crypto
.createHmac('sha256', process.env.WEBHOOK_SECRET)
.update(`${parts.t}.${req.body}`)
.digest('hex');
if (!crypto.timingSafeEqual(Buffer.from(expected), Buffer.from(parts.v1))) {
return res.sendStatus(401);
}
res.sendStatus(200); // acknowledge fast, process afterwards
});
Повторы
Any 2xx counts as delivered. Anything else is retried 1 min, 5 min, 30 min, 2 h after the first attempt. An endpoint that fails 20 times in a row is disabled automatically — re-enable it once it is fixed.
Every event carries a unique event_id. A retry reuses it,
so store the ones you have processed and ignore repeats — a delivery that timed out on
your side may still have been received.
Reply quickly. We wait 10 seconds; do the real work after responding, not before.
Callback на сообщение
Passing callback_url on a send delivers that message's
events to that URL as well. Those are not signed — there is no shared
secret behind a one-off URL — so treat them as a hint and confirm with
GET /api/v1/messages/{id} before acting on anything
that matters.