Gå til indhold

Webhook-integration

Webhooks lader dine systemer modtage realtidsnotifikationer, når der sker begivenheder på din Wink-konto — nye bookinger, aflysninger, betalingsopdateringer og mere. Denne guide fører dig gennem opsætning og bedste praksis.

Denne guide er til udviklere, der integrerer Wink med eksterne systemer som ejendomsadministrationssystemer (PMS), channel managers, CRM’er eller brugerdefinerede dashboards.

  1. Du registrerer en webhook-URL på Wink.
  2. Når en begivenhed opstår (f.eks. en ny booking), sender Wink en HTTP POST til din URL.
  3. Din server behandler payloaden og svarer med en 200 OK.
  1. Log ind på din konto (Extranet, Studio eller TripPay — alle understøtter webhooks).
  2. Gå til Applications og derefter Webhooks. Se Webhooks.
  3. Klik på Create webhook.
  4. Indtast et navn (f.eks. “PMS Booking Sync”).
  5. Indtast din webhook URL — HTTPS-endpointet på din server.
  6. Vælg begivenheder — Vælg specifikke begivenheder at abonnere på, eller lad det stå tomt for at modtage alle begivenheder.
  7. Skift Enabled til til.
  8. Klik på Save — svaret viser din signeringshemmelighed én gang; gem den nu.

Wink udgiver i dag 70 webhook-begivenhedstyper inden for bookinger, ejendomme, konti (styrende enheder) og lager (værelsestyper, rateplaner, masterrater, tillæg, faciliteter, salgskanaler, kampagner). Almindelige:

KategoriEksempler
Bookingbooking.create, booking.cancelled, booking.refund.partial, booking.refund.full, booking.review.created
Ejendomproperty.created, property.status.updated, property.policy.updated
Lagerroom_type.updated, rate_plan.created, master_rate.updated, special_rate.created, sales_channel.created
Kontomanaging_entity.created, managing_entity.status.updated, managing_entity.manager.added

Den komplette, genererede liste — med beskrivelse, hvem der modtager den, og et link til hver begivenheds reference-side — er Webhook Events Catalog. Referencesiden for hver begivenhed (JSON-body, headers, retry-politik) findes i Webhooks API.

Se alle begivenhedstyper

Hver levering er en HTTP POST til din webhook-URL med Content-Type: application/json og denne kuvert:

{
"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 — begivenhedsidentifikatoren; identisk for hvert endpoint på din konto, der modtager denne begivenhed, og for hver genforsøg. Brug den som din idempotensnøgle.
  • type — begivenhedstypenøglen (også sendt som Wink-Event-Type header). Branchér på type og schemaVersion for at parse object.
  • object — et kurateret resumé af ressourcen, som begivenheden handler om (identifikatorer, status, de felter du handler på) plus links.self, den leverandørsidige kanoniske REST-URL for den fulde ressource. Hent den med dine egne API-legitimationsoplysninger, når du har brug for mere end resumeet; hvis du modtager begivenheden som forhandler eller rejsebureau, brug da det tilsvarende ressource-endpoint i dit eget API for samme identifikator.

Hver payload-skema er dokumenteret pr. begivenhed i Webhooks API referencen.

HeaderBetydning
Wink-VersionWire-kontraktversion, 2.0.
Wink-Event-IdSamme som id i body — din idempotensnøgle.
Wink-Delivery-IdUnik pr. endpoint pr. begivenhed; ændres kun ved genlevering.
Wink-Event-TypeSamme som type i body.
Wink-Delivery-Attempt1-baseret forsøg nummer for denne levering.
Wink-SignatureHMAC-signatur — se nedenfor.

Hver webhook har en signeringshemmelighed (whsec_…), som Wink viser én gang, når du opretter webhooken eller roterer dens hemmelighed. Gem den som en adgangskode. Hver levering bærer

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

hvor t er et Unix-tidsstempel (sekunder) og v1 er den småbogstavede hex HMAC-SHA256 af strengen t + "." + rawBody, nøglekodet med din hemmelighed, og rawBody er de præcise request-body bytes som modtaget — serialiser ikke JSON på ny før verifikation. I 24 timer efter en hemmelighedsrotation bærer headeren en anden v1= værdi signeret med den tidligere hemmelighed; accepter leveringen hvis en hvilken som helst v1 matcher.

Verificer i fire trin: parse t og hver v1; genberegn HMAC over t.rawBody med din hemmelighed; sammenlign med en konstant-tids sammenligning; afvis hvis |nu − t| overstiger din tolerance (5 minutter anbefales).

// Node.js (Express-stil; sørg for at du har RAW body, ikke et parset objekt)
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)));
}

Roter hemmeligheden fra portalen eller med POST /api/managing-entity/{id}/webhook/{webhookId}/rotate-secret; svaret viser den nye hemmelighed én gang, og den gamle fortsætter med at verificere i 24 timer, mens du ruller den ud.

  • Svar med enhver 2xx inden for 10 sekunder for at bekræfte. Udfør tung behandling asynkront.
  • En 5xx, timeout, 408 eller 429 genforsøges med backoff: efter 1 minut, 5 minutter, 30 minutter, 2 timer, 6 timer, 12 timer, derefter dagligt — 10 forsøg over ca. 3 dage — hvorefter leveringen markeres som død.
  • Enhver anden 4xx behandles som “du afviste denne levering” og genforsøges ikke.
  • Hver begivenhed, levering og forsøg (status, svaruddrag) er synlig under Applications > Webhooks og via API’en (…/webhook/event/grid, …/webhook/delivery/grid). Du kan genlevere enhver levering (POST …/webhook/delivery/{deliveryId}/redeliver, som starter en ny retry-serie), genlevere alle døde leveringer for en webhook på én gang (POST …/webhook/{webhookId}/redeliver-dead), eller annullere en.
  • Leveringer opbevares i 30 dage.

Send dig selv en syntetisk webhook.test begivenhed fra portalen eller med POST /api/managing-entity/{id}/webhook/{webhookId}/test. Den er signeret og leveret præcis som en rigtig begivenhed, så du kan verificere dit endpoint, din signaturkontrol og din idempotenshåndtering før du abonnerer på live-begivenheder.

  • Brug HTTPS — Wink sender payloads kun til HTTPS-endpoints.
  • Svar hurtigt — Returner en 200 OK så snart du modtager payloaden. Udfør tung behandling asynkront.
  • Idempotens — Din handler bør være idempotent; dedupliker på Wink-Event-Id. Wink genforsøger, når den ikke modtager et 2xx svar.
  • Valider kilden — Verificer Wink-Signature headeren (se Verificering af signaturer) før behandling; afvis alt der fejler.
  • Logning — Log hver webhook-payload du modtager. Det gør fejlfinding af integrationsproblemer meget nemmere.

Du kan deaktivere en webhook uden at slette den. Dette pauser leveringen, så du kan fejlfinde uden at miste din konfiguration. Når du er klar, skifter du den til igen.

Sletning af en webhook fjerner den permanent. Enhver integration, der er afhængig af den webhook, vil stoppe med at modtage notifikationer.