Integração com Webhook
Webhooks permitem que seus sistemas recebam notificações em tempo real quando eventos acontecem na sua conta Wink — novas reservas, cancelamentos, atualizações de pagamento e mais. Este guia orienta você na configuração e nas melhores práticas.
Público
Seção intitulada “Público”Este guia é para desenvolvedores que integram o Wink com sistemas externos, como sistemas de gestão de propriedades (PMS), gerenciadores de canais, CRMs ou painéis personalizados.
Como os webhooks funcionam
Seção intitulada “Como os webhooks funcionam”- Você registra uma URL de webhook no Wink.
- Quando um evento ocorre (por exemplo, uma nova reserva), o Wink envia um HTTP POST para sua URL.
- Seu servidor processa o payload e responde com um
200 OK.
Configurando um webhook
Seção intitulada “Configurando um webhook”- Faça login na sua conta (Extranet, Studio ou TripPay — todos suportam webhooks).
- Navegue até
Applicationse depoisWebhooks. Veja Webhooks. - Clique em
Create webhook. - Insira um nome (ex.: “Sincronização de Reservas PMS”).
- Insira sua URL do webhook — o endpoint HTTPS no seu servidor.
- Selecione eventos — Escolha eventos específicos para assinar ou deixe vazio para receber todos os eventos.
- Ative o botão Enabled.
- Clique em
Save— a resposta mostrará seu segredo de assinatura uma única vez; armazene-o agora.
Tipos de eventos
Seção intitulada “Tipos de eventos”O Wink publica hoje 70 tipos de eventos de webhook relacionados a reservas, propriedades, contas (entidades gestoras) e inventário (tipos de quarto, planos de tarifa, tarifas mestre, adicionais, instalações, canais de venda, promoções). Os mais comuns:
| Categoria | Exemplos |
|---|---|
| Reserva | booking.create, booking.cancelled, booking.refund.partial, booking.refund.full, booking.review.created |
| Propriedade | property.created, property.status.updated, property.policy.updated |
| Inventário | room_type.updated, rate_plan.created, master_rate.updated, special_rate.created, sales_channel.created |
| Conta | managing_entity.created, managing_entity.status.updated, managing_entity.manager.added |
A lista completa e gerada — com descrição, quem a recebe e um link para a página de referência de cada evento — é o Catálogo de Eventos de Webhook. A página de referência para cada evento (corpo JSON, cabeçalhos, política de reenvio) está na API de Webhooks.
Veja todos os tipos de eventos
O que você recebe
Seção intitulada “O que você recebe”Cada entrega é um HTTP POST para sua URL de webhook com Content-Type: application/json e este envelope:
{ "id": "0198a4f2-6b0e-7c1d-9a3e-2f4b8c6d1e0a", "type": "booking.create", "occurredAt": "2026-08-15T09:30:00Z", "ownerIdentifier": "3c6b1a5d-8e2f-4a0b-9c7d-6e4f0a8b2c51", "recipientRole": "SUPPLIER", "schemaVersion": 2, "object": { "...": "payload específico do evento, ex.: BookingWebhookPayload" }}id— identificador do evento; idêntico para cada endpoint da sua conta que recebe este evento e para cada reenvio. Use como sua chave de idempotência.type— chave do tipo de evento (também enviada no cabeçalhoWink-Event-Type). Faça ramificações com base emtypeeschemaVersionpara analisarobject.object— um resumo curado do recurso ao qual o evento se refere (identificadores, status, os campos que você atua) maislinks.self, a URL REST canônica do lado do fornecedor do recurso completo. Busque com suas próprias credenciais de API quando precisar de mais que o resumo; se receber o evento como revendedor ou agente de viagens, use o endpoint correspondente da sua própria API para o mesmo identificador.
Cada esquema de payload está documentado por evento na referência da API de Webhooks.
Cabeçalhos
Seção intitulada “Cabeçalhos”| Cabeçalho | Significado |
|---|---|
Wink-Version | Versão do contrato de comunicação, 2.0. |
Wink-Event-Id | Igual ao id no corpo — sua chave de idempotência. |
Wink-Delivery-Id | Único por endpoint por evento; muda apenas se você reenviar. |
Wink-Event-Type | Igual ao type no corpo. |
Wink-Delivery-Attempt | Número da tentativa para esta entrega, começando em 1. |
Wink-Signature | Assinatura HMAC — veja abaixo. |
Verificando assinaturas
Seção intitulada “Verificando assinaturas”Cada webhook tem um segredo de assinatura (whsec_…) que o Wink mostra uma única vez, quando você cria o webhook ou gira seu segredo. Armazene como uma senha. Cada entrega carrega
Wink-Signature: t=1755250200,v1=5d41402abc4b2a76b9719d911017c592…onde t é um timestamp Unix (segundos) e v1 é o HMAC-SHA256 em hex minúsculo da string t + "." + rawBody, com chave do seu segredo, e rawBody é o corpo exato da requisição em bytes conforme recebido — não reserialize o JSON antes de verificar. Por 24 horas após a rotação do segredo, o cabeçalho carrega um segundo valor v1= assinado com o segredo anterior; aceite a entrega se qualquer v1 corresponder.
Verifique em quatro passos: analise t e cada v1; recalcule o HMAC sobre t.rawBody com seu segredo; compare com uma comparação em tempo constante; rejeite se |agora − t| exceder sua tolerância (recomendado 5 minutos).
// Node.js (estilo Express; certifique-se de ter o corpo RAW, não um objeto parseado)import { createHmac, timingSafeEqual } from 'node:crypto';
export function verifyWinkSignature(header, rawBody, secret, toleranceSeconds = 300) { const parts = Object.fromEntries(header.split(',').map((p) => p.split('=').map((s) => s.trim()))); const t = Number(parts.t); if (!Number.isFinite(t) || Math.abs(Date.now() / 1000 - t) > toleranceSeconds) return false; const expected = createHmac('sha256', secret).update(`${t}.${rawBody}`).digest('hex'); return header .split(',') .filter((p) => p.trim().startsWith('v1=')) .map((p) => p.trim().slice(3)) .some((v1) => v1.length === expected.length && timingSafeEqual(Buffer.from(v1, 'utf8'), Buffer.from(expected, 'utf8')));}// Javastatic boolean verify(String header, String rawBody, String secret, long nowSeconds, long toleranceSeconds) throws Exception { long t = Long.MIN_VALUE; List<String> signatures = new ArrayList<>(); for (String part : header.split(",")) { String[] kv = part.trim().split("=", 2); if (kv[0].equals("t")) t = Long.parseLong(kv[1]); else if (kv[0].equals("v1")) signatures.add(kv[1]); } if (t == Long.MIN_VALUE || Math.abs(nowSeconds - t) > toleranceSeconds) return false; Mac mac = Mac.getInstance("HmacSHA256"); mac.init(new SecretKeySpec(secret.getBytes(StandardCharsets.UTF_8), "HmacSHA256")); byte[] expected = HexFormat.of().formatHex(mac.doFinal((t + "." + rawBody).getBytes(StandardCharsets.UTF_8))).getBytes(StandardCharsets.US_ASCII); return signatures.stream().anyMatch(v1 -> MessageDigest.isEqual(expected, v1.toLowerCase().getBytes(StandardCharsets.US_ASCII)));}Gire o segredo pelo portal ou com POST /api/managing-entity/{id}/webhook/{webhookId}/rotate-secret; a resposta mostra o novo segredo uma única vez, e o antigo continua válido por 24 horas enquanto você o substitui.
Reenvios e redelivery
Seção intitulada “Reenvios e redelivery”- Responda com qualquer
2xxem até 10 segundos para confirmar. Faça o processamento pesado de forma assíncrona. - Um
5xx, timeout,408ou429é reenviado com backoff: após 1 minuto, 5 minutos, 30 minutos, 2 horas, 6 horas, 12 horas, depois diariamente — 10 tentativas em cerca de 3 dias — após o que a entrega é marcada como morta. - Qualquer outro
4xxé tratado como “você rejeitou esta entrega” e não é reenviado. - Cada evento, entrega e tentativa (status, trecho da resposta) é visível em Applications > Webhooks e via API (
…/webhook/event/grid,…/webhook/delivery/grid). Você pode reenviar qualquer entrega (POST …/webhook/delivery/{deliveryId}/redeliver, que inicia uma nova série de tentativas), reenviar todas as entregas mortas de um webhook de uma vez (POST …/webhook/{webhookId}/redeliver-dead), ou cancelar uma. - As entregas são mantidas por 30 dias.
Eventos de teste
Seção intitulada “Eventos de teste”Envie para si mesmo um evento sintético webhook.test pelo portal ou com POST /api/managing-entity/{id}/webhook/{webhookId}/test. Ele é assinado e entregue exatamente como um evento real, para que você possa verificar seu endpoint, a verificação da assinatura e o tratamento de idempotência antes de assinar eventos ao vivo.
Melhores práticas
Seção intitulada “Melhores práticas”- Use HTTPS — o Wink envia payloads apenas para endpoints HTTPS.
- Responda rapidamente — Retorne um
200 OKassim que receber o payload. Faça qualquer processamento pesado de forma assíncrona. - Idempotência — Seu handler deve ser idempotente; deduplique pelo
Wink-Event-Id. O Wink reenvia quando não recebe uma resposta2xx. - Valide a origem — Verifique o cabeçalho
Wink-Signature(veja Verificando assinaturas) antes de processar; rejeite qualquer coisa que falhar. - Registro de logs — Registre todo payload de webhook que receber. Isso facilita muito a depuração de problemas de integração.
Pausar e excluir
Seção intitulada “Pausar e excluir”Você pode desabilitar um webhook sem excluí-lo. Isso pausa a entrega para que você possa solucionar problemas sem perder sua configuração. Quando estiver pronto, ative-o novamente.
Excluir um webhook remove-o permanentemente. Qualquer integração que dependa desse webhook deixará de receber notificações.
Leitura adicional
Seção intitulada “Leitura adicional”- Catálogo de Eventos de Webhook — Todos os tipos de eventos, gerados a partir do catálogo da plataforma.
- Referência da API de Webhooks — Esquemas de payload por evento, cabeçalhos e endpoints de gerenciamento de assinatura/entrega.
- Webhooks — Referência completa para gerenciamento de webhooks.
- Applications — Gerencie suas credenciais de API.
- Developers > APIs — Documentação completa da API.
