Webhook
Webhook - это HTTP POST, который система отправляет на ваш URL при наступлении события.
Успешной доставкой считается любой ответ со статусом 200-299.
Формат payload
Тело запроса всегда JSON:
JSON
{
"type": "create_message",
"data": {}
}Мы не добавляем служебные поля в тело запроса: в payload находятся только type и data.
Подпись (secret)
Если указан secret, добавляется заголовок X-Webhook-Signature.
TEXT
X-Webhook-Signature: 2a1b... (hex hmac-sha256)Пример проверки подписи (Node.js):
TS
import { createHmac, timingSafeEqual } from 'crypto';
function verifySignature(bodyRaw: string, signature: string, secret: string) {
const expected = createHmac('sha256', secret).update(bodyRaw).digest('hex');
return timingSafeEqual(Buffer.from(signature, 'hex'), Buffer.from(expected, 'hex'));
}Повторные попытки
- Повторяются только неуспешные доставки.
- 5 попыток с экспоненциальной задержкой:
1m,2m,4m,8m,16m.
Список событий
- Messages:
create_message,edit_message,delete_message - Deals:
create_deal,move_deal,close_deal,delete_deal - Pipelines:
create_pipeline,update_pipeline,delete_pipeline - CRM Tags:
create_crm_tag,update_crm_tag,delete_crm_tag - Clients:
create_client,update_client - Chats:
create_chat,close_chat,transfer_chat,open_chat
Базовая типизация
TS
type WebhookEventType =
| 'create_message'
| 'edit_message'
| 'delete_message'
| 'create_chat'
| 'close_chat'
| 'open_chat'
| 'transfer_chat'
| 'create_deal'
| 'move_deal'
| 'close_deal'
| 'delete_deal'
| 'create_pipeline'
| 'update_pipeline'
| 'delete_pipeline'
| 'create_crm_tag'
| 'update_crm_tag'
| 'delete_crm_tag'
| 'create_client'
| 'update_client';
type WebhookEnvelope<T> = { type: WebhookEventType; data: T };Типы data для событий
create_message
TS
type CreateMessageData = {
id: string;
chatUuid: string;
content: string;
type: 'system' | 'default';
senderType: 'client' | 'operator';
senderUuid: string;
isUpdated: boolean;
isSpam: boolean;
isEmailSent: boolean;
answerMessageUuid: string | null;
socialMessageUuid: string | null;
aiOperatorMeta: any | null;
createdAt: string;
updatedAt: string;
};edit_message
TS
type EditMessageData = CreateMessageData;delete_message
TS
type DeleteMessageData = CreateMessageData & { deletedAt: string };create_chat
TS
type CreateChatData = {
id: string;
clientUuid: string;
operatorUuid: string;
channelUuid: string;
departmentUuid: string | null;
transfersUuid: string[];
status: 'active' | 'closed';
subject?: string | null;
createdAt: string;
updatedAt: string;
};close_chat
TS
type CloseChatData = CreateChatData & { closedAt: string };open_chat
TS
type OpenChatData = CreateChatData & { openedAt: string };transfer_chat
TS
type TransferChatData = CreateChatData & {
previousOperatorUuid: string;
newOperatorUuid: string;
transferredAt: string;
};create_deal
TS
type CreateDealData = {
id: string;
title: string;
description: string | null;
amount: number;
currency: string;
status: 'active' | 'won' | 'lost' | 'paused';
priority: 'low' | 'medium' | 'high' | 'urgent';
source: string;
expectedCloseDate: string | null;
actualCloseDate: string | null;
lossReason: string | null;
customFields: object | null;
clientUuid: string | null;
ownerUuid: string;
pipelineUuid: string;
stageUuid: string;
lostReasonCategoryUuid: string | null;
chatUuid: string | null;
rootChanelUuid: string;
createdAt: string;
updatedAt: string;
};delete_deal
TS
type DeleteDealData = CreateDealData & { deletedAt: string };move_deal
TS
type MoveDealData = CreateDealData & {
previousStageUuid: string;
newStageUuid: string;
movedAt: string;
};close_deal
TS
type CloseDealData = CreateDealData & { closedAt: string };create_pipeline
TS
type CreatePipelineData = {
id: string;
name: string;
description: string | null;
color: string;
isActive: boolean;
isDefault: boolean;
sortOrder: number;
rootChanelUuid: string;
createdAt: string;
updatedAt: string;
};update_pipeline
TS
type UpdatePipelineData = CreatePipelineData;delete_pipeline
TS
type DeletePipelineData = CreatePipelineData & { deletedAt: string };create_crm_tag
TS
type CreateCrmTagData = {
id: string;
name: string;
color: string;
description: string | null;
type: 'client' | 'deal' | 'universal';
isActive: boolean;
usageCount: number;
rootChanelUuid: string;
createdAt: string;
updatedAt: string;
};update_crm_tag
TS
type UpdateCrmTagData = CreateCrmTagData;delete_crm_tag
TS
type DeleteCrmTagData = CreateCrmTagData & { deletedAt: string };create_client
TS
type CreateClientData = {
id: string;
type: 'site' | 'telegram' | 'mail' | 'whatsapp' | 'vk' | 'max';
rootChanelUuid: string;
socialId: number | null;
nameSocial: string | null;
lastName: string | null;
name: string | null;
email: string[];
avatarUrl: string | null;
phone: string[];
ip: string[];
city: string[];
isOnline: boolean;
isContactRequestPending: boolean;
otherFields: object | null;
lastVisit: string;
createdAt: string;
updatedAt: string;
};update_client
TS
type UpdateClientData = CreateClientData;Поля в data могут расширяться обратно-совместимо. Не завязывайтесь на строго фиксированный набор полей без необходимости.