Tratamento de erros
Erro da requisição x erro no processamento, o catálogo de códigos e os problemas mais comuns.
Erro da requisição x erro no processamento
São duas famílias diferentes, e confundi-las é a causa mais comum de integração frágil. A pergunta que separa as duas: a consulta chegou a existir?
Erro da requisição: a consulta não nasceu
O pedido foi recusado na hora. O status HTTP é diferente de 2xx, não existe id e nada foi cobrado. O corpo é sempre o mesmo envelope:
{
"erro": "Placa inválida",
"codigo": "PLACA_INVALIDA",
"retryable": false,
"request_id": "9f2c1b7e-4d52-4a1f-9d3e-7c8a5b2e1f04"
}| Campo | O que é |
|---|---|
erro | Frase para humano. A redação pode mudar: não use como condição no seu código. |
codigo | Identificador estável. É nele que você programa. |
retryable | true: repetir a mesma chamada pode dar certo. false: corrija o pedido primeiro. |
request_id | Identificador desta requisição nos nossos registros (o mesmo do cabeçalho X-Request-Id). Informe ao suporte. |
detalhes | Só em VALIDATION_ERROR: lista de { campo, mensagem }. |
saldo | Só em 402 SALDO_INSUFICIENTE: o saldo atual da carteira. |
Correlacione com o seu sistema
X-Request-Id com um identificador seu (até 128 caracteres: letras, números, ponto, hífen e sublinhado). A API usa esse valor como request_id da chamada e o devolve no cabeçalho e no corpo de erro; sem o cabeçalho, ou fora do formato, ela gera um UUID. Assim o mesmo id aparece nos seus logs e nos nossos.Todo erro da /v1 traz erro, codigo e retryable, inclusive o 404 de URL errada e o 500 inesperado. O request_id vem sempre que a requisição passou pela API (no 429 do limite de requisições ele pode não vir). Você não precisa mapear status HTTP para decidir retry: leia retryable.
Erro no processamento: a consulta nasceu e falhou depois
O POST respondeu 201 e o saldo foi debitado; a falha aconteceu depois, na base consultada. Ela aparece no GET /v1/consultas/{id} com HTTP 200 (a requisição funcionou; a consulta é que falhou) e o valor é estornado.
{
"id": "6f1c2e2a-1b3d-4a9e-8f7c-2a1b3c4d5e6f",
"servico": "gravame",
"placa": "ABC1D23",
"status": "erro",
"schema_version": "1.0",
"erro": "A base consultada está temporariamente indisponível. Isso costuma se resolver em alguns minutos: tente novamente.",
"erro_codigo": "PROVIDER_UNAVAILABLE",
"retryable": true
}status: "erro" é terminal
GET no mesmo id nunca vai virar concluido. Se retryable for true, espere um pouco (2, 5, 10 s) e faça um POST novo, com Idempotency-Key nova. Três tentativas bastam.| Situação | HTTP | Cobrança | O que fazer |
|---|---|---|---|
| Erro da requisição | 4xx / 5xx | Nada foi cobrado | Ler codigo. Repetir só se retryable: true. |
| Consulta falhou no processamento | 200 | Estornado | Ler erro_codigo. Criar consulta nova se retryable: true. |
| Timeout do seu lado esperando | (nenhum) | Cobrada (a consulta segue viva) | Não recrie: guarde o id e consulte depois, ou use webhook. |
No erro de processamento, retryable tem três estados: true, false e ausente. Ausente significa que a falha não foi classificada (consultas anteriores a 02/09/2026, por exemplo): trate como definitiva e não repita automaticamente. Afirmar false sobre o que não sabemos faria você desistir de uma consulta recuperável; afirmar true faria você pagar à toa.
PROVIDER_TIMEOUT, CIRCUIT_OPEN e INTERNAL_ERROR), e no último o retryable difere de propósito: como erro da requisição, INTERNAL_ERROR é true (a chamada não chegou a ser processada); como falha de processamento, é false (repetir não conserta um defeito nosso, que a equipe já recebeu). A regra é ler o retryable que veio naquela resposta.Por status HTTP
- 200A requisição funcionouNo
GET /v1/consultas/{id}, um200pode carregarstatus: "erro": a requisição deu certo, a consulta é que falhou. - 400Pedido inválidoFalta campo, formato errado, UF não atendida. Nada foi criado nem cobrado: corrija e reenvie.
- 401Chave ausente, inválida ou revogadaConfira o cabeçalho Authorization. A revogação tem efeito imediato.
- 402Saldo insuficienteA resposta traz o
saldoatual. Recarregue e reenvie; nada foi cobrado. - 404Não encontrado, ou não é da sua contaId de consulta de outro cliente (ou do outro ambiente) responde 404, nunca o dado. Também é a resposta para método ou URL trocados e para documento, imagem ou FIPE que não existe.
- 409ConflitoMesma
Idempotency-Keyainda em processamento (espere e repita, sem criar outra consulta) ouaceite_atpve.versaodesatualizada. - 422Entendido, mas não processávelServiço indisponível para a conta,
Idempotency-Keyreusada com outro corpo, ATPV-e sem declaração, documento pedido com chave de teste ou documento armazenado inválido. - 429Limite de requisiçõesRespeite o
Retry-After. Não consome saldo. - 500Falha interna inesperadaTransitória (
retryable: true). Se insistir, envie orequest_idao suporte. - 502A fonte da FIPE respondeu com erroTransitório. O valor já foi estornado.
- 503Base ou ambiente de teste indisponívelCircuito aberto, fonte fora ou sandbox momentaneamente fora. Transitório.
- 504Tempo da base excedidoTransitório. Repita depois de um intervalo.
Catálogo de erros da requisição
Lido de GET /public/api-erros (público, sem chave), a mesma fonte que o backend usa para montar as respostas. Cada código tem link próprio: /api-integradores/docs/erros#CODIGO.
| HTTP | Código | Repetir? | Quando acontece e o que fazer |
|---|---|---|---|
| 400 | CHASSI_INVALIDO | não | Chassi inválido.Confira o chassi (17 caracteres). |
| 400 | CHAVE_NFE_INVALIDA | não | Chave de acesso da NF-e inválida: 44 dígitos com dígito verificador correto (consulta-nfe).Confira os 44 dígitos da chave de acesso (o dígito verificador é conferido). |
| 400 | CNH_INVALIDA | não | Número de registro da CNH ausente ou inválido (cnh-nacional).Envie o número de registro da CNH em cnh. |
| 400 | CONSULTA_WITHOUT_DATA | não | Consulta sem dados para gerar o documento.A consulta não tem dados para montar o documento. Refaça a consulta. |
| 400 | CRLV_DADOS_OBRIGATORIOS | não | Faltam campos exigidos pela UF (CPF/RENAVAM).Envie os campos que a UF exige: requer de cada UF em crlv.preco_por_uf. |
| 400 | DATA_NASCIMENTO_INVALIDA | não | Data de nascimento ausente ou inválida (situacao-cpf; use dd/mm/aaaa).Envie data_nascimento em dd/mm/aaaa. |
| 400 | DEBITOS_DADOS_OBRIGATORIOS | não | Faltam campos exigidos pela UF.Envie os campos que a UF exige: campos_por_uf em GET /v1/servicos. |
| 400 | DOCUMENTO_INVALIDO | não | CPF/CNPJ inválido.Confira o CPF/CNPJ e se o serviço aceita aquele tipo de documento. |
| 400 | FINALIDADE_OBRIGATORIA | não | Serviço com dado pessoal (comunicacao-venda e as consultas de pessoa: cadastro, crédito, CNH, débitos trabalhistas, dívida ativa): envie finalidade e declaracao_finalidade: true.Envie finalidade (NEGOCIACAO_VEICULO, ANALISE_CREDITO, VERIFICACAO_CADASTRAL ou OUTRA) e declaracao_finalidade: true. |
| 400 | IDEMPOTENCY_KEY_INVALIDA | não | Idempotency-Key fora do formato (8–255 chars).Use de 8 a 255 caracteres. |
| 400 | IMAGEM_INDICE_INVALIDO | não | Índice de imagem inválido (inteiro >= 0).indice deve ser inteiro maior ou igual a 0. |
| 400 | IMAGEM_TIPO_INVALIDO | não | Tipo de imagem desconhecido. Use leilao, outra, csv-imagem ou csv-pdf.tipo deve ser leilao, outra, csv-imagem ou csv-pdf. |
| 400 | MOTOR_INVALIDO | não | Número do motor inválido.Confira o número do motor. |
| 400 | PDF_NOT_READY | sim | Documento ainda em processamento; tente novamente.Espere status "concluido" antes de pedir o documento. |
| 400 | PLACA_INVALIDA | não | Placa em formato inválido.Envie a placa com 7 caracteres (AAA0A00 ou AAA0000), com ou sem hífen. |
| 400 | RENAVAM_INVALIDO | não | RENAVAM inválido.Confira os dígitos do RENAVAM. |
| 400 | SERVICO_INVALIDO | não | Slug de serviço desconhecido.Use um slug de GET /v1/servicos (campo servico). |
| 400 | UF_INDISPONIVEL | não | UF indisponível para o serviço.Use uma UF atendida pelo serviço (lista em GET /v1/servicos). |
| 400 | UF_INVALIDA | não | UF inválida.Envie uf com 2 letras. |
| 400 | VALIDATION_ERROR | não | Corpo da requisição inválido.O corpo não é um JSON válido ou tem campo com tipo errado. A resposta traz detalhes por campo. |
| 401 | CUSTOMER_NOT_FOUND | não | Conta associada à chave não encontrada.Fale com o suporte informando o request_id. |
| 401 | INVALID_API_KEY | não | Chave de API inválida ou revogada.Confira se a chave não foi revogada ou trocada. Gere outra em Conta › Integrações. |
| 401 | MISSING_API_KEY | não | Cabeçalho Authorization: Bearer <chave> ausente.Envie Authorization: Bearer <chave> (ou X-API-Key) em toda chamada. |
| 402 | SALDO_INSUFICIENTE | não | Saldo insuficiente na carteira.Recarregue a carteira no portal. A resposta traz o saldo atual. |
| 404 | CONSULTA_NOT_FOUND | não | Consulta não encontrada para esta conta.Confira o id e a chave usada: id de outra conta, do outro ambiente ou consulta de teste com mais de 24 h respondem 404. |
| 404 | FIPE_NAO_DISPONIVEL | não | Sem FIPE para esta placa.Não há FIPE para essa placa ou combinação. O valor foi estornado; repetir não muda o resultado. |
| 404 | IMAGEM_NOT_FOUND | não | Imagem inexistente para esta consulta. Consultas concluídas antes de 27/08/2026 não têm imagens armazenadas: reprocesse a consulta.Use os índices que vêm em dados.fotosLeilao[]. Consultas anteriores a 27/08/2026 não têm imagens. |
| 404 | PDF_NOT_FOUND | não | PDF não disponível para esta consulta.Este serviço ou esta consulta não tem documento. |
| 404 | ROTA_NAO_ENCONTRADA | não | Rota inexistente.Confira método e URL: criar é POST /v1/consultas (sem id); ver é GET /v1/consultas/{id}. |
| 409 | AVISO_ATPVE_DESATUALIZADO | não | aceite_atpve.versao diferente da vigente. Busque o aviso novo em GET /public/avisos/atpve, mostre ao usuário e reenvie.Busque o aviso vigente, mostre ao usuário de novo e reenvie com a versão nova. |
| 409 | IDEMPOTENCY_IN_PROGRESS | sim | Requisição idêntica ainda em processamento; repita em instantes.Espere alguns segundos e repita com a MESMA chave. Não crie outra consulta. |
| 422 | ACEITE_ATPVE_OBRIGATORIO | não | atpve sem aceite_atpve.aceito: true. Mostre o aviso de GET /public/avisos/atpve ao usuário e envie a declaração.Mostre o aviso de GET /public/avisos/atpve ao usuário e envie aceite_atpve com aceito: true. |
| 422 | DOCUMENTO_CORROMPIDO | não | O documento armazenado não é um arquivo válido (PDF/PNG/JPEG). Refaça a consulta: repetir o download não resolve.Refaça a consulta: repetir o download não resolve. |
| 422 | IDEMPOTENCY_KEY_REUSED | não | Mesma Idempotency-Key com payload diferente.Uma chave pertence a uma operação: gere outra para um corpo diferente. |
| 422 | SANDBOX_SEM_DOCUMENTO | não | O ambiente de teste não gera documentos (PDF/imagem). Use a chave zc_live_ para baixar um documento real.Documentos só existem com a chave zc_live_. |
| 422 | SERVICO_INDISPONIVEL | não | Serviço sem preço/indisponível para a conta.O serviço (ou a UF, no CRLV) não está liberado para a sua conta agora. Confira GET /v1/servicos. |
| 429 | RATE_LIMITED | sim | Limite de requisições excedido.Espere o tempo do cabeçalho Retry-After e repita. |
| 500 | INTERNAL_ERROR | sim | Erro interno inesperado.Repita uma vez; se persistir, envie o request_id ao suporte. |
| 502 | FIPE_ERRO | sim | Falha transitória ao consultar a FIPE.Repita depois de um intervalo. O valor já foi estornado. |
| 503 | CIRCUIT_OPEN | sim | Fornecedor temporariamente indisponível (circuito aberto).A base está fora. Repita depois de um intervalo (backoff). |
| 503 | FIPE_INDISPONIVEL | sim | Provedor FIPE temporariamente indisponível.Repita depois de um intervalo. O valor já foi estornado. |
| 503 | SANDBOX_INDISPONIVEL | sim | O ambiente de teste está momentaneamente indisponível. Tente em instantes.Repita em instantes. |
| 504 | PROVIDER_TIMEOUT | sim | Tempo de resposta do fornecedor excedido.Repita depois de um intervalo (backoff). |
Códigos de falha do processamento
Valores possíveis de erro_codigo numa consulta com status: "erro". Em todos eles o valor da consulta é estornado. A mensagem é a que vai em erro (sem nome de fornecedor).
| erro_codigo | Origem | retryable | Mensagem |
|---|---|---|---|
INVALID_PLATE | Dado enviado | false | A placa informada é inválida. Confira os caracteres e tente novamente. |
INVALID_CHASSIS | Dado enviado | false | O chassi informado é inválido. Confira o número e tente novamente. |
INVALID_ENGINE | Dado enviado | false | O número do motor informado é inválido. Confira e tente novamente. |
INVALID_RENAVAM | Dado enviado | false | O RENAVAM informado é inválido. Confira os dígitos e tente novamente. |
INVALID_DOCUMENT | Dado enviado | false | O CPF/CNPJ informado é inválido. Confira os dígitos e tente novamente. |
MISSING_REQUIRED_FIELD | Dado enviado | false | Faltou um dado obrigatório para esta consulta. Confira os campos e tente novamente. |
UF_UNAVAILABLE | Dado enviado | false | Este serviço não está disponível para o estado informado. |
QUERY_NOT_FOUND | Sem resultado | false | Não encontramos registros para os dados informados nas bases consultadas. Confira as informações antes de tentar de novo. |
PROVIDER_TIMEOUT | Base consultada | true | A base consultada demorou mais que o esperado e a consulta não foi concluída. Tente novamente em alguns minutos. |
PROVIDER_UNAVAILABLE | Base consultada | true | A base consultada está temporariamente indisponível. Isso costuma se resolver em alguns minutos: tente novamente. |
PROVIDER_INVALID_RESPONSE | Base consultada | true | A base consultada respondeu de forma incompleta e a consulta não pôde ser concluída. Tente novamente em alguns minutos. |
PROVIDER_AUTH_ERROR | Base consultada | false | Não foi possível concluir a consulta neste momento. Nossa equipe já foi avisada. |
PROVIDER_ERROR | Base consultada | false | A base consultada não conseguiu concluir esta consulta. Tente novamente mais tarde. |
PROVIDER_NO_DOCUMENT | Base consultada | false | O órgão emissor não devolveu o documento desta solicitação. Tente novamente mais tarde. |
CIRCUIT_OPEN | Base consultada | true | A base consultada está temporariamente indisponível. Isso costuma se resolver em alguns minutos: tente novamente. |
QUEUE_UNAVAILABLE | ZapCar | true | Não foi possível iniciar o processamento desta consulta agora. Tente novamente em alguns instantes. |
PROCESSING_INTERRUPTED | ZapCar | true | O processamento desta consulta foi interrompido e não pôde ser concluído. Você pode solicitar novamente. |
PDF_GENERATION_FAILED | ZapCar | false | A consulta foi realizada, mas houve um problema ao montar o documento. Nossa equipe já foi avisada. |
ADAPTER_ERROR | ZapCar | false | Não foi possível processar os dados retornados pela consulta. Nossa equipe já foi avisada. |
CONFIG_ERROR | ZapCar | false | Não foi possível processar esta consulta por um problema interno. Nossa equipe já foi avisada. |
INTERNAL_ERROR | ZapCar | false | Não foi possível processar esta consulta por um problema interno. Nossa equipe já foi avisada. |
Problemas comuns
Credencial inválida (401)
Faltou o cabeçalho Authorization: Bearer …, a chave foi revogada ou está com espaço/quebra de linha a mais (comum ao colar de um e-mail ou de um arquivo .env com aspas). No Postman, confira a aba Authorization em cada requisição.
Saldo insuficiente (402)
A carteira não cobre o preço do serviço. A resposta traz o saldo atual; recarregue na carteira e reenvie. Monitore com GET /v1/saldo para recarregar antes de acabar.
Parâmetro incorreto (400)
O codigo diz qual campo: PLACA_INVALIDA, UF_INVALIDA, CRLV_DADOS_OBRIGATORIOS… Os campos exigidos por serviço (e por UF, no CRLV) estão em requer de GET /v1/servicos: leia de lá em vez de fixar no código.
Serviço indisponível (422)
SERVICO_INDISPONIVEL significa que o serviço (ou a UF, no CRLV) não está liberado na API para a sua conta neste momento. Ele some de GET /v1/servicos enquanto estiver assim.
Consulta parada em processando
Na base estadual, a primeira consulta do dia de uma placa pode levar cerca de 2 minutos; CRLV em alguns estados e ATPV-e levam mais. Use teto de 5 minutos no polling. Se estourar, a consulta não se perdeu: guarde o id e consulte depois, ou deixe o webhook avisar.
Webhook não recebido
Confira, no portal, o histórico de entregas do endpoint (status, código HTTP e erro de cada tentativa). Causas comuns: URL sem HTTPS, endpoint desativado, resposta acima de 10 s, firewall bloqueando, assinatura recusada pelo seu código, URL apontando para rede interna. Use o botão Testar e o simulador. Enquanto isso, o polling continua funcionando.
Limite de requisições atingido (429)
Espere o Retry-After. Se acontece com frequência, o polling está apertado demais ou paralelo demais: aumente o intervalo, limite a concorrência ou troque por webhook. Ver Limites.
Resultado não encontrado
Duas situações diferentes. 404 CONSULTA_NOT_FOUND: o id não existe para esta chave (outra conta, outro ambiente, consulta de teste expirada, id digitado errado). erro_codigo: QUERY_NOT_FOUND: a consulta existiu e a base não encontrou registro para os dados enviados (placa inexistente ou digitada errada); o valor foi estornado e repetir não muda o resultado.
Falha da base consultada
PROVIDER_UNAVAILABLE, PROVIDER_TIMEOUT e CIRCUIT_OPEN são transitórios: a base caiu ou demorou. O valor foi estornado; crie uma consulta nova depois de um intervalo, com teto de tentativas. Muitas falhas seguidas no mesmo serviço costumam indicar instabilidade da base: acompanhe a página de status.
404 com codigo ROTA_NAO_ENCONTRADA
Método ou URL não batem. Quase sempre: POST com o id na URL (para ver é GET), GET em /v1/consultas sem id (para criar é POST) ou caminho digitado errado.
Ao pedir ajuda
request_id da resposta (ou o id da consulta), o horário aproximado e o endpoint. Com isso a equipe acha a chamada exata. Nunca envie a sua chave. Falar com a equipe de integração.