Skip to Content
VersõesUnstableWebhookConfiguração

Cadastro

Os webhooks são cadastrados pelo próprio anunciante, no painel da nonStop: Configurações → Webhooks (usenonstop.com/configuracoes?tab=webhook ). A aba aparece para contas com plano ativo.

São duas listas:

ListaEventos
Webhooks de imóveispublication:create, publication:delete, property:update e property:delete
Webhooks de leadslead:create

Para cada endpoint são dois campos:

  • Url: endereço completo, com https://. Endereços internos (localhost, redes privadas, IP de metadados de nuvem) são recusados ao salvar.
  • Token: opcional, mas recomendado. Veja Autenticação abaixo.

Dá para cadastrar mais de um endpoint por lista. Não dá para escolher eventos: cada endpoint recebe todos os da sua lista, e quem separa é o campo event do corpo.

Requisição

Cada evento é um POST com o corpo em JSON. Os formatos estão em Imóvel e Lead.

requisição
POST /webhooks/nonstop HTTP/1.1 Content-Type: application/json Authorization: Bearer <token cadastrado> {"event":"property:update","property":{"id":"6650f1c2a8b4e93d7c1a2b3c", ...}}

Autenticação

Com o campo Token preenchido, todo envio leva o header Authorization: Bearer <token>. Sem token, o envio sai sem o header.

  • O token é seu. É um segredo que você inventa e cadastra junto da URL, e não tem relação com o token da API da nonStop. Use um valor longo e aleatório, como a saída de openssl rand -hex 32.
  • Não há assinatura (HMAC). A autenticação é só esse header: responda 401 ao que chegar sem ele ou com outro valor, e use https para que ele não trafegue aberto.
  • Não há IP fixo. Os envios saem de infraestrutura de nuvem sem faixa de IP publicada, então liberar por IP não funciona. Valide pelo token.
app/api/webhooks/nonstop/route.ts
import { timingSafeEqual } from "node:crypto"; const expected = Buffer.from(`Bearer ${process.env.NONSTOP_WEBHOOK_TOKEN}`); export async function POST(request: Request) { const received = Buffer.from(request.headers.get("authorization") ?? ""); const authorized = received.length === expected.length && timingSafeEqual(received, expected); if (!authorized) return new Response(null, { status: 401 }); const body = await request.json(); switch (body.event) { case "publication:create": case "property:update": // grava ou atualiza body.property, com body.property.id como chave break; case "publication:delete": case "property:delete": // tira do ar body.propertyId break; case "lead:create": // cria body.lead no seu CRM, com body.lead.id como chave break; } return new Response(null, { status: 204 }); }

Entrega

  • Qualquer resposta 2xx em até 5 segundos conta como entregue. O corpo da resposta é ignorado. Se o processamento for demorado, enfileire do seu lado e responda antes.
  • Redirecionamentos são seguidos até 3 vezes, repetindo o mesmo POST com os mesmos headers, inclusive o Authorization. Cadastre a URL final.
  • Falhou (status fora de 2xx, timeout ou erro de conexão)? O evento entra numa fila e é reenviado a cada 5 minutos, até 3 vezes. Depois disso, é descartado.

Repetição e ordem

O mesmo evento pode chegar mais de uma vez: basta você processar e responder depois dos 5 segundos. E um reenvio pode chegar depois de um evento mais novo do mesmo imóvel, porque ele leva o conteúdo do momento em que o evento nasceu, não o atual.

  • Processe de forma idempotente, com property.id / propertyId (imóveis) e lead.id (leads) como chave.
  • Num property:update, compare property.updatedAt com o que você já tem e descarte o mais antigo.

Falhas seguidas

Cada falha conta contra o endpoint, e uma entrega bem-sucedida zera a contagem.

  • 1ª e 2ª falha: o e-mail da conta recebe um aviso com o endpoint e o erro.
  • 3ª falha: o endpoint é removido da lista, e o e-mail da conta recebe o aviso da remoção. A partir daí, nada mais é enviado para ele.

Depois de uma falha, as que vierem nos 10 minutos seguintes não contam: um lote de eventos que falha junto porque o seu servidor caiu gasta um aviso, não os três. Ou seja, para ser removido, o endpoint precisa falhar em três momentos diferentes, com pelo menos 10 minutos entre eles e nenhuma entrega bem-sucedida no meio.

Para voltar a receber, cadastre o endpoint de novo: salvar zera a contagem. Os eventos do período em que ele esteve fora não são reenviados. Para recuperar o estado, use a API de imóveis.

Quem recebe cada evento

  • publication:create / publication:delete: a conta em cujo próprio site o imóvel entrou ou de onde saiu, inclusive quando sai sozinho porque foi vendido ou ficou indisponível. Tirar o imóvel de um portal não gera evento.
  • property:update: as contas que têm o imóvel publicado no próprio site.
  • property:delete: as contas que tinham o imóvel em qualquer integração, site ou portal. Pode chegar para um propertyId que você nunca recebeu; nesse caso, ignore.
  • lead:create: a conta responsável pela lead. Se ela for de corretor vinculado a uma imobiliária, o evento vai só para os webhooks da imobiliária, e o userSlug diz qual corretor recebeu.

Um endpoint para vários clientes. Se você integra mais de uma conta, pode cadastrar a mesma URL e o mesmo token em todas. Quando mais de uma delas tem o mesmo imóvel, o evento chega uma vez só. Use o userSlug dos eventos de publicação e de lead para saber de qual conta ele é.

Como testar

  • Imóveis: coloque um imóvel no site e tire em seguida. Chegam um publication:create e um publication:delete.
  • Leads: crie uma lead pela API de leads. Ela gera um lead:create, mas é uma lead de verdade: entra no CRM da conta e avisa o responsável por WhatsApp e e-mail.
Last updated on