Die öffentliche Nowistay-REST-API nutzen

Aktualisiert

Die öffentliche Nowistay-REST-API verbindet Ihre Skripte und Partnerintegrationen mit Ihrem Konto. Lesen und aktualisieren Sie Unterkunftseinstellungen, Kalender, Buchungen und Aufträge; verwalten Sie Gästedatensätze, Konversationen, privates Wissen und Willkommensführer; fordern Sie Buchungszahlungen und Stornierungserstattungen an und lesen Sie Upsells, Käufe und Portfolioberichte. Die genauen Request- und Response-Schemas finden Sie unter /public/docs und /public/openapi.json.

Dieser Leitfaden zeigt Ihnen drei Wege: den schnellsten Weg, die API auszuprobieren (der interaktive Docs-Playground), den einfachsten Weg für eigene Skripte (ein in der App erstellter persönlicher API-Zugang) und den Standard-OAuth-Ablauf, den Sie beim Entwickeln einer App für andere Gastgeber verwenden.

Was Sie mit der API tun können

  • Unterkünfte und Kalender: Unterkünfte suchen und lesen, Betriebseinstellungen aktualisieren sowie tägliche Verfügbarkeit, Preise und Aufenthaltsbeschränkungen verwalten.
  • Buchungen und Zahlungen: Direktbuchungen erstellen, berechtigte Reservierungen aktualisieren, bei der Erstellung eine Zahlung anfordern, Stornierungserstattungen anweisen und den unbedenklichen Status von Zahlungsanforderungen lesen.
  • Gäste: Ihren Kundenstamm lesen, Gästedatensätze erstellen und den Aufenthaltsverlauf abrufen.
  • Aufträge: Aufträge erstellen, aktualisieren und zuweisen, Arbeitslasten filtern sowie Auftragsdetails und Abschlussberichte lesen.
  • Konversationen: Gästekonversationen finden, deren Nachrichten lesen und eine Gastgeberantwort über den gewählten Zustellkanal senden.
  • Privates Wissen: Fragen und Antworten zu Unterkünften lesen, hinzufügen und aktualisieren oder in andere Unterkünfte übernehmen.
  • Willkommensführer: lokalisierte Einleitungen und strukturierte Seiten bearbeiten, Seitenpositionen ändern und Bilder hochladen.
  • Upsells und Berichte: den Upsell-Katalog und Buchungskäufe lesen sowie Buchungs- oder Auftragslisten im Tabellenformat exportieren.
  • Bestehende Werkzeuge: benutzerdefinierte Buchungsparameter, Lesezugriff auf Teammitglieder, Aktivitätsfeeds der Unterkünfte und Buchungs-Webhooks bleiben verfügbar.

Bevor Sie beginnen

Der Zugriff wird anhand der Eigentümerschaft und der Assistenten-Berechtigung der Unterkunft geprüft. Für Vorgänge, die davon abhängen, ist eine aktive PMS-Verbindung erforderlich, darunter die Kalenderverwaltung und das Erstellen von Direktbuchungen. Andere Ressourcen benötigen zum reinen Lesen oder Bearbeiten keine PMS-Verbindung.

  • Sie benötigen ein aktives KI-Channel-Manager-Abonnement für die Unterkünfte, die Sie freigeben möchten. Die API gibt nur Unterkünfte zurück, bei denen diese Berechtigung aktiv ist.
  • Sie melden sich als Gastgeber oder Property Manager an. Die API legt nie Unterkünfte offen, die Ihnen nicht gehören.
  • Die Basis-URL lautet https://api.nowistay.com
  • Alle Endpunkte unter /public/v1/* erfordern ein OAuth2-Zugriffstoken, das als Authorization: Bearer ... gesendet wird.

Der schnellste Weg: im Docs-Playground ausprobieren

Öffnen Sie https://api.nowistay.com/public/docs in Ihrem Browser. Die Seite ist eine vollständige Swagger-UI der API mit einem integrierten OAuth-Playground, der automatisch einen Client für Sie registriert. Zum Testen der Aufrufe ist keine Programmierung nötig.

  1. Laden Sie die Seite komplett neu (Cmd+Shift+R auf dem Mac, Strg+F5 unter Windows).
  2. Warten Sie, bis das kleine Banner oben OAuth playground ready (OAuth-Playground bereit) anzeigt.
  3. Klicken Sie oben rechts auf die grüne Schaltfläche Authorize (Autorisieren).
  4. Klicken Sie im Dialog im Bereich OAuth2 auf Authorize (Autorisieren).
  5. Sie werden zur Anmelde- und Zustimmungsseite von Nowistay weitergeleitet.
  6. Melden Sie sich als Gastgeber oder Property Manager mit dem KI-Channel-Manager-Abonnement an.
  7. Prüfen Sie die Scopes, die der Playground anfordert, und stimmen Sie zu.
  8. Sie landen wieder auf /public/docs, bereits authentifiziert.
  9. Öffnen Sie GET /public/v1/properties, klicken Sie auf Try it out (Ausprobieren) und dann auf Execute (Ausführen).
  10. In der Antwort sollten Ihre Unterkünfte erscheinen.

Von hier aus können Sie jeden Endpunkt mit einem Klick ausprobieren, das exakte JSON sehen, das Nowistay zurückgibt, und für jeden Aufruf den cURL-Befehl kopieren. Das ist der empfohlene Weg, die API zu erkunden, bevor Sie Code schreiben.

Wichtig: Der Playground-Client existiert nur in Ihrem Browser. Zum Testen ist das in Ordnung, aber für eine echte Integration sollten Sie einen persönlichen API-Zugang erstellen oder Ihren eigenen OAuth-Client registrieren (beides wird unten erklärt).

Eigene Skripte: einen persönlichen API-Zugang erstellen

Wenn Sie Ihr eigenes Konto automatisieren (ein Berichtsskript, eine Synchronisierung mit Ihrem Buchhaltungstool, ein kleines Dashboard), brauchen Sie den vollständigen OAuth-Ablauf überhaupt nicht. Erstellen Sie in der App einen persönlichen API-Zugang und tauschen Sie ihn in einem einzigen Aufruf gegen ein Token. Kein Zustimmungsbildschirm, keine Refresh-Tokens, die Sie verwalten müssen.

  1. Öffnen Sie in der App das Menü und gehen Sie zu Mein Konto > Entwickler, oder öffnen Sie direkt app.nowistay.com/hub/user/developer.
  2. Klicken Sie auf Neue Zugangsdaten.
  3. Geben Sie einen aussagekräftigen Namen ein (zum Beispiel Reporting script) und aktivieren Sie nur die Berechtigungen, die Sie benötigen.
  4. Klicken Sie auf Zugangsdaten erstellen. Der geheime Schlüssel wird nur einmal angezeigt: Kopieren Sie ihn jetzt und bewahren Sie ihn sicher auf. Sie können ihn später nicht mehr einsehen.

Ihr Skript tauscht die Zugangsdaten dann gegen ein Zugriffstoken (eine Stunde gültig) und ruft die API auf:

curl -X POST https://api.nowistay.com/public/oauth/token \
  -H "Content-Type: application/x-www-form-urlencoded" \
  --data-urlencode "grant_type=client_credentials" \
  --data-urlencode "client_id=YOUR_CLIENT_ID" \
  --data-urlencode "client_secret=YOUR_CLIENT_SECRET"

Läuft das Token ab, fordern Sie auf dieselbe Weise ein neues an. In diesem Ablauf gibt es kein Refresh-Token, und das ist der Sinn: zwei Zeilen Code, nichts zu beaufsichtigen.

Ihre Zugangsdaten verwalten

  • Zuletzt verwendet zeigt, wann die jeweiligen Zugangsdaten zuletzt die API aufgerufen hat. So erkennen Sie am leichtesten ein altes Skript, das noch läuft, oder Zugangsdaten, die Sie bedenkenlos entfernen können.
  • Secret erneuern erzeugt einen neuen geheimen Schlüssel, falls der aktuelle kompromittiert sein könnte oder wenn Sie Schlüssel regelmäßig rotieren. Der neue Schlüssel wird einmalig angezeigt; der bisherige Schlüssel funktioniert noch 7 Tage weiter, damit Ihr Skript umgestellt werden kann, danach nicht mehr.
  • Löschen entfernt Zugangsdaten, die Sie nicht mehr nutzen. Alles, was sie noch verwendet, funktioniert sofort nicht mehr.

Sie können bis zu 10 Zugangsdaten erstellen, jeweils mit eigenem Namen und eigenen Berechtigungen. Zugangsdaten lesen und schreiben nur die Daten, auf die Ihr eigenes Konto zugreifen kann, und benötigen dasselbe aktive KI-Channel-Manager-Abonnement wie die übrige API.

So fügen Sie einem bestehenden API-Token Scopes hinzu

Die Scopes eines bestehenden Tokens oder persönlichen Zugangs lassen sich nicht bearbeiten. Erstellen Sie stattdessen neue Zugangsdaten mit dem vollständigen Satz an Berechtigungen, den Ihre Integration benötigt. Bestehende Clients, Zugriffstoken, Autorisierungscodes und Refresh-Tokens behalten ihre ursprünglichen Berechtigungen; es werden keine Berechtigungen automatisch hinzugefügt.

Persönliche Zugangsdaten: ersetzen, testen, dann umschalten

  1. Öffnen Sie Mein Konto > Entwickler oder rufen Sie https://app.nowistay.com/hub/user/developer auf. Notieren Sie die Berechtigungen, die die bestehende Integration verwendet.
  2. Klicken Sie auf Neue Zugangsdaten. Geben Sie dem Ersatz einen erkennbaren Namen und wählen Sie die bisherigen Berechtigungen, die Sie weiterhin brauchen, plus die neuen Scopes. Zum Beispiel benötigen Preisänderungen im Kalender calendar.write; das Senden von Nachrichten messages.write; das Anfordern einer Buchungszahlung sowohl bookings.write als auch payments.write.
  3. Klicken Sie auf Zugangsdaten erstellen und kopieren Sie die einmalig angezeigte Client-ID und das Client-Secret sicher.
  4. Fordern Sie mit POST /public/oauth/token, grant_type=client_credentials und den neuen Zugangsdaten ein neues Zugriffstoken an. Prüfen Sie den zurückgegebenen scope-Wert und testen Sie einen Endpunkt, den diese Scopes erlauben. GET /public/v1/properties erfordert ausdrücklich properties.read.
  5. Aktualisieren Sie die Zugangsdaten und das zwischengespeicherte Zugriffstoken Ihrer Integration. Prüfen Sie, dass sowohl die bisherigen Vorgänge als auch der neu freigeschaltete Vorgang funktionieren.
  6. Sobald alle Verbraucher umgestellt sind, verwenden Sie Löschen bei den bisherigen Zugangsdaten. Das Löschen beendet sofort alle Integrationen, die sie noch nutzen.

„Secret erneuern” fügt keine Scopes hinzu. Es ersetzt nur das Secret derselben Zugangsdaten; das vorherige Secret bleibt 7 Tage gültig. Auch das Aktualisieren oder erneute Anfordern eines Zugriffstokens kann die ursprüngliche Berechtigung nicht erweitern. Schreib-Scopes schließen Lese-Scopes nicht automatisch ein.

Partner-OAuth-Apps: neue Registrierung und neue Zustimmung

  1. Senden Sie POST /public/oauth/register mit dem vollständigen gewünschten Scope-Satz und Ihren üblichen Anwendungsangaben. Eine gleichwertige Registrierung mit exakt demselben Scope-Satz verwendet den passenden Client erneut; ein geänderter Scope-Satz erzeugt eine neue Registrierung. Speichern Sie die zurückgegebenen Client-Zugangsdaten.
  2. Starten Sie für diese Registrierung einen neuen Authorization-Code-Flow mit PKCE. Bitten Sie den Gastgeber, die gewünschten Scopes auf der Zustimmungsseite zu genehmigen, und tauschen Sie dann den neuen Code gegen Tokens.
  3. Stellen Sie die Integration nach dem Test auf diese Tokens um. Bestehende Refresh-Tokens und Autorisierungscodes behalten ihre ursprünglichen Scopes und können nicht verwendet werden, um Berechtigungen hinzuzufügen.

Laden Sie im Docs-Playground die Seite neu und autorisieren Sie erneut mit den erforderlichen Scopes. Neue Berechtigungen werden mit lesbaren Bezeichnungen und ihren Kennungen auf Englisch, Französisch, Spanisch, Deutsch, Niederländisch und Italienisch aufgeführt.

OAuth in einfachen Worten

Die API verwendet den Standard OAuth 2.1 mit dem Authorization-Code-Flow und PKCE. In einem Satz: Der Nutzer öffnet eine Nowistay-Seite und stimmt zu, Sie erhalten einen kurzen Code, tauschen ihn gegen ein Zugriffstoken und rufen die API mit diesem Token auf. Tokens laufen ab und lassen sich erneuern, ohne den Nutzer erneut zu behelligen.

Die drei OAuth-Endpunkte, die Sie verwenden:

  • Ihre App registrieren (einmalig): /public/oauth/register (POST)
  • Den Nutzer zur Zustimmung schicken: /public/oauth/authorize (GET, Browser-Weiterleitung)
  • Den Code gegen Tokens tauschen: /public/oauth/token (POST)

Sie können außerdem die OAuth-Metadaten unter /.well-known/oauth-authorization-server/public-api abrufen, die alle Endpunkte und unterstützten Funktionen auflisten.

Neue Apps starten als nicht verifiziert

Jeder kann einen OAuth-Client registrieren, daher brauchen Gastgeber eine Möglichkeit, eine brandneue App von einer etablierten Integration zu unterscheiden. Jede neu registrierte App startet deshalb als nicht verifiziert:

  • Der Zustimmungsbildschirm zeigt Gastgebern einen deutlichen Hinweis, dass die App von Nowistay nicht verifiziert wurde.
  • Eine nicht verifizierte App kann mit maximal 3 Gastgeberkonten verbunden werden.
  • Registrierte Clients, die nie eine einzige Verbindung abschließen, werden nach 30 Tagen automatisch bereinigt.

Sie entwickeln etwas für mehr als 3 Konten? Schreiben Sie dem Support mit Ihrem App-Namen, Ihrer Website und Ihrem Anwendungsfall. Sobald Ihre App verifiziert ist, verschwindet der Hinweis und die Kontenbegrenzung entfällt.

Verfügbare Scopes

Die REST-API unterstützt 25 Scopes, darunter zehn zusätzliche Berechtigungen für Unterkunftsänderungen, Nachrichten, Führer, Wissen, Gästeerstellung, Upsells und Zahlungen. Wählen Sie nur die Berechtigungen, die Ihre Integration benötigt.

  • properties.read: Unterkunftsdetails und Betriebseinstellungen lesen.
  • properties.write: Unterkunftsdetails und Betriebseinstellungen aktualisieren.
  • calendar.read: Verfügbarkeit, Übernachtungspreise und Aufenthaltsbeschränkungen lesen.
  • calendar.write: Verfügbarkeit, Übernachtungspreise und Aufenthaltsbeschränkungen aktualisieren.
  • bookings.read: Buchungen, Finanzdetails und den unbedenklichen Status von Zahlungsanforderungen lesen.
  • bookings.sensitive.read: Kontaktdaten der Gäste, Postanschriften und Zugangscodes in Buchungsantworten einbeziehen; erfordert zum Lesen zusätzlich bookings.read.
  • bookings.write: Direktbuchungen erstellen und aktualisieren. Zahlungsanforderungen und Erstattungen erfordern zusätzlich payments.write.
  • booking_parameters.read: Definitionen und Werte benutzerdefinierter Buchungsparameter lesen.
  • booking_parameters.write: Parameterdefinitionen und -werte erstellen und aktualisieren.
  • missions.read: Aufträge und Abschlussberichte lesen.
  • missions.write: Aufträge erstellen, aktualisieren und zuweisen.
  • activity.read: Aktivitätsprotokolle der Unterkünfte lesen.
  • team_members.read: Teammitglieder, Kontaktdaten und Unterkunftszuweisungen lesen.
  • webhooks.read: Webhook-Abonnements lesen.
  • webhooks.write: Webhook-Abonnements erstellen, aktualisieren, pausieren und löschen.
  • customers.read: Gästedatensätze, Kontaktdaten und Aufenthaltsverlauf lesen.
  • customers.write: Gästedatensätze erstellen.
  • upsells.read: den Upsell-Katalog und Buchungskäufe lesen.
  • payments.write: bei der Buchungserstellung eine Zahlung anfordern und vollständige oder teilweise Stornierungserstattungen anweisen; erfordert zusätzlich bookings.write.
  • messages.read: Gästekonversationen und Nachrichten lesen.
  • messages.write: Nachrichten an Gäste senden.
  • guides.read: Willkommensführer und Seiteninhalte lesen.
  • guides.write: Führer bearbeiten, Seiten erstellen und aktualisieren, Seitenpositionen ändern und Bilder hochladen.
  • knowledge.read: private Fragen und Antworten zu Unterkünften lesen.
  • knowledge.write: privates Wissen erstellen und aktualisieren. Das Kopieren erfordert zusätzlich knowledge.read.

Die acht Standard-REST-Scopes bleiben properties.read, calendar.read, bookings.read, booking_parameters.read, missions.read, activity.read, team_members.read und webhooks.read. Standardwerte erweitern bestehende Tokens nicht.

Vorgänge, die zwei Scopes erfordern

  • Zahlungsanforderungen und ausdrückliche vollständige/teilweise Stornierungserstattungen: bookings.write + payments.write. Eine Stornierung ohne Erstattung benötigt nur bookings.write.
  • Buchungsverlauf eines Gastes: customers.read + bookings.read.
  • Upsell-Käufe einer Buchung: upsells.read + bookings.read. Das Lesen des Katalogs benötigt nur upsells.read.
  • Kopieren von Wissen: knowledge.read + knowledge.write.
  • Ein Buchungs-PATCH, der Kernfelder und benutzerdefinierte Parameterwerte mischt: bookings.write + booking_parameters.write. Ein reiner Parameter-PATCH behält booking_parameters.write und funktioniert auch bei OTA-Buchungen.

Neue Schreib-Endpunkte geben nur minimale Aktionsergebnisse zurück, sofern das Token nicht auch den passenden Lese-Scope hat. Die bestehende Schwärzung von Buchungsdaten bleibt bestehen. Aufträge- und Konversations-Endpunkte enthalten den zugehörigen Buchungskontext unter ihren eigenen Scopes.

Schritt für Schritt: Ihre eigene Integration bauen

Diese Beispiele verwenden Platzhalter-IDs und -Zugangsdaten. Ersetzen Sie sie durch Ihre eigenen Werte. Dieser Ablauf gilt für Partner-Apps; persönliche Zugangsdaten verwenden client_credentials, wie oben gezeigt.

Schritt 1. Ihren OAuth-Client registrieren

Rufen Sie POST /public/oauth/register mit den benötigten Berechtigungen auf. Speichern Sie die zurückgegebenen Werte client_id und client_secret sicher. Das Beispiel fordert Lesezugriff auf Unterkünfte, Buchungen und Aufträge an.

curl -X POST https://api.nowistay.com/public/oauth/register \
  -H "Content-Type: application/json" \
  -d '{"clientName":"My integration","redirectUris":["https://my-app.example.com/oauth/callback"],"grantTypes":["authorization_code","refresh_token"],"responseTypes":["code"],"tokenEndpointAuthMethod":"client_secret_post","scope":"properties.read bookings.read missions.read"}'

Für einen öffentlichen Client ohne Backend verwenden Sie "tokenEndpointAuthMethod": "none" und PKCE, ohne Client-Secret.

Schritt 2. Den Nutzer zur Autorisierungs-URL schicken

Erzeugen Sie einen PKCE-Verifier, seine S256-Challenge und einen zufälligen state. Leiten Sie den Nutzer zum Autorisierungs-Endpunkt weiter. Die folgende URL steht in einer Zeile; kodieren Sie die Query-Werte per URL-Encoding.

https://api.nowistay.com/public/oauth/authorize?response_type=code&client_id=YOUR_CLIENT_ID&redirect_uri=https%3A%2F%2Fmy-app.example.com%2Foauth%2Fcallback&scope=properties.read%20bookings.read%20missions.read&state=RANDOM_STATE&code_challenge=BASE64URL_S256_HASH&code_challenge_method=S256

Der Gastgeber meldet sich an, prüft die Berechtigungen und genehmigt oder verweigert den Zugriff. Bei Genehmigung enthält der Callback einen einmaligen code und Ihren state. Weisen Sie einen Callback ab, dessen State nicht übereinstimmt.

https://my-app.example.com/oauth/callback?code=AUTHORIZATION_CODE&state=RANDOM_STATE

Schritt 3. Den Code gegen Tokens tauschen

curl -X POST https://api.nowistay.com/public/oauth/token \
  -H "Content-Type: application/x-www-form-urlencoded" \
  --data-urlencode "grant_type=authorization_code" \
  --data-urlencode "code=AUTHORIZATION_CODE" \
  --data-urlencode "redirect_uri=https://my-app.example.com/oauth/callback" \
  --data-urlencode "client_id=YOUR_CLIENT_ID" \
  --data-urlencode "client_secret=YOUR_CLIENT_SECRET" \
  --data-urlencode "code_verifier=ORIGINAL_PKCE_VERIFIER"

Die Antwort enthält access_token, token_type, expires_in, refresh_token und scope. Speichern Sie die Tokens sicher. Zugriffstoken gelten normalerweise eine Stunde; verwenden Sie die zurückgegebene Ablaufzeit.

Schritt 4. Die API aufrufen

Dieses Beispiel erfordert properties.read. Lesen Sie die Felder data und pagination in der Antwort.

curl "https://api.nowistay.com/public/v1/properties" \
  -H "Authorization: Bearer YOUR_ACCESS_TOKEN"

Schritt 5. Das Token bei Ablauf erneuern

curl -X POST https://api.nowistay.com/public/oauth/token \
  -H "Content-Type: application/x-www-form-urlencoded" \
  --data-urlencode "grant_type=refresh_token" \
  --data-urlencode "refresh_token=YOUR_REFRESH_TOKEN" \
  --data-urlencode "client_id=YOUR_CLIENT_ID" \
  --data-urlencode "client_secret=YOUR_CLIENT_SECRET"

Speichern Sie das Ersatz-Refresh-Token, das die Refresh-Antwort zurückgibt. Schlägt die Erneuerung fehl, starten Sie die Autorisierung neu. Die Erneuerung behält die zuvor gewährten Scopes. Persönliche Zugangsdaten haben kein Refresh-Token: Fordern Sie mit client_credentials ein neues Zugriffstoken an.

Endpunkt-Beispiele

Verfügbarkeit, Preise und Aufenthaltsbeschränkungen lesen

GET /public/v1/properties/{property_id}/calendar erfordert calendar.read. Übergeben Sie ein einschließliches Datum für from und to; eine Anfrage kann bis zu 730 Tage abdecken.

GET /public/v1/properties/101/calendar?from=2026-12-18&to=2026-12-20

Jeder Tag kann availability, rate, minStay, maxStay, stopSell, closedToArrival, closedToDeparture, restricted und restrictionReasons zurückgeben. availability ist das nach bestätigten Buchungen verbleibende verkaufbare Kontingent. Die Beschränkungsfelder erklären, warum ein Datum oder eine Check-in-/Check-out-Aktion eingeschränkt ist.

Den Kalender einer Unterkunft aktualisieren

PATCH /public/v1/properties/{property_id}/calendar erfordert calendar.write. Die Anfrage ist partiell: Senden Sie nur die Steuerelemente, die sich ändern sollen; ausgelassene Felder bleiben unverändert.

{
  "from": "2026-12-18",
  "to": "2026-12-31",
  "availability": 1,
  "rate": 145.0,
  "minStay": 2,
  "maxStay": 14,
  "stopSell": false,
  "closedToArrival": false,
  "closedToDeparture": false,
  "daysOfWeek": [0, 1, 2, 3, 4]
}

daysOfWeek ist optional: 0 ist Montag und 6 ist Sonntag. Lassen Sie es weg, um jedes Datum im Bereich zu aktualisieren. Die Antwort meldet daysUpdated und die normalisierte Aktualisierung, die angewendet wurde. Änderungen werden über das Nowistay PMS synchronisiert.

Kalendervorgänge erfordern Eigentümerschaft, die Assistenten-Berechtigung und eine aktive Nowistay-Kalenderverwaltung. Um Kalender-Scopes in einer bestehenden Integration zu aktivieren, folgen Sie oben dem Abschnitt So fügen Sie einem bestehenden API-Token Scopes hinzu; das Aktualisieren eines Tokens oder das Erneuern seines Secrets reicht nicht aus.

Buchungen einer Unterkunft in einem Zeitraum auflisten

Unterstützte Filter sind propertyId, wiederholtes propertyIds, status, channel, fromDate und toDate. Die Standard-JSON-Paginierung verwendet limit (maximal 100) und offset. Die Datumsfilter für Buchungen behalten ihre Überlappungssemantik: departure >= fromDate und arrival <= toDate.

curl "https://api.nowistay.com/public/v1/bookings?propertyId=101&fromDate=2026-12-01&toDate=2026-12-31&status=confirmed" \
  -H "Authorization: Bearer YOUR_ACCESS_TOKEN"

Buchungsdetails mit Kontaktdaten des Gastes abrufen

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

Erfordert den zusätzlichen Scope bookings.sensitive.read. Ohne ihn werden email, phone und der Smart-Lock-Code weggelassen.

Eine Direktbuchung aktualisieren

Änderungen an Kernfeldern einer Buchung erfordern bookings.write und eine berechtigte Direktbuchung. OTA-Reservierungen bleiben für Kernfelder schreibgeschützt. Ein PATCH, der nur customParameters enthält, unterstützt auch OTA-Buchungen und verwendet booking_parameters.write.

curl -X PATCH "https://api.nowistay.com/public/v1/bookings/9001" \
  -H "Authorization: Bearer YOUR_ACCESS_TOKEN" \
  -H "Content-Type: application/json" \
  -d '{
  "notes": "Guest requested a baby cot.",
  "reservationNumber": "DIRECT-9001",
  "silent": true
}'

PATCH-Anfragen für bestehende Buchungen verwenden standardmäßig silent=true. Setzen Sie silent=false, um die üblichen Aktualisierungsbenachrichtigungen auszulösen. Die Buchungserstellung verwendet standardmäßig silent=false. Ausgelassene Felder bleiben unverändert, und bestehende unterstützte null-Werte leeren weiterhin Felder. Die Verfügbarkeitssynchronisierung bleibt Teil des gemeinsamen Vorgangs.

Ein benutzerdefiniertes Feld zu Ihren Buchungen hinzufügen

Benutzerdefinierte Buchungsparameter sind nützlich, wenn Sie Daten aus Ihrem eigenen System in jeder Nowistay-Reservierung abbilden möchten.

curl -X POST "https://api.nowistay.com/public/v1/booking-parameters" \
  -H "Authorization: Bearer YOUR_ACCESS_TOKEN" \
  -H "Content-Type: application/json" \
  -d '{
  "key": "external_status",
  "name": "External status"
}'

curl -X PATCH "https://api.nowistay.com/public/v1/bookings/9001" \
  -H "Authorization: Bearer YOUR_ACCESS_TOKEN" \
  -H "Content-Type: application/json" \
  -d '{
  "customParameters": {
    "external_status": "ready"
  }
}'

Beide Beispiele verwenden booking_parameters.write. Gemischte Aktualisierungen von Kernfeldern und Parametern benötigen beide Buchungs-Schreib-Scopes; schlägt die Validierung fehl, bleibt beides unverändert.

Senden Sie null als Wert, um ein benutzerdefiniertes Feld einer Buchung zu leeren.

Einen Reinigungsauftrag erstellen und ein Teammitglied zuweisen

Erfordert missions.write. Zuweisungs- und Benachrichtigungsabläufe laufen auch für per API erstellte Aufträge.

curl -X POST "https://api.nowistay.com/public/v1/missions" \
  -H "Authorization: Bearer YOUR_ACCESS_TOKEN" \
  -H "Content-Type: application/json" \
  -d '{
  "propertyId": 101,
  "bookingId": 9001,
  "missionType": "cleaning",
  "title": "Checkout cleaning",
  "scheduledAt": "2026-12-18T11:30:00Z",
  "timezone": "Europe/Paris",
  "assignedTeamMemberId": 301
}'

Den Aktivitätsfeed einer Unterkunft lesen

Erfordert activity.read.

curl "https://api.nowistay.com/public/v1/properties/101/activity?limit=20" \
  -H "Authorization: Bearer YOUR_ACCESS_TOKEN"

Ereignisse sind in drei Kategorien gruppiert: booking, mission und automation (Gästenachrichten, Smart-Lock-Ereignisse).

Weitere Endpunkte und Beispiele

Alle Pfade in diesem Abschnitt beziehen sich auf /public/v1. Ersetzen Sie die Beispiel-IDs durch Ressourcen, die dem verbundenen Konto gehören. Das OpenAPI-Schema listet jedes unterstützte Feld, jedes Enum und jede Antwortstruktur auf.

Unterkunftsdetails und Betriebseinstellungen

Verwenden Sie GET /properties/{id} mit properties.read und PATCH /properties/{id} mit properties.write. Unterkunftslisten akzeptieren search. Unterstützte Änderungen umfassen Name, Adresse, Kapazität, Unterkunftstyp, Inseratslinks, Titelbild, Check-in-/Check-out-Zeiten, Buchungsschlusszeiten und Standardeinstellungen für Preise und Aufenthalt.

curl -X PATCH "https://api.nowistay.com/public/v1/properties/101" \
  -H "Authorization: Bearer YOUR_ACCESS_TOKEN" \
  -H "Content-Type: application/json" \
  -d '{
  "capacity": 4,
  "defaultMinStay": 2,
  "cutOffDays": 1
}'

Eine Buchung erstellen und Zahlung anfordern

POST /bookings erfordert bookings.write, die Assistenten-Berechtigung und eine aktive PMS-Verbindung. Geben Sie Daten, die E-Mail-Adresse des Gastes und Gästedetails an, mit den unterstützten Preis- und Betriebsfeldern. requestPayment=true erfordert zusätzlich payments.write und erstellt die Buchung mit ausstehender Zahlung.

curl -X POST "https://api.nowistay.com/public/v1/bookings" \
  -H "Authorization: Bearer YOUR_ACCESS_TOKEN" \
  -H "Content-Type: application/json" \
  -d '{
  "propertyId": 101,
  "arrival": "2026-12-18",
  "departure": "2026-12-20",
  "guestFirstName": "Maya",
  "guestLastName": "Martin",
  "guestEmail": "maya@example.com",
  "adults": 2,
  "amount": "290.00",
  "currency": "EUR",
  "requestPayment": true
}'

Die Erstellung kann gelingen, auch wenn die Erzeugung des Zahlungslinks fehlschlägt. Die Antwort enthält dann weiterhin die gespeicherte Buchung oder ihre ID, mit paymentRequest.sent=false und einem ausdrücklichen Fehler. Prüfen Sie dieses Ergebnis, bevor Sie es erneut versuchen, damit Sie keine doppelte Reservierung erstellen. Eine Checkout-URL wird nur von einer autorisierten Zahlungsanforderungs-Aktion zurückgegeben.

Lesen Sie GET /bookings/{id}/payment-request mit bookings.read, um den unbedenklichen Status von Buchung und Zahlungsanforderung zu erhalten. Es gibt keine Checkout-URLs zurück. Diese Version bringt keine eigenständige API zur Zahlungsverwaltung.

Erstattungen und zahlungsbezogene Buchungsbeschränkungen

Der bestehende Buchungs-PATCH unterstützt reservationNumber, cancellationRefundMode (none, full oder partial) und cancellationRefundAmount. Eine ausdrückliche vollständige oder teilweise Stornierungserstattung erfordert sowohl bookings.write als auch payments.write. Eine Stornierung ohne Erstattung erfordert nur bookings.write.

curl -X PATCH "https://api.nowistay.com/public/v1/bookings/9001" \
  -H "Authorization: Bearer YOUR_ACCESS_TOKEN" \
  -H "Content-Type: application/json" \
  -d '{
  "status": "cancelled",
  "cancellationRefundMode": "partial",
  "cancellationRefundAmount": "50.00"
}'

Eine stornierte Buchung beweist nicht, dass eine Erstattung abgeschlossen wurde. Prüfen Sie den Zahlungsstatus, bevor Sie dem Gast mitteilen, dass seine Erstattung erfolgreich war. payments.write autorisiert Zahlungsanforderungen und Stornierungserstattungen, nicht die Neuberechnung eines bestehenden Checkouts.

  • Sobald ein Zahlungsauftrag existiert, werden geänderte Daten, Gesamtbetrag, Übernachtungspreis, Reinigungsbetrag, Steuer oder Währung abgelehnt. Das gilt auch für frühere fehlgeschlagene oder abgelaufene Aufträge. Akzeptierte Preisangaben ohne Wirkung bleiben zulässig.
  • Eine bezahlte bestätigte Buchung kann nicht auf ausstehend zurückgesetzt werden. Eine erstattete stornierte Buchung kann nicht reaktiviert werden.
  • Kontaktdaten, Postanschriften, Notizen und unterstützte Änderungen von Check-in/Check-out bleiben zulässig.
  • Gleichzeitige Änderungen und die Erstellung von Zahlungsanforderungen verwenden einen konsistenten Buchungs-Snapshot: Die Zahlungsanforderung nutzt eine frühere erfolgreiche Änderung, oder die kollidierende Änderung wird abgelehnt, nachdem der Auftrag existiert.

Gästedatensätze und Aufenthaltsverlauf

POST /guests verwendet customers.write; das doppelte Erstellen eines Gastes gibt 409 zurück. Bestehende Kundenlesezugriffe auf Eigentümerebene bleiben verfügbar. Gästelisten akzeptieren propertyId, wiederholtes propertyIds und die unterstützten orderBy-Werte: created_at, updated_at, full_name, bookings_count, total_amount, last_stay. Stellen Sie - voran für absteigende Reihenfolge; der Standard ist -updated_at.

curl -X POST "https://api.nowistay.com/public/v1/guests" \
  -H "Authorization: Bearer YOUR_ACCESS_TOKEN" \
  -H "Content-Type: application/json" \
  -d '{
  "firstName": "Maya",
  "lastName": "Martin",
  "email": "maya@example.com",
  "language": "en"
}'

GET /guests/{id}/bookings erfordert sowohl customers.read als auch bookings.read und gibt den berechtigten Aufenthaltsverlauf zurück.

Auftragsdetails, Berichte und Filter

GET /missions/{id} und GET /missions/{id}/report verwenden missions.read. Ein gültiger Auftrag ohne Abschlussbericht gibt 200 mit report: null zurück. Auftragslisten akzeptieren einschließliche Datumsfilter für die geplante UTC-Zeit fromDate/toDate, wiederholte propertyIds und teamMemberIds zusätzlich zu den bestehenden Filtern.

curl "https://api.nowistay.com/public/v1/missions?propertyIds=101&propertyIds=102&teamMemberIds=301&fromDate=2026-12-01&toDate=2026-12-31" \
  -H "Authorization: Bearer YOUR_ACCESS_TOKEN"

Konversationen lesen und eine Gastgeberantwort senden

GET /conversations unterstützt die Filter propertyId und bookingId. GET /conversations/{id}/messages liest den Nachrichtenverlauf. Beide erfordern messages.read. Senden Sie eine Antwort mit POST /messages und messages.write und geben Sie genau eines von conversationId oder bookingId an. Das optionale channelKind oder threadChannelId wählt einen Kanal; geben Sie nicht beide Selektoren an.

curl -X POST "https://api.nowistay.com/public/v1/messages" \
  -H "Authorization: Bearer YOUR_ACCESS_TOKEN" \
  -H "Content-Type: application/json" \
  -d '{
  "bookingId": 9001,
  "message": "Hello Maya, your arrival instructions are ready."
}'

Nachrichten folgen dem normalen Zustellweg für Gastgeberantworten, einschließlich des Routings bei Buchungen mit mehreren Zimmern. Eine gespeicherte Nachricht mit fehlgeschlagener Zustellung gibt ihre ID und den Zustellstatus zurück: Prüfen Sie das Ergebnis, bevor Sie es erneut versuchen. Anhänge von Gästenachrichten werden von diesen Endpunkten nicht unterstützt.

Private Fragen und Antworten zur Unterkunft

Verwenden Sie GET /properties/{id}/knowledge-questions und GET /properties/{id}/knowledge-questions/{questionId} mit knowledge.read. Verwenden Sie POST auf die Sammlung und PATCH auf eine einzelne Frage mit knowledge.write.

curl -X POST "https://api.nowistay.com/public/v1/properties/101/knowledge-questions" \
  -H "Authorization: Bearer YOUR_ACCESS_TOKEN" \
  -H "Content-Type: application/json" \
  -d '{
  "question": "Where is the recycling area?",
  "answer": "In the courtyard, next to the bicycle shelter."
}'

POST /properties/{id}/knowledge-questions/copy behandelt {id} als Quelle und erfordert knowledge.read plus knowledge.write. Senden Sie targetPropertyIds, um in andere Unterkünfte zusammenzuführen. Das Kopieren löscht oder überschreibt nie Antworten am Ziel; jedes Ziel wird validiert, bevor Schreibvorgänge beginnen.

curl -X POST "https://api.nowistay.com/public/v1/properties/101/knowledge-questions/copy" \
  -H "Authorization: Bearer YOUR_ACCESS_TOKEN" \
  -H "Content-Type: application/json" \
  -d '{
  "targetPropertyIds": [102, 103]
}'

Lokalisierte Willkommensführer, Seiten und Bilder

  • GET/PATCH /properties/{id}/welcome-guide: den Führer lesen oder bearbeiten, einschließlich lokalisierter Einleitungen.
  • GET/POST /properties/{id}/welcome-guide/pages: Seiten auflisten oder erstellen.
  • GET/PATCH /properties/{id}/welcome-guide/pages/{pageId}: eine einzelne Seite und ihre Position lesen oder bearbeiten.
  • POST /properties/{id}/welcome-guide/images: ein Bild von einer unterstützten öffentlichen URL oder per Base64-Eingabe hochladen.

Lesezugriffe erfordern guides.read; Schreibzugriffe erfordern guides.write. Behalten Sie beim Bearbeiten strukturierter Seiten die EditorJS-Blöcke content/contents samt ihren IDs, verschachtelter Formatierung und Medien bei. Ausgelassene Sprachen bleiben unverändert. Das Ersetzen einer strukturierten Seite durch reinen Text wird abgelehnt. Führer-Tokens und Gästezugangslinks werden nicht zurückgegeben.

curl -X PATCH "https://api.nowistay.com/public/v1/properties/101/welcome-guide" \
  -H "Authorization: Bearer YOUR_ACCESS_TOKEN" \
  -H "Content-Type: application/json" \
  -d '{
  "intros": {
    "en": "Welcome! Your practical information is below.",
    "fr": "Bienvenue ! Retrouvez les informations pratiques ci-dessous."
  }
}'

Bilder müssen von öffentlich erreichbaren Adressen heruntergeladen werden. Weiterleitungen werden geprüft und Größenlimits durchgesetzt. Die unterstützten URL-/Base64-Felder und Limits finden Sie im Schema der Bildanfrage.

Upsells und Käufe lesen

GET /upsells erfordert upsells.read. GET /bookings/{id}/upsell-purchases erfordert sowohl upsells.read als auch bookings.read. Diese Endpunkte sind schreibgeschützt.

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

Buchungs- und Auftragstabellen exportieren

Fügen Sie responseFormat=table zu Buchungs- oder Auftragslisten hinzu, um columns, rows und pagination zu erhalten, mit limit bis zu 500. Standard-JSON bleibt die Voreinstellung und behält sein Maximum von 100. Verwenden Sie offset, um weitere Seiten abzurufen. Mehrere propertyIds werden mit propertyId geschnitten, wenn beide Filter angegeben sind.

curl "https://api.nowistay.com/public/v1/bookings?propertyIds=101&propertyIds=102&fromDate=2026-12-01&toDate=2026-12-31&responseFormat=table&limit=500&offset=0" \
  -H "Authorization: Bearer YOUR_ACCESS_TOKEN"

Buchungstabellen verwenden bookings.read; Auftragstabellen verwenden missions.read. Reinigungszuweisungen in Buchungsberichten erfordern zusätzlich missions.read, und die Konversationspräsenz erfordert messages.read. Buchungsdatumsfilter behalten die Überlappungssemantik; Auftragsdatumsfilter verwenden geplante UTC-Daten.

Kompatibilität mit bestehenden Integrationen

Bestehende REST-Routen, Standard-JSON-Voreinstellungen, Paginierung, Schwärzung von Buchungsdaten, unterstütztes Leeren per null und Benachrichtigungsvoreinstellungen bleiben verfügbar. Die oben beschriebenen zahlungsbezogenen Buchungsbeschränkungen werden neu durchgesetzt. REST und MCP teilen sich die zugrunde liegenden Vorgänge und deren Nebenwirkungen, während die MCP-Tool-Verträge und das Vorschau-/Bestätigungsverhalten unverändert bleiben.

So strukturieren Sie die Seitenblöcke eines Willkommensführers

Eine Nowistay-Seite enthält pro Sprache ein EditorJS-Dokument. Das Array blocks bestimmt die Anzeigereihenfolge. Jedes Objekt in diesem Array ist ein Block; setzen Sie die folgenden Beispiele in content.blocks oder contents.<locale>.blocks ein. Die Beispielwerte sind fiktiv und sollten an Ihre Unterkunft angepasst werden.

Gemeinsame Struktur: id ist ein stabiler String, eindeutig innerhalb des Dokuments; behalten Sie bestehende IDs bei und vergeben Sie für jeden neuen Block eine neue. type ist der exakte, von Groß- und Kleinschreibung abhängige Blockname. data ist ein Objekt, dessen Felder vom Typ abhängen. Behalten Sie außerdem vorhandene tunes und Dokument-Metadaten bei, die ein Lesezugriff zurückgibt, statt sie unnötig neu aufzubauen.

Create-Anfrage: POST /public/v1/properties/{id}/welcome-guide/pages mit guides.write. Verwenden Sie locale + title + content für eine Sprache oder titles + contents für mehrere Sprachen. icon ist standardmäßig info. position akzeptiert start, end oder after_page; Letzteres erfordert afterPageId. Hier ist ein vollständiger Anfragekörper auf Englisch/Französisch:

{
  "titles": {
    "en": "Arrival",
    "fr": "Arrivée"
  },
  "contents": {
    "en": {
      "blocks": [
        {
          "id": "arrival001",
          "type": "header",
          "data": {
            "text": "Getting here",
            "level": 2
          }
        },
        {
          "id": "arrival002",
          "type": "paragraph",
          "data": {
            "text": "Use the <b>main entrance</b>."
          }
        }
      ]
    },
    "fr": {
      "blocks": [
        {
          "id": "arrival001",
          "type": "header",
          "data": {
            "text": "Venir au logement",
            "level": 2
          }
        },
        {
          "id": "arrival002",
          "type": "paragraph",
          "data": {
            "text": "Utilisez l’<b>entrée principale</b>."
          }
        }
      ]
    }
  },
  "position": "end"
}

Überschriften (header)

data.text ist der Überschriftentext. Verwenden Sie data.level: 2, passend zum Führer-Editor. Der Seitentitel selbst gehört in title oder titles, außerhalb der Blöcke.

{
  "id": "guide00001",
  "type": "header",
  "data": {
    "text": "Arrival / Arrivée",
    "level": 2
  }
}

Absätze und Inline-Formatierung (paragraph)

data.text ist ein String. Verwenden Sie Inline-Markup mit <b>, <i> und <a href="https://…"> für Fett, Kursiv und Links. Maskieren Sie doppelte Anführungszeichen in JSON-Strings. Senden Sie nicht eine ganze HTML-Seite oder Markdown als content.

{
  "id": "guide00002",
  "type": "paragraph",
  "data": {
    "text": "<b>Wi-Fi</b>: GuestNetwork. <i>Welcome / Bienvenue !</i> <a href=\"https://example.com/\">Information</a>"
  }
}

Aufzählungen und verschachtelte Listen (list)

Verwenden Sie style: unordered. items enthält Objekte, keine Strings. Jedes Element hat content (formatierter Text), meta (ein Objekt) und items (ein Array untergeordneter Elemente, bei einem Blatt leer). Wiederholen Sie dieselbe Struktur für die Verschachtelung.

{
  "id": "guide00003",
  "type": "list",
  "data": {
    "style": "unordered",
    "meta": {},
    "items": [
      {
        "content": "Kitchen / Cuisine",
        "meta": {},
        "items": [
          {
            "content": "Coffee machine / Machine à café",
            "meta": {},
            "items": []
          }
        ]
      }
    ]
  }
}

Nummerierte Listen (list)

Verwenden Sie style: ordered mit Wurzel-meta.counterType: numeric. Behalten Sie dieselbe Elementstruktur und verschachtelte Arrays wie bei einer Aufzählung bei.

{
  "id": "guide00004",
  "type": "list",
  "data": {
    "style": "ordered",
    "meta": {
      "counterType": "numeric"
    },
    "items": [
      {
        "content": "Close the windows / Fermez les fenêtres",
        "meta": {},
        "items": []
      },
      {
        "content": "Return the keys / Rendez les clés",
        "meta": {},
        "items": []
      }
    ]
  }
}

Checklisten (list)

Verwenden Sie style: checklist. Legen Sie den anfänglichen booleschen Kontrollkästchenzustand in meta.checked jedes Elements fest. Dies ist Führer-Inhalt, kein Abschlussbericht eines Auftrags.

{
  "id": "guide00005",
  "type": "list",
  "data": {
    "style": "checklist",
    "meta": {},
    "items": [
      {
        "content": "Windows closed / Fenêtres fermées",
        "meta": {
          "checked": false
        },
        "items": []
      }
    ]
  }
}

Zitate und Hinweisboxen (quote)

data.text ist das Zitat, caption ist seine Quellenangabe (oder ein leerer String), und alignment ist die Ausrichtungseinstellung des Editors. Verwenden Sie left; die Gastansicht wendet ihr eigenes Zitatlayout an.

{
  "id": "guide00006",
  "type": "quote",
  "data": {
    "text": "Please respect the neighbours / Merci de respecter le voisinage.",
    "caption": "Your host / Votre hôte",
    "alignment": "left"
  }
}

Trennlinien (delimiter)

Eine visuelle Trennlinie hat ein leeres data-Objekt. Ihre Position in blocks bestimmt, wo die Trennung erscheint.

{
  "id": "guide00007",
  "type": "delimiter",
  "data": {}
}

Tabellen (table)

data.content ist ein Array von Zeilen; jede Zeile ist ein Array von Zell-Strings. Behalten Sie in jeder Zeile dieselbe Zellenanzahl bei. Mit withHeadings: true liefert die erste Zeile die Spaltenüberschriften. Verwenden Sie false, wenn jede Zeile gewöhnliche Daten enthält.

{
  "id": "guide00008",
  "type": "table",
  "data": {
    "withHeadings": true,
    "content": [
      [
        "Service",
        "Time / Horaire"
      ],
      [
        "Check-in / Arrivée",
        "16:00"
      ],
      [
        "Check-out / Départ",
        "10:00"
      ]
    ]
  }
}

Bilder (image)

data.file.url ist die URL des hochgeladenen Bildes, kein lokaler Dateiname und kein Base64-String. caption ist ein String; withBorder, withBackground und stretched sind boolesche Werte. Senden Sie das Bild zuerst per POST an /public/v1/properties/{id}/welcome-guide/images und fügen Sie dann den zurückgegebenen editorJsImageBlock in content.blocks ein. Behalten Sie seine zurückgegebenen Felder bei und verwenden Sie eine eindeutige Block-ID. Die URL unten dient nur der Veranschaulichung: Ersetzen Sie sie durch die tatsächlich zurückgegebene URL.

{
  "id": "guide00009",
  "type": "image",
  "data": {
    "file": {
      "url": "https://images.example.com/replace-with-uploaded-image.jpg"
    },
    "caption": "Entrance / Entrée",
    "withBorder": false,
    "withBackground": false,
    "stretched": false
  }
}

YouTube-Videos und Shorts (video)

Verwenden Sie service: youtube für ein normales YouTube-Video oder youtubeShort für einen Short. source ist die Original-URL; embed ist die passende YouTube-Einbettungs-URL. width und height sind Zahlen und caption ist ein String. Der Editor verwendet 580 × 320 für ein normales Video und 315 × 560 für einen Short. Ersetzen Sie VIDEO_ID_11 in beiden URLs durch dieselbe echte 11-stellige Video-ID; bei Shorts lautet der Quellpfad /shorts/VIDEO_ID_11. Beliebiges Iframe-HTML ist nicht das Blockformat.

{
  "id": "guide00010",
  "type": "video",
  "data": {
    "service": "youtube",
    "source": "https://www.youtube.com/watch?v=VIDEO_ID_11",
    "embed": "https://www.youtube.com/embed/VIDEO_ID_11",
    "width": 580,
    "height": 320,
    "caption": "Arrival instructions / Instructions d’arrivée"
  }
}

Bestehende Embed-Blöcke (embed)

embed verwendet dieselben data-Felder wie video. Behalten Sie beim Bearbeiten einer Seite den bestehenden Typ bei; beide stellen YouTube und YouTube Shorts dar. Gehen Sie nicht davon aus, dass jeder von EditorJS unterstützte Embed-Anbieter von Nowistay unterstützt wird.

{
  "id": "guide00011",
  "type": "embed",
  "data": {
    "service": "youtubeShort",
    "source": "https://www.youtube.com/shorts/VIDEO_ID_11",
    "embed": "https://www.youtube.com/embed/VIDEO_ID_11",
    "width": 315,
    "height": 560,
    "caption": ""
  }
}

Upsell-Katalog (upsellCatalog)

Verwenden Sie ein leeres data-Objekt, um den Katalog der berechtigten Upsells hier zu platzieren. Produkte, Preise und Verfügbarkeit stammen aus dem konfigurierten Katalog und dem Gastkontext; sie sind nicht in diesem Block eingebettet.

{
  "id": "guide00012",
  "type": "upsellCatalog",
  "data": {}
}

Ein einzelnes Upsell-Produkt (upsellProduct)

data.itemId ist die numerische ID eines bestehenden Upsells. Die richtige ID finden Sie mit GET /public/v1/upsells unter upsells.read; ersetzen Sie die fiktive 401 unten. Behalten Sie die ursprüngliche ID bei, es sei denn, Sie wählen absichtlich ein anderes Produkt. Zum Schreiben der Seite wird guides.write verwendet; dieser Block erstellt kein Produkt, legt keinen Preis fest und kauft nichts.

{
  "id": "guide00013",
  "type": "upsellProduct",
  "data": {
    "itemId": 401
  }
}

REST-Validierung: Das Erstellen und Aktualisieren von Seiten lehnt nicht unterstützte Blocktypen und fehlerhafte Daten mit HTTP 422 ab. Jede angegebene Sprache wird vor jedem Schreibvorgang geprüft, einschließlich verschachtelter Listenelemente, Tabellenzellen und Medienfelder. Der Fehler benennt das betroffene Dokument und den Block. IDs bleiben bei bestehenden Dokumenten optional; wenn angegeben, müssen sie nicht leere, eindeutige Strings sein. Metadaten und Formatierung bleiben erhalten. Diese strukturelle Validierung prüft nicht, ob ein Bild erreichbar ist oder ein Upsell existiert.

Editor-Steuerelemente und Formate, die erhalten bleiben müssen

imageLibrary ist das Bildauswahl-Steuerelement des Editors, kein API-Galerieblock. Verwenden Sie image-Blöcke. linkPreview ist eine Blockeinstellung (tunes), kein eigener Inhaltstyp; behalten Sie vorhandene Daten bei. Erfinden Sie keine html-, code- oder button-Blöcke und keine nicht dokumentierten Videoanbieter: Dass ein JSON-Objekt akzeptiert wird, garantiert nicht, dass es im Führer angezeigt wird.

Eine Seite bearbeiten, ohne Inhalt zu verlieren

Lesen Sie zuerst GET /public/v1/properties/{id}/welcome-guide/pages/{pageId} mit guides.read, um content und contents zu erhalten. Arbeiten Sie an einer Kopie des vollständigen Dokuments der bearbeiteten Sprache, ändern Sie nur die vorgesehenen Blöcke und senden Sie dieses Dokument dann per PATCH an dieselbe URL mit guides.write. Wenn Sie nur einen Block senden, ersetzt das das Dokument durch diesen einen Block; Blöcke werden nicht anhand von id zusammengeführt. Ausgelassene Sprachen bleiben unverändert. Um eine bestehende Seite zu verschieben, verwenden Sie order, nicht position.

Die Felder text und texts sind kein Ersatz für das strukturierte Dokument. Folgen Sie den Hinweisen simpleTextUpdateAllowed, recommendedUpdateMode und recommendedUpdateField der Leseantwort; eine strukturierte Seite lehnt das Ersetzen durch reinen Text ab. Die einzelnen Beispiele in diesem Abschnitt beschreiben Blöcke, nicht vollständige PATCH-Anfragen für eine bestehende Seite. Lesen Sie die Seite nach dem Bearbeiten erneut und prüfen Sie Sprachen, IDs, Links und Medien. Mit nur guides.write ist die Schreibantwort minimal; fügen Sie guides.read hinzu, um Details zu erhalten.

Webhooks (Echtzeit-Ereignisse)

Wenn Sie die API nicht abfragen möchten, um Änderungen zu erkennen, können Sie Webhooks abonnieren. Nowistay ruft dann jedes Mal, wenn in der Unterkunft eine Buchung erstellt oder aktualisiert wird, eine von Ihnen angegebene URL auf und sendet dieselben Buchungsdaten, die GET /public/v1/bookings/{id} zurückgibt.

Derzeit werden zwei Ereignisse unterstützt:

  • booking.created: Eine neue Reservierung wurde in der Unterkunft erfasst.
  • booking.updated: Eine bestehende Reservierung hat sich geändert (Daten, Status, Gästedaten, Smart-Lock-Code usw.).

Jeder Webhook ist an eine einzelne Unterkunft gebunden, und Sie können bis zu drei pro Unterkunft registrieren. Zustellungen sind signiert (HMAC-SHA256), sodass Sie prüfen können, dass sie wirklich von Nowistay stammen, werden bei Fehlern mit exponentiellem Backoff wiederholt, und der Endpunkt wird automatisch deaktiviert, wenn er länger als 72 Stunden dauerhaft fehlschlägt. Webhook-Payloads enthalten keine sensiblen Gästefelder (E-Mail, Telefon, Adresse, Smart-Lock-Code). Wenn Sie diese benötigen, rufen Sie die API mit dem Scope bookings.sensitive.read auf.

Alle Details zur Einrichtung und zur Prüfung der Signatur finden Sie im eigenen Artikel: Öffentliche API: Buchungs-Webhooks in Echtzeit empfangen.

Rate Limits

  • Lese-Endpunkte: 120 Anfragen pro Minute pro Client und pro Route.
  • Schreib-Endpunkte (POST, PATCH): 30 Anfragen pro Minute pro Client und pro Route.
  • OAuth-Endpunkte: 20 Anfragen pro Minute pro IP oder Client.

Wenn Sie das Limit erreichen, gibt die API 429 Rate limit exceeded zurück. Warten Sie einige Sekunden und versuchen Sie es dann erneut.

Fehlerformat

Jeder Fehler hat dieselbe Struktur: einen stabilen code, eine verständliche Meldung und eine requestId, die Sie in Supportanfragen angeben können.

{
  "error": {
    "code": "validation_error",
    "message": "The request contains an invalid value.",
    "requestId": "example-request-id"
  }
}
  • 400: Ungültige Anfrage (fehlerhafter Body, fehlendes Feld).
  • 401: Bearer-Token fehlt oder ist ungültig.
  • 403: Das Token ist gültig, aber ein erforderlicher Scope fehlt, oder Sie haben keine Berechtigung für den KI-Channel-Manager.
  • 404: Ressource nicht gefunden, oder Sie haben keinen Zugriff darauf.
  • 409: Konflikt (zum Beispiel existiert der Parameterschlüssel bereits).
  • 422: Validierung fehlgeschlagen.
  • 429: Rate Limit erreicht.

Bewährte Vorgehensweisen

  • Fordern Sie so wenige Scopes wie möglich an. Fügen Sie später weitere hinzu, wenn Ihre Integration wächst.
  • Speichern Sie Tokens serverseitig. Liefern Sie nie ein langlebiges Token an einen öffentlichen Client aus und committen Sie es nie in ein Repository.
  • Reagieren Sie auf 401 mit einer Token-Erneuerung. Schlägt auch die Erneuerung fehl, schicken Sie den Nutzer erneut durch den Autorisierungsablauf.
  • Nutzen Sie das Flag silent bei Schreibvorgängen. Setzen Sie es auf true, wenn Sie Daten in großen Mengen synchronisieren und keine Gästebenachrichtigungen auslösen möchten.
  • Behalten Sie die requestId in Ihren Logs. So lassen sich Supportanfragen viel schneller lösen.

Wie geht es weiter

  • Öffnen Sie die Live-Dokumentation und testen Sie jeden Endpunkt: api.nowistay.com/public/docs.
  • Lesen Sie das vollständige Schema und laden Sie eine OpenAPI-Datei unter /public/openapi.json herunter.
  • Sie benötigen einen Scope oder einen Endpunkt, der noch nicht aufgeführt ist? Schreiben Sie dem Support und schildern Sie Ihren Anwendungsfall.

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.