Bijgewerkt
De openbare REST API van Nowistay koppelt je scripts en partnerintegraties aan je account. Je leest en wijzigt instellingen van accommodaties, agenda’s, boekingen en opdrachten; beheert gastgegevens, gesprekken, privékennis en welkomstgidsen; vraagt betalingen voor boekingen aan en geeft restituties bij annuleringen opdracht; en leest upsells, aankopen en portefeuillerapporten. De exacte schema’s voor verzoeken en antwoorden vind je op /public/docs en /public/openapi.json.
Deze gids beschrijft drie manieren: de snelste manier om de API uit te proberen (de interactieve docs-playground), de eenvoudigste manier om je eigen scripts uit te voeren (een persoonlijke API-inlog die je in de app aanmaakt) en de standaard OAuth-flow die je gebruikt wanneer je een app bouwt voor andere hosts.
De toegang wordt gecontroleerd op eigendom en op het assistentrecht van de accommodatie. Voor bewerkingen die ervan afhankelijk zijn, zoals agendabeheer en het aanmaken van directe boekingen, is een actieve PMS-verbinding vereist. Voor het lezen of bewerken van andere resources is niet alleen daarvoor een PMS-verbinding nodig.
https://api.nowistay.com/public/v1/* vereisen een OAuth2-toegangstoken, verzonden als Authorization: Bearer ....Open https://api.nowistay.com/public/docs in je browser. De pagina is een volledige Swagger UI van de API, met een ingebouwde OAuth-playground die automatisch een client voor je registreert. Je hoeft niet te programmeren om aanroepen te testen.
Cmd+Shift+R op Mac, Ctrl+F5 op Windows)./public/docs, al geauthenticeerd.GET /public/v1/properties, klik op Try it out en dan op Execute.Vanaf hier kun je elk endpoint met één klik uitproberen, de exacte JSON zien die Nowistay teruggeeft en het cURL-commando van elke aanroep kopiëren. Dit is de aanbevolen manier om de API te verkennen voordat je code schrijft.
Belangrijk. De playground-client bestaat alleen in je browser. Hij is prima om te testen, maar voor een echte integratie maak je een persoonlijke API-inlog aan of registreer je je eigen OAuth-client (beide worden hieronder uitgelegd).
Als je je eigen account automatiseert (een rapportagescript, een koppeling met je boekhoudtool, een klein dashboard), heb je de volledige OAuth-flow helemaal niet nodig. Maak een persoonlijke API-inlog aan in de app en wissel die in één aanroep om voor een token. Geen toestemmingsscherm, geen refresh-tokens om te beheren.
Reporting script) en vink alleen de rechten aan die nodig zijn.Je script wisselt de inlog vervolgens om voor een toegangstoken (een uur geldig) en roept de API aan:
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"
Als het token verloopt, vraag je op dezelfde manier een nieuw token aan. Er is geen refresh-token in deze flow, en dat is juist de bedoeling: twee regels code, niets om op te letten.
Je kunt maximaal 10 inloggegevens aanmaken, elk met een eigen naam en eigen rechten. Een inlog leest en schrijft alleen gegevens waartoe je eigen account toegang heeft, en heeft hetzelfde actieve abonnement AI Channel Manager nodig als de rest van de API.
Je kunt de scopes van een bestaand token of een bestaande persoonlijke inlog niet bewerken. Maak een vervangende inlog aan met de volledige set rechten die je integratie nodig heeft. Bestaande clients, toegangstokens, autorisatiecodes en refresh-tokens behouden hun oorspronkelijke rechten; er worden geen rechten automatisch toegevoegd.
https://app.nowistay.com/hub/user/developer. Noteer de rechten die de bestaande integratie gebruikt.calendar.write nodig; voor het versturen van berichten messages.write; voor het aanvragen van een boekingsbetaling zowel bookings.write als payments.write.POST /public/oauth/token met grant_type=client_credentials en de vervangende inloggegevens. Controleer de teruggegeven waarde van scope en test een endpoint dat door die scopes is toegestaan. GET /public/v1/properties vereist specifiek properties.read.Secret vernieuwen voegt geen scopes toe. Het vervangt alleen het secret van dezelfde inlog; het vorige secret blijft 7 dagen geldig. Het verversen of opnieuw aanvragen van een toegangstoken kan de oorspronkelijke rechten niet uitbreiden. Schrijfscopes omvatten niet automatisch leesscopes.
POST /public/oauth/register met de volledige gewenste set scopes en je gebruikelijke applicatiegegevens. Een gelijkwaardige registratie met exact dezelfde set scopes hergebruikt de bijbehorende client; een gewijzigde set scopes maakt een nieuwe registratie aan. Bewaar de teruggegeven clientgegevens.Ververs in de docs-playground de pagina en autoriseer opnieuw met de vereiste scopes. Nieuwe rechten worden getoond met leesbare labels en hun identifiers in het Engels, Frans, Spaans, Duits, Nederlands en Italiaans.
De API gebruikt standaard OAuth 2.1 met de authorization-code-flow en PKCE. In één zin: de gebruiker opent een Nowistay-pagina, zegt ja, jij ontvangt een korte code, je wisselt die om voor een toegangstoken en je roept de API aan met dat token. Tokens verlopen en kunnen worden ververst zonder de gebruiker opnieuw lastig te vallen.
De drie OAuth-endpoints die je gebruikt:
/public/oauth/register (POST)/public/oauth/authorize (GET, browserredirect)/public/oauth/token (POST)Je kunt ook de OAuth-metadata ophalen op /.well-known/oauth-authorization-server/public-api, waar elk endpoint en elke ondersteunde functie staat.
Iedereen kan een OAuth-client registreren, dus hosts moeten een gloednieuwe app kunnen onderscheiden van een gevestigde integratie. Elke nieuw geregistreerde app start daarom als niet-geverifieerd:
Bouw je iets voor meer dan 3 accounts? Schrijf naar de support met de naam van je app, je website en je toepassing. Zodra je app is geverifieerd, verdwijnt de waarschuwing en vervalt de limiet op het aantal accounts.
De REST API ondersteunt 25 scopes, waaronder tien extra rechten voor het bewerken van accommodaties, berichten, gidsen, kennis, het aanmaken van gasten, upsells en betalingen. Selecteer alleen de rechten die je integratie nodig heeft.
properties.read: details en operationele instellingen van accommodaties lezen.properties.write: details en operationele instellingen van accommodaties bijwerken.calendar.read: beschikbaarheid, nachttarieven en verblijfsbeperkingen lezen.calendar.write: beschikbaarheid, nachttarieven en verblijfsbeperkingen bijwerken.bookings.read: boekingen, financiële gegevens en de veilige status van betaalverzoeken lezen.bookings.sensitive.read: contactgegevens van gasten, postadressen en toegangscodes opnemen in boekingsantwoorden; vereist bij het lezen ook bookings.read.bookings.write: directe boekingen aanmaken en bijwerken. Voor betaalverzoeken en restituties is ook payments.write nodig.booking_parameters.read: definities en waarden van aangepaste boekingsparameters lezen.booking_parameters.write: definities en waarden van parameters aanmaken en bijwerken.missions.read: opdrachten en afrondingsrapporten lezen.missions.write: opdrachten aanmaken, bijwerken en toewijzen.activity.read: activiteitenlogs van accommodaties lezen.team_members.read: teamleden, contactgegevens en toewijzingen aan accommodaties lezen.webhooks.read: webhookabonnementen lezen.webhooks.write: webhookabonnementen aanmaken, bijwerken, pauzeren en verwijderen.customers.read: gastgegevens, contactgegevens en verblijfsverleden lezen.customers.write: gastgegevens aanmaken.upsells.read: de upsellcatalogus en aankopen bij boekingen lezen.payments.write: tijdens het aanmaken van een boeking een betaling aanvragen en volledige of gedeeltelijke restituties bij annulering opdragen; vereist ook bookings.write.messages.read: gastgesprekken en berichten lezen.messages.write: berichten naar gasten sturen.guides.read: welkomstgidsen en pagina-inhoud lezen.guides.write: gidsen bewerken, pagina’s aanmaken en bijwerken, de positie van pagina’s wijzigen en afbeeldingen uploaden.knowledge.read: privévragen en -antwoorden over accommodaties lezen.knowledge.write: privékennis aanmaken en bijwerken. Voor kopiëren is ook knowledge.read nodig.De acht standaard REST-scopes blijven properties.read, calendar.read, bookings.read, booking_parameters.read, missions.read, activity.read, team_members.read en webhooks.read. Standaardwaarden werken bestaande tokens niet bij.
bookings.write + payments.write. Annuleren zonder restitutie gebruikt alleen bookings.write.customers.read + bookings.read.upsells.read + bookings.read. Voor het lezen van de catalogus is alleen upsells.read nodig.knowledge.read + knowledge.write.bookings.write + booking_parameters.write. Een PATCH met alleen parameters houdt booking_parameters.write en werkt ook voor OTA-boekingen.Nieuwe schrijfendpoints geven minimale resultaten terug, tenzij het token ook de relevante leesscope heeft. De bestaande afscherming van boekingsgegevens blijft van kracht. Endpoints voor opdrachten en gesprekken bevatten hun gerelateerde boekingscontext onder hun eigen scopes.
In deze voorbeelden worden plaatsaanduidingen voor ID’s en inloggegevens gebruikt. Vervang ze door je eigen waarden. Deze flow is voor partnerapps; persoonlijke inloggegevens gebruiken client_credentials, zoals hierboven getoond.
Roep POST /public/oauth/register aan met de rechten die je nodig hebt. Bewaar de teruggegeven client_id en client_secret veilig. Het voorbeeld vraagt leesrechten voor accommodaties, boekingen en opdrachten.
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"}'
Gebruik voor een publieke client zonder backend "tokenEndpointAuthMethod": "none" en PKCE, zonder client secret.
Genereer een PKCE-verifier, de bijbehorende S256-challenge en een willekeurige state. Stuur de gebruiker door naar het autorisatie-endpoint. De volgende URL staat op één regel; codeer de waarden van de querystring als URL.
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
De host meldt zich aan, bekijkt de rechten en keurt de toegang goed of af. Bij goedkeuring bevat de callback een eenmalige code en je state. Weiger een callback waarvan de state niet overeenkomt.
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"
Het antwoord bevat access_token, token_type, expires_in, refresh_token en scope. Bewaar tokens veilig. Toegangstokens gelden normaal een uur; gebruik de teruggegeven vervaldatum.
Dit voorbeeld vereist properties.read. Lees de velden data en pagination in het antwoord.
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"
Bewaar het nieuwe refresh-token dat het verversingsantwoord teruggeeft. Mislukt het verversen, begin dan opnieuw met autoriseren. Bij het verversen blijven de eerder verleende scopes behouden. Persoonlijke inloggegevens hebben geen refresh-token: vraag een nieuw toegangstoken aan met client_credentials.
GET /public/v1/properties/{property_id}/calendar vereist calendar.read. Geef een inclusieve from- en to-datum mee; één verzoek kan tot 730 dagen beslaan.
GET /public/v1/properties/101/calendar?from=2026-12-18&to=2026-12-20
Elke dag kan availability, rate, minStay, maxStay, stopSell, closedToArrival, closedToDeparture, restricted en restrictionReasons teruggeven. availability is de resterende verkoopbare voorraad na bevestigde boekingen. De velden voor beperkingen verklaren waarom een datum of een check-in- of check-outactie beperkt is.
PATCH /public/v1/properties/{property_id}/calendar vereist calendar.write. Het verzoek is gedeeltelijk: stuur alleen de instellingen mee die moeten veranderen, weggelaten velden blijven ongewijzigd.
{
"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 is optioneel: 0 is maandag en 6 is zondag. Laat het weg om elke datum in de periode bij te werken. Het antwoord meldt daysUpdated en de genormaliseerde wijziging die is toegepast. Wijzigingen worden gesynchroniseerd via Nowistay PMS.
Voor agendabewerkingen zijn eigendom, het assistentrecht en actief agendabeheer in Nowistay vereist. Om agendascopes in te schakelen voor een bestaande integratie, volg je Scopes toevoegen aan een bestaand API-token hierboven; het verversen van een token of het vernieuwen van een secret is niet genoeg.
Ondersteunde filters zijn onder meer propertyId, herhaalde propertyIds, status, channel, fromDate en toDate. Standaard JSON-paginering gebruikt limit (maximaal 100) en offset. Datumfilters voor boekingen behouden hun overlaplogica: departure >= fromDate en 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"
Vereist de extra scope bookings.sensitive.read. Zonder die scope worden email, phone en de code van het slimme slot weggelaten.
Voor kernwijzigingen aan boekingen zijn bookings.write en een geschikte directe boeking vereist. OTA-reserveringen blijven voor kernvelden alleen-lezen. Een PATCH met alleen customParameters werkt ook voor OTA-boekingen en gebruikt 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-verzoeken voor bestaande boekingen hebben standaard silent=true. Stel silent=false in om de gebruikelijke meldingen over wijzigingen te versturen. Bij het aanmaken van een boeking is de standaardwaarde silent=false. Weggelaten velden blijven ongewijzigd en bestaande ondersteunde null-waarden wissen nog steeds velden. De synchronisatie van beschikbaarheid blijft deel uitmaken van de gedeelde bewerking.
Aangepaste boekingsparameters zijn handig als je gegevens uit je eigen systeem bij elke Nowistay-reservering wilt spiegelen.
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 voorbeelden gebruiken booking_parameters.write. Gecombineerde wijzigingen van kernvelden en parameters vereisen beide schrijfscopes voor boekingen; als de validatie mislukt, blijven beide ongewijzigd.
Stuur null als waarde om een aangepast veld bij een boeking te wissen.
Vereist missions.write. Workflows voor toewijzing en meldingen worden ook uitgevoerd voor opdrachten die via de API zijn aangemaakt.
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
}'
Vereist activity.read.
curl "https://api.nowistay.com/public/v1/properties/101/activity?limit=20" \
-H "Authorization: Bearer YOUR_ACCESS_TOKEN"
Gebeurtenissen zijn gegroepeerd in drie categorieën: booking, mission en automation (gastberichten, gebeurtenissen van slimme sloten).
Alle paden in dit onderdeel zijn relatief ten opzichte van /public/v1. Vervang de voorbeeld-ID’s door resources van het verbonden account. Het OpenAPI-schema vermeldt elk ondersteund veld, elke enum en elke vorm van antwoorden.
Gebruik GET /properties/{id} met properties.read en PATCH /properties/{id} met properties.write. Lijsten van accommodaties accepteren search. Ondersteunde wijzigingen zijn onder meer naam, adres, capaciteit, type accommodatie, links naar advertenties, omslagfoto, check-in- en check-outtijden, boekingsafsluitingen en standaardinstellingen voor prijzen en verblijf.
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 vereist bookings.write, het assistentrecht en een actieve PMS-verbinding. Neem datums, het e-mailadres van de gast en gastgegevens op, met ondersteunde velden voor prijzen en operationele gegevens. requestPayment=true vereist bovendien payments.write en maakt de boeking aan met de status in afwachting van betaling.
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
}'
Het aanmaken kan slagen, ook als het genereren van de betaallink mislukt. Het antwoord bevat dan nog steeds de opgeslagen boeking of de ID ervan, met paymentRequest.sent=false en een expliciete fout. Controleer dit resultaat voordat je het opnieuw probeert, zodat je geen dubbele reservering aanmaakt. Een checkout-URL wordt alleen teruggegeven door een geautoriseerde actie voor een betaalverzoek.
Lees GET /bookings/{id}/payment-request met bookings.read voor de veilige status van de boeking en het betaalverzoek. Het geeft geen checkout-URL’s terug. Deze release voegt geen zelfstandige API voor betalingsbeheer toe.
De PATCH voor bestaande boekingen ondersteunt reservationNumber, cancellationRefundMode (none, full of partial) en cancellationRefundAmount. Een expliciete volledige of gedeeltelijke restitutie bij annulering vereist zowel bookings.write als payments.write. Annuleren zonder restitutie vereist alleen 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"
}'
Een geannuleerde boeking bewijst niet dat een restitutie is voltooid. Controleer de betalingsstatus voordat je de gast vertelt dat de restitutie is gelukt. payments.write autoriseert betaalverzoeken en restituties bij annulering, niet het opnieuw prijzen van een bestaande checkout.
POST /guests gebruikt customers.write; het dubbel aanmaken van een gast geeft 409 terug. Bestaande leesacties voor klanten op eigenaarsniveau blijven beschikbaar. Gastlijsten accepteren propertyId, herhaalde propertyIds en ondersteunde orderBy-waarden: created_at, updated_at, full_name, bookings_count, total_amount, last_stay. Zet er - voor voor aflopende volgorde; de standaardwaarde is -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 vereist zowel customers.read als bookings.read en geeft het in aanmerking komende verblijfsverleden terug.
GET /missions/{id} en GET /missions/{id}/report gebruiken missions.read. Een geldige opdracht zonder afrondingsrapport geeft 200 terug met report: null. Lijsten van opdrachten accepteren inclusieve datumfilters fromDate/toDate voor de geplande UTC-datum, herhaalde propertyIds en teamMemberIds, naast de bestaande filters.
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 ondersteunt de filters propertyId en bookingId. GET /conversations/{id}/messages leest de berichtgeschiedenis. Beide vereisen messages.read. Verstuur een antwoord met POST /messages en messages.write, met precies één van conversationId of bookingId. Met de optionele channelKind of threadChannelId selecteer je een kanaal; geef niet beide selectors mee.
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."
}'
Berichten volgen het normale afleverpad voor antwoorden van de host, inclusief routering bij boekingen met meerdere kamers. Een opgeslagen bericht waarvan de aflevering is mislukt, geeft zijn ID en afleverstatus terug: controleer het resultaat voordat je het opnieuw probeert. Bijlagen bij gastberichten worden door deze endpoints niet ondersteund.
Gebruik GET /properties/{id}/knowledge-questions en GET /properties/{id}/knowledge-questions/{questionId} met knowledge.read. Gebruik POST op de collectie en PATCH op een afzonderlijke vraag met 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 de bron en vereist knowledge.read plus knowledge.write. Stuur targetPropertyIds mee om samen te voegen met andere accommodaties. Kopiëren verwijdert of overschrijft nooit antwoorden in de doelaccommodaties; elk doel wordt gevalideerd voordat het schrijven begint.
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: de gids lezen of bewerken, inclusief gelokaliseerde inleidingen.GET/POST /properties/{id}/welcome-guide/pages: pagina’s weergeven of aanmaken.GET/PATCH /properties/{id}/welcome-guide/pages/{pageId}: een afzonderlijke pagina en haar positie lezen of bewerken.POST /properties/{id}/welcome-guide/images: een afbeelding uploaden vanaf een ondersteunde openbare URL of als base64-invoer.Voor lezen is guides.read vereist; voor schrijven guides.write. Behoud bij het bewerken van gestructureerde pagina’s de EditorJS-blokken content/contents met hun ID’s, geneste opmaak en media. Weggelaten talen blijven ongewijzigd. Vervanging van een gestructureerde pagina door platte tekst wordt geweigerd. Gidstokens en toegangslinks voor gasten worden niet teruggegeven.
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."
}
}'
Afbeeldingen moeten worden gedownload van openbaar bereikbare adressen. Redirects worden gecontroleerd en groottelimieten worden afgedwongen. Raadpleeg het schema van het afbeeldingsverzoek voor de ondersteunde URL- en base64-velden en limieten.
GET /upsells vereist upsells.read. GET /bookings/{id}/upsell-purchases vereist zowel upsells.read als bookings.read. Deze endpoints zijn alleen-lezen.
curl "https://api.nowistay.com/public/v1/bookings/9001/upsell-purchases" \
-H "Authorization: Bearer YOUR_ACCESS_TOKEN"
Voeg responseFormat=table toe aan lijsten van boekingen of opdrachten voor columns, rows en pagination, met limit tot 500. Standaard JSON blijft de standaardwaarde en houdt zijn maximum van 100. Gebruik offset om volgende pagina’s op te halen. Meerdere propertyIds worden doorsneden met propertyId als beide filters worden opgegeven.
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"
Tabellen met boekingen gebruiken bookings.read; tabellen met opdrachten gebruiken missions.read. Voor toewijzingen van schoonmaak in boekingsrapporten is bovendien missions.read nodig, en voor de aanwezigheid van gesprekken messages.read. Datumfilters voor boekingen behouden hun overlaplogica; datumfilters voor opdrachten gebruiken geplande UTC-datums.
Bestaande REST-routes, standaard JSON-instellingen, paginering, afscherming van boekingsgegevens, het wissen met null en standaardinstellingen voor meldingen blijven beschikbaar. De hierboven beschreven betalingsgerelateerde beperkingen bij boekingen worden nieuw afgedwongen. REST en MCP delen dezelfde onderliggende bewerkingen en bijwerkingen, terwijl de MCP-toolcontracten en het gedrag van voorbeeldweergave en bevestiging ongewijzigd blijven.
Een Nowistay-pagina bevat per taal één EditorJS-document. De array blocks bepaalt de volgorde van weergave. Elk object in die array is één blok; plaats de onderstaande voorbeelden in content.blocks of contents.<locale>.blocks. De voorbeeldwaarden zijn fictief en moeten worden aangepast aan je accommodatie.
Gemeenschappelijke structuur: id is een stabiele string, uniek binnen het document; behoud bestaande ID’s en wijs aan elk nieuw blok een nieuw ID toe. type is de exacte, hoofdlettergevoelige naam van het blok. data is een object waarvan de velden van het type afhangen. Behoud ook alle bestaande tunes en documentmetadata die bij het lezen worden teruggegeven, in plaats van ze onnodig opnieuw op te bouwen.
Aanmaakverzoek: POST /public/v1/properties/{id}/welcome-guide/pages met guides.write. Gebruik locale + title + content voor één taal, of titles + contents voor meerdere talen. icon is standaard info. position accepteert start, end of after_page; die laatste vereist afterPageId. Hier is een volledige request body in het Engels en Frans:
{
"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 is de koptekst. Gebruik data.level: 2, zoals in de gidseditor. De titel van de pagina zelf hoort in title of titles, buiten de blokken.
{
"id": "guide00001",
"type": "header",
"data": {
"text": "Arrival / Arrivée",
"level": 2
}
}
data.text is een string. Gebruik inline <b>, <i> en <a href="https://…"> voor vet, cursief en links. Escape dubbele aanhalingstekens in JSON-strings. Stuur geen complete HTML-pagina of 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>"
}
}
Gebruik style: unordered. items bevat objecten, geen strings. Elk item heeft content (opgemaakte tekst), meta (een object) en items (een array met onderliggende items, leeg voor een blad). Herhaal dezelfde structuur voor nesting.
{
"id": "guide00003",
"type": "list",
"data": {
"style": "unordered",
"meta": {},
"items": [
{
"content": "Kitchen / Cuisine",
"meta": {},
"items": [
{
"content": "Coffee machine / Machine à café",
"meta": {},
"items": []
}
]
}
]
}
}
Gebruik style: ordered met meta.counterType: numeric op rootniveau. Behoud dezelfde itemstructuur en geneste arrays als bij een lijst met opsommingstekens.
{
"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": []
}
]
}
}
Gebruik style: checklist. Zet de oorspronkelijke booleaanse status van het selectievakje in de meta.checked van elk item. Dit is inhoud van de gids, geen afrondingsrapport van een opdracht.
{
"id": "guide00005",
"type": "list",
"data": {
"style": "checklist",
"meta": {},
"items": [
{
"content": "Windows closed / Fenêtres fermées",
"meta": {
"checked": false
},
"items": []
}
]
}
}
data.text is het citaat, caption is de bronvermelding (of een lege string) en alignment is de uitlijningsinstelling van de editor. Gebruik left; de gastweergave past zijn eigen citaatlay-out toe.
{
"id": "guide00006",
"type": "quote",
"data": {
"text": "Please respect the neighbours / Merci de respecter le voisinage.",
"caption": "Your host / Votre hôte",
"alignment": "left"
}
}
Een visuele scheiding heeft een leeg data-object. De positie in blocks bepaalt waar de scheiding verschijnt.
{
"id": "guide00007",
"type": "delimiter",
"data": {}
}
data.content is een array van rijen; elke rij is een array van cel-strings. Houd het aantal cellen per rij gelijk. Met withHeadings: true levert de eerste rij de kolomkoppen. Gebruik false wanneer elke rij gewone gegevens bevat.
{
"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 is de URL van de geüploade afbeelding, geen lokale bestandsnaam of base64-string. caption is een string; withBorder, withBackground en stretched zijn booleans. Verstuur de afbeelding eerst met POST naar /public/v1/properties/{id}/welcome-guide/images en voeg daarna de teruggegeven editorJsImageBlock in content.blocks in. Behoud de teruggegeven velden en gebruik een uniek blok-ID. De onderstaande URL is ter illustratie: vervang hem door de werkelijk teruggegeven 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
}
}
Gebruik service: youtube voor een gewone YouTube-video, of youtubeShort voor een Short. source is de oorspronkelijke URL; embed is de bijbehorende YouTube-embed-URL. width en height zijn getallen en caption is een string. De editor gebruikt 580 × 320 voor een gewone video en 315 × 560 voor een Short. Vervang VIDEO_ID_11 in beide URL’s door hetzelfde echte video-ID van 11 tekens; bij Shorts is het bronpad /shorts/VIDEO_ID_11. Willekeurige iframe-HTML is niet het blokformaat.
{
"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 gebruikt dezelfde data-velden als video. Behoud bij het bewerken van een pagina het bestaande type; beide tonen YouTube en YouTube Shorts. Ga er niet van uit dat elke embedprovider die EditorJS ondersteunt ook door Nowistay wordt ondersteund.
{
"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": ""
}
}
Gebruik een leeg data-object om hier de in aanmerking komende upsellcatalogus te plaatsen. Producten, prijzen en beschikbaarheid komen uit de geconfigureerde catalogus en de context van de gast; ze zijn niet in dit blok opgenomen.
{
"id": "guide00012",
"type": "upsellCatalog",
"data": {}
}
data.itemId is het numerieke ID van een bestaande upsell. Zoek het juiste ID op met GET /public/v1/upsells en upsells.read; vervang het fictieve 401 hieronder. Behoud het oorspronkelijke ID, tenzij je bewust een ander product kiest. Het schrijven van de pagina gebruikt guides.write; dit blok maakt geen product aan, stelt geen prijs in en koopt niets.
{
"id": "guide00013",
"type": "upsellProduct",
"data": {
"itemId": 401
}
}
REST-validatie: het aanmaken en bijwerken van pagina’s weigert niet-ondersteunde bloktypen en onjuist opgemaakte gegevens met HTTP 422. Elke opgegeven taal wordt gecontroleerd voordat er iets wordt geschreven, inclusief geneste lijstitems, tabelcellen en mediavelden. De fout geeft het betrokken document en blok aan. ID’s blijven optioneel voor bestaande documenten; als ze worden opgegeven, moeten het niet-lege, unieke strings zijn. Metadata en opmaak blijven behouden. Deze structurele validatie controleert niet of een afbeelding bereikbaar is of een upsell bestaat.
imageLibrary is het besturingselement van de afbeeldingskiezer van de editor, geen galerijblok van de API. Gebruik image-blokken. linkPreview is een blokinstelling (tunes), geen apart inhoudstype; behoud bestaande gegevens. Verzin geen html-, code- of button-blokken of niet-gedocumenteerde videoproviders: dat een JSON-object wordt geaccepteerd, garandeert niet dat het in de gids wordt weergegeven.
Lees eerst GET /public/v1/properties/{id}/welcome-guide/pages/{pageId} met guides.read om content en contents te verkrijgen. Werk met een kopie van het volledige document voor de taal die je bewerkt, wijzig alleen de bedoelde blokken en stuur dat document daarna met PATCH naar dezelfde URL met guides.write. Als je maar één blok verstuurt, vervangt dat het document door dat ene blok; blokken worden niet samengevoegd op id. Weggelaten talen blijven ongewijzigd. Gebruik order, niet position, om een bestaande pagina te verplaatsen.
De velden text en texts zijn geen vervanging voor het gestructureerde document. Volg de aanwijzingen simpleTextUpdateAllowed, recommendedUpdateMode en recommendedUpdateField uit het leesantwoord; een gestructureerde pagina weigert vervanging door platte tekst. De afzonderlijke voorbeelden in dit onderdeel beschrijven blokken, geen volledige PATCH-verzoeken voor een bestaande pagina. Lees de pagina na het bewerken opnieuw en controleer talen, ID’s, links en media. Met alleen guides.write is het schrijfantwoord minimaal; voeg guides.read toe om details te ontvangen.
Als je de API niet wilt bevragen om wijzigingen op te merken, kun je je abonneren op webhooks. Nowistay roept dan een URL aan die jij opgeeft telkens wanneer er een boeking voor de accommodatie wordt aangemaakt of bijgewerkt, en stuurt dezelfde boekingsgegevens die GET /public/v1/bookings/{id} teruggeeft.
Momenteel worden twee gebeurtenissen ondersteund:
booking.created: er is een nieuwe reservering voor de accommodatie vastgelegd.booking.updated: een bestaande reservering is gewijzigd (datums, status, gastgegevens, code van het slimme slot enzovoort).Elke webhook is gekoppeld aan één accommodatie en je kunt er maximaal drie per accommodatie registreren. Leveringen zijn ondertekend (HMAC-SHA256) zodat je kunt controleren dat ze echt van Nowistay komen, worden bij mislukken opnieuw geprobeerd met exponentiële backoff, en het endpoint wordt automatisch uitgeschakeld als het langer dan 72 uur blijft mislukken. Webhook-payloads bevatten geen gevoelige gastgegevens (e-mail, telefoon, adres, code van het slimme slot). Heb je die nodig, roep dan de API aan met de scope bookings.sensitive.read.
De volledige installatie en de verificatie van handtekeningen staan in het speciale artikel: Openbare API: boekingswebhooks in realtime ontvangen.
Wanneer je de limiet bereikt, geeft de API 429 Rate limit exceeded terug. Wacht even en probeer het na een paar seconden opnieuw.
Elke fout heeft dezelfde vorm, met een stabiele code, een leesbaar bericht en een requestId die je in supportverzoeken kunt vermelden.
{
"error": {
"code": "validation_error",
"message": "The request contains an invalid value.",
"requestId": "example-request-id"
}
}
400: ongeldig verzoek (onjuist opgemaakte body, ontbrekend veld).
silent bij schrijfacties. Zet hem op true wanneer je gegevens in bulk synchroniseert en geen meldingen naar gasten wilt versturen.requestId in je logs. Daarmee worden supportverzoeken veel sneller opgelost./public/openapi.json.Gidsen voor hosts: lees de blog.
Klaar om je verhuur op de automatische piloot te zetten?