OctoSolveAjuda

Webhooks

Receba avisos da OctoSolve no seu sistema quando algo acontecer, com assinatura e reenvio automático.

Webhooks

Com a API você pergunta para a OctoSolve. Com webhook, a OctoSolve avisa você: toda vez que algo acontece na sua conta, mandamos uma requisição POST para o endereço que você cadastrar.

Serve para coisas como registrar o agendamento no seu sistema, avisar o time num canal interno quando cair um lead, ou disparar uma automação no Make ou no n8n quando um pagamento for confirmado.

Você cadastra os endereços em Configurações, aba API e integrações.

Eventos disponíveis

Cada endereço cadastrado escolhe quais eventos quer receber. Não é tudo ou nada.

EventoQuando dispara
contact.createdUm contato novo foi criado
contact.updatedUm contato foi alterado
appointment.createdUm agendamento foi criado
appointment.updatedUm agendamento foi remarcado ou teve dados alterados
appointment.cancelledUm agendamento foi cancelado
payment.confirmedUm pagamento foi confirmado
conversation.handoffUma conversa passou do agente para uma pessoa do seu time

Mensagens de conversa não geram evento nesta versão, de propósito: o volume é alto e o conteúdo é sensível.

Formato do envio

Todo evento chega com a mesma casca:

{
  "id": "evt_9f1c2d3e4a5b6c7d8e9f0a1b2c3d4e5f",
  "type": "appointment.created",
  "created_at": "2026-08-13T14:00:00+00:00",
  "data": {}
}

O data muda conforme o tipo. Campos podem vir null.

contact.created e contact.updated

Mesmo formato do contato na API: id, telefone, nome, email, cidade, data_nascimento, observacoes, tags, status, ig_username, telegram_username, updated_at.

O telefone pode vir null: contato que chegou pelo Instagram ou pelo Telegram se identifica por usuário.

appointment.created, appointment.updated e appointment.cancelled

CampoTipo
iduuid
contact_iduuid
data_horadatetime
statusstring
duracao_minutosint ou null
servico_iduuid ou null
profissional_iduuid ou null
valornúmero ou null
pagobooleano ou null
motivo_cancelamentostring ou null
created_atdatetime ou null

payment.confirmed

CampoTipo
iduuid
contact_iduuid ou null
appointment_iduuid ou null
valor_brlnúmero
tipostring
statusstring
paid_atdatetime ou null
created_atdatetime

conversation.handoff

CampoTipo
conversation_iduuid
contact_iduuid
canalstring
motivostring
ocorrido_emdatetime

Nenhum trecho da conversa é enviado.

Cabeçalhos

CabeçalhoPara que serve
X-Octo-EventTipo do evento
X-Octo-TimestampMomento do envio, em segundos Unix
X-Octo-SignatureAssinatura no formato sha256=<hex>
X-Octo-DeliveryIdentificador desta tentativa de envio

Verificar a assinatura

Verifique sempre. Sem isso, qualquer um que descubra a sua URL pode fingir ser a OctoSolve.

A assinatura é um HMAC SHA256 do texto {timestamp}.{corpo}, usando o secret do endereço como chave. O corpo é o texto cru recebido, antes de virar objeto.

Rejeite envios com X-Octo-Timestamp de mais de 5 minutos atrás, para bloquear reenvio malicioso.

Python

import hashlib
import hmac
import time
 
SECRET = "whsec_exemplo_troque_pelo_seu"
 
def assinatura_confere(corpo: bytes, timestamp: str, assinatura: str) -> bool:
    if abs(time.time() - float(timestamp)) > 300:
        return False
    esperada = hmac.new(
        SECRET.encode(), f"{timestamp}.".encode() + corpo, hashlib.sha256
    ).hexdigest()
    recebida = assinatura.removeprefix("sha256=")
    return hmac.compare_digest(esperada, recebida)

Node

const crypto = require("crypto");
 
const SECRET = "whsec_exemplo_troque_pelo_seu";
 
function assinaturaConfere(corpo, timestamp, assinatura) {
  if (Math.abs(Date.now() / 1000 - Number(timestamp)) > 300) return false;
  const esperada = crypto
    .createHmac("sha256", SECRET)
    .update(`${timestamp}.`)
    .update(corpo)
    .digest("hex");
  const recebida = assinatura.replace(/^sha256=/, "");
  return crypto.timingSafeEqual(Buffer.from(esperada), Buffer.from(recebida));
}

No Express, guarde o corpo cru com express.json({ verify: (req, _res, buf) => { req.rawBody = buf; } }). Se você assinar em cima do JSON já convertido e convertido de volta, a assinatura não vai bater.

O mesmo evento pode chegar duas vezes

Esta é a parte mais importante desta página.

A entrega é pelo menos uma vez. Em falha de rede ou reenvio, o mesmo evento pode chegar repetido. O seu sistema precisa aguentar isso.

Como resolver: guarde o campo id do evento (o evt_...) e ignore o que você já processou. Esse id é estável, inclusive quando você clica em Reenviar no painel.

A ordem também não é garantida. Uma tentativa que falhou e foi reenviada pode chegar depois de um evento mais novo. Se a ordem importa para você, use o created_at do evento, não a ordem de chegada.

Se o seu endereço não responder

Consideramos entregue quando a resposta é 2xx. Qualquer outra coisa é falha.

Tentamos de novo, com espaço crescente entre as tentativas:

TentativaDepois de
1 minuto
5 minutos
30 minutos
2 horas
6 horas
última24 horas

Algumas respostas não são tentadas de novo, porque insistir não adiantaria:

  • 3xx (redirecionamento): não seguimos redirecionamento, por segurança. Cadastre o endereço final.
  • 4xx, com exceção de 408 e 429: quer dizer que o endereço existe mas recusou. Corrija e reenvie pelo painel.

Respondemos ao Retry-After quando ele pede um tempo maior que o nosso, até o limite de 24 horas.

Endereço desligado automaticamente

Depois de 20 tentativas seguidas com falha, desligamos o endereço e avisamos você no painel. É proteção contra endereço abandonado gerando fila infinita.

Ele não é apagado: você conserta o seu lado e clica em reativar.

Requisitos do endereço

RegraMotivo
Precisa ser https:// na porta 443Evento trafega com dado do seu cliente
Não pode apontar para rede internaProteção contra uso da OctoSolve para atacar redes privadas
Não pode ter usuário e senha na URLFormato usado para enganar leitor humano
Responda rápido, em até 10 segundosPassou disso, tratamos como falha e tentamos de novo

Responda 200 assim que receber e processe depois, em segundo plano. Não deixe o processamento inteiro dentro da requisição.

Limites por plano

PlanoWebhooksEndereços
Starternão0
Plussim5
Prosim10
Enterprisesimsob medida

O limite de requisições por minuto da página de Limites vale para a API. Envio de webhook é nosso, não consome a sua cota.

Receita para Make ou n8n

  1. Crie um cenário (Make) ou workflow (n8n) começando com Webhook ou Webhook Trigger.
  2. Copie a URL que a ferramenta gerar.
  3. Na OctoSolve, vá em Configurações, aba API e integrações, e cadastre essa URL escolhendo os eventos.
  4. Copie o secret que aparece uma única vez e guarde.
  5. No fluxo, adicione um passo que confira a assinatura (as duas ferramentas têm nó de código; use o exemplo em Node acima).
  6. Adicione um passo que ignore evento com id já visto, guardando os ids num Data Store (Make) ou numa tabela (n8n).
  7. Só depois disso, ligue o passo que faz o trabalho de verdade.

Os passos 5 e 6 parecem burocracia, mas são o que separa uma automação que funciona de uma que duplica cobrança no fim de semana.

Testar

Enquanto você monta, aponte para um coletor público (como o webhook.site) para ver o formato real do evento chegando. Depois troque para o seu endereço definitivo e rotacione o secret, porque o antigo passou por um serviço de terceiro.