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.
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
}
| UF | Preço (atacado) | Exige além da placa |
|---|---|---|
| SP, MG, PR, MT, MS, MA, PI, RO, SE, TO, AP | R$ 15,00 | — |
| BA, GO, PA | R$ 25,00 | — |
| AC | R$ 22,00 | renavam + documento |
| RR | R$ 30,00 | renavam + documento |
| RJ | R$ 48,00 | — |
| AL | R$ 70,00 | — |
| CE | R$ 92,00 | — |
| PE | R$ 115,00 | — |
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
}
| Campo | Tipo | Obrigatório | Observação |
|---|---|---|---|
placa | string | sim | ABC1234 ou ABC1D23, com ou sem hífen. |
uf | string | não | Sigla do estado de emplacamento. Omitida = detectada pela placa. Informada e diferente da real = 422 uf_divergente (traz uf_detectada). |
renavam | string | se a UF exigir | 9 a 11 dígitos. Veja campos_extras da UF em GET /v1/crlv/estados (hoje AC e RR). |
documento | string | se a UF exigir | CPF (11) ou CNPJ (14) do proprietário, com ou sem pontuação (hoje AC e RR). |
| Situação | HTTP | Cobra? |
|---|---|---|
| Emissão criada e em processamento | 202 | ✅ 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 faltando | 422 placa_invalida, uf_divergente, uf_indisponivel, uf_obrigatoria, renavam_obrigatorio, documento_obrigatorio | ❌ Não |
| Saldo insuficiente | 402 saldo_insuficiente (traz necessario) | ❌ Não |
| Limite por minuto atingido | 429 limite_taxa | ❌ Não |
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 -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()));