Webhooks e notificações
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
- Acesse o painel do Radar DOU e navegue ate Configuracoes > Webhooks
- Clique em "Criar Webhook"
- Preencha a URL do seu endpoint (deve ser HTTPS)
- Selecione os eventos que deseja receber
- Configure os filtros de publicacao (termos, secoes, orgaos)
- 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
| Evento | Descricao | Quando Ocorre |
|---|---|---|
publicacao.nova | Nova publicacao detectada | Quando uma publicacao corresponde aos filtros |
publicacao.atualizada | Publicacao foi atualizada | Retificacoes ou correcoes |
edicao.publicada | Nova edicao disponivel | Edicao regular ou extra publicada |
alerta.match | Alerta personalizado disparado | Criterios 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
| Header | Descricao |
|---|---|
Content-Type | application/json |
X-Radar-Signature | Assinatura HMAC-SHA256 do payload |
X-Radar-Timestamp | Timestamp Unix do envio |
X-Radar-Event | Tipo do evento (ex: publicacao.nova) |
X-Radar-Delivery | ID 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}), 200JavaScript/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}), 200Testando 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}/retryPrecisa 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.
