API de Emissão de CRLV-e

O Certificado de Registro e Licenciamento de Veículo digital, pela placa, em PDF direto do Detran — a mesma emissão que os lojistas fazem no painel da CredPro, a preço de atacado. A UF de emplacamento é conferida pela placa antes de cobrar; se o Detran não devolver o documento, o valor volta pro seu saldo.

📄
Emissão de CRLV-eCobra o preço da UF na criação. Placa fora do padrão, UF errada, UF sem cobertura e saldo insuficiente não cobram. Documento não emitido é estornado automaticamente.
a partir de R$ 15,00por emissão — preço de atacado
GET/v1/crlv/estados POST/v1/crlv GET/v1/crlv/{id} GET/v1/crlv/{id}/pdf

🗺️ Estados e preços — GET /v1/crlv/estados

Lista as UFs com CRLV-e disponível, o preço que será cobrado em cada uma (o custo do Detran varia muito por estado) e os campos_extras que o Detran daquela UF exige além da placa (renavam e documento do proprietário). Consulte antes de emitir: a cobertura cresce e os preços podem mudar — este endpoint é a fonte da verdade.

GET /v1/crlv/estados
Authorization: Bearer SUA_CHAVE_AQUI

{
  "estados": [
    {"uf": "AC", "preco": 22.00, "campos_extras": ["renavam", "documento"]},
    {"uf": "AL", "preco": 70.00, "campos_extras": []},
    {"uf": "AP", "preco": 15.00, "campos_extras": []},
    {"uf": "BA", "preco": 25.00, "campos_extras": []},
    {"uf": "CE", "preco": 92.00, "campos_extras": []},
    {"uf": "SP", "preco": 15.00, "campos_extras": []},
    ...
  ],
  "saldo_reais": 132.48,
  "sandbox": false
}
UFPreço (atacado)Exige além da placa
SP, MG, PR, MT, MS, MA, PI, RO, SE, TO, APR$ 15,00
BA, GO, PAR$ 25,00
ACR$ 22,00renavam + documento
RRR$ 30,00renavam + documento
RJR$ 48,00
ALR$ 70,00
CER$ 92,00
PER$ 115,00
Preços. A tabela acima é a de 17/09/2026; o valor vigente é sempre o de GET /v1/crlv/estados. A emissão é cobrada do mesmo saldo em reais das outras APIs. Estados fora da lista (AM, DF, ES, PB, RN, RS, SC) ainda não têm emissão pela API.

🚀 Emitir — POST /v1/crlv

Só a placa é obrigatória: a UF de emplacamento é detectada automaticamente. Se você mandar uf, ela é conferida — placa emplacada em outro estado volta 422 com a UF certa, sem cobrar (esse era o motivo nº 1 de emissão paga que não saía). O preço da UF é debitado na hora e a emissão entra em processamento (202): o Detran responde em segundos, alguns estados em até ~2 minutos.

POST /v1/crlv
Authorization: Bearer SUA_CHAVE_AQUI
Content-Type: application/json

{
  "placa": "ABC1D23"
}

HTTP 202
{
  "emissao_id": 512,
  "status": "processando",
  "placa": "ABC1D23",
  "uf": "SP",
  "valor_cobrado": 15.00,
  "saldo_reais": 117.48,
  "consulte_em": "/v1/crlv/512",
  "sandbox": false
}
CampoTipoObrigatórioObservação
placastringsimABC1234 ou ABC1D23, com ou sem hífen.
ufstringnãoSigla do estado de emplacamento. Omitida = detectada pela placa. Informada e diferente da real = 422 uf_divergente (traz uf_detectada).
renavamstringse a UF exigir9 a 11 dígitos. Veja campos_extras da UF em GET /v1/crlv/estados (hoje AC e RR).
documentostringse a UF exigirCPF (11) ou CNPJ (14) do proprietário, com ou sem pontuação (hoje AC e RR).
SituaçãoHTTPCobra?
Emissão criada e em processamento202✅ preço da UF
Detran não devolveu o documento (placa sem CRLV, débitos que impedem, instabilidade persistente)— (status: erro em GET /v1/crlv/{id})↩️ estornado no fim do processamento
Placa fora do padrão / UF diferente da emplacada / UF sem cobertura / UF não detectada / campo extra faltando422 placa_invalida, uf_divergente, uf_indisponivel, uf_obrigatoria, renavam_obrigatorio, documento_obrigatorio❌ Não
Saldo insuficiente402 saldo_insuficiente (traz necessario)❌ Não
Limite por minuto atingido429 limite_taxa❌ Não
Instabilidade do Detran. Erros passageiros ("consulta momentaneamente indisponível", erro interno do provedor, tempo esgotado) são repetidos automaticamente até 3 vezes antes de a emissão ser dada como erro — você não precisa reenviar. Só reenvie depois de status: erro.

📬 Consultar situação — GET /v1/crlv/{id}

Faça polling a cada 3–5 s até status sair de processando. concluido traz o link do PDF; erro traz o motivo em erro e valor_cobrado volta a zero (estorno já feito).

GET /v1/crlv/512
Authorization: Bearer SUA_CHAVE_AQUI

{
  "emissao_id": 512,
  "status": "concluido",
  "placa": "ABC1D23",
  "uf": "SP",
  "valor_cobrado": 15.00,
  "criado_em": "2026-09-17 15:02:11",
  "expira_em": "2026-10-17 15:02:11",
  "erro": null,
  "pdf": "/v1/crlv/512/pdf",
  "sandbox": false
}

📄 PDF — GET /v1/crlv/{id}/pdf

Depois de concluido, devolve o CRLV-e em PDF (application/pdf, cabeçalho Content-Disposition: attachment) — o documento do Detran, com QR code, do jeito que o lojista baixa no painel. Fica disponível por 30 dias; guarde o arquivo se precisar dele depois. Antes de concluir ou em erro, responde 409 documento_indisponivel.

🧪 Sandbox

Com a chave de teste (cpk_test_…) os mesmos endpoints devolvem um CRLV-e de demonstração (PDF com dados fictícios, sem validade), sem cobrar e sem chegar no Detran. A UF informada é aceita como está (ou SP quando omitida). Regra: placa começando com ZZZ termina em status: erro ("CRLV não encontrado"), pra você testar o caminho de falha. Regras gerais do sandbox →

💻 Exemplos de código

cURL
Python
Node.js
curl -X POST https://cred-pro.com/v1/crlv \
  -H "Authorization: Bearer SUA_CHAVE_AQUI" \
  -H "Content-Type: application/json" \
  -d '{"placa": "ABC1D23"}'

# depois, até status = concluido ou erro:
curl https://cred-pro.com/v1/crlv/512 -H "Authorization: Bearer SUA_CHAVE_AQUI"

# PDF:
curl -o crlv.pdf https://cred-pro.com/v1/crlv/512/pdf -H "Authorization: Bearer SUA_CHAVE_AQUI"
import requests, time

CHAVE = "SUA_CHAVE_AQUI"
H = {"Authorization": f"Bearer {CHAVE}"}

r = requests.post("https://cred-pro.com/v1/crlv", headers=H, timeout=30, json={"placa": "ABC1D23"})
if r.status_code != 202:
    raise SystemExit(f"erro {r.status_code}: {r.json()['detail']['erro']}")
eid = r.json()["emissao_id"]
print("UF detectada:", r.json()["uf"], "| cobrado:", r.json()["valor_cobrado"])

while True:
    e = requests.get(f"https://cred-pro.com/v1/crlv/{eid}", headers=H, timeout=30).json()
    if e["status"] != "processando":
        break
    time.sleep(4)

if e["status"] == "erro":
    raise SystemExit(f"não emitido (valor estornado): {e['erro']}")

pdf = requests.get(f"https://cred-pro.com/v1/crlv/{eid}/pdf", headers=H, timeout=60)
open(f"CRLV_{e['placa']}.pdf", "wb").write(pdf.content)
const CHAVE = "SUA_CHAVE_AQUI";
const H = { Authorization: `Bearer ${CHAVE}`, "Content-Type": "application/json" };

const r = await fetch("https://cred-pro.com/v1/crlv", { method: "POST", headers: H, body: JSON.stringify({ placa: "ABC1D23" }) });
const criado = await r.json();
if (r.status !== 202) throw new Error(JSON.stringify(criado.detail.erro));

let e;
do {
  await new Promise(s => setTimeout(s, 4000));
  e = await (await fetch(`https://cred-pro.com/v1/crlv/${criado.emissao_id}`, { headers: H })).json();
} while (e.status === "processando");

if (e.status === "erro") throw new Error(`não emitido (valor estornado): ${e.erro}`);
const pdf = await fetch(`https://cred-pro.com/v1/crlv/${criado.emissao_id}/pdf`, { headers: H });
require("fs").writeFileSync(`CRLV_${e.placa}.pdf`, Buffer.from(await pdf.arrayBuffer()));
Combinando. A consulta de placa + FIPE (R$ 0,12) já traz a UF de emplacamento — use-a pra mostrar o preço certo antes de emitir. E a base estadual (R$ 2,00) mostra os débitos que podem impedir o licenciamento.