Skip to main content

Visão Geral

Webhooks permitem que sua aplicação receba notificações automáticas quando eventos importantes ocorrem na API Uvvipague, como mudanças de status de pagamento, liquidação de débitos e conclusão de consultas.
Comunicação Assíncrona: Os webhooks são enviados de forma assíncrona. Configure sua URL para receber as notificações automaticamente.
Correlacionando Requisições e Webhooks: Todos os webhooks incluem o campo externalId que você enviou na requisição original. Use este campo para identificar qual requisição gerou cada webhook. Se você não enviar um externalId, a API gerará um automaticamente, mas é altamente recomendado que você envie seus próprios IDs únicos.

Cadastro de Webhook

Endpoint

POST /uvvi/v1/webhook-register

Parâmetros

url
string
required
URL do endpoint que receberá as notificações webhook. Deve ser uma URL válida e acessível publicamente.Exemplo: https://sua-api.com.br/webhook/uvvipague

Headers Obrigatórios

x-api-key
string
required
Sua API Key para autenticação

Exemplo de Requisição

curl --request POST \
  --url 'https://api.uvvipague.com.br/uvvi/v1/webhook-register' \
  --header 'x-api-key: SUA_API_KEY_AQUI' \
  --header 'Content-Type: application/json' \
  --data '{
    "url": "https://sua-api.com.br/webhook/uvvipague"
  }'

Resposta de Sucesso

{
  "request_id": "req_abc123def456",
  "status": "success",
  "message": "Webhook cadastrado com sucesso"
}

Política de Retentativas

A Uvvipague implementa uma política robusta de retentativas para garantir que você receba as notificações:
1

Tentativa Inicial

Enviamos a primeira requisição imediatamente após o evento ocorrer.
2

1ª Retentativa - 15 minutos

Se não recebermos resposta 200, tentamos novamente após 15 minutos.
3

2ª Retentativa - 60 minutos

Segunda tentativa após 60 minutos da tentativa inicial.
4

3ª Retentativa - 90 minutos

Terceira e última tentativa após 90 minutos da tentativa inicial.
5

Após 3 Retentativas

Após as 3 retentativas sem sucesso, nenhuma nova tentativa será realizada.O cliente precisará consultar o status manualmente usando o transactionId ou o externalId enviado na requisição original.
Importante: Após 3 tentativas falhadas, você deve consultar o status do pedido manualmente através da API de consulta de pagamento.

Timeline de Retentativas

Evento ocorre (t=0)

Tentativa 1 (imediato)
    ↓ (falha)
Tentativa 2 (t=15min)
    ↓ (falha)
Tentativa 3 (t=60min)
    ↓ (falha)
Tentativa 4 (t=90min)
    ↓ (falha)
Fim das tentativas

Recebendo Webhooks

Estrutura do Payload

Quando um evento ocorre, enviamos uma requisição POST para sua URL cadastrada:
{
  "type": "debts",
  "transactionId": 817210768,
  "externalId": "c676c954-aa6d-4cb5-a812-c1907a53a442",
  "vehicle": {
    "uf": "DF",
    "document": "39268450828",
    "licensePlate": "DIS9865",
    "renavam": "01203988813"
  },
  "debts": [
    {
      "id": "9547B3A8-05B9-4D1C-8C72-A500BB6D93EF",
      "amount": 85.13,
      "title": "Infração Vencida - I004242123",
      "description": "I004242123 - Infração de Trânsito",
      "type": "ticket",
      "dueDate": "2024-01-15T00:00:00Z",
      "isExpired": true
    }
  ]
}

Resposta Esperada

Seu endpoint deve retornar HTTP 200 para confirmar o recebimento:
HTTP/1.1 200 OK
Content-Type: application/json

{
  "received": true
}
Importante: Retorne 200 o mais rápido possível. Processe o webhook de forma assíncrona em sua aplicação para não bloquear a resposta.

Implementação do Endpoint

Exemplo Completo

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

app.use(express.json());

// Endpoint para receber webhooks
app.post('/webhook/uvvipague', async (req, res) => {
  try {
    // 1. Retorne 200 imediatamente
    res.status(200).json({ received: true });
    
    // 2. Processe o webhook de forma assíncrona
    processWebhookAsync(req.body);
    
  } catch (error) {
    console.error('Erro ao receber webhook:', error);
    res.status(500).json({ error: 'Internal server error' });
  }
});

async function processWebhookAsync(payload) {
  const { type, transactionId, externalId } = payload;
  
  console.log(`Webhook recebido: ${type}`);
  console.log(`Transaction ID: ${transactionId}`);
  console.log(`External ID: ${externalId}`);
  
  // Processar baseado no tipo
  switch (type) {
    case 'debts':
      await handleDebtsFound(payload);
      break;
      
    case 'VehicleWithoutDebts':
      await handleNoDebts(payload);
      break;
      
    case 'VehicleNotFound':
      await handleVehicleNotFound(payload);
      break;
      
    case 'search-error-event':
      await handleSearchError(payload);
      break;
      
    case 'payment-status-update':
      await handlePaymentUpdate(payload);
      break;
      
    default:
      console.warn(`Tipo de webhook desconhecido: ${type}`);
  }
}

async function handleDebtsFound(payload) {
  const { transactionId, debts } = payload;
  
  // Salvar débitos no banco de dados
  await database.debts.create({
    transactionId,
    debts: debts,
    status: 'found',
    receivedAt: new Date()
  });
  
  // Notificar cliente
  await notifyClient(transactionId, 'Débitos encontrados');
}

async function handlePaymentUpdate(payload) {
  const { paymentId, status, liquidationStatus } = payload;
  
  // Atualizar status do pagamento
  await database.payments.update(
    { paymentId },
    { 
      status, 
      liquidationStatus,
      updatedAt: new Date() 
    }
  );
  
  // Se pago e liquidado, liberar serviço
  if (status === 'paid' && liquidationStatus === 'settled') {
    await releaseService(paymentId);
  }
}

app.listen(3000, () => {
  console.log('Servidor rodando na porta 3000');
});

Segurança

Validações Recomendadas

Valide que a requisição vem dos servidores da Uvvipague:
  • Verifique o IP de origem (lista fornecida pelo suporte)
  • Implemente whitelist de IPs
Valide a estrutura do payload antes de processar:
function isValidWebhook(payload) {
  return payload.type && 
         payload.transactionId && 
         payload.externalId;
}
Implemente idempotência usando transactionId ou externalId:
async function processWebhook(payload) {
  const { transactionId, externalId } = payload;
  
  // Verificar se já foi processado usando externalId
  const exists = await database.webhooks.findOne({ externalId });
  if (exists) {
    console.log('Webhook já processado');
    return;
  }
  
  // Processar e marcar como processado
  await processPayload(payload);
  await database.webhooks.create({ 
    transactionId,
    externalId,
    processedAt: new Date() 
  });
}
Configure timeout adequado no seu servidor:
  • Responda em menos de 5 segundos
  • Processe de forma assíncrona
  • Use filas (Redis, RabbitMQ) para processamento

Consulta Manual de Status

Se todas as tentativas de webhook falharem, consulte o status manualmente:

Endpoint de Consulta

POST /uvvi/v1/payment/status
curl --request POST \
  --url 'https://api.uvvipague.com.br/uvvi/v1/payment/status' \
  --header 'x-api-key: SUA_API_KEY_AQUI' \
  --header 'Content-Type: application/json' \
  --data '{
    "paymentId": "pay_abc123def456"
  }'

Testando Webhooks

Ferramentas Úteis

Webhook.site

Use webhook.site para testar e visualizar webhooks durante o desenvolvimento.

ngrok

Use ngrok para expor seu localhost e receber webhooks em desenvolvimento.

RequestBin

Use RequestBin para inspecionar payloads de webhook.

Postman

Simule webhooks usando Postman para testar seu endpoint.

Exemplo com ngrok

# 1. Instale o ngrok
npm install -g ngrok

# 2. Inicie seu servidor local
node server.js  # rodando na porta 3000

# 3. Exponha com ngrok
ngrok http 3000

# 4. Use a URL gerada para cadastrar o webhook
# Exemplo: https://abc123.ngrok.io/webhook/uvvipague

Boas Práticas

1

Responda Rapidamente

Retorne HTTP 200 em menos de 5 segundos. Processe o webhook de forma assíncrona.
2

Implemente Idempotência

Use transactionId ou externalId para evitar processar o mesmo webhook múltiplas vezes.
3

Log Tudo

Registre todos os webhooks recebidos para auditoria e debugging.
4

Use Filas

Implemente filas (Redis, RabbitMQ, SQS) para processar webhooks de forma resiliente.
5

Monitore Falhas

Configure alertas para webhooks que falharem após todas as retentativas.
6

Tenha Fallback

Implemente consulta periódica de status como fallback caso os webhooks falhem.

Próximos Passos

Fluxo Completo

Veja como integrar webhooks no fluxo completo

Consulta de Débitos

Entenda os tipos de resposta via webhook

ENUMs e Tipos

Consulte os tipos de eventos e status

Autenticação

Configure sua API Key