Atualizado em
A API REST pública da Nowistay liga os seus scripts e as integrações de parceiros à sua conta. Leia e atualize as definições dos alojamentos, os calendários, as reservas e as missões; gira fichas de hóspedes, conversas, conhecimento privado e guias de boas-vindas; peça pagamentos de reservas e reembolsos de cancelamentos; e consulte extras, compras e relatórios do portefólio. Explore os esquemas exatos de pedido e de resposta em /public/docs e /public/openapi.json.
Este guia apresenta três caminhos: a forma mais rápida de experimentar a API (o ambiente de testes da documentação interativa), a forma mais simples de executar os seus próprios scripts (uma credencial de API pessoal criada na aplicação) e o fluxo OAuth padrão que vai usar quando criar uma aplicação para outros anfitriões.
O acesso é verificado em função da propriedade e do direito de assistente do alojamento. É necessária uma ligação PMS ativa para as operações que dependem dela, incluindo a gestão do calendário e a criação de reservas diretas. Os outros recursos não exigem uma ligação PMS apenas para serem lidos ou editados.
https://api.nowistay.com/public/v1/* exigem um token de acesso OAuth2, enviado como Authorization: Bearer ....Abra https://api.nowistay.com/public/docs no navegador. A página é uma interface Swagger UI completa da API, com um ambiente de testes OAuth integrado que regista automaticamente um cliente por si. Não é preciso programar para testar chamadas.
Cmd+Shift+R no Mac, Ctrl+F5 no Windows)./public/docs, já autenticado.GET /public/v1/properties, clique em Try it out e depois em Execute.A partir daqui, pode experimentar cada endpoint com um clique, ver o JSON exato que a Nowistay devolve e copiar o comando cURL de qualquer chamada. É a forma recomendada de explorar a API antes de escrever código.
Importante. O cliente do ambiente de testes só existe no seu navegador. Serve para testar, mas numa integração real deve criar uma credencial de API pessoal ou registar o seu próprio cliente OAuth (ambos explicados abaixo).
Se está a automatizar a sua própria conta (um script de relatórios, uma sincronização com a sua ferramenta de contabilidade, um pequeno painel), não precisa de todo o fluxo OAuth. Crie uma credencial de API pessoal na aplicação e troque-a por um token numa única chamada. Sem ecrã de consentimento e sem tokens de atualização para gerir.
Reporting script) e marque apenas as permissões de que precisa.O seu script troca então a credencial por um token de acesso (válido durante uma hora) e chama a API:
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"
Quando o token expirar, peça um novo da mesma forma. Neste fluxo não há token de atualização, e é essa a ideia: duas linhas de código, nada para vigiar.
Pode criar até 10 credenciais, cada uma com o seu nome e as suas permissões. Uma credencial só lê e escreve os dados a que a sua própria conta tem acesso e precisa da mesma subscrição ativa do AI Channel Manager que o resto da API.
Não pode editar os âmbitos de um token ou de uma credencial pessoal existente. Crie uma credencial de substituição com o conjunto completo de permissões de que a sua integração precisa. Os clientes, os tokens de acesso, os códigos de autorização e os tokens de atualização existentes mantêm as concessões originais; nenhuma permissão é adicionada automaticamente.
https://app.nowistay.com/hub/user/developer. Anote as permissões usadas pela integração existente.calendar.write; o envio de mensagens precisa de messages.write; pedir o pagamento de uma reserva precisa de bookings.write e payments.write.POST /public/oauth/token com grant_type=client_credentials e as credenciais de substituição. Verifique o valor scope devolvido e teste um endpoint permitido por esses âmbitos. GET /public/v1/properties exige especificamente properties.read.Rodar o segredo não adiciona âmbitos. Apenas substitui o segredo da mesma credencial; o segredo anterior continua válido durante 7 dias. Atualizar ou pedir outro token de acesso não pode ampliar a concessão original. Os âmbitos de escrita não incluem automaticamente os de leitura.
POST /public/oauth/register com o conjunto completo de âmbitos pretendido e os dados normais da sua aplicação. Um registo equivalente com exatamente o mesmo conjunto de âmbitos reutiliza o cliente correspondente; um conjunto de âmbitos alterado cria um novo registo. Guarde as credenciais de cliente devolvidas.No ambiente de testes da documentação, atualize a página e autorize de novo com os âmbitos necessários. As novas permissões são listadas com etiquetas legíveis e os respetivos identificadores em inglês, francês, espanhol, alemão, neerlandês e italiano.
A API usa o OAuth 2.1 padrão, com o fluxo de código de autorização e PKCE. Numa frase: o utilizador abre uma página da Nowistay, diz que sim, a aplicação recebe um código curto, troca-o por um token de acesso e chama a API com esse token. Os tokens expiram e podem ser atualizados sem voltar a incomodar o utilizador.
Os três endpoints OAuth que vai usar:
/public/oauth/register (POST)/public/oauth/authorize (GET, redirecionamento do navegador)/public/oauth/token (POST)Pode também obter os metadados OAuth em /.well-known/oauth-authorization-server/public-api, que lista todos os endpoints e as funcionalidades suportadas.
Qualquer pessoa pode registar um cliente OAuth, pelo que os anfitriões precisam de uma forma de distinguir uma aplicação recém-criada de uma integração consolidada. Por isso, todas as aplicações recém-registadas começam como não verificadas:
Está a criar algo para mais de 3 contas? Escreva ao suporte com o nome da sua aplicação, o site e o caso de utilização. Depois de a sua aplicação ser verificada, o aviso desaparece e o limite de contas é levantado.
A API REST suporta 25 âmbitos, incluindo dez permissões adicionais para edições de alojamentos, mensagens, guias, conhecimento, criação de hóspedes, extras e pagamentos. Selecione apenas as permissões de que a sua integração precisa.
properties.read: ler os detalhes e as definições de funcionamento dos alojamentos.properties.write: atualizar os detalhes e as definições de funcionamento dos alojamentos.calendar.read: ler a disponibilidade, as tarifas por noite e as restrições de estadia.calendar.write: atualizar a disponibilidade, as tarifas por noite e as restrições de estadia.bookings.read: ler reservas, detalhes financeiros e o estado seguro dos pedidos de pagamento.bookings.sensitive.read: incluir nas respostas das reservas os contactos dos hóspedes, as moradas postais e os códigos de acesso; exige também bookings.read para leituras.bookings.write: criar e atualizar reservas diretas. Os pedidos de pagamento e os reembolsos exigem também payments.write.booking_parameters.read: ler as definições e os valores dos parâmetros de reserva personalizados.booking_parameters.write: criar e atualizar definições e valores de parâmetros.missions.read: ler missões e relatórios de conclusão.missions.write: criar, atualizar e atribuir missões.activity.read: ler os registos de atividade dos alojamentos.team_members.read: ler membros da equipa, contactos e atribuições a alojamentos.webhooks.read: ler as subscrições de webhooks.webhooks.write: criar, atualizar, pausar e eliminar subscrições de webhooks.customers.read: ler fichas de hóspedes, contactos e histórico de estadias.customers.write: criar fichas de hóspedes.upsells.read: ler o catálogo de extras e as compras das reservas.payments.write: pedir o pagamento durante a criação da reserva e instruir reembolsos totais ou parciais de cancelamentos; exige também bookings.write.messages.read: ler conversas e mensagens dos hóspedes.messages.write: enviar mensagens aos hóspedes.guides.read: ler guias de boas-vindas e o conteúdo das páginas.guides.write: editar guias, criar e atualizar páginas, alterar a posição das páginas e carregar imagens.knowledge.read: ler as perguntas e respostas privadas dos alojamentos.knowledge.write: criar e atualizar conhecimento privado. A cópia exige também knowledge.read.Os oito âmbitos REST predefinidos continuam a ser properties.read, calendar.read, bookings.read, booking_parameters.read, missions.read, activity.read, team_members.read e webhooks.read. Os predefinidos não atualizam os tokens existentes.
bookings.write + payments.write. O cancelamento sem reembolso usa apenas bookings.write.customers.read + bookings.read.upsells.read + bookings.read. A leitura do catálogo só precisa de upsells.read.knowledge.read + knowledge.write.bookings.write + booking_parameters.write. Um PATCH só com parâmetros mantém booking_parameters.write e funciona também em reservas OTA.Os novos endpoints de escrita devolvem resultados de ação mínimos, a menos que o token tenha também o âmbito de leitura correspondente. A ocultação de dados nas reservas existentes mantém-se. Os endpoints de missões e de conversas incluem o contexto da reserva associada sob os seus próprios âmbitos.
Estes exemplos usam IDs e credenciais fictícios. Substitua-os pelos seus valores. Este fluxo destina-se a aplicações de parceiros; as credenciais pessoais usam client_credentials, como mostrado acima.
Chame POST /public/oauth/register com as permissões de que precisa. Guarde com segurança o client_id e o client_secret devolvidos. O exemplo pede leituras de alojamentos, reservas e missões.
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"}'
Para um cliente público sem backend, use "tokenEndpointAuthMethod": "none" e PKCE, sem client secret.
Gere um verificador PKCE, o respetivo desafio S256 e um state aleatório. Redirecione o utilizador para o endpoint de autorização. O URL seguinte está numa só linha; codifique os valores da query como 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
O anfitrião inicia sessão, revê as permissões e aprova ou nega o acesso. Se aprovar, o callback contém um code de utilização única e o seu state. Rejeite um callback cujo state não coincida.
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"
A resposta inclui access_token, token_type, expires_in, refresh_token e scope. Guarde os tokens com segurança. Os tokens de acesso duram normalmente uma hora; use o prazo devolvido.
Este exemplo exige properties.read. Leia os campos data e pagination da resposta.
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"
Guarde o novo token de atualização devolvido pela resposta de atualização. Se a atualização falhar, reinicie a autorização. A atualização mantém os âmbitos concedidos anteriormente. As credenciais pessoais não têm token de atualização: peça um novo token de acesso com client_credentials.
GET /public/v1/properties/{property_id}/calendar exige calendar.read. Indique as datas from e to (inclusivas); um pedido pode abranger até 730 dias.
GET /public/v1/properties/101/calendar?from=2026-12-18&to=2026-12-20
Cada dia pode devolver availability, rate, minStay, maxStay, stopSell, closedToArrival, closedToDeparture, restricted e restrictionReasons. availability é o inventário vendável restante depois das reservas confirmadas. Os campos de restrição explicam por que razão uma data, ou uma ação de check-in/check-out, está restringida.
PATCH /public/v1/properties/{property_id}/calendar exige calendar.write. O pedido é parcial: envie apenas os controlos que devem mudar e os campos omitidos permanecem inalterados.
{
"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 é opcional: 0 é segunda-feira e 6 é domingo. Omita-o para atualizar todas as datas do intervalo. A resposta indica daysUpdated e a atualização normalizada que foi aplicada. As alterações são sincronizadas através do Nowistay PMS.
As operações de calendário exigem propriedade, o direito de assistente e a gestão de calendário ativa da Nowistay. Para ativar os âmbitos de calendário numa integração existente, siga Como adicionar âmbitos a um token de API existente acima; atualizar um token ou rodar o respetivo segredo não é suficiente.
Os filtros suportados incluem propertyId, propertyIds repetido, status, channel, fromDate e toDate. A paginação JSON padrão usa limit (máximo 100) e offset. Os filtros de data das reservas mantêm a semântica de sobreposição: departure >= fromDate e 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"
Exige o âmbito adicional bookings.sensitive.read. Sem ele, email, phone e o código da fechadura inteligente são omitidos.
As edições principais de uma reserva exigem bookings.write e uma reserva direta elegível. As reservas OTA permanecem só de leitura nos campos principais. Um PATCH que contenha apenas customParameters suporta também reservas OTA e usa 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
}'
Os pedidos PATCH de reservas existentes usam por predefinição silent=true. Defina silent=false para desencadear as notificações de atualização habituais. A criação de reservas usa por predefinição silent=false. Os campos omitidos permanecem inalterados e os valores null já suportados continuam a limpar campos. A sincronização da disponibilidade continua a fazer parte da operação partilhada.
Os parâmetros de reserva personalizados são úteis quando quer espelhar em cada reserva da Nowistay dados do seu próprio sistema.
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"
}
}'
Ambos os exemplos usam booking_parameters.write. As atualizações mistas de campos principais e de parâmetros exigem os dois âmbitos de escrita de reservas; uma falha de validação deixa ambos inalterados.
Envie null como valor para limpar um campo personalizado numa reserva.
Exige missions.write. Os fluxos de atribuição e de notificação também são executados nas missões criadas pela API.
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
}'
Exige activity.read.
curl "https://api.nowistay.com/public/v1/properties/101/activity?limit=20" \
-H "Authorization: Bearer YOUR_ACCESS_TOKEN"
Os eventos estão agrupados em três categorias: booking, mission e automation (mensagens aos hóspedes, eventos de fechaduras inteligentes).
Todos os caminhos desta secção são relativos a /public/v1. Substitua os IDs de exemplo por recursos pertencentes à conta ligada. O esquema OpenAPI lista todos os campos, enumerações e formatos de resposta suportados.
Use GET /properties/{id} com properties.read e PATCH /properties/{id} com properties.write. As listas de alojamentos aceitam search. As edições suportadas incluem o nome, a morada, a capacidade, o tipo de alojamento, os links de arrendamento, a capa, as horas de check-in/check-out, os limites de reserva e as definições predefinidas de preços e de estadia.
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 exige bookings.write, o direito de assistente e uma ligação PMS ativa. Inclua as datas, o e-mail e os dados do hóspede, com os campos de preços e operacionais suportados. requestPayment=true exige adicionalmente payments.write e cria a reserva pendente de pagamento.
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
}'
A criação pode ter êxito mesmo que a geração do link de pagamento falhe. A resposta continua a conter a reserva persistida ou o respetivo ID, com paymentRequest.sent=false e um erro explícito. Verifique este resultado antes de tentar de novo, para não criar uma reserva duplicada. Um URL de checkout só é devolvido por uma ação de pedido de pagamento autorizada.
Leia GET /bookings/{id}/payment-request com bookings.read para obter o estado seguro da reserva e do pedido de pagamento. Não devolve URLs de checkout. Esta versão não acrescenta uma API autónoma de administração de pagamentos.
O PATCH de reservas existentes suporta reservationNumber, cancellationRefundMode (none, full ou partial) e cancellationRefundAmount. Um reembolso explícito total ou parcial de um cancelamento exige bookings.write e payments.write. O cancelamento sem reembolso exige apenas 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"
}'
Uma reserva cancelada não prova que o reembolso foi concluído. Verifique o estado do pagamento antes de dizer ao hóspede que o reembolso foi efetuado. payments.write autoriza pedidos de pagamento e reembolsos de cancelamentos, não a revisão do preço de um checkout existente.
POST /guests usa customers.write; a criação duplicada de um hóspede devolve 409. As leituras existentes de clientes ao nível do proprietário continuam disponíveis. As listas de hóspedes aceitam propertyId, propertyIds repetido e os valores de orderBy suportados: created_at, updated_at, full_name, bookings_count, total_amount, last_stay. Use o prefixo - para ordem descendente; a predefinição é -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 exige customers.read e bookings.read e devolve o histórico de estadias elegível.
GET /missions/{id} e GET /missions/{id}/report usam missions.read. Uma missão válida sem relatório de conclusão devolve 200 com report: null. As listas de missões aceitam filtros de datas UTC agendadas, inclusivos, fromDate/toDate, propertyIds e teamMemberIds repetidos, a par dos filtros existentes.
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 suporta os filtros propertyId e bookingId. GET /conversations/{id}/messages lê o histórico de mensagens. Ambos exigem messages.read. Envie uma resposta com POST /messages e messages.write, indicando exatamente um de conversationId ou bookingId. O channelKind ou threadChannelId opcional seleciona um canal; não indique os dois seletores.
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."
}'
As mensagens seguem o circuito normal de envio de respostas do anfitrião, incluindo o encaminhamento de reservas com vários quartos. Uma mensagem persistida cujo envio falhou devolve o respetivo ID e o estado de envio: inspecione o resultado antes de tentar de novo. Os anexos de mensagens de hóspedes não são suportados por estes endpoints.
Use GET /properties/{id}/knowledge-questions e GET /properties/{id}/knowledge-questions/{questionId} com knowledge.read. Use POST na coleção e PATCH numa pergunta individual com 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 trata {id} como a origem e exige knowledge.read e knowledge.write. Envie targetPropertyIds para fundir noutros alojamentos. A cópia nunca elimina nem substitui respostas de destino; cada destino é validado antes de começar qualquer escrita.
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: ler ou editar o guia, incluindo as introduções localizadas.GET/POST /properties/{id}/welcome-guide/pages: listar ou criar páginas.GET/PATCH /properties/{id}/welcome-guide/pages/{pageId}: ler ou editar uma página individual e a sua posição.POST /properties/{id}/welcome-guide/images: carregar uma imagem a partir de um URL público suportado ou de uma entrada base64.As leituras exigem guides.read; as escritas exigem guides.write. Ao editar páginas estruturadas, mantenha os blocos EditorJS content/contents e os respetivos IDs, a formatação aninhada e os conteúdos multimédia. Os idiomas omitidos permanecem inalterados. A substituição de uma página estruturada por texto simples é rejeitada. Os tokens dos guias e os links de acesso dos hóspedes não são devolvidos.
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."
}
}'
As transferências de imagens têm de usar endereços acessíveis publicamente. Os redirecionamentos são verificados e os limites de tamanho são aplicados. Consulte o esquema do pedido de imagem para ver os campos de URL/base64 suportados e os limites.
GET /upsells exige upsells.read. GET /bookings/{id}/upsell-purchases exige upsells.read e bookings.read. Estes endpoints são só de leitura.
curl "https://api.nowistay.com/public/v1/bookings/9001/upsell-purchases" \
-H "Authorization: Bearer YOUR_ACCESS_TOKEN"
Acrescente responseFormat=table às listas de reservas ou de missões para obter columns, rows e pagination, com limit até 500. O JSON padrão continua a ser a predefinição e mantém o máximo de 100. Use offset para obter as páginas seguintes. Vários propertyIds são intersetados com propertyId se ambos os filtros forem indicados.
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"
As tabelas de reservas usam bookings.read; as tabelas de missões usam missions.read. As atribuições de limpeza nos relatórios de reservas exigem adicionalmente missions.read e a presença nas conversas exige messages.read. Os filtros de data das reservas mantêm a semântica de sobreposição; os filtros de data das missões usam datas UTC agendadas.
As rotas REST existentes, as predefinições de JSON padrão, a paginação, a ocultação de dados nas reservas, a limpeza de valores nulos suportada e as predefinições de notificação continuam disponíveis. As restrições de reservas relacionadas com pagamentos descritas acima passam a ser aplicadas. O REST e o MCP partilham as operações subjacentes e os respetivos efeitos secundários, enquanto os contratos das ferramentas MCP e o comportamento de pré-visualização/confirmação permanecem inalterados.
Uma página da Nowistay contém um documento EditorJS por idioma. A matriz blocks define a ordem de apresentação. Cada objeto dessa matriz é um bloco; coloque os exemplos abaixo dentro de content.blocks ou contents.<locale>.blocks. Os valores dos exemplos são fictícios e devem ser adaptados ao seu alojamento.
Estrutura comum: id é uma cadeia estável, única dentro do documento; mantenha os IDs existentes e atribua um novo a cada bloco novo. type é o nome exato do bloco, sensível a maiúsculas e minúsculas. data é um objeto cujos campos dependem do tipo. Preserve também os tunes e os metadados do documento existentes devolvidos numa leitura, em vez de os reconstruir sem necessidade.
Pedido de criação: POST /public/v1/properties/{id}/welcome-guide/pages com guides.write. Use locale + title + content para um idioma, ou titles + contents para vários. icon tem como predefinição info. position aceita start, end ou after_page; este último exige afterPageId. Eis um corpo de pedido completo em inglês/francês:
{
"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 é o texto do título. Use data.level: 2, em linha com o editor de guias. O próprio título da página pertence a title ou titles, fora dos blocos.
{
"id": "guide00001",
"type": "header",
"data": {
"text": "Arrival / Arrivée",
"level": 2
}
}
data.text é uma cadeia. Use as marcas em linha <b>, <i> e <a href="https://…"> para negrito, itálico e links. Escape as aspas duplas dentro de cadeias JSON. Não envie uma página HTML inteira nem Markdown como content.
{
"id": "guide00002",
"type": "paragraph",
"data": {
"text": "<b>Wi-Fi</b>: GuestNetwork. <i>Welcome / Bienvenue !</i> <a href=\"https://example.com/\">Information</a>"
}
}
Use style: unordered. items contém objetos, não cadeias. Cada item tem content (texto formatado), meta (um objeto) e items (uma matriz de itens filhos, vazia numa folha). Repita a mesma estrutura para o aninhamento.
{
"id": "guide00003",
"type": "list",
"data": {
"style": "unordered",
"meta": {},
"items": [
{
"content": "Kitchen / Cuisine",
"meta": {},
"items": [
{
"content": "Coffee machine / Machine à café",
"meta": {},
"items": []
}
]
}
]
}
}
Use style: ordered com meta.counterType: numeric na raiz. Mantenha a mesma estrutura de itens e as mesmas matrizes aninhadas de uma lista com marcadores.
{
"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": []
}
]
}
}
Use style: checklist. Coloque o estado inicial booleano da caixa em meta.checked de cada item. É conteúdo do guia, não um relatório de conclusão de missão.
{
"id": "guide00005",
"type": "list",
"data": {
"style": "checklist",
"meta": {},
"items": [
{
"content": "Windows closed / Fenêtres fermées",
"meta": {
"checked": false
},
"items": []
}
]
}
}
data.text é a citação, caption é a sua atribuição (ou uma cadeia vazia) e alignment é a definição de alinhamento do editor. Use left; a vista do hóspede aplica o seu próprio esquema de citação.
{
"id": "guide00006",
"type": "quote",
"data": {
"text": "Please respect the neighbours / Merci de respecter le voisinage.",
"caption": "Your host / Votre hôte",
"alignment": "left"
}
}
Um separador visual tem um objeto data vazio. A sua posição em blocks determina onde aparece a separação.
{
"id": "guide00007",
"type": "delimiter",
"data": {}
}
data.content é uma matriz de linhas; cada linha é uma matriz de cadeias de células. Mantenha o mesmo número de células em cada linha. Com withHeadings: true, a primeira linha fornece os cabeçalhos das colunas. Use false quando todas as linhas contiverem dados normais.
{
"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 é o URL da imagem carregada, não um nome de ficheiro local nem uma cadeia base64. caption é uma cadeia; withBorder, withBackground e stretched são booleanos. Faça primeiro POST da imagem para /public/v1/properties/{id}/welcome-guide/images e insira depois em content.blocks o editorJsImageBlock devolvido. Preserve os campos devolvidos e use um ID de bloco único. O URL abaixo é ilustrativo: substitua-o pelo URL real devolvido.
{
"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
}
}
Use service: youtube para um vídeo normal do YouTube, ou youtubeShort para um Short. source é o URL original; embed é o URL de incorporação do YouTube correspondente. width e height são números e caption é uma cadeia. O editor usa 580 × 320 para um vídeo normal e 315 × 560 para um Short. Substitua VIDEO_ID_11 nos dois URLs pelo mesmo ID real de 11 carateres do vídeo; nos Shorts, o caminho de origem é /shorts/VIDEO_ID_11. O HTML arbitrário de iframe não é o formato do bloco.
{
"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 usa os mesmos campos data que video. Preserve o tipo existente ao editar uma página; ambos apresentam vídeos e Shorts do YouTube. Não presuma que todos os fornecedores de incorporação suportados pelo EditorJS são suportados pela Nowistay.
{
"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": ""
}
}
Use um objeto data vazio para colocar aqui o catálogo de extras elegíveis. Os produtos, os preços e a disponibilidade vêm do catálogo configurado e do contexto do hóspede; não estão incorporados neste bloco.
{
"id": "guide00012",
"type": "upsellCatalog",
"data": {}
}
data.itemId é o ID numérico de um extra existente. Encontre o ID correto com GET /public/v1/upsells usando upsells.read; substitua o 401 fictício abaixo. Mantenha o ID original, a menos que queira selecionar outro produto. Escrever a página usa guides.write; este bloco não cria um produto, não define um preço nem o compra.
{
"id": "guide00013",
"type": "upsellProduct",
"data": {
"itemId": 401
}
}
Validação REST: a criação e as atualizações de páginas rejeitam tipos de bloco não suportados e dados malformados com HTTP 422. Todos os idiomas fornecidos são verificados antes de qualquer escrita, incluindo itens de listas aninhadas, células de tabelas e campos multimédia. O erro identifica o documento e o bloco em causa. Os IDs continuam opcionais nos documentos existentes; quando fornecidos, têm de ser cadeias únicas não vazias. Os metadados e a formatação são preservados. Esta validação estrutural não verifica se uma imagem está acessível nem se um extra existe.
imageLibrary é o controlo de seleção de imagens do editor, não um bloco de galeria da API. Use blocos image. linkPreview é uma definição de bloco (tunes), não um tipo de conteúdo separado; preserve os dados existentes. Não invente blocos html, code, button nem fornecedores de vídeo não documentados: a aceitação de um objeto JSON não garante que seja apresentado no guia.
Comece por ler GET /public/v1/properties/{id}/welcome-guide/pages/{pageId} com guides.read para obter content e contents. Trabalhe numa cópia do documento completo do idioma que está a editar, altere apenas os blocos pretendidos e faça depois PATCH desse documento para o mesmo URL com guides.write. Enviar apenas um bloco substitui o documento por esse único bloco; os blocos não são fundidos por id. Os idiomas omitidos permanecem inalterados. Para mover uma página existente, use order, não position.
Os campos text e texts não substituem o documento estruturado. Siga as indicações simpleTextUpdateAllowed, recommendedUpdateMode e recommendedUpdateField da resposta de leitura; uma página estruturada rejeita a substituição por texto simples. Os exemplos individuais desta secção descrevem blocos, não pedidos PATCH completos para uma página existente. Volte a ler a página depois de editar e verifique idiomas, IDs, links e conteúdos multimédia. Só com guides.write, a resposta de escrita é mínima; acrescente guides.read para receber os detalhes.
Se não quer consultar a API repetidamente para detetar alterações, pode subscrever webhooks. A Nowistay chamará então um URL que indicar sempre que uma reserva for criada ou atualizada no alojamento e enviará os mesmos dados da reserva que GET /public/v1/bookings/{id} devolve.
Hoje são suportados dois eventos:
booking.created: foi registada uma nova reserva no alojamento.booking.updated: uma reserva existente mudou (datas, estado, dados do hóspede, código da fechadura inteligente, etc.).Cada webhook está associado a um único alojamento e pode registar até três por alojamento. As entregas são assinadas (HMAC-SHA256) para poder verificar que provêm mesmo da Nowistay, são repetidas com recuo exponencial em caso de falha e o endpoint é desativado automaticamente se continuar a falhar durante mais de 72 horas. Os payloads dos webhooks não contêm campos sensíveis do hóspede (e-mail, telefone, morada, código da fechadura inteligente). Quando precisar deles, chame a API com o âmbito bookings.sensitive.read.
Os detalhes completos de configuração e de verificação da assinatura estão no artigo dedicado: API pública: receber webhooks de reservas em tempo real.
Quando atinge o limite, a API devolve 429 Rate limit exceeded. Aguarde e tente de novo passados alguns segundos.
Todos os erros seguem a mesma estrutura, com um code estável, uma mensagem legível e um requestId que pode incluir nos pedidos de suporte.
{
"error": {
"code": "validation_error",
"message": "The request contains an invalid value.",
"requestId": "example-request-id"
}
}
400: pedido inválido (corpo malformado, campo em falta).
silent nas escritas. Defina-o como true quando sincroniza dados em massa e não quer desencadear notificações aos hóspedes.requestId nos seus registos. Torna os pedidos de suporte muito mais rápidos de resolver./public/openapi.json.Guias para anfitriões: leia o blogue.
Pronto para pôr o seu alojamento em piloto automático?