Eventos e webhooks
A owiew é quem inicia a conexão: ela envia eventos assinados, por POST, ao endereço https que a instalação cadastrou. Seu sistema responde 2xx para confirmar. A assinatura está em assinatura de webhook.
Inscrição
Seção intitulada “Inscrição”A inscrição pertence à instalação: uma URL https, uma lista de tipos de evento e um segredo de assinatura. Ela cobre todos os projetos consentidos e ativos da instalação, e o projeto vai dentro de cada evento.
Regras da inscrição:
- A URL precisa ser
https, sem usuário e senha, sem fragmento e com até 512 caracteres. - Os tipos de evento precisam estar ativos no catálogo, e a instalação precisa ter o escopo que cada evento exige. Caso contrário, o cadastro é recusado (
evento-desconhecidoouescopo-ausente-para-evento). - O módulo de webhooks de aplicativos precisa estar ativo em cada projeto. Sem ele, nada é enviado.
- O envio real de eventos acontece somente em produção.
Catálogo de eventos
Seção intitulada “Catálogo de eventos”O catálogo é fechado e versionado. O sufixo .v1 identifica a versão do formato: o payload de uma versão publicada não muda, e uma mudança incompatível vira .v2.
| Evento | Escopo exigido | Quando é enviado | Estado |
|---|---|---|---|
instalacao.teste.v1 |
instalacao:read |
Quando se pede um evento de teste, um por projeto consentido | Disponível |
projeto.metricas.diarias.v1 |
metricas:read |
Um por projeto e por dia fechado | Planejado |
conversao.registrada.v1 |
conversoes:read |
Um por conversão registrada | Planejado |
relatorio.publicado.v1 |
relatorios:read |
Um por relatório publicado | Planejado |
Os três eventos planejados estão no catálogo, mas ainda não podem ser assinados, e as fontes de dados deles ainda não estão todas ligadas. O formato abaixo mostra o que está previsto, para você preparar o receptor. Ele pode mudar antes da liberação.
Envelope
Seção intitulada “Envelope”Todo evento chega com o mesmo envelope, em JSON, com até 256 KiB:
{ "evento_id": "evento-exemplo-0001", "tipo": "instalacao.teste.v1", "versao_contrato": 1, "ocorrido_em": "2026-10-22T03:05:00Z", "app_id": "app_01JC8M4Z2QXW5N7R9T3V6B0KHE", "instalacao_id": "ins_01JC8M9A7D3F5H2K4N6P8R0STV", "projeto_id": "<identificador do projeto>", "dados": { "mensagem": "evento de teste", "gerado_em": "2026-10-22T03:05:00Z" }}| Campo | Descrição |
|---|---|
evento_id |
Identificador do evento |
tipo |
O tipo do catálogo (igual ao cabeçalho X-Owiew-Event) |
versao_contrato |
Versão do formato do envelope |
ocorrido_em |
Quando o fato ocorreu (RFC 3339, UTC) |
app_id, instalacao_id |
Quem recebe |
projeto_id |
O projeto do evento. Sempre um projeto consentido e ativo |
dados |
O conteúdo, específico do tipo |
Ignore campos desconhecidos: campos novos são opcionais e aditivos.
Dados previstos dos eventos planejados
Seção intitulada “Dados previstos dos eventos planejados”projeto.metricas.diarias.v1 (valores monetários em centavos, inteiros):
{ "data": "2026-10-21", "fuso": "America/Sao_Paulo", "moeda": "BRL", "completo": true, "revisao_dado": 1, "totais": { "investimento_centavos": 125000, "impressoes": 54000, "cliques": 1200, "conversoes": 31 }, "por_rede": []}Quando uma rede ainda não sincronizou o dia, completo vem false e o evento é reenviado com revisao_dado maior. Fique com a maior revisão de cada dia.
conversao.registrada.v1: conversao_id, tipo, ocorrida_em, valor_centavos (ou null), moeda (ou null) e origem (rede e campanha, ou null). Não há nome, e-mail, telefone nem IP do comprador.
relatorio.publicado.v1: relatorio_id, titulo, publicado_em, url e expira_em (ou null). O url abre sem login. Trate-o como uma credencial: quem o tem, lê o relatório.
Cabeçalhos da entrega
Seção intitulada “Cabeçalhos da entrega”| Cabeçalho | Valor |
|---|---|
Content-Type |
application/json |
User-Agent |
owiew-apps/1 |
X-Owiew-Event |
O tipo do evento |
X-Owiew-Delivery-Id |
Identificador da entrega. É o mesmo em todos os reenvios |
X-Owiew-Timestamp |
Segundos desde 1970 (UTC), em decimal. Muda a cada tentativa |
X-Owiew-Signature |
v1=<hex>, ou duas assinaturas separadas por vírgula durante a rotação |
Resposta esperada
Seção intitulada “Resposta esperada”Responda 2xx em até 10 segundos. Qualquer outra coisa conta como falha: outro status, tempo esgotado, erro de rede, erro de certificado e redirecionamento (3xx). A owiew não segue redirecionamentos. O corpo da sua resposta é descartado.
Confirme rápido e processe depois. Se o seu processamento demora, grave o evento e responda 200.
Repetição
Seção intitulada “Repetição”Em caso de falha, a owiew repete a entrega com espera exponencial e variação aleatória (jitter de mais ou menos 20%):
| Falha | Espera até a próxima tentativa (base) |
|---|---|
| 1ª | 30 segundos |
| 2ª | 1 minuto |
| 3ª | 2 minutos |
| 4ª | 4 minutos |
| seguintes | dobra a cada falha, até 3 horas |
A entrega é abandonada depois de 10 tentativas ou 24 horas desde a criação, o que vier primeiro. Ela vai para uma fila de entregas esgotadas, visível para a equipe, e pode ser reenviada manualmente com o mesmo X-Owiew-Delivery-Id.
Proteções por destino:
- Pausa: 5 falhas seguidas pausam o destino por 5 minutos.
- Desativação automática: depois de 24 horas de falha contínua, a inscrição é desativada.
- Isolamento: um destino fora do ar não atrasa as entregas de outros aplicativos.
Idempotência
Seção intitulada “Idempotência”Seu receptor deve ser idempotente. Uma entrega pode chegar mais de uma vez: nova tentativa depois de timeout, reenvio manual ou resposta perdida. Use o X-Owiew-Delivery-Id como chave:
- Verifique a assinatura.
- Se o
X-Owiew-Delivery-Idjá foi tratado com sucesso, responda200sem repetir o efeito. - Senão, trate o evento e só então registre o identificador.
Grave o identificador num banco com índice único. Um Set em memória, como no exemplo, só serve para testes. O evento_id identifica o fato e o X-Owiew-Delivery-Id identifica a entrega: para deduplicar, use o segundo.
A owiew não garante a ordem de entrega. Eventos diferentes seguem caminhos independentes, e as repetições com espera fazem um evento antigo chegar depois de um novo. Para decidir qual dado vale:
- compare
ocorrido_ementre eventos do mesmo recurso; - nos eventos que têm
revisao_dado, fique com a maior; - projete o estado de forma que reaplicar um evento antigo não desfaça um novo.
Proteção contra SSRF no endereço cadastrado
Seção intitulada “Proteção contra SSRF no endereço cadastrado”SSRF (requisição forjada pelo servidor) é o ataque em que alguém cadastra um endereço que aponta para uma rede interna, para fazer o servidor da owiew chamá-la. A owiew bloqueia isso em camadas:
- Validação da URL: só
https, sem credencial na URL, sem fragmento, porta válida. Recusa o nome de máquina local e nomes de rede interna (como.internale.local), IP literal de rede privada ou reservada e formas disfarçadas de IP (decimal, hexadecimal, octal). - Resolução de DNS conferida na conexão: a owiew resolve o nome e confere os IPs a cada conexão, não só no cadastro. Se qualquer endereço resolvido pertencer a rede interna, reservada, de metadados de nuvem ou de faixa que embute IPv4, a entrega é recusada por inteiro (defesa contra DNS rebinding).
- Sem redirecionamento: um
3xxé falha, nunca é seguido. - Sem proxy e sem conexão reutilizada: cada entrega abre uma conexão nova, validada. TLS mínimo 1.2.
- Códigos de falha sanitizados: o motivo informado nunca contém URL, IP, cabeçalho nem corpo do seu servidor (por exemplo,
destino-proibido,destino-fora-da-lista,redirecionamento,timeout,tls,dns).
Para você, isso significa: o receptor precisa ter um nome DNS público com certificado TLS válido. Endereços de rede privada e portas de teste locais não funcionam como destino.