Перейти до вмісту

Інтеграція Webhook

Webhook дозволяють вашим системам отримувати сповіщення в реальному часі, коли відбуваються події у вашому акаунті Wink — нові бронювання, скасування, оновлення платежів та інше. Цей посібник проведе вас через налаштування та найкращі практики.

Цей посібник призначений для розробників, які інтегрують Wink з зовнішніми системами, такими як системи управління нерухомістю (PMS), менеджери каналів, CRM або кастомні панелі керування.

  1. Ви реєструєте URL webhook у Wink.
  2. Коли відбувається подія (наприклад, нове бронювання), Wink надсилає HTTP POST на ваш URL.
  3. Ваш сервер обробляє дані та відповідає з 200 OK.
  1. Увійдіть у свій акаунт (Extranet, Studio або TripPay — всі підтримують webhook).
  2. Перейдіть до Applications, а потім Webhooks. Див. Webhooks.
  3. Натисніть Create webhook.
  4. Введіть назву (наприклад, “PMS Booking Sync”).
  5. Введіть свій URL webhook — HTTPS-ендпоінт на вашому сервері.
  6. Виберіть події — Оберіть конкретні події для підписки або залиште порожнім, щоб отримувати всі події.
  7. Увімкніть перемикач Enabled.
  8. Натисніть Save — відповідь покаже ваш секрет підпису лише один раз; збережіть його зараз.

Wink сьогодні публікує 70 типів подій webhook, що охоплюють бронювання, об’єкти, акаунти (керуючі суб’єкти) та інвентар (типи номерів, тарифні плани, основні тарифи, додаткові послуги, об’єкти, канали продажів, акції). Поширені:

КатегоріяПриклади
Бронюванняbooking.create, booking.cancelled, booking.refund.partial, booking.refund.full, booking.review.created
Об’єктproperty.created, property.status.updated, property.policy.updated
Інвентарroom_type.updated, rate_plan.created, master_rate.updated, special_rate.created, sales_channel.created
Акаунтmanaging_entity.created, managing_entity.status.updated, managing_entity.manager.added

Повний згенерований список — з описом, хто його отримує, та посиланням на сторінку довідки по кожній події — це Каталог подій Webhook. Сторінка довідки для кожної події (JSON-тіло, заголовки, політика повторних спроб) знаходиться у Webhooks API.

Переглянути всі типи подій

Кожна доставка — це HTTP POST на ваш URL webhook з Content-Type: application/json та таким конвертом:

{
"id": "0198a4f2-6b0e-7c1d-9a3e-2f4b8c6d1e0a",
"type": "booking.create",
"occurredAt": "2026-08-15T09:30:00Z",
"ownerIdentifier": "3c6b1a5d-8e2f-4a0b-9c7d-6e4f0a8b2c51",
"recipientRole": "SUPPLIER",
"schemaVersion": 2,
"object": { "...": "event-specific payload, e.g. BookingWebhookPayload" }
}
  • id — ідентифікатор події; однаковий для кожного ендпоінта вашого акаунта, що отримує цю подію, і для кожної повторної спроби. Використовуйте його як ключ ідемпотентності.
  • type — ключ типу події (також надсилається в заголовку Wink-Event-Type). Відгалужуйте логіку за type і schemaVersion, щоб розпарсити object.
  • object — курований підсумок ресурсу, про який подія (ідентифікатори, статус, поля, на які ви реагуєте), а також links.self — канонічний REST URL повного ресурсу зі сторони постачальника. Отримуйте його з власними API-обліковими даними, якщо потрібна детальніша інформація; якщо ви отримуєте подію як реселер або турагент, використовуйте відповідний ресурс вашого API для того ж ідентифікатора.

Кожна схема даних описана для кожної події у довідці Webhooks API.

ЗаголовокЗначення
Wink-VersionВерсія контракту, 2.0.
Wink-Event-IdТе саме, що id у тілі — ваш ключ ідемпотентності.
Wink-Delivery-IdУнікальний для ендпоінта на подію; змінюється лише при повторній доставці.
Wink-Event-TypeТе саме, що type у тілі.
Wink-Delivery-AttemptНомер спроби доставки, починаючи з 1.
Wink-SignatureHMAC-підпис — див. нижче.

Кожен webhook має секрет підпису (whsec_…), який Wink показує лише один раз при створенні webhook або зміні секрету. Збережіть його як пароль. Кожна доставка містить

Wink-Signature: t=1755250200,v1=5d41402abc4b2a76b9719d911017c592…

де t — Unix-мітка часу (секунди), а v1 — нижній регістр hex HMAC-SHA256 рядка t + "." + rawBody, підписаного вашим секретом, а rawBody — точний байтовий вміст тіла запиту, як отримано — не перетворюйте JSON перед перевіркою. Протягом 24 годин після зміни секрету заголовок містить друге значення v1=, підписане попереднім секретом; приймайте доставку, якщо будь-який v1 співпадає.

Перевіряйте у чотири кроки: розпарсіть t і всі v1; повторно обчисліть HMAC для t.rawBody з вашим секретом; порівняйте з використанням порівняння з постійним часом; відхиліть, якщо |now − t| перевищує ваш поріг (рекомендується 5 хвилин).

// Node.js (Express-style; переконайтеся, що у вас є RAW body, а не розпарсений об’єкт)
import { createHmac, timingSafeEqual } from 'node:crypto';
export function verifyWinkSignature(header, rawBody, secret, toleranceSeconds = 300) {
const parts = Object.fromEntries(header.split(',').map((p) => p.split('=').map((s) => s.trim())));
const t = Number(parts.t);
if (!Number.isFinite(t) || Math.abs(Date.now() / 1000 - t) > toleranceSeconds) return false;
const expected = createHmac('sha256', secret).update(`${t}.${rawBody}`).digest('hex');
return header
.split(',')
.filter((p) => p.trim().startsWith('v1='))
.map((p) => p.trim().slice(3))
.some((v1) => v1.length === expected.length && timingSafeEqual(Buffer.from(v1, 'utf8'), Buffer.from(expected, 'utf8')));
}
// Java
static boolean verify(String header, String rawBody, String secret, long nowSeconds, long toleranceSeconds) throws Exception {
long t = Long.MIN_VALUE;
List<String> signatures = new ArrayList<>();
for (String part : header.split(",")) {
String[] kv = part.trim().split("=", 2);
if (kv[0].equals("t")) t = Long.parseLong(kv[1]);
else if (kv[0].equals("v1")) signatures.add(kv[1]);
}
if (t == Long.MIN_VALUE || Math.abs(nowSeconds - t) > toleranceSeconds) return false;
Mac mac = Mac.getInstance("HmacSHA256");
mac.init(new SecretKeySpec(secret.getBytes(StandardCharsets.UTF_8), "HmacSHA256"));
byte[] expected = HexFormat.of().formatHex(mac.doFinal((t + "." + rawBody).getBytes(StandardCharsets.UTF_8))).getBytes(StandardCharsets.US_ASCII);
return signatures.stream().anyMatch(v1 -> MessageDigest.isEqual(expected, v1.toLowerCase().getBytes(StandardCharsets.US_ASCII)));
}

Змініть секрет у порталі або за допомогою POST /api/managing-entity/{id}/webhook/{webhookId}/rotate-secret; відповідь покаже новий секрет один раз, а старий буде дійсний ще 24 години, поки ви його не заміните.

Повторні спроби та повторна доставка

Section titled “Повторні спроби та повторна доставка”
  • Відповідайте будь-яким 2xx протягом 10 секунд для підтвердження. Важку обробку виконуйте асинхронно.
  • 5xx, таймаут, 408 або 429 повторюються з інтервалом: через 1 хвилину, 5 хвилин, 30 хвилин, 2 години, 6 годин, 12 годин, потім щодня — 10 спроб протягом приблизно 3 днів — після чого доставка позначається як мертва.
  • Будь-який інший 4xx вважається відмовою від доставки і не повторюється.
  • Кожна подія, доставка та спроба (статус, фрагмент відповіді) доступні у Applications > Webhooks та через API (…/webhook/event/grid, …/webhook/delivery/grid). Ви можете повторно доставити будь-яку доставку (POST …/webhook/delivery/{deliveryId}/redeliver, що починає нову серію спроб), повторно доставити всі мертві доставки webhook одночасно (POST …/webhook/{webhookId}/redeliver-dead), або скасувати одну.
  • Доставки зберігаються 30 днів.

Надішліть собі синтетичну подію webhook.test з порталу або за допомогою POST /api/managing-entity/{id}/webhook/{webhookId}/test. Вона підписана і доставляється так само, як реальна подія, тож ви можете перевірити свій ендпоінт, перевірку підпису та обробку ідемпотентності перед підпискою на живі події.

  • Використовуйте HTTPS — Wink надсилає дані лише на HTTPS-ендпоінти.
  • Відповідайте швидко — Поверніть 200 OK одразу після отримання даних. Важку обробку виконуйте асинхронно.
  • Ідемпотентність — Ваш обробник має бути ідемпотентним; уникайте дублювання за Wink-Event-Id. Wink повторює спроби, якщо не отримує 2xx.
  • Перевіряйте джерело — Перевіряйте заголовок Wink-Signature (див. Перевірка підписів) перед обробкою; відхиляйте все, що не проходить перевірку.
  • Логування — Логуйте кожен отриманий webhook. Це значно полегшує налагодження інтеграції.

Призупинення та видалення

Section titled “Призупинення та видалення”

Ви можете відключити webhook без видалення. Це призупиняє доставку, щоб ви могли усунути неполадки без втрати налаштувань. Коли будете готові, увімкніть його знову.

Видалення webhook назавжди його видаляє. Будь-яка інтеграція, що покладається на цей webhook, припинить отримувати сповіщення.

  • Каталог подій Webhook — Кожен тип події, згенерований з каталогу платформи.
  • Довідка Webhooks API — Схеми даних для кожної події, заголовки та ендпоінти керування підписками/доставкою.
  • Webhooks — Повна довідка з керування webhook.
  • Applications — Керуйте своїми API-обліковими даними.
  • Розробники > API — Повна документація API.