Öffentliche API: Buchungs-Webhooks in Echtzeit empfangen

Aktualisiert

Webhooks sind der schnellste Weg, mit Nowistay synchron zu bleiben. Statt die API alle paar Minuten abzufragen, um neue oder geänderte Reservierungen zu erkennen, teilen Sie Nowistay mit, wohin die Ereignisse gesendet werden sollen, und Ihr Dienst erhält sie, sobald sie eintreten. Dieser Artikel zeigt Ihnen, wie Sie einen Webhook erstellen, die Signatur prüfen und Wiederholungen behandeln.

Kurze Erinnerung: Was die öffentliche API ist

Mit der öffentlichen REST-API von Nowistay können Ihre Tools und Partner Nowistay-Daten über HTTPS lesen und schreiben. Sie authentifizieren sich mit OAuth2 (Authorization Code + PKCE), erhalten ein Access Token und rufen Endpunkte unter /public/v1/* auf. Webhooks sind das Push-Gegenstück: dieselben Daten, dieselbe Struktur wie GET /public/v1/bookings/{id}, aber Nowistay sendet sie Ihnen, wenn sich etwas ändert.

Haben Sie OAuth noch nicht eingerichtet, beginnen Sie mit der Hauptanleitung: Die öffentliche REST-API von Nowistay nutzen. Sie behandelt Registrierung, Zustimmungsablauf, Scopes und das Testen von Aufrufen im Playground der Dokumentation.

Was Sie erhalten

  • Zustellung der Ereignisse booking.created und booking.updated in Echtzeit.
  • Denselben JSON-Body wie GET /public/v1/bookings/{id}, einschließlich Daten, Kanal, Status, Beträgen, für Aufträge relevanten Feldern und Ihren benutzerdefinierten Buchungsparametern.
  • Eine HMAC-SHA256-Signatur, damit Sie prüfen können, dass jede Anfrage wirklich von Nowistay kommt.
  • Automatische Wiederholungen mit exponentiellem Backoff, wenn Ihr Endpunkt ausfällt oder in ein Timeout läuft.
  • Automatische Deaktivierung nach 72 Stunden ununterbrochener Fehler (Sie können sie über die API wieder aktivieren).

Bevor Sie starten

  • Sie brauchen das Abonnement KI-Channel-Manager für die Unterkunft. Ohne es werden Zustellungen übersprungen.
  • Das OAuth-Token, mit dem Sie den Webhook erstellen, muss den Scope webhooks.write enthalten. POST /public/v1/webhooks erfordert außerdem bookings.read, weil die Nutzdaten ein vollständiges Buchungsdetail sind.
  • Ihre Empfangs-URL muss im öffentlichen Internet erreichbar sein, in der Produktion über HTTPS bereitgestellt werden und innerhalb von 10 Sekunden mit einem 2xx-Status antworten.
  • Ein Webhook ist an eine Unterkunft gebunden. Sie können bis zu 3 Webhooks pro Unterkunft registrieren.

Schritt 1. Einen Webhook erstellen

curl -X POST https://api.nowistay.com/public/v1/webhooks \
  -H "Authorization: Bearer nis_access_token_example" \
  -H "Content-Type: application/json" \
  -d '{
    "propertyId": 101,
    "url": "https://partner.example.com/nowistay/webhooks",
    "events": ["booking.created", "booking.updated"],
    "description": "PMS sync"
  }'

Antwort:

{
  "id": 801,
  "propertyId": 101,
  "url": "https://partner.example.com/nowistay/webhooks",
  "events": ["booking.created", "booking.updated"],
  "description": "PMS sync",
  "status": "active",
  "createdAt": "2026-05-27T16:40:00Z",
  "updatedAt": "2026-05-27T16:40:00Z",
  "signingSecret": "whsec_9npwH6J8QyZp1L8U3xqG7sN2"
}

Speichern Sie das signingSecret jetzt. Es wird nur einmal bei der Erstellung zurückgegeben. Über die API können Sie es nicht noch einmal abrufen. Wenn Sie es verlieren, löschen Sie den Webhook und erstellen Sie einen neuen.

Schritt 2. Das erste Ereignis empfangen

Jede Zustellung ist ein HTTP-POST an Ihre URL mit diesen Headern:

  • Content-Type: application/json
  • User-Agent: Nowistay-Webhooks/1.0
  • Nowistay-Webhook-Id: 801
  • Nowistay-Webhook-Event-Id: evt_LkP2sxR9zV8QyW... (eindeutig pro Ereignis)
  • Nowistay-Webhook-Event-Type: booking.updated
  • Nowistay-Webhook-Timestamp: 1779292800 (Unix-Sekunden)
  • Nowistay-Webhook-Signature: v1=3a7b...e1c (HMAC-SHA256 hex)

Und einem JSON-Body in dieser Form:

{
  "id": "evt_LkP2sxR9zV8QyW...",
  "type": "booking.updated",
  "createdAt": "2026-05-27T16:40:00Z",
  "apiVersion": "2026-05-27",
  "propertyId": 101,
  "bookingId": 9001,
  "data": {
    "booking": {
      "id": 9001,
      "propertyId": 101,
      "arrival": "2026-07-14",
      "departure": "2026-07-18",
      "status": "confirmed",
      "channel": "airbnb",
      "reservationNumber": "HMABCDE",
      "guest": { "firstName": "Maya", "lastName": "M." },
      "amounts": { "amount": "620.00", "currency": "EUR" },
      "identity": { "status": "verified" }
    }
  }
}

Ihr Endpunkt sollte mit einem beliebigen 2xx-Status antworten (200 oder 204 sind üblich). Alles andere oder eine Antwort, die länger als 10 Sekunden dauert, gilt als Fehler und löst eine Wiederholung aus.

Schritt 3. Die Signatur prüfen

Prüfen Sie immer die Signatur, bevor Sie dem Body vertrauen. Ohne Prüfung könnte jeder, der Ihre URL errät, gefälschte Ereignisse an Ihren Dienst senden.

Nowistay berechnet die Signatur so:

signature = "v1=" + HMAC_SHA256(
  signing_secret,
  timestamp + "." + event_id + "." + raw_request_body
).hex()

Berechnen Sie sie auf Ihrer Seite neu, mit den Headern Nowistay-Webhook-Timestamp und Nowistay-Webhook-Event-Id und dem exakten rohen Request-Body (parsen und serialisieren Sie das JSON vor der Prüfung nicht erneut, sonst riskieren Sie Byte-Abweichungen).

Node.js-Beispiel

import crypto from "node:crypto";

function verify(req, signingSecret) {
  const timestamp = req.headers["nowistay-webhook-timestamp"];
  const eventId = req.headers["nowistay-webhook-event-id"];
  const signature = req.headers["nowistay-webhook-signature"];
  const rawBody = req.rawBody; // Buffer of the raw HTTP body

  const signed = Buffer.concat([
    Buffer.from(`${timestamp}.${eventId}.`, "utf8"),
    rawBody,
  ]);
  const expected = "v1=" + crypto
    .createHmac("sha256", signingSecret)
    .update(signed)
    .digest("hex");

  const a = Buffer.from(signature);
  const b = Buffer.from(expected);
  return a.length === b.length && crypto.timingSafeEqual(a, b);
}

Python-Beispiel

import hmac, hashlib

def verify(request, signing_secret: str) -> bool:
    timestamp = request.headers["Nowistay-Webhook-Timestamp"]
    event_id = request.headers["Nowistay-Webhook-Event-Id"]
    signature = request.headers["Nowistay-Webhook-Signature"]
    raw_body = request.body  # bytes

    signed = f"{timestamp}.{event_id}.".encode("utf-8") + raw_body
    expected = "v1=" + hmac.new(
        signing_secret.encode("utf-8"),
        signed,
        hashlib.sha256,
    ).hexdigest()

    return hmac.compare_digest(signature, expected)

Prüfen Sie außerdem, dass der Zeitstempel aktuell ist (zum Beispiel innerhalb der letzten 5 Minuten), um sich vor Replay-Angriffen zu schützen.

Was in den Nutzdaten enthalten ist (und was nicht)

Das Objekt data.booking entspricht dem, was GET /public/v1/bookings/{id} ohne den Scope bookings.sensitive.read zurückgibt. Das heißt:

  • Enthalten: Daten, Kanal, Status, Beträge, Vor- und Nachname des Gastes, Erwachsene/Kinder, benutzerdefinierte Buchungsparameter (wenn für den Webhook aktiviert).
  • Nicht enthalten: E-Mail, Telefon, Adresse, Stadt, Postleitzahl, Land und Sprache des Gastes sowie der Smart-Lock-Code. Sie gelten als sensibel, und Nowistay sendet sie nicht an Webhook-Abonnenten.

Braucht Ihr Tool eines dieser sensiblen Felder, rufen Sie das Buchungsdetail über die API mit einem Token ab, das den Scope bookings.sensitive.read enthält. Die bookingId im Webhook-Umschlag ist die passende Eingabe für diesen Aufruf.

curl https://api.nowistay.com/public/v1/bookings/9001 \
  -H "Authorization: Bearer nis_access_token_with_sensitive_scope"

Wiederholungen und die automatische Deaktivierung nach 72 Stunden

Gibt Ihr Endpunkt einen Nicht-2xx-Status zurück, läuft in ein Timeout oder schlägt aus einem anderen Grund fehl, verwirft Nowistay das Ereignis nicht. Es plant eine Wiederholung, mit exponentiellem Backoff und etwas Jitter:

    1. Wiederholung: etwa 1 Minute nach dem Fehler.
    1. Wiederholung: etwa 2 Minuten später.
    1. Wiederholung: etwa 4 Minuten später, dann 8, 16, 32 und so weiter.
  • Obergrenze: Wiederholungen liegen höchstens 6 Stunden auseinander.

Das geht weiter, bis Ihr Endpunkt das Ereignis akzeptiert oder bis der Webhook mehr als 72 Stunden am Stück fehlschlägt. Dann setzt Nowistay den Status des Webhooks auf disabled und sendet keine neuen Ereignisse mehr daran. Die Fehlerzähler werden bei jeder erfolgreichen Zustellung zurückgesetzt, ein einzelner Vorfall löst die automatische Deaktivierung also nie aus.

Zustellungsprotokolle werden 30 Tage aufbewahrt und dann gelöscht.

Einen deaktivierten Webhook reaktivieren

Ein deaktivierter Webhook lässt sich über die API wieder einschalten, sobald Ihr Endpunkt wieder in Ordnung ist. Senden Sie ein PATCH mit status: "active":

curl -X PATCH https://api.nowistay.com/public/v1/webhooks/801 \
  -H "Authorization: Bearer nis_access_token_example" \
  -H "Content-Type: application/json" \
  -d '{"status": "active"}'

Nowistay spielt die Ereignisse, die während der Deaktivierung ausgelöst wurden, nicht erneut ab. Haben Sie welche verpasst, führen Sie einmalig einen Nachabruf mit GET /public/v1/bookings und einem Datumsfilter durch und setzen Sie dann Ihren Webhook-gesteuerten Ablauf fort.

Pausieren, fortsetzen, löschen

Sie können Zustellungen vorübergehend pausieren (zum Beispiel während eines Wartungsfensters), ohne die Webhook-Konfiguration zu verlieren:

# Pause
curl -X PATCH https://api.nowistay.com/public/v1/webhooks/801 \
  -H "Authorization: Bearer nis_access_token_example" \
  -H "Content-Type: application/json" \
  -d '{"status": "paused"}'

# Resume
curl -X PATCH https://api.nowistay.com/public/v1/webhooks/801 \
  -H "Authorization: Bearer nis_access_token_example" \
  -H "Content-Type: application/json" \
  -d '{"status": "active"}'

# Delete permanently
curl -X DELETE https://api.nowistay.com/public/v1/webhooks/801 \
  -H "Authorization: Bearer nis_access_token_example"

Im selben Aufruf können Sie auch die url, die Liste events oder die description ändern. Das Ändern der URL erneuert das Signing Secret nicht.

Ihre Webhooks einsehen

# List all webhooks (optionally filtered by property)
curl "https://api.nowistay.com/public/v1/webhooks?propertyId=101" \
  -H "Authorization: Bearer nis_access_token_example"

# Read one webhook
curl https://api.nowistay.com/public/v1/webhooks/801 \
  -H "Authorization: Bearer nis_access_token_example"

Die Listenantwort zeigt dieselben Felder wie die Antwort beim Erstellen, abzüglich des Signing Secrets (es wird nur bei der Erstellung zurückgegeben).

URL-Regeln und Limits

  • Absolute HTTP- oder HTTPS-URL, höchstens 2048 Zeichen. In der Produktion ist HTTPS erforderlich.
  • Keine Basic-Auth-Zugangsdaten in der URL (https://user:pass@... wird abgelehnt).
  • Kein localhost, keine privaten oder reservierten IP-Bereiche. Nowistay löst den Hostnamen außerdem zum Zustellzeitpunkt auf und blockiert Aufrufe, die auf private Adressen zeigen.
  • Keine HTTP-Weiterleitungen. Nowistay folgt ihnen nicht, die Zustellung wird als fehlgeschlagen markiert, wenn Ihr Server weiterleitet.
  • Höchstens 3 Webhooks pro Unterkunft, über alle Ihre Apps hinweg.
  • Beschreibung: optional, höchstens 120 Zeichen.

Bewährte Vorgehensweisen

  • Prüfen Sie die Signatur jedes Mal. Sie ist das Einzige, was beweist, dass der Aufruf wirklich von Nowistay kommt.
  • Seien Sie idempotent. Dieselbe Ereignis-ID kann nach einem Fehler erneut zugestellt werden. Speichern Sie die id aus dem Body und überspringen Sie das Ereignis, wenn Sie es schon verarbeitet haben.
  • Antworten Sie schnell. Bestätigen Sie den Aufruf sofort mit einem 2xx und verarbeiten Sie das Ereignis in einem Hintergrundjob, wenn es aufwendig ist.
  • Protokollieren Sie die Header. Bewahren Sie Nowistay-Webhook-Event-Id und die Request-ID in Ihren Logs auf. Das beschleunigt den Support.
  • Behandeln Sie den Webhook als Hinweis, nicht als Quelle der Wahrheit. Braucht Ihre Geschäftslogik sensible Felder oder die allerneuesten Daten, rufen Sie nach dem Empfang des Ereignisses GET /public/v1/bookings/{id} auf.

Wie es weitergeht

Bereit, Ihre Ferienunterkunft auf Autopilot zu schalten?

Schließen Sie sich über 1.000 Property Managern an, die dank KI-gestützter Gästekommunikation jede Woche Stunden sparen.