Radar DOU
Central de Ajuda/API e Desenvolvedores/Webhooks e notificações
Voltar para API e Desenvolvedores
API e Desenvolvedores

Webhooks e notificações

5 min de leitura

Webhooks permitem que voce receba notificacoes em tempo real quando novas publicacoes correspondem aos seus criterios de monitoramento, sem precisar fazer polling na API.

O que sao Webhooks?

Webhooks sao callbacks HTTP que enviam dados para sua aplicacao automaticamente quando um evento ocorre. Em vez de sua aplicacao verificar periodicamente se ha novos dados (polling), o Radar DOU envia uma notificacao diretamente para seu servidor quando uma nova publicacao corresponde aos seus filtros.

Vantagens dos Webhooks

  • Tempo real: Receba notificacoes imediatamente apos a publicacao
  • Eficiencia: Evite requisicoes desnecessarias com polling
  • Economia: Reduza o consumo de sua quota de API
  • Simplicidade: Logica reativa em vez de polling constante

Configurando Webhooks

1. Via Dashboard

  1. Acesse o painel do Radar DOU e navegue ate Configuracoes > Webhooks
  2. Clique em "Criar Webhook"
  3. Preencha a URL do seu endpoint (deve ser HTTPS)
  4. Selecione os eventos que deseja receber
  5. Configure os filtros de publicacao (termos, secoes, orgaos)
  6. Salve e teste a conexao

2. Via API

POST /api/v1/webhooks
Content-Type: application/json
X-API-Key: sua_api_key

{
  "url": "https://seu-servidor.com/webhook/radar-dou",
  "eventos": ["publicacao.nova", "publicacao.atualizada"],
  "filtros": {
    "termos": ["licitacao", "contrato"],
    "secoes": ["3"],
    "orgaos": ["Ministerio da Saude"]
  },
  "ativo": true,
  "secret": "seu_secret_para_validacao"
}

Eventos Disponiveis

EventoDescricaoQuando Ocorre
publicacao.novaNova publicacao detectadaQuando uma publicacao corresponde aos filtros
publicacao.atualizadaPublicacao foi atualizadaRetificacoes ou correcoes
edicao.publicadaNova edicao disponivelEdicao regular ou extra publicada
alerta.matchAlerta personalizado disparadoCriterios do alerta atendidos

Estrutura do Payload

Quando um evento ocorre, enviamos uma requisicao POST para sua URL com o seguinte payload:

{
  "id": "evt_abc123xyz",
  "tipo": "publicacao.nova",
  "criado_em": "2024-01-15T08:30:00Z",
  "webhook_id": "wh_xyz789",
  "dados": {
    "publicacao": {
      "id": "pub_def456",
      "titulo": "AVISO DE LICITACAO PREGAO ELETRONICO N 15/2024",
      "resumo": "Contratacao de servicos de...",
      "data_publicacao": "2024-01-15",
      "secao": "3",
      "orgao": "Ministerio da Saude",
      "tipo_ato": "Aviso de Licitacao",
      "url_original": "https://...",
      "termos_correspondentes": ["licitacao", "pregao"]
    }
  }
}

Headers da Requisicao

HeaderDescricao
Content-Typeapplication/json
X-Radar-SignatureAssinatura HMAC-SHA256 do payload
X-Radar-TimestampTimestamp Unix do envio
X-Radar-EventTipo do evento (ex: publicacao.nova)
X-Radar-DeliveryID unico desta entrega

Validando a Assinatura

Sempre valide a assinatura do webhook para garantir que a requisicao veio do Radar DOU:

Python

import hmac
import hashlib
import time

WEBHOOK_SECRET = 'seu_webhook_secret'

def validar_assinatura(payload: bytes, signature: str, timestamp: str) -> bool:
    """Valida a assinatura do webhook."""
    # Verificar se o timestamp nao e muito antigo (5 minutos)
    current_time = int(time.time())
    webhook_time = int(timestamp)
    if abs(current_time - webhook_time) > 300:
        return False

    # Calcular assinatura esperada
    message = f"{timestamp}.{payload.decode('utf-8')}"
    expected_signature = hmac.new(
        WEBHOOK_SECRET.encode('utf-8'),
        message.encode('utf-8'),
        hashlib.sha256
    ).hexdigest()

    return hmac.compare_digest(f"sha256={expected_signature}", signature)

# Exemplo com Flask
from flask import Flask, request, jsonify

app = Flask(__name__)

@app.route('/webhook/radar-dou', methods=['POST'])
def handle_webhook():
    payload = request.get_data()
    signature = request.headers.get('X-Radar-Signature')
    timestamp = request.headers.get('X-Radar-Timestamp')

    if not validar_assinatura(payload, signature, timestamp):
        return jsonify({'erro': 'Assinatura invalida'}), 401

    # Processar evento
    evento = request.json
    print(f"Evento recebido: {evento['tipo']}")
    print(f"Publicacao: {evento['dados']['publicacao']['titulo']}")

    # Sempre retorne 200 rapidamente
    return jsonify({'recebido': True}), 200

JavaScript/Node.js

const crypto = require('crypto');
const express = require('express');

const WEBHOOK_SECRET = 'seu_webhook_secret';

function validarAssinatura(payload, signature, timestamp) {
  // Verificar timestamp
  const currentTime = Math.floor(Date.now() / 1000);
  const webhookTime = parseInt(timestamp, 10);
  if (Math.abs(currentTime - webhookTime) > 300) {
    return false;
  }

  // Calcular assinatura esperada
  const message = `${timestamp}.${payload}`;
  const expectedSignature = crypto
    .createHmac('sha256', WEBHOOK_SECRET)
    .update(message)
    .digest('hex');

  return crypto.timingSafeEqual(
    Buffer.from(`sha256=${expectedSignature}`),
    Buffer.from(signature)
  );
}

const app = express();
app.use(express.raw({ type: 'application/json' }));

app.post('/webhook/radar-dou', (req, res) => {
  const payload = req.body.toString();
  const signature = req.headers['x-radar-signature'];
  const timestamp = req.headers['x-radar-timestamp'];

  if (!validarAssinatura(payload, signature, timestamp)) {
    return res.status(401).json({ erro: 'Assinatura invalida' });
  }

  const evento = JSON.parse(payload);
  console.log(`Evento: ${evento.tipo}`);
  console.log(`Publicacao: ${evento.dados.publicacao.titulo}`);

  // Processar de forma assincrona se necessario
  processarEvento(evento).catch(console.error);

  // Retornar 200 imediatamente
  res.json({ recebido: true });
});

async function processarEvento(evento) {
  // Sua logica de processamento aqui
}

Boas Praticas

Recomendacoes

  • Responda rapidamente: Retorne 200 em menos de 5 segundos para evitar timeout
  • Processe de forma assincrona: Use filas para processamento pesado
  • Valide a assinatura: Sempre verifique X-Radar-Signature
  • Use HTTPS: Webhooks so sao enviados para URLs seguras
  • Implemente idempotencia: Trate entregas duplicadas graciosamente
  • Registre eventos: Mantenha logs para debug e auditoria

Politica de Retentativas

Se seu endpoint nao responder com sucesso (2xx), tentaremos reenviar o webhook:

  • 1a retentativa: Apos 1 minuto
  • 2a retentativa: Apos 5 minutos
  • 3a retentativa: Apos 30 minutos
  • 4a retentativa: Apos 2 horas
  • 5a retentativa: Apos 24 horas

Importante: Apos 5 falhas consecutivas, o webhook sera desativado automaticamente. Voce recebera um email de notificacao e podera reativa-lo no painel.

Tratando Entregas Duplicadas

Em casos raros, o mesmo evento pode ser entregue mais de uma vez. Implemente idempotencia usando o ID do evento:

import redis

# Usando Redis para rastrear eventos processados
redis_client = redis.Redis()
EVENTO_TTL = 86400  # 24 horas

def evento_ja_processado(evento_id: str) -> bool:
    """Verifica se o evento ja foi processado."""
    key = f"webhook:evento:{evento_id}"
    return redis_client.exists(key)

def marcar_evento_processado(evento_id: str):
    """Marca evento como processado."""
    key = f"webhook:evento:{evento_id}"
    redis_client.setex(key, EVENTO_TTL, "1")

@app.route('/webhook/radar-dou', methods=['POST'])
def handle_webhook():
    # ... validacao de assinatura ...

    evento = request.json
    evento_id = evento['id']

    # Verificar duplicata
    if evento_ja_processado(evento_id):
        print(f"Evento {evento_id} ja processado, ignorando")
        return jsonify({'recebido': True}), 200

    # Processar evento
    processar_evento(evento)

    # Marcar como processado
    marcar_evento_processado(evento_id)

    return jsonify({'recebido': True}), 200

Testando Webhooks

Voce pode testar seus webhooks de diferentes formas:

1. Via Dashboard

Na pagina de configuracao do webhook, use o botao "Enviar Teste" para disparar um evento de teste para seu endpoint.

2. Via API

POST /api/v1/webhooks/{webhook_id}/test
X-API-Key: sua_api_key

{
  "tipo": "publicacao.nova"
}

3. Usando ngrok para Desenvolvimento Local

# Instalar ngrok
npm install -g ngrok

# Expor sua aplicacao local
ngrok http 3000

# Use a URL gerada (ex: https://abc123.ngrok.io)
# como URL do webhook para testes

Monitorando Webhooks

No dashboard, voce pode acompanhar:

  • Historico de entregas: Todas as tentativas de entrega com status
  • Taxa de sucesso: Porcentagem de entregas bem-sucedidas
  • Tempo de resposta: Latencia media do seu endpoint
  • Erros recentes: Detalhes dos ultimos erros para debug

Gerenciando Webhooks via API

# Listar webhooks
GET /api/v1/webhooks

# Obter detalhes de um webhook
GET /api/v1/webhooks/{webhook_id}

# Atualizar webhook
PATCH /api/v1/webhooks/{webhook_id}
{
  "filtros": {
    "termos": ["novo termo"]
  }
}

# Desativar webhook
PATCH /api/v1/webhooks/{webhook_id}
{
  "ativo": false
}

# Deletar webhook
DELETE /api/v1/webhooks/{webhook_id}

# Listar entregas de um webhook
GET /api/v1/webhooks/{webhook_id}/deliveries

# Reenviar entrega especifica
POST /api/v1/webhooks/{webhook_id}/deliveries/{delivery_id}/retry

Precisa de ajuda? Use nosso assistente virtual para tirar duvidas sobre configuracao de webhooks ou entre em contato com o suporte tecnico.

Ainda tem dúvidas?

Converse com nosso assistente virtual especializado para obter ajuda personalizada sobre qualquer funcionalidade.

Abrir Assistente