Webhooks para Monitoramento de Processos Judiciais em Tempo Real
O monitoramento de processos judiciais manualmente não escala. Um escritório com 500 processos ativos que depende de alguém verificando portais de tribunal diariamente está, na prática, operando às cegas — qualquer andamento que acontece entre uma verificação e outra pode passar despercebido por dias.
A solução técnica para esse problema é o webhook: no monitoramento de processos judiciais, em vez de a aplicação perguntar ao tribunal “houve novidade?”, a API avisa a aplicação quando algo acontece.
Este artigo explica como implementar isso corretamente com a Judit API — do conceito à produção.
Monitoramento de processos judiciais: polling vs. webhook
Antes de escrever código, vale entender por que polling é a abordagem errada para esse problema.
Polling: a abordagem ingênua
// Não faça isso em produção
setInterval(async () => {
const resultado = await consultarProcesso(numeroCNJ);
if (resultado.last_step.step_id !== ultimoStepConhecido) {
notificar(resultado);
}
}, 60 * 60 * 1000); // a cada 1 hora
O problema com polling é triplo. Primeiro, você paga por cada requisição, mesmo quando não há novidade — que é a maioria das vezes. Segundo, o intervalo mínimo entre verificações cria uma janela cega. Terceiro, em escala com centenas de processos monitorados, o volume de requisições consome cota rapidamente e pode gerar throttling.
Webhook: a abordagem correta
Com webhook, a lógica se inverte. Você registra um processo (ou CPF/CNPJ) para monitoramento uma única vez, com uma recurrence configurável em dias. A partir daí, quando a Judit detectar um novo andamento ao consultar o tribunal, ela faz um POST no endpoint que você configurou — com o processo completo e atualizado no payload.
Zero polling. Zero custo de requisições desnecessárias.
Arquitetura de integração para monitoramento de processos judiciais
Uma integração de monitoramento processual tem três componentes:
[Tribunal] → [Judit Crawler] → [Seu servidor (endpoint webhook)] → [Sistema interno]
- Registro do monitoramento — sua aplicação chama a API uma vez para cadastrar o processo, CPF, CNPJ ou OAB que quer acompanhar
- Endpoint receptor — um endpoint HTTP na sua infraestrutura que recebe e processa os callbacks
- Lógica de negócio — o que fazer com cada evento: salvar no banco, disparar notificação, atualizar score, acionar um fluxo
Autenticação
Todas as chamadas à Judit API usam o header api-key:
curl -H "api-key: SUA_API_KEY" https://tracking.prod.judit.io/tracking
A chave é obtida com o time comercial da Judit. Armazene-a em variável de ambiente — nunca no código-fonte.
1. Registrando um monitoramento
A chamada de registro precisa ser feita apenas uma vez por entidade monitorada. O endpoint é POST /tracking no host tracking.prod.judit.io.
Monitorando um processo pelo número CNJ
curl --location 'https://tracking.prod.judit.io/tracking' \
--header 'api-key: SUA_API_KEY' \
--header 'Content-Type: application/json' \
--data '{
"recurrence": 1,
"search": {
"search_type": "lawsuit_cnj",
"search_key": "1111111-04.2024.8.19.0001"
},
"callback_url": "https://seu-servidor.com/webhooks/judit"
}'
Monitorando todas as ações de um CPF ou CNPJ
Para monitorar novas ações distribuídas contra um documento, use o endpoint de Monitoramento de Novas Ações (/tracking/document):
curl --location 'https://tracking.prod.judit.io/tracking/document' \
--header 'api-key: SUA_API_KEY' \
--header 'Content-Type: application/json' \
--data '{
"recurrence": 1,
"search": {
"search_type": "cpf",
"search_key": "123.456.789-00"
},
"callback_url": "https://seu-servidor.com/webhooks/judit"
}'
Os search_type suportados são: lawsuit_cnj, cpf, cnpj, oab e name.
Resposta da criação
{
"tracking_id": "d923253e-45c1-46e5-ac70-164839d9851c",
"user_id": "7f8065a3-4891-428d-9456-dedfc12ff850",
"status": "created",
"recurrence": 1,
"hour_range": 21,
"search": {
"search_type": "lawsuit_cnj",
"search_key": "1111111-04.2024.8.19.0001"
},
"created_at": "2026-04-16T13:58:56.352Z"
}
O campo hour_range indica o horário em que a primeira consulta ao tribunal será realizada. O monitoramento começa dentro das próximas 24 horas da data de criação, na janela de menor concorrência.
Guarde o tracking_id — você vai precisar dele para pausar, reativar ou remover o monitoramento.
2. Filtrando notificações por termos de andamento
Se você quer ser notificado apenas quando determinados tipos de movimentação ocorrerem — uma sentença, uma penhora, um despacho específico — use o campo step_terms dentro de notification_filters:
{
"recurrence": 1,
"search": {
"search_type": "lawsuit_cnj",
"search_key": "1111111-04.2024.8.19.0001"
},
"callback_url": "https://seu-servidor.com/webhooks/judit",
"notification_filters": {
"step_terms": ["sentença", "penhora", "acordo", "bloqueio"]
}
}
Com esse filtro ativo, o webhook só é disparado se algum dos termos aparecer em um novo andamento. Útil para reduzir ruído em processos com muitas movimentações menores.
3. Construindo o endpoint receptor
O endpoint precisa responder rápido (em menos de 2 segundos) e processar o evento de forma assíncrona. A Judit pode reenviar o callback se o servidor demorar ou retornar erro — então a lógica pesada deve acontecer fora do handler da requisição.
Node.js (Express)
import express from 'express';
import { Queue } from 'bullmq';
const app = express();
const eventQueue = new Queue('judicial-events');
app.use(express.json());
app.post('/webhooks/judit', async (req, res) => {
// Responde imediatamente
res.status(200).json({ received: true });
// Enfileira para processamento assíncrono
await eventQueue.add('processar-callback', req.body);
});
Python (FastAPI)
from fastapi import FastAPI, Request, BackgroundTasks
app = FastAPI()
@app.post("/webhooks/judit")
async def receber_callback(request: Request, background_tasks: BackgroundTasks):
payload = await request.json()
background_tasks.add_task(processar_callback_judicial, payload)
return {"received": True}
4. Entendendo a estrutura do payload
Todo callback da Judit segue este envelope:
{
"user_id": "...",
"callback_id": "...",
"event_type": "response_created",
"reference_type": "tracking",
"reference_id": "d923253e-45c1-46e5-ac70-164839d9851c",
"payload": {
"request_id": "...",
"response_id": "...",
"response_type": "lawsuit",
"response_data": { ... },
"tags": {
"cached_response": false
}
}
}
Pontos importantes:
reference_type pode ser request (consulta avulsa) ou tracking (monitoramento). Para monitoramentos, o reference_id corresponde ao tracking_id que você criou.
response_type define o que está no response_data. Os tipos relevantes são:
– lawsuit — dados completos de um processo judicial
– application_info — sinal de controle (fim de entrega)
– application_error — erro na consulta
cached_response (dentro de tags) indica a origem dos dados:
– true → dados vieram do datalake da Judit (resposta imediata)
– false → dados foram coletados diretamente do tribunal nesta rodada
É possível receber dois callbacks para a mesma atualização: o primeiro com cached_response: true e o segundo com cached_response: false. Processe os dois, mas use o response_id para garantir idempotência.
Sinal de fim de entrega
Quando todas as respostas de uma execução foram entregues, a Judit envia um callback final com response_type: "application_info":
{
"payload": {
"response_type": "application_info",
"response_data": {
"code": 600,
"message": "REQUEST_COMPLETED"
}
}
}
Sinal de erro
Se o processo não for encontrado ou houver falha na consulta ao tribunal:
{
"payload": {
"response_type": "application_error",
"response_data": {
"code": 2,
"message": "LAWSUIT_NOT_FOUND"
}
}
}
5. Processando os callbacks
Com a estrutura clara, o handler de processamento fica assim:
async function processarCallbackJudicial(callback) {
const { reference_id, payload } = callback;
const { response_type, response_data, response_id } = payload;
// Sinal de conclusão — apenas registra no log
if (response_type === 'application_info' && response_data.code === 600) {
console.log(`Entrega concluída para tracking ${reference_id}`);
return;
}
// Erro na consulta — registra para análise
if (response_type === 'application_error') {
await registrarErroMonitoramento(reference_id, response_data);
return;
}
// Dados de processo
if (response_type === 'lawsuit') {
// Idempotência: ignora se já processamos este response_id
const jaProcessado = await verificarResponseId(response_id);
if (jaProcessado) return;
const isCached = payload.tags?.cached_response;
await salvarProcesso(response_data);
await marcarResponseIdProcessado(response_id);
// Notifica apenas para dados frescos do tribunal
if (!isCached) {
await notificarAndamento(response_data);
}
}
}
async def processar_callback_judicial(callback: dict):
payload = callback['payload']
response_type = payload['response_type']
response_data = payload['response_data']
response_id = payload['response_id']
if response_type == 'application_info' and response_data['code'] == 600:
print(f"Entrega concluída: {callback['reference_id']}")
return
if response_type == 'application_error':
await registrar_erro(callback['reference_id'], response_data)
return
if response_type == 'lawsuit':
if await ja_processado(response_id):
return
is_cached = payload.get('tags', {}).get('cached_response', False)
await salvar_processo(response_data)
await marcar_processado(response_id)
if not is_cached:
await notificar_andamento(response_data)
6. Gerenciando o ciclo de vida dos monitoramentos
Pausar
curl -X POST \
"https://tracking.prod.judit.io/tracking/{tracking_id}/pause" \
-H "api-key: SUA_API_KEY"
Reativar
curl -X POST \
"https://tracking.prod.judit.io/tracking/{tracking_id}/resume" \
-H "api-key: SUA_API_KEY"
Atualizar recorrência
curl -X PATCH \
"https://tracking.prod.judit.io/tracking/{tracking_id}" \
-H "api-key: SUA_API_KEY" \
-H "Content-Type: application/json" \
-d '{"recurrence": 3}'
Remover definitivamente
curl -X DELETE \
"https://tracking.prod.judit.io/tracking/{tracking_id}" \
-H "api-key: SUA_API_KEY"
Listar monitoramentos ativos
curl "https://tracking.prod.judit.io/tracking?status=updated&page=1&page_size=50" \
-H "api-key: SUA_API_KEY"
Os status possíveis são: created, updating, updated, paused e deleted.
7. Consultando o histórico de um monitoramento
Para recuperar todas as respostas já entregues por um monitoramento — útil para sincronização ou debugging — use o endpoint de histórico no host requests.prod.judit.io:
curl "https://requests.prod.judit.io/responses/tracking/{tracking_id}?order=asc&page=1&page_size=50" \
-H "api-key: SUA_API_KEY"
Filtre por período com created_at_gte e created_at_lte no formato ISO 8601.
Dicas para produção
Idempotência pelo response_id. A Judit pode reenviar o mesmo callback em caso de falha de entrega. Antes de processar, verifique se o response_id já foi tratado — idealmente com uma chave no Redis ou uma coluna única no banco.
Separe endpoints por ambiente. Use URLs distintas para dev, staging e prod. Compartilhar a mesma URL em todos os ambientes garante que eventos de teste acabem em produção.
Monitore application_error. Um erro ocasional é normal — tribunal fora do ar, CAPTCHA, instabilidade. Mas LAWSUIT_NOT_FOUND persistente para o mesmo número CNJ geralmente indica que o processo foi arquivado ou o número está incorreto.
Prefira cached_response: false para decisões críticas. O dado cacheado é útil para velocidade, mas para decisões de crédito ou compliance, use apenas os dados frescos do crawler como base.
Registre o payload completo antes de processar. Em caso de bug na lógica, você vai querer fazer replay do evento original — o que só é possível se você guardou o payload bruto.
Testando localmente
Durante o desenvolvimento, você precisa de uma URL pública para receber os callbacks:
# ngrok — mais popular
ngrok http 3000
# Usa a URL gerada como callback_url no payload de registro
# Webhook.site — sem instalar nada
# Acesse https://webhook.site para inspecionar payloads reais antes de implementar o handler
Recapitulando
O monitoramento por webhook é a única abordagem que escala para operações com centenas ou milhares de processos. A implementação correta envolve:
- Registro com
search.search_typeesearch.search_keyno endpoint/trackingdo hosttracking.prod.judit.io callback_urlno payload para receber os eventos- Endpoint receptor que responde rápido e processa de forma assíncrona
- Tratamento correto dos três tipos de
response_type:lawsuit,application_infoeapplication_error - Idempotência pelo
response_idpara evitar processamento duplicado - Gerenciamento ativo do ciclo de vida com pause, resume e delete
A documentação completa de monitoramento e a referência de webhooks têm todos os detalhes de schema e parâmetros.
- Webhooks para monitoramento processual: como receber alertas em tempo real via API
- Traduzindo termos técnicos para pessoas não técnicas
- Como integrar dados jurídicos via REST API: tutorial completo com Python e Node.js
- API de Processos Judiciais no Brasil: Guia para Desenvolvedores 2026
- Simplificando Termos Jurídicos Para Quem Não É Advogado





