API OmniStay
Versão 1 · Última atualização: 22 de outubro de 2026
Ligue os seus outros softwares ao OmniStay: contabilidade, painel, ferramenta de manutenção, Zapier ou Make. A API dá acesso aos seus alojamentos, reservas, tarefas, proprietários e à sua equipa, e permite agir: tarefas, orçamentos, faturas, calendário, preços… Os webhooks avisam os seus softwares assim que chega uma reserva, uma mensagem ou uma tarefa. A sua IA (ChatGPT, Claude, Gemini) também se liga, através do servidor MCP.
Em resumo
- Endereço base:
https://escale-roan.vercel.app/api/v1 - Formato: JSON em UTF-8. As datas estão no formato
AAAA-MM-JJ, as horasHH:MM(hora de Paris), os montantes em euros. - Autenticação: uma chave de API da sua empresa de gestão no cabeçalho
Authorization: Bearer esk_…. - Permissões: cada chave é só de leitura, ou de leitura e escrita (para agir: criar tarefas, e as 91 ações).
- IA ligadas: servidor MCP no endereço
https://app.omnistay.ai/mcp, ligação OAuth ou por chave de API (detalhes). - Limite: 120 pedidos por minuto e por chave.
Criar uma chave
- No OmniStay, abra Definições › Chaves API. Só a proprietária e os administradores da conta têm acesso.
- Dê à chave o nome do software a ligar, e autorize a escrita apenas se esse software tiver de agir no OmniStay.
- Copie a chave de imediato: começa por
esk_e só é mostrada uma vez. O OmniStay guarda apenas um hash dela. - Uma chave que já não é usada, ou que possa ter sido vista por outra pessoa: revogue-a. Deixa de funcionar de imediato.
Autenticar-se
Cada pedido leva a chave. Para verificar que funciona:
curl https://escale-roan.vercel.app/api/v1/me \
-H "Authorization: Bearer esk_VOTRE_CLE"
{
"data": {
"organization": { "id": "11111111-1111-4111-8111-111111111111", "name": "Les Clés du Canal" },
"key": { "name": "Comptabilité", "prefix": "esk_Ab12Cd", "scopes": ["read"] }
}
}
O cabeçalho X-Api-Key: esk_… também é aceite.
Recursos
| Metodologia | Endereço | O que devolve |
|---|---|---|
| GET | /me | A sua empresa de gestão e a chave utilizada |
| GET | /properties, /properties/{id} | Alojamentos |
| GET | /bookings, /bookings/{id} | Reservas |
| GET | /missions, /missions/{id} | Tarefas: limpezas, chaves, manutenção… |
| POST | /missions | Cria uma tarefa (chave com permissão de escrita) |
| GET | /actions | As 91 ações, com o esquema dos respetivos parâmetros |
| POST | /actions/{nom} | Executa uma ação (chave com permissão de escrita para agir) |
| POST | /webhooks | Subscreve um endereço a eventos (webhooks) |
| GET | /webhooks, /webhooks/{id} | As subscrições criadas com esta chave |
| DELETE | /webhooks/{id} | Elimina uma subscrição |
| GET | /owners, /owners/{id} | Proprietários |
| GET | /team, /team/{id} | Equipa |
Alojamentos
GET /properties
{
"data": [{
"id": "p1", "name": "Loft Canal Saint-Martin", "internal_name": "Valmy 3e G", "type": "appartement", "status": "active",
"address": { "street": "42 quai de Valmy", "zip": "75010", "city": "Paris" },
"surface_m2": 58,
"capacity": { "guests": 4, "double_beds": 1, "single_beds": 0, "sofa_beds_double": 1, "sofa_beds_single": 0 },
"check_in": { "from": "16:00", "until": "23:00", "mode": "lockbox" }, "check_out": "11:00",
"platforms": ["airbnb", "booking"], "base_price": 145, "cleaning_fee": 70,
"owner_id": "c1", "created_at": "2026-10-17", "updated_at": "2026-10-17T09:12:44.512Z"
}],
"total": 6, "limit": 100, "offset": 0
}
Os códigos de acesso (cofre de chaves, fechadura) e o Wi-Fi nunca são devolvidos pela API.
Reservas
GET /bookings?from=2026-10-01&to=2026-11-01&property_id=p1
| Filtro | Efeito |
|---|---|
from, to | As reservas que tocam o período: saída depois de from, chegada antes de to |
property_id | Um só alojamento |
status | confirmed ou cancelled |
updated_since | Apenas o que mudou desde uma data e hora ISO 8601 (2026-10-17T09:00:00Z): prático para sincronizar |
{
"data": [{
"id": "cx_8f2a", "property_id": "p1", "platform": "airbnb", "reference": "HMX4K2P9QA", "status": "confirmed",
"check_in": "2026-10-17", "check_out": "2026-10-21", "nights": 4, "arrival_time": "16:30", "departure_time": null,
"guest": { "first_name": "Camille", "last_name": "Laurent", "email": "camille@exemple.fr", "phone": "+33 6 12 34 56 78",
"language": "fr", "country": "France", "count": 2 },
"amounts": { "currency": "EUR", "guest_paid": 690.8, "accommodation": 600, "nightly": 150, "cleaning": 70, "linen": 15,
"tourist_tax": 20.8, "platform_fees": 103.85, "payout": 566.15, "tax_collected_by_platform": true },
"created_at": "2026-09-30", "updated_at": "2026-10-16T18:02:11.870Z"
}],
"total": 1, "limit": 100, "offset": 0
}
O dia de saída (check_out) não é uma noite reservada. platform vale airbnb, booking, vrbo, expedia, direct ou manual.
Tarefas
GET /missions?from=2026-10-20&to=2026-10-31&type=cleaning
Filtros: from e to (data da tarefa, incluídas), property_id, member_id, type, status, updated_since.
{
"data": [{
"id": "cl_8f2a", "type": "cleaning", "title": "Ménage de fin de séjour", "description": null,
"property_id": "p1", "booking_id": "cx_8f2a", "member_id": "t1",
"date": "2026-10-21", "time": "11:00", "duration": "02:30", "pay": 55, "billed": 70, "status": "accepted",
"report": null, "created_at": "2026-09-30", "updated_at": "2026-10-16T18:02:12.004Z"
}],
"total": 1, "limit": 100, "offset": 0
}
| Campo | Valores |
|---|---|
type | cleaning (limpeza), keys (chaves), diy, linen, plumbing, electricity, photo, delivery, pool, tour, decoration, pests, hvac, taxi, massage, food, babysitting, pets, housekeeper, other |
status | unassigned, offered (proposta), accepted, done (feita, por validar), validated, cancelled |
pay, billed | Pago ao interveniente, e refaturado ao proprietário (euros) |
report | Depois da tarefa: número de fotos, comentário, duração em minutos, objetos em falta e danos |
Criar uma tarefa
Com uma chave que tenha permissão de escrita. A tarefa é proposta à pessoa escolhida (member_id) ou, caso contrário, à equipa do alojamento; essa pessoa aceita-a na sua app, e a tarefa aparece de imediato no OmniStay.
curl -X POST https://escale-roan.vercel.app/api/v1/missions \
-H "Authorization: Bearer esk_VOTRE_CLE" \
-H "Content-Type: application/json" \
-d '{ "type": "plumbing", "property_id": "p1", "date": "2026-10-18", "time": "09:00",
"member_id": "t2", "description": "Fuite sous l’évier de la cuisine" }'
| Campo | Obrigatório | Por defeito |
|---|---|---|
property_id | Sim | — |
date | Sim | — |
type | Não | cleaning |
time | Não | Hora de saída do alojamento para uma limpeza, 16:00 para as chaves, 10:00 nos restantes casos |
duration | Não | Duração de limpeza do alojamento, caso contrário 02:00 |
pay, billed | Não | Definições do alojamento para uma limpeza |
member_id, booking_id | Não | Nenhum |
title, description | Não | O nome do tipo de tarefa |
Resposta 201 com a tarefa criada, no mesmo formato que GET /missions.
Ações
Tudo o que o Assistente de IA sabe fazer no OmniStay passa também pela API: 91 ações (orçamentos, faturas, reservas, calendário, preços, tarefas, equipa e ausências, proprietários, alojamentos, mensagens, avaliações, cauções, incidentes, danos e litígios, prospects, estimativas de rendimentos, receção dos hóspedes e mensagens agendadas, taxa turística, estatísticas das reservas e previsão…), com os mesmos controlos: permissões da pessoa que criou a chave, registo, anulação durante 24 horas a partir da app. A lista, com o esquema JSON dos parâmetros de cada uma:
curl https://escale-roan.vercel.app/api/v1/actions \
-H "Authorization: Bearer esk_VOTRE_CLE"
{ "data": [{ "name": "creer_devis", "title": "Créer un devis", "module": "Facturation", "kind": "write", "confirmation": false,
"description": "…", "input_schema": { "type": "object", "properties": { … } },
"method": "POST", "path": "/api/v1/actions/creer_devis" }], "total": 91 }
Para executar uma ação, envie os respetivos parâmetros em JSON:
curl -X POST https://escale-roan.vercel.app/api/v1/actions/creer_devis \
-H "Authorization: Bearer esk_VOTRE_CLE" \
-H "Content-Type: application/json" \
-d '{ "client": "Sophie Martin", "objet": "Ménage de printemps",
"lignes": [{ "designation": "Grand ménage", "prix_unitaire": 120 }] }'
{ "status": "done", "message": "Devis en brouillon pour Sophie Martin : « Ménage de printemps »…",
"data": { "id": "doc_…" }, "url": "https://app.omnistay.ai/app/#/facturation/document/doc_…", "journal_id": "…" }
- Resposta
201quando a ação é feita ("status": "done"),200para uma leitura ("status": "ok"). - Acrescente
"dry_run": truepara ver o que a ação faria, sem alterar nada: resposta"status": "preview"com a pré-visualização. - As ações
"confirmation": trueenviam algo ou não se podem anular (emitir uma fatura, enviar uma mensagem, calendário e preços enviados às plataformas, debitar uma caução…). Pela API, são executadas logo no pedido: experimente-as primeiro comdry_run. - As ações
"kind": "write"exigem uma chave com permissão de escrita. Nunca há códigos de acesso nem palavras-passe de Wi-Fi nas respostas.
IA ligadas (MCP)
O OmniStay é um servidor MCP (Model Context Protocol): o ChatGPT, o Claude, o Gemini, o Claude Code, o Gemini CLI ou os seus próprios agentes leem e agem no OmniStay com as 91 ações acima, sob a forma de ferramentas. Controlar o OmniStay a partir de uma IA faz parte da opção Assistente de IA.
- Endereço:
https://app.omnistay.ai/mcp(HTTP «streamable», respostas JSON, sem sessão). - Versões do protocolo: 2024-11-05, 2025-03-26, 2025-06-18, 2025-11-25 e 2026-07-28.
- Ligação OAuth 2.1 (ChatGPT, Claude, Gemini): descoberta através de
/.well-known/oauth-protected-resourcee/.well-known/oauth-authorization-server, registo dinâmico (/oauth/register) ou documento de metadados do cliente, PKCE S256 obrigatório, tokens associados ao recurso, renovação com rotação. A pessoa inicia sessão, escolhe a sua empresa de gestão e pode autorizar apenas a leitura; desliga a IA com um clique em Definições › Chaves API. - Ligação por chave de API (Claude Code, Gemini CLI, os seus agentes): cabeçalho
Authorization: Bearer esk_…. - Confirmação: as ferramentas que enviam algo ou não se podem anular têm um parâmetro
confirmer. Sem ele, não fazem nada e devolvem uma pré-visualização que começa por «Rien n’est fait» (nada foi feito); a IA mostra-a à pessoa e volta a chamar a ferramenta com"confirmer": truedepois do seu acordo. - Registo: cada ação fica registada em Definições › Diário da IA, em nome da pessoa que ligou a IA, e pode ser anulada durante 24 horas. 120 pedidos por minuto e por IA ligada.
Claude Code:
claude mcp add --transport http omnistay https://app.omnistay.ai/mcp \
--header "Authorization: Bearer esk_VOTRE_CLE"
Gemini CLI, em ~/.gemini/settings.json:
{ "mcpServers": { "omnistay": { "httpUrl": "https://app.omnistay.ai/mcp",
"headers": { "Authorization": "Bearer esk_VOTRE_CLE" } } } }
ChatGPT, Claude e Gemini: os passos, atualizados, estão no OmniStay, em Definições › Chaves API.
Webhooks
O OmniStay avisa o seu software assim que algo acontece: envia um POST em JSON para o endereço que indicar. Subscreva na app (Definições › Integrações, com «Enviar um teste» e os últimos envios) ou pela API com uma chave, segundo o modelo «REST Hooks».
| Evento | Quando |
|---|---|
booking.created | Chega uma reserva futura: plataforma, reserva direta ou introduzida manualmente. Uma reserva feita no site de uma empresa de gestão ou de um anfitrião é enviada depois de paga, nunca enquanto aguarda o pagamento (nem se for cancelada antes) |
booking.updated | Datas, alojamento, horas de chegada ou de saída, hóspede ou montantes alterados (várias alterações antes do envio: um só envio, o mais recente) |
booking.cancelled | Uma reserva é cancelada |
precheckin.completed | O hóspede preencheu o pré-check-in: data.precheckin (completed_at, guests, forms), nunca os registos de hóspedes |
message.received | Uma nova mensagem de um hóspede, um envio por mensagem (text, translation, sent_at) |
review.received | Uma nova avaliação: kind vale review (plataforma) ou first_impression (app do hóspede) |
incident.opened | Um hóspede comunica um problema (água quente, chaves, Wi-Fi, fuga…) |
mission.created, mission.accepted, mission.done | Uma tarefa futura é criada, aceite por uma pessoa da equipa, concluída (com o seu relatório) |
invoice.issued | Uma fatura, um sinal ou uma nota de crédito recebe o seu número: source vale invoicing (Faturação) ou owner_statement (fatura do mês de um proprietário) |
lead.received | Alguém preenche o formulário do seu site institucional |
As estadias e as tarefas passadas, as avaliações e as mensagens antigas, e o que uma importação a partir de um software antigo acrescenta não desencadeiam nada.
O que o seu endereço recebe
POST https://votre-outil.exemple.fr/omnistay
Content-Type: application/json; charset=utf-8
User-Agent: OmniStay-Webhooks/1.0
X-OmniStay-Event: booking.created
X-OmniStay-Event-Id: evt_6f1c0b7e2d4a4c1f9b3e8d5a7c2f1e09
X-OmniStay-Delivery: 1842
X-OmniStay-Signature: t=1792656000,v1=5257a869e7ecebeda32affa62cdca3fa51cad7e77a0e56ff536d0ce8e108d8bd
{
"id": "evt_6f1c0b7e2d4a4c1f9b3e8d5a7c2f1e09",
"type": "booking.created",
"created_at": "2026-10-22T09:14:03Z",
"test": false,
"organization": { "id": "11111111-1111-4111-8111-111111111111", "name": "Les Clés du Canal" },
"data": {
"id": "cx_8f2a", "property_id": "p1", "property": { "id": "p1", "name": "Loft Canal Saint-Martin" },
"platform": "airbnb", "reference": "HMX4K2P9QA", "status": "confirmed",
"check_in": "2026-10-24", "check_out": "2026-10-28", "nights": 4, "arrival_time": "16:30", "departure_time": null,
"guest": { "first_name": "Camille", "last_name": "Laurent", "email": "camille@exemple.fr", "phone": "+33 6 12 34 56 78",
"language": "fr", "country": "France", "count": 2 },
"amounts": { "currency": "EUR", "guest_paid": 690.8, "payout": 566.15, "…": "…" },
"created_at": "2026-10-22"
}
}
datasegue o formato da API (reserva, tarefa…), com o nome do alojamento (property), da pessoa da equipa (member) ou do hóspede (guest). Nunca códigos de acesso, Wi-Fi, caução nem registo de hóspedes.- Responda com um código
2xxem menos de 8 segundos; os redirecionamentos não são seguidos. - Um mesmo evento pode chegar duas vezes (nova tentativa):
idpermite ignorar um duplicado. A ordem de chegada não é garantida:created_atdá a ordem. - «Enviar um teste», na app, envia um exemplo do evento escolhido com
"test": truee dados de exemplo: estão lá todos os campos, para que o Zapier ou o Make aprendam a forma dos dados.
Verificar a assinatura
O cabeçalho X-OmniStay-Signature vale t=<horodatage>,v1=<signature>. A assinatura é o HMAC-SHA256 (em hexadecimal) de <t>.<corps brut>, calculado com o segredo do webhook (whsec_…, dado na criação e visível na app). Recuse um carimbo temporal com mais de 5 minutos.
import crypto from 'node:crypto';
// corps : le texte brut reçu, avant tout JSON.parse
function signatureValable(secret, entete, corps) {
const m = /^t=(\d+),v1=([0-9a-f]{64})$/.exec(entete || '');
if (!m || Math.abs(Date.now() / 1000 - Number(m[1])) > 300) return false;
const attendue = crypto.createHmac('sha256', secret).update(`${m[1]}.${corps}`).digest('hex');
return crypto.timingSafeEqual(Buffer.from(attendue), Buffer.from(m[2]));
}
Novas tentativas e desativação
- Sem resposta
2xx: nova tentativa após 1 min, 5 min, 30 min, 2h e depois 8h (6 tentativas no total), com exatamente o mesmo corpo e o mesmoid. - 24 horas de falhas seguidas: o webhook é desativado. Reativa-se na app.
- Uma resposta
410 Gonedesativa-o de imediato (modelo REST Hooks). - Revogar uma chave desativa os webhooks que ela criou. O histórico dos envios é guardado durante 30 dias.
Subscrever pela API
| Metodologia | Endereço | Efeito |
|---|---|---|
| POST | /webhooks | Cria uma subscrição: { "url": "https://…", "events": ["booking.created"], "name": "…" } (target_url e event também são aceites). Resposta 201 com data e secret, dado uma só vez pela API |
| GET | /webhooks, /webhooks/{id} | As subscrições criadas com esta chave, e a lista dos eventos (events) |
| DELETE | /webhooks/{id} | Elimina uma subscrição criada com esta chave |
curl -X POST https://escale-roan.vercel.app/api/v1/webhooks \
-H "Authorization: Bearer esk_VOTRE_CLE" \
-H "Content-Type: application/json" \
-d '{ "url": "https://votre-outil.exemple.fr/omnistay", "events": ["booking.created", "booking.cancelled"] }'
Basta uma chave só de leitura. Endereços apenas em https:// (porta 443), nunca um endereço IP, local ou interno; no máximo 20 webhooks por empresa de gestão.
Zapier e Make
O OmniStay não tem app oficial no Zapier nem no Make: a ligação faz-se pelos webhooks (para ser avisado) e pela chave de API (para agir). Os passos estão na app, em Definições › Integrações; o passo a passo, com três exemplos (reservas no Google Sheets, mensagens dos hóspedes no Slack, tarefa criada a partir de um formulário), está no centro de ajuda (em francês): «Relier OmniStay à Zapier» e «Relier OmniStay à Make».
| Ser avisado | Agir no OmniStay | |
|---|---|---|
| Zapier | «Webhooks by Zapier» › «Catch Hook» (planos pagos do Zapier) | «Webhooks by Zapier» › «Custom Request»: Method, URL, Data (JSON) e, em Headers, Authorization: Bearer esk_… |
| Make | «Webhooks» › «Custom webhook» | «HTTP» › «Make a request»: Authentication type «API key» (chave Bearer esk_… no cabeçalho Authorization), corpo application/JSON |
Proprietários e equipa
GET /owners
{ "data": [{ "id": "c1", "civility": "Mme", "first_name": "Sophie", "last_name": "Martin", "email": "sophie@exemple.fr",
"phone": "06 12 34 56 78", "address": "8 rue Lepic, 75018 Paris", "commission": { "mode": "percent", "value": 20 },
"since": "2023-04-02", "property_ids": ["p1", "p2"] }], "total": 1, "limit": 100, "offset": 0 }
GET /team
{ "data": [{ "id": "t1", "first_name": "Fatima", "last_name": "B.", "role": "cleaning", "status": "active",
"property_ids": ["p1", "p2"] }], "total": 1, "limit": 100, "offset": 0 }
role vale cleaning, keys, maintenance ou other. Os antigos membros da equipa não aparecem.
Listas e páginas
As listas devolvem data, total, limit e offset. Por defeito, 100 elementos; limit vai até 500. Para a página seguinte, aumente offset: ?limit=100&offset=100. As reservas são ordenadas por data de chegada, as tarefas por data e hora.
Erros
Em caso de erro, a resposta contém um código estável para os seus programas e uma mensagem em francês:
{ "error": { "code": "read_only_key", "message": "Cette clé est en lecture seule : créez une clé avec le droit d’écriture." } }
| Estado | Códigos | Significado |
|---|---|---|
| 400 | invalid_date, invalid_period, invalid_status, invalid_type, invalid_limit, invalid_offset, invalid_json | Um filtro ou o corpo do pedido está mal formado |
| 401 | missing_key, invalid_key | Chave ausente, desconhecida ou revogada |
| 403 | read_only_key | A chave não tem permissão de escrita |
| 404 | not_found | Endereço ou elemento não encontrado |
| 405 | method_not_allowed | Método não suportado neste endereço |
| 422 | property_required, unknown_property, unknown_member, unknown_booking, invalid_time, invalid_duration, invalid_amount, invalid_text | A tarefa a criar não é válida |
| 403, 404, 409, 422 | read_only, forbidden, unknown_action, not_found, conflict, invalid_input, invalid_state, ambiguous, already_exists… | Ações: permissões insuficientes, ação ou elemento desconhecido, elemento alterado entretanto (tente novamente), parâmetros a corrigir, vários elementos possíveis (especifique), já feito. A mensagem diz o que fazer. |
| 409, 422 | url_required, invalid_url, events_required, already_exists, too_many_webhooks | Webhooks: endereço em falta ou recusado (apenas https público), nenhum evento conhecido, endereço já subscrito, mais de 20 webhooks |
| 429 | rate_limited | Mais de 120 pedidos no mesmo minuto: tente novamente um pouco mais tarde |
| 500, 503 | server_error, not_configured | Problema do nosso lado: tente novamente dentro de instantes |
Limites e segurança
- Uma chave dá acesso aos dados da sua empresa de gestão: guarde-a como uma palavra-passe. Use-a a partir de um servidor ou de uma ferramenta de automatização, nunca numa página web ou numa app pública.
- Uma chave só vê a sua empresa de gestão. Nunca dá acesso aos códigos de acesso, ao Wi-Fi nem aos meios de pagamento; as cauções só são libertadas ou debitadas através das ações previstas, registadas no diário.
- Os dados dos seus hóspedes, proprietários e membros da equipa continuam sob a sua responsabilidade: ligue apenas softwares de confiança, e revogue uma chave assim que deixar de ser usada.
- 120 pedidos por minuto e por chave, no máximo 20 chaves ativas por empresa de gestão.
- Os endereços da versão 1 não vão mudar. As novidades chegarão sob a forma de novos campos ou novos endereços.
Se pedir ajuda, indique o nome da chave utilizada, nunca a própria chave.