Webhooks

Ereignisse statt Nachfragen

Ein Abo je Adresse, signierte Zustellungen, Wiederholungen mit wachsendem Abstand. Ereignisse entstehen bei JEDER Änderung — auch wenn sie über ein Portal oder das Dashboard kommt, nicht über diese API.

Ereignis

EreignisWann es feuert
reservation.createdEine Buchung ist entstanden — über welchen Kanal auch immer.
reservation.updatedEine bestehende Buchung hat sich geändert.
reservation.cancelledEine Buchung wurde storniert. Eigenes Ereignis, weil darauf anders zu reagieren ist als auf eine Änderung.
availability.changedDer Kalender eines Objekts hat sich geändert (Buchung, Sperre, Freigabe).
rate.changedEin Tagespreis oder eine Aufenthaltsregel hat sich geändert.
task.createdEine Aufgabe ist entstanden.
task.completedEine Aufgabe wurde abgeschlossen.

Abo anlegen

Eine https-Adresse und die Ereignisse, die du willst. Optional nur für bestimmte Objekte. Interne Adressen werden abgelehnt — die Prüfung läuft beim Anlegen UND vor jeder einzelnen Zustellung.

Anfrage
curl -X POST https://open-api.mynextdays.com/v1/webhooks \
  -H 'Authorization: Bearer <access_token>' \
  -H 'Content-Type: application/json' \
  -d '{
    "url": "https://meine-anwendung.de/haken/mynextdays",
    "events": ["reservation.created", "reservation.cancelled"]
  }'

Die Antwort enthält das Signier-Secret genau einmal. Jetzt speichern — es wird nie wieder ausgeliefert.

Was ankommt

Schmal gehalten: IDs und die Felder, die die Änderung beschreiben. Den vollen Datensatz holst du bei Bedarf über die API — so bekommt ein Empfänger nichts zugestellt, was er inzwischen nicht mehr sehen dürfte.

Zustellung
{
  "id": "b7c9e1a2-…",
  "event": "reservation.created",
  "created_at": "2026-08-21T09:14:02.418Z",
  "property_id": "8f14e45f-…",
  "data": {
    "reservation_id": "d41d8cd9-…",
    "property_id": "8f14e45f-…",
    "unit_id": "1c3b5a7d-…",
    "status": "confirmed",
    "channel": "booking",
    "check_in": "2026-09-10",
    "check_out": "2026-09-13",
    "booked_at": "2026-08-20T18:33:11Z",
    "received_at": "2026-08-21T09:14:01Z"
  }
}

Signatur prüfen

Jede Zustellung trägt einen Header mit Zeitstempel und HMAC-SHA256 über ZEITSTEMPEL.BODY, berechnet mit dem Secret deines Abos. Weil der Zeitstempel mitsigniert ist, erkennst du eine aufgezeichnete und später erneut eingespielte Zustellung — bei einer Signatur nur über den Body ist das nicht möglich.

MyNextDays-Signature: t=<unix-sekunden>,v1=<hmac-sha256>

  • Nimm den ROHEN Körper der Anfrage, nicht das geparste und neu serialisierte Objekt — eine andere Byte-Folge ergibt eine andere Signatur. Das ist der häufigste Grund für „Signatur passt nicht“.
  • Prüfe das Alter über den Zeitstempel; fünf Minuten Toleranz sind ein guter Wert.
  • Vergleiche zeitkonstant (timingSafeEqual, hmac.compare_digest). Ein normales == macht die Signatur erratbar.
Signatur prüfen (Node)
import crypto from "node:crypto";

// WICHTIG: den ROHEN Body verwenden, nicht das geparste Objekt. Ein
// re-serialisiertes JSON hat eine andere Byte-Folge und damit eine andere
// Signatur — der häufigste Grund für „Signatur passt nicht".
export function signaturPruefen(rohBody, header, secret) {
  const teile = new Map(
    header.split(",").map((t) => t.split("=").map((s) => s.trim())),
  );
  const t = teile.get("t");
  const empfangen = teile.get("v1");
  if (!t || !empfangen) return false;

  // Alter der Zustellung prüfen: der Zeitstempel ist mitsigniert, damit eine
  // aufgezeichnete Zustellung nicht später erneut eingespielt werden kann.
  const alterSekunden = Math.abs(Date.now() / 1000 - Number(t));
  if (alterSekunden > 300) return false;

  const erwartet = crypto
    .createHmac("sha256", secret)
    .update(`${t}.${rohBody}`)
    .digest("hex");

  // Zeitkonstanter Vergleich — ein == würde die Signatur erratbar machen.
  return crypto.timingSafeEqual(
    Buffer.from(erwartet),
    Buffer.from(empfangen),
  );
}

Wiederholungen

Wiederholungen

Antwortet deine Adresse nicht mit 2xx, wird bis zu zehnmal erneut zugestellt — mit wachsendem Abstand von einer Minute bis zu einer Stunde. Antworte schnell und verarbeite danach; ein langsamer Empfänger wird als Fehler gewertet.

Reihenfolge

Nicht garantiert. Nutze created_at des Ereignisses, um eine ältere Zustellung nicht über eine neuere zu schreiben.

Doppelte Zustellung

Ist unwahrscheinlich, aber möglich — behandle die Ereignis-id als Schlüssel und verarbeite jede nur einmal. Diese Zusage gilt für jeden Webhook-Anbieter, nicht nur für diesen.

Nach einem Ausfall nachholen

Waren deine Server weg, holst du die verpassten Ereignisse über GET /v1/events?since=… nach — älteste zuerst, mit denselben ids wie die Zustellung, höchstens 30 Tage zurück. Ein Push allein ist keine Zustellgarantie: irgendwann laufen die Wiederholversuche aus, und ohne diesen Schritt fehlen dir genau die Ereignisse, von denen du nie erfahren hast.

Nächste SeiteEinschränkungen
Webhooks — API & Entwickler — myNextDays