Справочник событий, которые магазин отправляет в Альбато. Для каждого события указано, какое действие его вызывает и какие поля приходят в запросе. Пути полей нужны при настройке связки: в шагах Альбато поля выбирают из пришедшего примера, например order.total или stock.stockQtyAfter.
Формат запроса
Магазин отправляет каждое событие отдельным запросом POST на адрес вебхука. Тело — JSON, заголовки такие:
Content-Type—application/json.X-Webhook-Event— код события, напримерorder.created.X-Webhook-Delivery— ID доставки, то же значение, что в полеdeliveryId.X-Webhook-Signature— подпись тела:sha256=и HMAC-SHA256 в шестнадцатеричном виде.
В теле всегда есть три служебных поля и объект с данными:
{
"event": "order.paid",
"deliveryId": "5b0e7a2c-3f1d-4c8e-9a6b-1d2e3f4a5b6c",
"timestamp": "2026-09-16T10:05:00Z",
"order": {
"id": 123,
"total": 1175
}
}
event— код события. Используйте его в условии связки;deliveryId— уникальный ID события. При повторной отправке он не меняется, по нему отсеивают дубли;timestamp— время, когда событие поставлено в очередь, в UTC. Это не дата заказа: дату создания берите изorder.createdAt;- объект с данными называется по первой части кода:
orderдляorder.*,client,message,good,stock,performer,absence,booking.
Даты приходят в формате ISO 8601 с часовым поясом, суммы приходят числами, отсутствующие значения — null.
Событие — снимок данных на момент действия. Повторная отправка содержит тот же снимок, даже если данные в магазине уже изменились. Кто выполнил действие, в событии не указано: если связка сама меняет данные через API, магазин пришлёт об этом событие. Не запускайте по событию действие, которое вызовет это же событие, иначе связка зациклится.
Список событий
- «Новый заказ»,
order.created— заказ оформлен на сайте, в боте Telegram или MAX, создан в панели или через API. - «Изменение статуса заказа»,
order.status_changed— заказ подтверждён, выполнен или получил новый статус в панели либо через API. - «Оплата заказа»,
order.paid— платёжная система подтвердила оплату или сотрудник отметил заказ оплаченным. - «Отмена заказа»,
order.cancelled— заказ отменён в панели или через API. - «Новый клиент»,
client.created— в магазине появился клиент: из панели, API, сайта или мессенджера. - «Изменение клиента»,
client.updated— карточку клиента изменили в панели или через API, гость зарегистрировался на сайте. - «Входящее сообщение»,
message.received— клиент написал боту в Telegram или MAX. - «Новый товар»,
good.created— товар создан в карточке панели или через API. - «Изменение товара»,
good.updated— карточку товара сохранили в панели или изменили через API. - «Удаление товара»,
good.deleted— товар удалён в панели или через API. - «Изменение остатков»,
stock.changed— остаток изменился: резерв или возврат по заказу, приход или списание. - «Малый остаток»,
stock.low— остаток опустился до порога или ниже. - «Новый исполнитель»,
performer.created— исполнитель добавлен в панели или через API. - «Изменение исполнителя»,
performer.updated— данные исполнителя изменены. - «Удаление исполнителя»,
performer.deleted— исполнитель удалён. - «Новое отсутствие исполнителя»,
absence.created— исполнителю добавлено отсутствие: отпуск, больничный. - «Удаление отсутствия»,
absence.deleted— отсутствие удалено. - «Новая запись на услугу»,
booking.created— клиент записался на услугу на витрине. - «Подтверждение записи»,
booking.confirmed— запись подтверждена в панели или через API. - «Завершение записи»,
booking.completed— запись отмечена завершённой. - «Отмена записи»,
booking.cancelled— запись отменил магазин или клиент. - «Неявка клиента»,
booking.no_show— запись отмечена как неявка. - «Перенос записи»,
booking.rescheduled— клиент перенёс запись на витрине.
Событие отправляется, только если в момент действия услуга подключена, отправка включена и событие отмечено в настройках. Импорт из файла и прямые изменения в базе данных событий не создают. Подробности и исключения — в разделах ниже.
Заказы
Все четыре события о заказах передают одинаковый объект order: клиента, позиции, оплату, доставку и скидки. Дополнительный запрос к API за этими данными не нужен.
Когда отправляются
order.created— после успешного оформления на сайте, в боте Telegram или MAX, после создания в панели или через API. Если оформление сорвалось, например не удалось забронировать интервал доставки, события не будет. Заказы Яндекс Маркета и заказы, созданные записью на услугу, это событие не отправляют: для записей естьbooking.created.order.status_changed— когда заказ подтверждают, переводят в статус «Новый», «В обработке» или «Доставляется» и когда выполняют. Автоматический перевод в «В обработке» после оплаты в Telegram отправляет толькоorder.paid.order.paid— когда оплату подтвердили ЮKassa, Яндекс Пэй или Telegram или когда сотрудник поставил отметку об оплате. Снятие отметки события не создаёт.order.cancelled— когда заказ отменяют в панели или через API. Запрос клиента на отмену само событие не вызывает, оно придёт, когда магазин отменит заказ.
Поля заказа
order.id— ID заказа.order.status— код статуса:0— Новый,1— Подтверждён,2— В обработке,4— Доставляется,3— Выполнен,-1— Отменён.order.total,order.currency— итог заказа и валюта. Скидки уже вычтены, доставка, включённая в заказ, и наценка способа оплаты уже прибавлены.order.source— откуда заказ:web,telegram,max,manual(панель или API).order.createdAt,order.updatedAt— дата создания и последнего изменения заказа.order.contactName,order.contactPhone,order.email— контакты, указанные в заказе. Могут отличаться от профиля клиента; если не заполнены — пустые строки.order.comment— комментарий к заказу.order.storeId,order.clientId— ID магазина и клиента.order.externalId,order.externalSource— ID во внешней системе и её название, если заказ создан через API с этими полями.order.client— профиль клиента:id,name,firstName,lastName,phone,email.null, если клиент не найден.
Позиции — массив order.items, по элементу на позицию. В Альбато его обрабатывают как список: например, добавляют строку в таблицу на каждый товар.
id,goodId— ID позиции заказа и ID товара.name,article— название и артикул товара на момент события.type— тип:physical,digital,service.quantity,price,total— количество, цена за единицу из заказа и их произведение до скидок на заказ.currency— валюта позиции.options— выбранные опции:groupId,groupCaption(например «Размер»),valueId,valueCaption(«M»), иногдаvalueImage. Без опций — пустой массив.optionsJson— те же опции одной строкой JSON, без опций —"[]". Удобно, когда в поле Альбато нужна строка.
Оплата — объект order.payment:
id,name— ID и название способа оплаты в магазине;method— онлайн-провайдер:yookassa,telegram,yandexpayилиnullдля оплаты при получении;paidиstatus— признак оплаты и состояние:paid— оплачен,waiting— клиенту выставлена ссылка,unpaid— не оплачен;fee— наценка способа оплаты, уже включённая в итог.
Доставка — объект order.delivery:
typeId,type,name— ID, код и название способа доставки.kind— вид доставки:courier— по адресу,pickup— самовывоз,digital— цифровая доставка.provider— служба доставки, напримерcdek. Для собственных способов магазина —null.price,includedValue— стоимость доставки и часть стоимости, уже включённая вorder.total. Если стоимость ещё не рассчитана,priceравенnull— это не бесплатная доставка.priceStatus— расчёт стоимости:calculated— стоимость известна,pending— магазин рассчитает её после оформления,free— бесплатно.paymentMode,paymentStatus— как оплачивается доставка:included— в составе заказа,separate_invoice— отдельным счётом,cash_on_delivery— при получении. Статус отдельного счёта:not_required,pending,paidилиnull.pricingType— способ расчёта цены:fixed— известна заранее,calculated_later— рассчитывается после оформления. Для обычной доставки —null.address,entrance,floor,apartment,addressComment— адрес, подъезд, этаж, квартира и комментарий к адресу.addressMode,lat,lng— тип адреса:home_address— адрес клиента,pvz_address— пункт выдачи. Координаты точки.date,slotFrom,slotTo— дата и интервал доставки по местному времени:2026-09-20,10:00:00,12:00:00.pickupPoint— точка самовывоза:id,name,address. Для доставки по адресу —null.
Скидки — объект order.discounts: promo — скидка по промокоду, promoCode — сам промокод или null, referral — скидка по партнёрской программе, bonusPointsUsed — оплачено бонусами, manual — ручная скидка, total — сумма всех скидок. Скидки уже учтены в order.total, вычитать их повторно не нужно.
Дополнительные поля по событиям
order.status_changed—order.previousStatus(прежний код статуса) иorder.statusChangedAt(время смены);order.cancelled—order.previousStatusиorder.cancelledAt;order.paid—order.paidвсегда равенtrue, вorder.paymentстоятpaid: trueиstatus: "paid".
Сокращённый пример «Нового заказа»:
{
"event": "order.created",
"deliveryId": "22222222-2222-4222-8222-222222222222",
"timestamp": "2026-09-15T10:00:01Z",
"order": {
"id": 123,
"status": 0,
"total": 1175,
"currency": "RUB",
"source": "web",
"contactName": "Тестовый покупатель",
"contactPhone": "+79990000001",
"createdAt": "2026-09-15T10:00:00Z",
"items": [
{
"goodId": 10,
"name": "Футболка",
"article": "SHIRT-M",
"quantity": 2,
"price": 500,
"total": 1000,
"optionsJson": "[{\"groupCaption\":\"Размер\",\"valueCaption\":\"M\"}]"
},
{
"goodId": 11,
"name": "Носки",
"article": "SOCKS",
"quantity": 1,
"price": 250,
"total": 250,
"optionsJson": "[]"
}
],
"payment": {"name": "При получении", "method": null, "paid": false, "status": "unpaid", "fee": 0},
"delivery": {"name": "Курьер", "kind": "courier", "price": 100, "includedValue": 100, "address": "Тестовая улица, 10", "date": "2026-09-20", "slotFrom": "10:00:00", "slotTo": "12:00:00"},
"discounts": {"promo": 50, "promoCode": "WELCOME", "referral": 25, "bonusPointsUsed": 50, "manual": 50, "total": 175}
}
}
Клиенты
Когда отправляются
client.created приходит, когда в магазине появляется клиент:
- сотрудник создал его в панели или связка — через API;
- посетитель зарегистрировался на сайте по email и паролю;
- на сайт пришёл новый посетитель — магазин заводит для него анонимного клиента без контактов;
- человек впервые написал боту в Telegram или MAX, нажал кнопку бота или «Начать» в MAX;
- человек впервые открыл мини-приложение магазина в Telegram или MAX.
При входе на сайт кнопкой «Войти через Telegram» событие не отправляется.
⚠️ Важно: «Новый клиент» — не всегда контакт с телефоном. У посетителей сайта и пользователей мессенджеров phone и email пустые, а контакты появляются позже. Если связка создаёт лиды в CRM, добавьте условие: телефон или email заполнены.
client.updated приходит, когда:
- карточку клиента сохранили в панели или изменили через API — даже если значения не поменялись;
- гость сайта зарегистрировался: к его карточке добавились email, телефон и пароль;
- клиент без пароля, например вошедший через Telegram, добавил email и пароль.
Не отправляют событие правка профиля самим клиентом на сайте, контакты, введённые при оформлении заказа, и обновление имени из мессенджера.
Поля клиента
client.id,client.storeId— ID клиента и магазина.client.caption— отображаемое имя, строка. У анонимного посетителя сайта — «Анонимный пользователь».client.firstName,client.lastName,client.middleName— имя, фамилия, отчество.client.phone,client.email— телефон и email, могут бытьnull.client.source— откуда клиент:manual— панель или API,web— сайт,registration— регистрация на сайте,telegramиmax— мессенджеры.client.externalId,client.externalSource— ID во внешней системе и её название.client.createdAt,client.updatedAt— дата создания и изменения.
Логин, пароль и служебные данные клиента в событие не попадают.
Входящие сообщения
message.received приходит на каждое новое сообщение клиента боту в Telegram или MAX, включая команду /start и ответы на вопросы сценария. Нажатия кнопок, кнопка «Начать» в MAX, сообщения сотрудников, ответы сценариев и рассылки события не создают. Поэтому связка «клиент написал → ответить» не зациклится на собственном ответе.
message.id— ID сообщения.message.clientId— ID клиента. Имя и телефон получите методомGET /api/v2/clients/info?id=….message.platform—telegramилиmax.message.botId— ID бота магазина, который получил сообщение.message.type—text,photo,video,voice,document,contact,location. В MAX встречаются и другие типы вложений, а пустое сообщение приходит какunknown.message.text— текст сообщения. Для документа — имя файла, для контакта в Telegram — номер телефона, для геопозиции в Telegram — координаты вида55.751244,37.618423.
Сами файлы и ссылки на них в событие не входят. У фото, видео и голосовых сообщений из Telegram поле text пустое: подпись к медиа не передаётся. В MAX подпись приходит в text.
Товары
События о товарах отправляются, когда карточку товара создают, сохраняют или удаляют в панели или через API. good.updated приходит после каждого сохранения, даже если значения не изменились.
Событий нет при импорте каталога из файла, массовых действиях со списком товаров и изменении остатка: об остатках сообщают отдельные события. Когда удаляют товар с вариантами, good.deleted приходит только для самого товара.
good.id— ID товара. Вgood.deletedэто единственное поле.good.storeId— ID магазина.good.caption,good.article— название и артикул.good.otherId— код товара во внешней системе.good.price— цена.good.type—physical,digital,serviceилиcategory.
Остатки
События об остатках касаются физических товаров и вариантов, у которых включён учёт остатка.
| Действие | Что происходит с остатком |
|---|---|
| Оформлен заказ | Уменьшается на количество товара: товар резервируется |
| В заказе увеличили количество | Уменьшается на разницу |
| В заказе уменьшили количество или удалили позицию | Увеличивается на разницу |
| Заказ отменён | Резерв возвращается |
| Приход или списание на вкладке «Склад» либо корректировка через API | Меняется на указанное количество |
При оплате и выполнении заказа остаток не меняется — товар зарезервирован ещё при оформлении, поэтому событий нет. Не создают событий и остаток, заданный при создании или изменении товара, и импорт каталога.
Поля stock.changed:
stock.goodId,stock.article— ID и артикул товара или варианта.stock.delta— изменение: отрицательное — списание или резерв, положительное — приход или возврат.stock.stockQtyBefore,stock.stockQtyAfter— остаток до и после изменения.stock.reason— причина:order_created— резерв по заказу,order_cancelled— возврат по заказу,income— приход,manual_adjust— списание или ручная корректировка, либо значение, переданное через API.stock.movementId— ID записи в истории движений товара.stock.orderId— ID заказа, если изменение связано с заказом, иначеnull.
stock.low отправляется вместе с stock.changed, когда у товара задан порог больше нуля и остаток перешёл из состояния «выше порога» в «равен порогу или ниже». Дальнейшие списания ниже порога событие не повторяют; после пополнения выше порога следующее пересечение снова его вызовет. Поля: goodId, caption, article, stockQty (остаток после изменения), lowStockThreshold (порог), а также delta, stockQtyBefore, reason, movementId и orderId.
{
"event": "stock.changed",
"deliveryId": "d146d97b-67a2-41f2-9259-b00dbb22daee",
"timestamp": "2026-09-15T12:00:00.482913Z",
"stock": {
"goodId": 42,
"article": "SKU-42",
"delta": -2,
"stockQtyBefore": 10,
"stockQtyAfter": 8,
"reason": "order_created",
"movementId": 1234,
"orderId": 122
}
}
💡 Чтобы синхронизировать остатки с учётной системой, записывайте абсолютное значение stockQtyAfter, а не прибавляйте delta: при повторной доставке разница применится дважды. Храните последний movementId по товару и не перезаписывайте остаток событием с меньшим movementId — при повторах события могут прийти не по порядку.
Исполнители и отсутствия
События приходят, когда исполнителя добавляют, изменяют или удаляют, а также когда ему добавляют или удаляют отсутствие. Изменение графика работы, фото, точек и привязки к услугам событий не создаёт.
performer.created,performer.updated—performer.id,performer.storeId,performer.fullName,performer.phone,performer.email.performer.updatedприходит после каждого сохранения;performer.deleted— толькоperformer.id;absence.created—absence.id,absence.performerId,absence.startAt,absence.endAt(начало и конец периода),absence.reason(причина);absence.deleted—absence.idиabsence.performerId.
Если при добавлении отсутствия магазин отменил пересекающиеся записи, по каждой из них сначала придёт booking.cancelled, а затем absence.created.
Записи на услуги
Когда отправляются
booking.created— клиент записался на услугу на витрине. Событие приходит сразу после оформления, в том числе для записи, которая ждёт предоплаты (status: "pending_payment").booking.confirmed— сотрудник подтвердил запись в панели или связка — через API.booking.completed— запись отмечена завершённой.booking.no_show— запись отмечена как неявка.booking.cancelled— запись отменил магазин (в панели, через API или добавлением отсутствия с отменой записей) или клиент на витрине.booking.rescheduled— клиент перенёс запись на витрине. Перенос создаёт новую запись, и событие описывает её.
⚠️ Важно: часть изменений проходит без событий. Не отправляются: перевод записи из «Ожидает оплаты» в рабочий статус после оплаты, отмена из-за неоплаты или истёкшего срока оплаты, отмена записей вместе с заказом, отмена исходной записи при переносе клиентом. Изменение времени, исполнителя и заметок сотрудником в панели или через API тоже событий не создаёт. Если связке важен итоговый статус, периодически сверяйте записи методом получения записи.
Поля записи
Все шесть событий передают одинаковый объект booking:
id,storeId— ID записи и магазина.status— статус записи, значения ниже.serviceMode— режим оказания:on_site— на точке,at_client— с выездом к клиенту,online— онлайн,async— без фиксированного времени, к сроку.goodId,goodName— ID и название услуги.performerId,performerName— ID и имя исполнителя.startAt,endAt— начало и конец. У записейasync—null.dueBy— срок выполнения для записейasync, дата вида2026-10-01.timezone— часовой пояс исполнителя, иначе точки, иначеUTC.clientId,clientName,clientPhone,clientEmail— ID клиента и контакты. Контакты из формы записи важнее данных профиля.locationId,locationName,address— точка оказания услуги и адрес: адрес выезда или адрес точки.clientNotes— комментарий клиента.orderId,orderCompositionId— ID заказа, созданного записью, и позиции в нём.price,quantity,total,currency— цена из заказа, количество, их произведение и валюта.orderTotal,paid,prepaidAmount,paymentMethod— сумма всего заказа, признак оплаты, внесённая предоплата и онлайн-провайдер оплаты.cancellationReason— причина отмены. Если её нет — пустая строка.createdAt,updatedAt,confirmedAt,completedAt,cancelledAt— время создания, изменения, подтверждения, завершения и отмены.
Служебные заметки исполнителя и ссылки на оплату в событие не попадают.
Значения status:
pending_payment— ожидает оплаты;pending_confirmation— ждёт подтверждения магазином;confirmed— подтверждена;completed— услуга оказана;cancelled_by_clientиcancelled_by_store— отменена клиентом или магазином;no_show— клиент не пришёл.
В booking.rescheduled есть ещё четыре поля: rescheduledFromBookingId — ID прежней записи, previousStartAt и previousEndAt — прежнее время, previousPerformerId — прежний исполнитель.
{
"event": "booking.confirmed",
"deliveryId": "8f2b6c1d-4e5a-4b7c-9d8e-0f1a2b3c4d5e",
"timestamp": "2026-09-16T10:15:31Z",
"booking": {
"id": 501,
"status": "confirmed",
"serviceMode": "on_site",
"goodName": "Стрижка",
"performerName": "Анна Иванова",
"startAt": "2026-09-20T07:00:00+00:00",
"endAt": "2026-09-20T08:00:00+00:00",
"timezone": "Europe/Moscow",
"clientName": "Мария",
"clientPhone": "+79991234567",
"locationName": "Салон на Ленина",
"price": 1500,
"total": 1500,
"paid": false,
"cancellationReason": ""
}
}
Проверка подписи
Подпись нужна, если события принимает ваш сервер. Чтобы проверить запрос:
- Возьмите тело запроса ровно в том виде, в каком оно пришло, до разбора JSON.
- Вычислите HMAC-SHA256 от тела с ключом — секретом подписи из настроек вебхука — и запишите результат в шестнадцатеричном виде.
- Добавьте в начало
sha256=и сравните с заголовкомX-Webhook-Signature. Если значения не совпали, ответьте кодом 401 и не обрабатывайте запрос.
Пример на PHP:
$body = file_get_contents('php://input');
$expected = 'sha256=' . hash_hmac('sha256', $body, $secret);
$received = $_SERVER['HTTP_X_WEBHOOK_SIGNATURE'] ?? '';
if (!hash_equals($expected, $received)) {
http_response_code(401);
exit;
}
Пример на Node.js, где rawBody — тело запроса в виде Buffer:
const crypto = require('crypto');
function isValidSignature(rawBody, header, secret) {
const expected = 'sha256=' + crypto.createHmac('sha256', secret).update(rawBody).digest('hex');
const a = Buffer.from(expected);
const b = Buffer.from(header || '');
return a.length === b.length && crypto.timingSafeEqual(a, b);
}
Если разобрать JSON и собрать его заново, порядок полей и пробелы изменятся, и подпись не совпадёт. Считайте подпись только от исходного тела.
Повторы и порядок событий
- Успешной доставкой считается ответ с кодом от 200 до 299. При другом коде или без ответа за 10 секунд магазин повторит отправку через 5 и через 30 секунд, всего три попытки.
- Одно событие может прийти дважды, например если получатель обработал запрос, но не успел ответить. Отсеивайте повторы по
deliveryId. - При повторных попытках порядок событий может нарушиться. Не полагайтесь на то, что «Оплата заказа» придёт позже «Нового заказа»: сверяйте данные по времени и ID.
- Для нового клиента мессенджера «Входящее сообщение» может прийти раньше «Нового клиента».
Короткие ответы
Чем поле timestamp отличается от даты заказа?
timestamp — время, когда магазин поставил событие в очередь на отправку. Дата создания заказа лежит в order.createdAt, а время смены статуса — в order.statusChangedAt. Для отчётов и таблиц используйте поля заказа: при повторной доставке timestamp останется прежним, но к заказу он не относится.
Почему в «Новом клиенте» нет телефона?
Событие приходит и для анонимных посетителей сайта, и для людей, которые только написали боту: контактов у таких клиентов ещё нет. Телефон и email появятся, когда клиент зарегистрируется, и тогда придёт «Изменение клиента». Контакты из заказа передаются в событиях о заказах.
Как выгрузить каждый товар заказа отдельной строкой?
Используйте массив order.items: в Альбато обработайте его инструментом для списков, и каждый элемент станет отдельной строкой с полями name, quantity, price и total. Общие поля заказа, например order.id и order.createdAt, можно добавить в каждую строку.