Concar
Documentação técnica

API REST de consulta veicular

Endpoints HTTP padrão pra integrar consulta veicular com seu sistema interno (ERP, TMS, CRM, esteira de crédito). Disponível a partir do plano Pro.

Autenticação

Todas as requests requerem header Authorization: Bearer {API_KEY}. API key é gerada no painel B2B (apenas owner pode gerar/regenerar). Formato: cp_live_{48-char-hex}.

Importante: trate a API key como senha. Não commit em repo público, não inclua em apps client-side. Regenerar invalida a chave anterior — usado em vazamentos.

Base URL

https://www.concar.com.br/api/v1

Em ambiente de testes: https://www.concar.com.br/api/v1 (mesma URL — diferenciamos por API key sandbox vs prod, fornecida no onboarding).

Criar consulta

POST /api/v1/consultas
Authorization: Bearer cp_live_xxx
Content-Type: application/json

{
  "sku": "COMBO-PREMIUM",
  "plate": "ABC1D23",
  "purpose": "pre_purchase_evaluation"
}

Body fields:

  • sku — código do produto (ver lista completa em /empresas/precos)
  • plate — placa Mercosul (ABC1D23) ou antiga (ABC1234, sem hífen)
  • purpose — motivação LGPD: pre_purchase_evaluation, fleet_audit, transfer_request, insurance_quote, credit_analysis, recall_check

Resposta success (200):

{
  "consultaId": "cn_abc123",
  "status": "SUCCESS",
  "creditsConsumed": 9,
  "creditsRemaining": 491,
  "durationMs": 4823,
  "data": {
    "agregados-chassi": { /* ... */ },
    "leilao-v2": { /* ... */ },
    /* outros endpoints */
  },
  "pdfUrl": "https://www.concar.com.br/api/consultas/cn_abc123/pdf"
}

Erros possíveis:

  • 400 — placa inválida, SKU desconhecido, purpose ausente
  • 401 — API key inválida ou ausente
  • 402 — saldo de créditos insuficiente
  • 429 — rate limit (1 req/seg por API key sandbox, 5 req/seg prod)
  • 500 — erro interno (raro — base upstream indisponível ou bug nosso)

Consultar status

GET /api/v1/consultas/{consultaId}
Authorization: Bearer cp_live_xxx

Retorna o mesmo schema do POST. Útil pra retry idempotente.

Listar consultas

GET /api/v1/consultas?limit=50&cursor=cn_xyz
Authorization: Bearer cp_live_xxx

Paginação por cursor. limit max 100. Filtros opcionais: ?status=SUCCESS, ?sku=COMBO-PREMIUM, ?since=2026-01-01.

Webhook events

Configure URL no painel B2B (apenas owner). Eventos disparados:

  • consulta.success — consulta concluída com sucesso
  • consulta.failed — consulta falhou (erro de provider, etc)
  • order.paid — pedido pago, créditos liberados (Starter+)
  • credits.low — saldo abaixo de 10% do plano
  • recall.detected — recall novo do fabricante afeta um veículo da sua frota recentemente consultada (Business+)

Payload exemplo (consulta.success):

POST [seu webhook URL]
X-Signature: sha256=abc123...
Content-Type: application/json

{
  "event": "consulta.success",
  "timestamp": "2026-05-01T15:30:00Z",
  "consultaId": "cn_abc123",
  "sku": "COMBO-PREMIUM",
  "plate": "ABC1D23",
  "creditsConsumed": 9,
  "pdfUrl": "https://www.concar.com.br/api/consultas/cn_abc123/pdf"
}

Validação da assinatura HMAC

O header X-Signature é HMAC-SHA256 do body com sua webhookSecret (gerada no painel). Validar do seu lado:

// Node.js
const crypto = require('crypto');
const expected = 'sha256=' + crypto
  .createHmac('sha256', WEBHOOK_SECRET)
  .update(rawBody)
  .digest('hex');
if (expected !== request.headers['x-signature']) {
  return res.status(401).end();
}

Rate limits

  • Sandbox: 1 req/seg, 1.000 req/dia
  • Pro: 5 req/seg, 50.000 req/mês
  • Business: 10 req/seg, 200.000 req/mês
  • Enterprise: customizado por contrato

Excesso retorna 429 com header Retry-After: {seconds}.

Idempotência

Pra evitar consulta duplicada (importante quando seu worker roda retry após timeout), inclua header Idempotency-Key: {seu-uuid-único}. Se receber a mesma key dentro de 24h, retornamos a resposta cacheada sem cobrar créditos novamente.

Sandbox vs produção

Sandbox usa fixtures fixas (resposta determinística por placa de teste). Útil pra desenvolvimento sem consumir créditos reais. Placas teste: OQH3065, ABC1D23, BRA2E19. API key sandbox tem prefixo cp_test_.

Códigos de exemplo

Node.js (fetch)

const res = await fetch('https://www.concar.com.br/api/v1/consultas', {
  method: 'POST',
  headers: {
    'Authorization': 'Bearer ' + process.env.CP_API_KEY,
    'Content-Type': 'application/json',
    'Idempotency-Key': 'order-12345'
  },
  body: JSON.stringify({
    sku: 'COMBO-PREMIUM',
    plate: 'ABC1D23',
    purpose: 'pre_purchase_evaluation'
  })
});
const data = await res.json();

Python (requests)

import requests, os, uuid

resp = requests.post(
    'https://www.concar.com.br/api/v1/consultas',
    headers={
        'Authorization': f'Bearer {os.environ["CP_API_KEY"]}',
        'Idempotency-Key': str(uuid.uuid4())
    },
    json={'sku': 'COMBO-PREMIUM', 'plate': 'ABC1D23', 'purpose': 'pre_purchase_evaluation'},
    timeout=30
)
resp.raise_for_status()
data = resp.json()

PHP (Guzzle)

$client = new GuzzleHttp\Client();
$response = $client->post('https://www.concar.com.br/api/v1/consultas', [
    'headers' => [
        'Authorization' => 'Bearer ' . getenv('CP_API_KEY'),
        'Idempotency-Key' => Ramsey\Uuid\Uuid::uuid4()->toString()
    ],
    'json' => ['sku' => 'COMBO-PREMIUM', 'plate' => 'ABC1D23', 'purpose' => 'pre_purchase_evaluation']
]);
$data = json_decode($response->getBody(), true);

Suporte técnico

Dúvidas técnicas: [email protected](resposta <24h em dias úteis pra Pro+, <4h pra Business+, <1h pra Enterprise).

Status page: incidentes e manutenção planejada são publicados em status.www.concar.com.br (em construção pré-launch).