Skip to main content

Visão Geral

A API de Consulta de Débitos permite buscar todos os débitos pendentes de um veículo de forma assíncrona. O sistema gera um pedido de consulta que é processado e retorna os resultados via webhook.
Processamento Assíncrono: A consulta é processada de forma assíncrona. Os resultados são enviados via webhook quando a consulta for concluída.

Como Funciona

O fluxo de consulta de débitos segue estas etapas:
1

Enviar Requisição

Faça uma requisição POST com os dados do veículo (placa, renavam, CPF/CNPJ)
2

Receber Confirmação

A API retorna imediatamente confirmando que a consulta foi iniciada
3

Aguardar Processamento

O sistema consulta os débitos nos sistemas dos Detrans
4

Receber Webhook

Quando concluída, os resultados são enviados para sua URL de webhook configurada

Endpoint

POST /uvvi/v1/debts

Parâmetros da Requisição

state
string
required
Sigla do estado (UF) onde o veículo está registrado. Exemplo: SP, RJ, MG
licensePlate
string
required
Placa do veículo no formato ABC1234 ou ABC1D23 (Mercosul)
renavam
string
required
Número do RENAVAM do veículo (11 dígitos)
cpfCnpj
string
required
CPF ou CNPJ do proprietário do veículo (apenas números)
externalId
string
Identificador único (UUID) para rastreamento da consulta no seu sistema. Este mesmo ID será retornado nos webhooks para correlação.
Sobre o externalId: Este campo é opcional mas altamente recomendado. Envie um UUID único gerado pelo seu sistema para rastrear a consulta. A API retornará este mesmo valor no campo externalId da resposta e dos webhooks, permitindo que você correlacione facilmente as notificações com as requisições originais.

Exemplo de Requisição

curl --request POST \
  --url 'https://api.uvvipague.com.br/uvvi/v1/debts' \
  --header 'x-api-key: SUA_API_KEY_AQUI' \
  --header 'Content-Type: application/json' \
  --data '{
    "state": "DF",
    "licensePlate": "JFI8753",
    "renavam": "56387604559",
    "cpfCnpj": "11111111111",
    "externalId": "550e8400-e29b-41d4-a716-446655440000"
  }'

Resposta Imediata

Ao enviar a requisição, você recebe uma confirmação imediata:
{
  "message": "Consulta iniciada com sucesso",
  "transactionId": 817210768,
  "externalId": "550e8400-e29b-41d4-a716-446655440000",
  "status": "PROCESSING"
}

Respostas via Webhook

Os resultados da consulta são enviados via webhook. Existem diferentes tipos de resposta:

1. Veículo com Débitos

Quando o veículo possui débitos pendentes:
{
  "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",
      "ait": "5E0083715",
      "dueDate": null,
      "expirationDate": null,
      "hasDiscount": false,
      "isExpired": true,
      "type": "ticket",
      "year": null,
      "required": false,
      "dependsOn": [],
      "distinct": []
    },
    {
      "id": "312D6A5F-2B5A-4694-84DA-F640FC01CC74",
      "amount": 1009.36,
      "title": "Licenciamento 2022",
      "description": "Licenciamento 2022",
      "dueDate": null,
      "expirationDate": "2022-12-28T00:00:00Z",
      "hasDiscount": false,
      "isExpired": true,
      "type": "licensing",
      "year": 2022,
      "required": false,
      "dependsOn": [],
      "distinct": []
    }
  ]
}

2. Veículo sem Débitos

Quando o veículo não possui débitos:
{
  "type": "VehicleWithoutDebts",
  "transactionId": 817622466,
  "externalId": "0a384059-eaf0-4240-9dc7-f4125671b4c9",
  "vehicle": {
    "uf": "DF",
    "document": "3138777503",
    "licensePlate": "RCK0E56",
    "renavam": "33864569420"
  }
}

3. Veículo Não Encontrado

Quando o veículo não é encontrado nos sistemas do Detran:
{
  "type": "VehicleNotFound",
  "transactionId": 817211803,
  "externalId": "0a384059-eaf0-4240-9dc7-f4125671b4c9"
}

4. Erro na Consulta

Quando há erro nos sistemas do Detran:
{
  "type": "search-error-event",
  "status": "ERROR",
  "transactionId": 817211803,
  "externalId": "bbf6c1c8-6c60-4806-9454-21a71e1ce1df",
  "error": [
    {
      "errorCode": "900",
      "message": "Serviço indisponível."
    }
  ]
}

Estrutura dos Débitos

Cada débito retornado contém as seguintes informações:
id
string
Identificador único do débito (UUID)
amount
number
Valor do débito em reais
title
string
Título descritivo do débito
description
string
Descrição detalhada do débito
type
string
Tipo do débito: ticket (multa), ipva, licensing (licenciamento), service (taxa)
dueDate
string
Data de vencimento original (formato ISO 8601)
expirationDate
string
Data de vencimento com juros/multa (formato ISO 8601)
hasDiscount
boolean
Indica se o débito possui desconto disponível
isExpired
boolean
Indica se o débito está vencido
year
number
Ano de referência do débito (para IPVA e licenciamento)
required
boolean
Indica se o débito é obrigatório para licenciamento
dependsOn
array
Lista de IDs de débitos que precisam ser pagos junto com este
distinct
array
Lista de IDs de débitos que não podem ser pagos junto com este
ait
string
Número do Auto de Infração de Trânsito (apenas para multas)

Tipos de Débitos

Multas (ticket)

Infrações de trânsito e multas gerenciadas pelo RENAINF

IPVA (ipva)

Imposto sobre Propriedade de Veículos Automotores (cota única ou parcelada)

Licenciamento (licensing)

Taxa anual de licenciamento do veículo

Taxas (service)

Taxas de serviços diversos, como multa de pátio

Dependências entre Débitos

Alguns débitos possuem dependências que devem ser respeitadas no momento do pagamento:

dependsOn (Dependências)

Lista de débitos que devem ser pagos junto com o débito atual. Por exemplo, uma multa pode depender do pagamento do IPVA.
{
  "id": "DEBITO-A",
  "amount": 100.00,
  "title": "Multa de Trânsito",
  "dependsOn": ["DEBITO-B", "DEBITO-C"]
}
Neste caso, para pagar o DEBITO-A, você também deve incluir DEBITO-B e DEBITO-C no pagamento.

distinct (Exclusões)

Lista de débitos que não podem ser pagos junto com o débito atual. Por exemplo, IPVA cota única não pode ser pago junto com parcelas.
{
  "id": "IPVA-COTA-UNICA",
  "amount": 1500.00,
  "title": "IPVA 2024 - Cota Única",
  "distinct": ["IPVA-PARCELA-1", "IPVA-PARCELA-2", "IPVA-PARCELA-3"]
}

Limitações por Estado

Atenção: Alguns estados possuem limitações específicas nas consultas.

Estados com IPVA Cota Única Apenas

Os seguintes estados retornam apenas IPVA em cota única:
  • Goiás (GO)
  • Maranhão (MA)
  • Mato Grosso do Sul (MS)
  • Rio Grande do Sul (RS)

Manutenção São Paulo

São Paulo (SP): O Detran-SP realiza manutenções diárias entre 00h e 07h. Durante este período, não é possível realizar consultas para veículos de SP.

Validações

Validação de RENAVAM

A API valida automaticamente o dígito verificador do RENAVAM antes de processar a consulta:
Se o RENAVAM for válido, a consulta prossegue normalmente.
Se o dígito verificador for inválido, a API retorna erro imediatamente:
{
  "error": "Bad Request",
  "message": "RENAVAM inválido. Verifique o dígito verificador.",
  "statusCode": 400
}
Esta validação ocorre tanto em sandbox quanto em produção.

Códigos de Erro

400
Bad Request
Dados inválidos na requisição (RENAVAM inválido, campos obrigatórios ausentes, etc.)
401
Unauthorized
API Key inválida ou ausente
404
Not Found
Veículo não encontrado nos sistemas do Detran
429
Too Many Requests
Limite de requisições excedido
500
Server Error
Erro interno do servidor
503
Service Unavailable
Serviço do Detran temporariamente indisponível

Códigos de Erro Específicos

CódigoDescrição
900Serviço indisponível
901Timeout na consulta ao Detran
902Dados inconsistentes retornados pelo Detran
903Manutenção programada do Detran

Boas Práticas

1

Configure Webhooks

Configure corretamente sua URL de webhook para receber os resultados das consultas. Veja Configuração de Webhooks.
2

Use externalId

Sempre envie um externalId único para rastrear a consulta no seu sistema e correlacionar com o webhook recebido.
3

Valide os Dados

Valide placa, RENAVAM e CPF/CNPJ antes de enviar para evitar erros desnecessários.
4

Trate Dependências

Ao processar débitos, respeite os campos dependsOn e distinct para garantir pagamentos corretos.
5

Implemente Retry

Em caso de erro 503 (serviço indisponível), implemente retry com backoff exponencial.
6

Cache Inteligente

Considere cachear resultados por algumas horas para evitar consultas duplicadas do mesmo veículo.

Exemplo Completo de Integração

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

app.use(express.json());

// Endpoint para iniciar consulta
app.post('/consultar-debitos', async (req, res) => {
  const { placa, renavam, cpfCnpj, estado } = req.body;
  
  const payload = {
    state: estado,
    licensePlate: placa,
    renavam: renavam,
    cpfCnpj: cpfCnpj,
    externalId: generateUUID()
  };
  
  try {
    const response = await fetch(
      'https://api.uvvipague.com.br/uvvi/v1/debts',
      {
        method: 'POST',
        headers: {
          'x-api-key': process.env.UVVIPAGUE_API_KEY,
          'Content-Type': 'application/json'
        },
        body: JSON.stringify(payload)
      }
    );
    
    const data = await response.json();
    
    // Salvar transactionId no banco para correlacionar com webhook
    await salvarConsulta({
      transactionId: data.transactionId,
      externalId: payload.externalId,
      status: 'PROCESSING'
    });
    
    res.json(data);
  } catch (error) {
    res.status(500).json({ error: 'Erro ao consultar débitos' });
  }
});

// Webhook para receber resultados
app.post('/webhook/debts', async (req, res) => {
  const resultado = req.body;
  
  // Processar resultado baseado no tipo
  switch (resultado.type) {
    case 'debts':
      await processarDebitos(resultado);
      break;
    case 'VehicleWithoutDebts':
      await processarSemDebitos(resultado);
      break;
    case 'VehicleNotFound':
      await processarNaoEncontrado(resultado);
      break;
    case 'search-error-event':
      await processarErro(resultado);
      break;
  }
  
  // Sempre retornar 200 para confirmar recebimento
  res.status(200).json({ received: true });
});

function generateUUID() {
  return 'xxxxxxxx-xxxx-4xxx-yxxx-xxxxxxxxxxxx'.replace(/[xy]/g, function(c) {
    const r = Math.random() * 16 | 0;
    const v = c == 'x' ? r : (r & 0x3 | 0x8);
    return v.toString(16);
  });
}

Próximos Passos