Pular para o conteúdo

Receber conversões por webhook

Use esta integração quando o resultado acontece fora do site: um negócio ganho no CRM, uma venda por telefone, um pedido pago num ERP. O seu sistema envia um webhook assinado para uma fonte da owiew. As regras do projeto decidem se o evento vai para a Meta (API de Conversões), o Google Analytics 4 (Measurement Protocol) ou o TikTok (Events API).

A owiew só lê os eventos que o seu sistema manda; quem decide o que enviar a cada plataforma são as regras que você cria no painel.

  • Um projeto na owiew com permissão para gerenciar conversões.
  • Uma fonte criada no painel, em Conversões, aba Fontes, botão Nova fonte.
  • Um sistema capaz de fazer POST com JSON e, de preferência, de calcular HMAC-SHA256.
  1. Abra Conversões e entre na aba Fontes.
  2. Clique em Nova fonte e dê um nome fácil de reconhecer.
  3. Em Como o aviso chega, escolha Webhook assinado (recomendado). Use Webhook com segredo no endereço apenas se o seu sistema não sabe assinar.
  4. Marque Exigir carimbo de data e hora (recomendado).
  5. Clique em Criar fonte. A owiew mostra o Endereço de recepção e o Segredo uma única vez. Guarde os dois.

O endereço tem a forma /v1/recepcao/conversoes/<id-da-fonte>, no domínio exibido pelo painel. Nos exemplos abaixo, $OWIEW_FONTE_URL guarda o endereço completo e $OWIEW_FONTE_SEGREDO guarda o segredo.

Existem dois modelos de fonte.

Envie o cabeçalho X-Owiew-Signature com sha256= seguido de 64 caracteres hexadecimais minúsculos, sem espaços. A assinatura é o HMAC-SHA256 do corpo bruto, tal como enviado, com o segredo da fonte. Maiúsculas ou espaços resultam em 401.

Com carimbo de data e hora, envie também X-Owiew-Timestamp (segundos Unix). Nesse caso a assinatura é o HMAC-SHA256 do texto <timestamp>.<corpo>, e o carimbo precisa estar a até 5 minutos do relógio da owiew. Isso inutiliza o replay de uma requisição capturada. Sincronize o relógio do seu servidor por NTP. Se a fonte exige carimbo, o cabeçalho é obrigatório.

Para sistemas que não assinam o corpo. O segredo vai no final do endereço: /v1/recepcao/conversoes/<id-da-fonte>/<segredo>. Não registre esse caminho nos seus logs. O segredo pode ficar gravado em registros de erro do servidor de entrada, por isso este modelo é o menos seguro.

POST /v1/recepcao/conversoes/{fonte_id}
POST /v1/recepcao/conversoes/{fonte_id}/{segredo}
Content-Type: application/json
Parâmetro Onde Descrição
fonte_id caminho Id da fonte.
evento query, opcional Nome do evento, quando não vier no corpo.
X-Owiew-Signature cabeçalho Fonte com assinatura.
X-Owiew-Timestamp cabeçalho Segundos Unix; obrigatório se a fonte exige carimbo.

O corpo tem teto de 256 KB. Não precisa de sessão nem de chave de API.

Campo Tipo Obrigatório Descrição
id_externo string, até 128 sim Id do fato no seu sistema (pedido, negócio). Base da deduplicação.
evento string sim, no corpo ou na query Nome em minúsculas: letras, números, _, ., -, de 1 a 48 caracteres. Vira webhook:<nome>.
ocorrido_em RFC 3339 não Quando aconteceu. Ausente vale “agora”. Não pode estar mais de 10 minutos no futuro.
valor número ou texto decimal não Em unidades da moeda, até 6 casas.
valor_micros inteiro não Alternativa ao valor, em micros (R$ 1,00 é 1000000). Vence o valor.
moeda string não Código de 3 letras, como BRL.
pedido objeto não Dados do pedido, com id e itens (sku, qtd, preco_micros).
cliente objeto não email, telefone, nome, cep, external_id em claro, ou as versões *_sha256.
atribuicao objeto não Identificadores de clique e campanha: fbp, fbc, fbclid, gclid, wbraid, gbraid, ttclid, utm_source, utm_medium, utm_campaign, client_id_ga.
consentimento objeto não base_legal e marketing (verdadeiro, falso ou nulo).
dados objeto não Campos livres, usáveis nas condições das regras.

Tratamento de dados pessoais:

  • E-mail, telefone, nome e CEP em claro são convertidos em SHA-256 na chegada. A owiew só guarda e envia o hash.
  • Em id_externo, pedido.id, sku, UTMs e textos de dados, e-mails e telefones viram hash ou são descartados. Número puro (como um id de pedido de 13 dígitos) não é alterado.
  • Chaves de PII dentro de dados viram hash e segredos são removidos.
  • Campos de clique (fbclid, gclid, wbraid, gbraid, ttclid) aceitam só letras, números, ., _ e -, de 4 a 200 caracteres. Fora disso o campo é descartado, o evento segue e o motivo é registrado.
Janela do terminal
CORPO='{
"evento": "venda_telefone",
"id_externo": "ped-exemplo-0001",
"ocorrido_em": "2026-10-20T14:30:00Z",
"valor": "189.90",
"moeda": "BRL",
"cliente": { "email": "cliente@exemplo.invalid", "telefone": "+5511900000000" },
"atribuicao": { "gclid": "EXEMPLO-gclid-0001" },
"consentimento": { "base_legal": "consentimento_coletado_pelo_anunciante", "marketing": true }
}'
TS=$(date +%s)
ASSINATURA=$(printf '%s.%s' "$TS" "$CORPO" \
| openssl dgst -sha256 -hmac "$OWIEW_FONTE_SEGREDO" -hex | sed 's/^.* //')
curl -i -X POST "$OWIEW_FONTE_URL" \
-H "Content-Type: application/json" \
-H "X-Owiew-Timestamp: $TS" \
-H "X-Owiew-Signature: sha256=$ASSINATURA" \
--data-binary "$CORPO"

Assine exatamente os bytes que você envia. Se o seu cliente HTTP reformatar o JSON, a assinatura deixa de bater.

Sem carimbo, a assinatura é só o HMAC do corpo: printf '%s' "$CORPO" | openssl dgst -sha256 -hmac "$OWIEW_FONTE_SEGREDO" -hex.

HTTP/1.1 202 Accepted
Content-Type: application/json
{ "status": "aceito", "duplicado": false }

A owiew responde 202 rápido e avalia as regras de forma assíncrona. Reenviar o mesmo fato devolve 202 com "duplicado": true e é inofensivo.

A recepção deduplica por fonte, evento e id_externo. Essa memória dura o período de retenção mais 30 dias (padrão de 120 dias). Sem carimbo assinado, um replay depois disso seria aceito; com carimbo, uma requisição capturada deixa de valer após 5 minutos. Por isso o carimbo é recomendado.

Depois, cada regra tem a sua própria janela de deduplicação para o envio às plataformas, de 1 hora a 30 dias (padrão de 7 dias). Veja Destinos e entregas.

Os erros seguem RFC 9457 (application/problem+json) e trazem um codigo.

Status Código Quando
400 CORPO_INVALIDO JSON ilegível, evento ou id_externo inválidos, ocorrido_em mal formatado ou mais de 10 minutos no futuro.
401 ASSINATURA_INVALIDA Assinatura errada, segredo errado ou fonte inexistente. A resposta é a mesma nos três casos.
401 TIMESTAMP_FORA_DA_JANELA Carimbo a mais de 5 minutos do relógio da owiew, com assinatura correta.
413 CORPO_GRANDE Corpo acima de 256 KB.
415 TIPO_NAO_SUPORTADO Content-Type diferente de application/json.
429 LIMITE_EXCEDIDO Muitas tentativas inválidas do mesmo IP (30 por minuto) ou do mesmo IP contra a mesma fonte (10 por minuto), ou limite da fonte. Há o cabeçalho Retry-After. Acertos não gastam o limite de tentativas inválidas.
503 INDISPONIVEL Serviço indisponível. Tente de novo; o id_externo torna o reenvio seguro.

Entrada hostil nunca devolve 5xx.

  1. Crie uma fonte e um destino em modo teste (veja Destinos e entregas).
  2. Crie uma regra com gatilho webhook:venda_telefone na fonte. Ela nasce desligada.
  3. Use Testar na regra com um envelope de exemplo para ver o que ela enviaria. O teste não grava nem envia.
  4. Ligue a regra e envie o curl acima com dados inventados.
  5. Abra a aba Entregas e procure a entrega do evento. Em modo de registro ela aparece como Gravada; com envio real ativo e destino em modo real, como Enviada.
Sintoma Causa provável
401 ASSINATURA_INVALIDA Corpo diferente do assinado, hexadecimal em maiúsculas, espaço no cabeçalho, ou segredo antigo.
401 TIMESTAMP_FORA_DA_JANELA Relógio do seu servidor desajustado, ou carimbo em milissegundos em vez de segundos.
202 e nada em Entregas A regra está desligada, o gatilho não casa com o nome do evento ou as condições não valeram. Use Testar na regra.
Entrega Descartada Falta de base legal ou marketing recusado; evento fora da janela da plataforma; destino desligado. O motivo aparece no detalhe.
duplicado: true inesperado O id_externo se repetiu para o mesmo evento.