Для каждого запроса требуется API-ключ компании (раздел «Интеграции» → «Вебхуки и API» в панели управления), который необходимо отправить в поле «Authorization: Bearer tt_live_….». Ответы и ошибки передаются в формате JSON.
curl "https://api.tapti.me/v1/company/reservations?status=confirmed&updatedSince=2026-09-01T00:00:00Z" \
-H "Authorization: Bearer tt_live_…"
Аутентификация
Каждый запрос содержит API-ключ компании в качестве токена «bearer». Создайте его в панели управления — «Интеграции» → «Вебхуки и API» → «Ключи REST API» — где он отображается однократно и хранится на стороне сервера исключительно в виде хеша SHA-256; утерянный ключ аннулируется и заменяется, но не восстанавливается. Компания может иметь до 10 активных ключей.
- Ключи только для чтения могут вызывать любую конечную точку GET, а также подписывать и отписывать веб-хуки — подписка не передаёт ничего, что ключ не мог бы прочитать и так.
- Ключи для чтения и записи также могут менять статус бронирования запросом POST; ключ только для чтения получает на этих маршрутах ответ 403 Forbidden.
- Ключ принадлежит одной компании — все списки и запросы уже ограничены ею, параметра companyId нет.
Ограничения по скорости
50 запросов в минуту на ключ в скользящем окне — общий лимит для всех конечных точек. При превышении возвращается 429 Too Many Requests; сделайте паузу и повторите запрос, а не опрашивайте чаще — или подпишите веб-хук и перестаньте опрашивать вовсе.
Конечные точки
/v1/company
Только для чтения или для чтения и записи
Получить текущую компанию
Компания, которой принадлежит ключ, и какие возможности предоставляет сам ключ.
/v1/company/reservations
Только для чтения или для чтения и записи
Список бронирований
Бронирования столиков для компании, в порядке убывания даты начала — или, если установлено значение updatedSince, в порядке убывания даты последнего обновления.
| Параметр | Type | Значение |
|---|---|---|
status |
string | Разделены запятыми: «в ожидании», «подтверждено», «присутствовал», «завершено», «не явился», «отменено». Статус «отменено» соответствует обеим причинам отмены. |
branchId |
integer | Ограничить до одной ветви. |
from |
ISO 8601 datetime | Только бронирования, начинающиеся в это время или позже (по UTC, если смещение не указано). |
to |
ISO 8601 datetime | Только бронирования, начинающиеся до этого времени. |
updatedSince |
ISO 8601 datetime | Только бронирования, измененные с этого момента; переключает сортировку на updatedAt по возрастанию для синхронизации. |
limit |
integer | Размер страницы: от 1 до 100. По умолчанию — 50. |
page |
integer | Нумерация страниц, начинающаяся с 1. По умолчанию — 1. |
/v1/company/appointments
Только для чтения или для чтения и записи
Список встреч
Такой же формат и фильтры, как и в модуле «Бронирования», для модуля «Встречи».
| Параметр | Type | Значение |
|---|---|---|
status |
string | Разделены запятыми: в ожидании, подтверждено, завершено, не явился, отменено. |
branchId |
integer | Ограничить до одной ветви. |
from |
ISO 8601 datetime | Только бронирования, начинающиеся в это время или позже. |
to |
ISO 8601 datetime | Только бронирования, начинающиеся до этого времени. |
updatedSince |
ISO 8601 datetime | Только бронирования, измененные с этого момента; сортировка по updatedAt в порядке возрастания. |
limit |
integer | Размер страницы: от 1 до 100. По умолчанию — 50. |
page |
integer | Нумерация страниц, начинающаяся с 1. По умолчанию — 1. |
/v1/company/reservations/{id}
Только для чтения или для чтения и записи
Забронировать номер
Одно ограничение: данные передаются в том же формате, в котором они поступают через веб-хуки, с указанием источника. Возвращается код 404, если идентификатор не принадлежит компании, указанной в ключе.
/v1/company/appointments/{id}
Только для чтения или для чтения и записи
Записаться на прием
Одно назначение, формат и правила такие же, как при поиске бронирования.
/v1/company/reservations/{id}/status
Только для чтения и записи
Изменить статус бронирования
Подтвердить, закрепить за столом, завершить, отметить как «не явился», отменить или возобновить — вызывает те же веб-хуки и конверсии, что и при изменении статуса на доске. Тело JSON: {"status": "..."}.
| Параметр | Type | Значение |
|---|---|---|
status |
string, required | Один из следующих вариантов: «в ожидании», «подтверждено», «зарегистрирован», «завершено», «не явился», «отменено» (также допускаются варианты «canceled» и «canceled_by_venue»). |
/v1/company/appointments/{id}/status
Только для чтения и записи
Изменить статус встречи
То же самое, что и конечная точка бронирования, но без состояния «занято».
| Параметр | Type | Значение |
|---|---|---|
status |
string, required | Одно из следующих: «в процессе», «подтверждено», «завершено», «не явился», «отменено» (также допускаются варианты «canceled» и «canceled_by_venue»). |
/v1/company/events
Только для чтения или для чтения и записи
Обработать поток событий
Все события бронирований, заказов и лояльности, начиная с самых старых, — та же лента, из которой формируются веб-хуки. Передайте последний полученный курсор в after, чтобы получить только новое, и type — чтобы получать только некоторые виды событий.
| Параметр | Type | Значение |
|---|---|---|
after |
integer cursor | Курсор после последнего обработанного события. Если не указано, то начнется с самого начала. |
type |
string | Типы или семейства событий через запятую: booking.confirmed,order.placed или order, loyalty.*. Не указывайте, чтобы получать все события. |
limit |
integer | Размер страницы: от 1 до 100. По умолчанию — 50. |
/v1/company/orders
Только для чтения или для чтения и записи
Список заказов
Заказы гостей за столом, навынос и с доставкой, а также все продажи, пробитые на кассе, начиная с самых старых — или, если задан paidSince, в порядке оплаты. Заказ, который ещё ждёт предоплаты, не выводится.
| Параметр | Type | Значение |
|---|---|---|
status |
string | Через запятую: open, paid. |
source |
string | customer (оформлен гостем) или staff (пробит персоналом). |
fulfilment |
string | Через запятую: dine_in, takeaway, delivery. |
branchId |
integer | Только один филиал. |
from |
ISO 8601 datetime | Только заказы, созданные в это время или позже. |
to |
ISO 8601 datetime | Только заказы, созданные до этого времени. |
paidSince |
ISO 8601 datetime | Только заказы, оплаченные с этого момента; сортировка по paidAt по возрастанию — для синхронизации продаж. |
limit |
integer | Размер страницы: от 1 до 100. По умолчанию — 50. |
page |
integer | Нумерация страниц, начинающаяся с 1. По умолчанию — 1. |
/v1/company/orders/{id}
Только для чтения или для чтения и записи
Получить заказ
Один заказ с позициями, суммами и атрибуцией — в том же формате, что и в веб-хуках заказов.
/v1/company/loyalty/programs
Только для чтения или для чтения и записи
Список программ лояльности
Все программы со штампами: название, статус, сколько штампов нужно, награда и где она действует.
/v1/company/loyalty/cards
Только для чтения или для чтения и записи
Список карт лояльности
Карты участников в формате объекта лояльности. Когда участник заполняет карту, она получает статус completed, а рядом появляется новая активная; customer.id — это участник.
| Параметр | Type | Значение |
|---|---|---|
programId |
integer | Только одна программа. |
customerId |
integer | Только один участник. |
status |
string | Через запятую: active, completed. |
updatedSince |
ISO 8601 datetime | Только карты, получившие штамп или заполненные с этого момента; сортировка по updatedAt по возрастанию. |
limit |
integer | Размер страницы: от 1 до 100. По умолчанию — 50. |
page |
integer | Нумерация страниц, начинающаяся с 1. По умолчанию — 1. |
/v1/company/loyalty/rewards
Только для чтения или для чтения и записи
Список наград лояльности
Награды, полученные за заполненную карту, — с кодом, сроком действия и отметкой, использованы ли они.
| Параметр | Type | Значение |
|---|---|---|
programId |
integer | Только одна программа. |
customerId |
integer | Только один участник. |
status |
string | Через запятую: issued, redeemed, expired. |
from |
ISO 8601 datetime | Только награды, выданные в это время или позже. |
to |
ISO 8601 datetime | Только награды, выданные до этого времени. |
limit |
integer | Размер страницы: от 1 до 100. По умолчанию — 50. |
page |
integer | Нумерация страниц, начинающаяся с 1. По умолчанию — 1. |
/v1/company/webhooks
Только для чтения или для чтения и записи
Список подписок на веб-хуки
Подписки, созданные этим ключом. Веб-хуки, добавленные в панели, здесь не показываются.
/v1/company/webhooks
Только для чтения или для чтения и записи
Подписать веб-хук
Начинает отправлять события на URL — этот вызов делает приложение платформы автоматизации, когда пользователь включает триггер. Возвращает подписку и её секрет подписи — один раз. Тело JSON: {"url": "…", "events": ["order.placed"]}; формат Zapier {"target_url": "…", "event": "…"} тоже принимается.
| Параметр | Type | Значение |
|---|---|---|
url |
string, required | Адрес https, на который отправлять события (также принимается target_url). |
events |
array of strings, required | Типы событий, семейства вроде order.* или loyalty либо * для всех событий (для одного типа также принимается event). |
description |
string | Название, которое показывается в панели. По умолчанию — платформа и имя ключа. |
/v1/company/webhooks/{id}
Только для чтения или для чтения и записи
Отписать веб-хук
Прекращает отправку по подписке, созданной этим ключом. Возвращает 204. При отзыве ключа удаляются и все его подписки.
Объект бронирования
Бронирование и запись на прием представлены в виде одного общего шаблона: тип, идентификатор, статус, источник, guestInitiated, startsAt/endsAt/часовой пояс (пояс филиала), валюта, компания, филиал, гость, атрибуция, conversionId, createdAt/updatedAt — плюс partySize и таблица для бронирования, услуга и специалист для записи на приём. Это именно то, что передаёт веб-хук, поэтому получатель, обрабатывающий одно из них, обрабатывает и другое.
{
"data": {
"kind": "reservation",
"id": 4821,
"status": "confirmed",
"source": "online",
"guestInitiated": true,
"startsAt": "2026-09-12T20:00:00+03:00",
"endsAt": "2026-09-12T21:30:00+03:00",
"timezone": "Asia/Baku",
"currency": "AZN",
"company": { "id": 12, "name": "Cafe Aroma", "slug": "cafe-aroma", "country": "AZ" },
"branch": { "id": 3, "name": "Nizami st." },
"partySize": 4,
"table": { "id": 9, "label": "T3" },
"guest": { "name": "Maria K.", "phone": "…", "email": "…" },
"locale": "en",
"note": null,
"conversionId": "tt3f9c…",
"createdAt": "2026-09-10T08:12:04+00:00",
"updatedAt": "2026-09-12T20:00:03+00:00",
"attribution": { "channel": "widget", "utmSource": "instagram", "gclid": null, "fbclid": "IwAR2…" }
}
}
Объект заказа
Заказ выглядит одинаково везде — в REST API, в веб-хуках заказов и в ленте событий: kind ("order"), id, number (номер, который называет персонал), status (open или paid), source (customer или staff), guestInitiated, fulfilment, table, label, deliveryAddress, note, currency, timezone, company, branch, customer (участник программы лояльности, если персонал его указал), items (name, variant, quantity, unitPriceCents, subtotalCents), itemCount, subtotalCents, discountCents, deliveryFeeCents, tipCents, totalCents, valueCents (стоимость заказа без чаевых — именно эту сумму передают конверсии), paymentMethod, servedBy, conversionId, createdAt, paidAt и attribution. Суммы всегда указаны в минимальных единицах валюты.
{
"data": {
"kind": "order",
"id": 9170,
"number": 42,
"status": "paid",
"source": "customer",
"guestInitiated": true,
"fulfilment": "takeaway",
"table": null,
"label": "Ana",
"currency": "EUR",
"branch": { "id": 3, "name": "Vitosha Blvd" },
"customer": { "id": 311, "name": "Ana", "phone": "…" },
"items": [
{ "menuItemId": 88, "name": "Flat white", "variant": "Large",
"quantity": 2, "unitPriceCents": 450, "subtotalCents": 900 }
],
"itemCount": 2,
"subtotalCents": 900,
"discountCents": 0,
"deliveryFeeCents": 0,
"tipCents": 100,
"totalCents": 1000,
"valueCents": 900,
"paymentMethod": "online",
"conversionId": "tt81ad…",
"createdAt": "2026-09-12T12:04:10+03:00",
"paidAt": "2026-09-12T12:05:02+03:00",
"attribution": { "channel": "web", "utmSource": "google", "gclid": "Cj0K…" }
}
}
Объект лояльности
Все события, карты и награды лояльности имеют один формат: kind ("loyalty"), id (карта), timezone, company, branch (где это произошло, если применимо), program (id, name, stampsRequired, rewardTitle), customer (id, name, phone, locale), card (id, status, stampsCount, stampsRequired, stampsToReward, createdAt), stamp (для штампа: source, issuedBy, createdAt) и reward (для награды: code, title, status, expiresAt, redeemedAt, redeemedBy), а также conversionId — идентификатор, под которым передаётся регистрация в программе лояльности.
{
"kind": "loyalty",
"id": 5120,
"program": { "id": 4, "name": "Coffee card", "stampsRequired": 8, "rewardTitle": "Free coffee" },
"customer": { "id": 311, "name": "Ana", "phone": "…", "locale": "bg" },
"card": { "id": 5120, "status": "active", "stampsCount": 5,
"stampsRequired": 8, "stampsToReward": 3 },
"branch": { "id": 3, "name": "Vitosha Blvd" },
"stamp": { "source": "qr_scan", "issuedBy": "Ivan", "createdAt": "…" },
"reward": null,
"conversionId": "tt5c02…"
}
Лента событий
Каждая строка имеет вид { id, cursor, type, createdAt, previousStatus, data }. В data лежит объект под ключом, который задаёт префикс события: data.booking, data.order или data.loyalty. Сохраняйте наибольший обработанный курсор и передавайте его обратно в after — строки никогда не пропускаются и не повторяются, поэтому после сбоя можно спокойно продолжить. Игнорируйте типы, которые вы не обрабатываете: могут появиться новые.
| Тип события | Значение |
|---|---|
booking.requested | Гость запросил бронирование, которое ждёт вашего подтверждения. |
booking.confirmed | Бронирование подтверждено — сразу при создании или позже персоналом. |
booking.cancelled | Отменено гостем или заведением; кем именно — видно в status. |
booking.no_show | Гость не пришёл. |
booking.completed | Визит завершён. |
order.placed | Заказ гостя поступил в заведение — со страницы, по QR-коду стола, навынос или с доставкой; если заведение берёт предоплату — после оплаты. |
order.paid | Оплачен любой заказ, включая продажи, пробитые на кассе. |
loyalty.member_joined | Клиент получил свой первый штамп в программе. |
loyalty.stamp_added | На карту добавлен штамп. |
loyalty.reward_issued | Карта заполнена, награда начислена. |
loyalty.reward_redeemed | Награда выдана гостю. |
curl "https://api.tapti.me/v1/company/events?after=998&limit=100" \
-H "Authorization: Bearer tt_live_…"
Веб-хуки
Создайте конечную точку в разделе «Интеграции» → «Вебхуки и API» — или подключите Zapier, Make, n8n или Pipedream в разделе «Интеграции» → «Автоматизация», — и TapTime будет отправлять подписанное событие в формате JSON методом POST в момент, когда меняется бронирование, заказ или карта лояльности. События выбираются отдельно для каждой конечной точки. У компании может быть до 50 веб-хуков, постбэков, чатов и подключений автоматизации в сумме.
| Заголовок | Значение |
|---|---|
TapTime-Event | Тип события, например booking.confirmed. |
TapTime-Event-Id | Уникальный идентификатор события — используйте его для удаления дубликатов при повторной попытке доставки. |
TapTime-Delivery | Идентификатор данной конкретной попытки доставки. |
TapTime-Signature | t = <время по системе Unix>, v1 = <шестнадцатеричное значение HMAC-SHA256 выражения «t.rawBody»>, подписанное собственным секретным ключом конечной точки. |
- Любой ответ с кодом 2xx считается доставленным; в случае ответа, отличного от 2xx, или истечения времени ожидания повторная попытка осуществляется с интервалом отсрочки (1 мин, 5 мин, 15 мин, 1 ч, 3 ч, 6 ч, 12 ч) до 8 попыток — при получении кода 410 повторные попытки прекращаются.
- Перенаправления не обрабатываются.
- В производственной среде URL-адрес должен использовать протокол HTTPS и не должен указывать на частный или петлевой адрес.
- Доставка осуществляется как минимум один раз: всегда проверяйте подпись и удаляйте дубликаты по TapTime-Event-Id.
{
"id": "evt_9f3c2a7e1b",
"type": "booking.confirmed",
"createdAt": "2026-09-12T19:02:11+03:00",
"test": false,
"data": { "booking": { "kind": "reservation", "id": 4821, "status": "confirmed", "…": "…" } }
}
const [t, v1] = req.headers["taptime-signature"]
.split(",").map(part => part.split("=")[1]);
const expected = crypto
.createHmac("sha256", process.env.TAPTIME_WEBHOOK_SECRET)
.update(`${t}.${rawBody}`)
.digest("hex");
const valid = crypto.timingSafeEqual(
Buffer.from(expected), Buffer.from(v1));
Подписки на веб-хуки
Платформы автоматизации включают и выключают триггеры через API, а не просят пользователя вставить URL («REST hooks»): отправьте POST с собственным URL платформы и нужными событиями, сохраните возвращённый id и удалите подписку запросом DELETE, когда триггер выключат. Подписка — обычный подписанный веб-хук: она видна в панели с отметкой ключа, который её создал.
- Ключ видит и удаляет только созданные им подписки; при отзыве ключа удаляются все они.
- Адреса на hooks.zapier.com, make.com и pipedream.net распознаются и показываются с названием платформы; любой другой адрес https — обычный веб-хук.
- Секрет подписи возвращается один раз — в ответе на POST; владелец может снова посмотреть его в панели.
curl -X POST "https://api.tapti.me/v1/company/webhooks" \
-H "Authorization: Bearer tt_live_…" -H "Content-Type: application/json" \
-d '{"url": "https://hooks.zapier.com/hooks/catch/123/abc/", "events": ["order.placed"]}'
Отправка данных
GET- или POST-запрос на собственный URL вашего трекера с заполненными макросами — для платформ, которые принимают постбэки в строке запроса, а не JSON-вебхуки. Для заказа {value} — сумма заказа без чаевых, а {order_id} — его идентификатор.
https://tracker.example/postback
?cid={click_id}&event={event}&status={status}
&payout={value}&cur={currency}
Доступные заполнители
{event}{event_id}{status}{booking_id}{booking_type}{order_id}{customer_id}{conversion_id}{value}{currency}{party_size}{branch_id}{timestamp}{utm_source}{utm_medium}{utm_campaign}{utm_term}{utm_content}{gclid}{fbclid}{msclkid}{ttclid}{click_id}
Ошибки
Каждая ошибка имеет формат JSON: { "error": "<code>", "message": "<human-readable>" }.
| Status | ошибка | Значение |
|---|---|---|
| 401 | unauthorized |
Отсутствует заголовок «Authorization», либо ключ недействителен или его действие отозвано. |
| 403 | forbidden |
Ключ, доступный только для чтения, называемый конечной точкой записи (изменение статуса). |
| 404 | not_found |
Бронирования с этим идентификатором у компании, владеющей ключом, нет. |
| 409 | conflict |
Изменение статуса привело бы к дублированию бронирования стола или места; ничего не изменилось. |
| 422 | invalid_status |
Значение поля «Статус» не входит в перечень допустимых значений для данного типа бронирования. |
| 422 | invalid_type |
Параметр type ленты событий не соответствует ни одному типу или семейству событий. |
| 422 | invalid_url |
URL подписки не является публичным адресом https. |
| 429 | rate_limited |
За эту минуту поступило более 50 запросов по этому ключу. Уменьшите частоту запросов и повторите попытку. |
Доступ к API, веб-хуки и интеграции с чатами и платформами автоматизации входят в каждый модуль — без доплаты и без отдельного тарифа для разработчиков.
Начните бесплатную пробную версию