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.
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.
https://api.nowistay.com/public/v1/* erfordern ein OAuth2-Zugriffstoken, das als Authorization: Bearer ... gesendet wird.Ö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.
Cmd+Shift+R auf dem Mac, Strg+F5 unter Windows)./public/docs, bereits authentifiziert.GET /public/v1/properties, klicken Sie auf Try it out (Ausprobieren) und dann auf Execute (Ausführen).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).
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.
Reporting script) und aktivieren Sie nur die Berechtigungen, die Sie benötigen.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.
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.
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.
https://app.nowistay.com/hub/user/developer auf. Notieren Sie die Berechtigungen, die die bestehende Integration verwendet.calendar.write; das Senden von Nachrichten messages.write; das Anfordern einer Buchungszahlung sowohl bookings.write als auch payments.write.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.„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.
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.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.
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:
/public/oauth/register (POST)/public/oauth/authorize (GET, Browser-Weiterleitung)/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.
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:
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.
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.
bookings.write + payments.write. Eine Stornierung ohne Erstattung benötigt nur bookings.write.customers.read + bookings.read.upsells.read + bookings.read. Das Lesen des Katalogs benötigt nur upsells.read.knowledge.read + knowledge.write.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.
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.
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.
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
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.
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"
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.
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.
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.
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"
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.
Ä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.
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.
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
}'
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).
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.
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
}'
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.
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.
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.
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"
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.
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]
}'
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.
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"
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.
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.
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"
}
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
}
}
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>"
}
}
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": []
}
]
}
]
}
}
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": []
}
]
}
}
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": []
}
]
}
}
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"
}
}
Eine visuelle Trennlinie hat ein leeres data-Objekt. Ihre Position in blocks bestimmt, wo die Trennung erscheint.
{
"id": "guide00007",
"type": "delimiter",
"data": {}
}
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"
]
]
}
}
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
}
}
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"
}
}
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": ""
}
}
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": {}
}
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.
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.
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.
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.
Wenn Sie das Limit erreichen, gibt die API 429 Rate limit exceeded zurück. Warten Sie einige Sekunden und versuchen Sie es dann erneut.
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"
}
}
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.requestId in Ihren Logs. So lassen sich Supportanfragen viel schneller lösen./public/openapi.json herunter.Ratgeber für Gastgeber: zum Blog.
Bereit, Ihre Ferienunterkunft auf Autopilot zu schalten?