Um guia de implementação escrito com base no comportamento documentado da API; não cita nenhum cliente. Publicado em .
O problema: o registro cita um carro que ninguém consegue ver
Um formulário de cotação, um registro de apólice e um aviso de sinistro identificam o veículo da mesma forma: pelo VIN, digitado pelo cliente ou lido em um documento de registro. Tudo o que uma pessoa vê depois sobre o carro é texto: um ano, uma marca, um modelo e talvez uma versão. Perguntar "este é o seu veículo?" ao lado de uma linha de texto convida a um sim para qualquer coisa.
Uma imagem do modelo para o qual o VIN decodifica permite que o cliente e o perito confirmem num relance que o registro indica o tipo certo de carro. Ela não consegue mostrar qual carro: um render é uma ilustração de estúdio de uma marca, modelo e ano do catálogo e não retrata nenhum veículo físico específico. Esse único fato define toda a integração abaixo.
Como fica a integração
- Decodifique na entrada. O fluxo de cotação ou o sistema de apólices decodifica o VIN uma vez, gratuitamente, e armazena o id de veículo do catálogo junto com a apólice. Os sinistros abertos na apólice o herdam.
- Uma só vista em todo lugar.
front-3-4, o ângulo principal, em um mesmo quadro na tela de cotação, na bancada de sinistros, no PDF da cotação e no portal da apólice, para que todas as telas mostrem o modelo da mesma forma. - URLs assinadas, nunca a chave. Navegadores e geradores de PDF carregam URLs sem chave que o seu servidor gera.
- Palavras para o que uma imagem não consegue dizer. Versão, opcionais, a cor registrada, danos e quilometragem continuam em texto e fotos, e a imagem informa que é meramente ilustrativa.
Etapa 1: decodifique o VIN de graça
GET /api/v1/vin/{vin} não custa nada e exige uma chave com images:read. Ele retorna os campos decodificados dos dados do vPIC da NHTSA (ano, marca, modelo, versão, série, tipo de carroceria, motor e todos os outros atributos que o vPIC conhece) e, quando o catálogo tem o veículo, um objeto vehicle com seu id estável e um image_path pronto.
curl --fail-with-body \
-H "Authorization: Bearer $CAR_IMAGE_API_KEY" \
"https://carimage.dev/api/v1/vin/WP0AA2A96RS201834"{
"data": {
"vin": "WP0AA2A96RS201834",
"valid": true,
"errors": [],
"suggested_vin": null,
"year": 2024,
"make": "Porsche",
"model": "911",
"trim": "Carrera, Carrera T, Carrera 4",
"series": "Type 992",
"body_class": "Coupe",
"vehicle": {
"id": "veh_78qtwrgh37bkr",
"make": "Porsche",
"model": "911",
"year": 2024,
"image_path": "/api/v1/images/car?vehicle=veh_78qtwrgh37bkr"
},
"source": "vpic-db"
}
}Leia o trim: "Carrera, Carrera T, Carrera 4". O padrão deste VIN abrange três versões, então nem a decodificação consegue dizer qual delas a apólice segura, e muito menos uma renderização do 911 2024. Peça ao cliente que confirme a versão, guarde-a junto com series e body_class como texto e deixe a imagem mostrar o modelo.
- Um VIN com dígito verificador incorreto ainda é decodificado, com
valid: falsee o problema emerrors;suggested_vinmarca com!o caractere que o vPIC considera errado, e é isso que você deve mostrar a quem está digitando. - Um formulário que tenha apenas os primeiros caracteres pode enviar um VIN parcial: pelo menos cinco caracteres, com
*para cada posição desconhecida e umyearopcional. - Um
404significa que o vPIC não tem registro desse padrão. O vPIC cobre veículos fabricados para o mercado dos EUA; para outros mercados, comece pela marca e pelo modelo comPOST /api/v1/images/resolve, que também é gratuito.
Passo 2: mantenha o ID do veículo na apólice e no sinistro
Armazene data.vehicle.id na apólice como uma string simples e copie-o para cada sinistro aberto contra ela. O id é determinístico e permanente: o mesmo veículo tem o mesmo id em cada deploy e após cada nova versão do catálogo, por isso é seguro usá-lo como chave estrangeira, e cada requisição posterior informa vehicle=veh_78qtwrgh37bkr em vez de escrever a marca e o modelo.
Quando data.vehicle é null, a marca e o modelo decodificados não estão no catálogo, como acontece com reboques e alguns chassis comerciais. Os campos decodificados continuam disponíveis para você exibir. Exiba-os sem imagem e nunca coloque um carro parecido no lugar.
Etapa 3: uma vista no processo de sinistro e no PDF da cotação
A tela de cotação, a bancada de sinistros e o portal de apólices são aplicativos de navegador, então seu servidor gera URLs assinadas com POST /api/v1/image-urls: 1 crédito por URL no momento em que ela é gerada, até 50 por chamada, e o carregamento é gratuito até ela expirar. Enquadre a imagem uma vez e reutilize o formato: front-3-4 em uma caixa de 640×400 com fit: "contain", e trim com um pouco de padding para que um cupê e uma picape preencham a caixa da mesma forma. Quanto tempo cada URL deve durar depende de onde ela é exibida:
- A bancada de sinistros. Gere a URL quando a tela for renderizada. A validade padrão de 1 hora cobre uma sessão de trabalho, e um sinistro reaberto amanhã recebe uma nova URL.
- O PDF da cotação. Quando o PDF é gerado a partir de HTML, o renderizador carrega a imagem uma vez e a incorpora, então o tempo de validade padrão é mais do que suficiente, e o serviço de PDF nunca tem acesso à sua chave.
format: "jpg"aplica a imagem sobre um fundo branco, que é o que um documento pede. - O portal da apólice e o e-mail de renovação. Eles duram mais do que qualquer tempo de validade, então emita com
renew: trueettl_seconds: 604800(7 dias). A URL continua funcionando, cada semana adicional em que ela é aberta custa 1 crédito, erenew_days: 365, o máximo permitido, cobre a vigência de uma apólice de um ano.
Configure no painel uma lista de origens permitidas para a chave que gera as URLs: uma URL carregada de outro site responde 403 com origin_not_allowed, enquanto clientes de e-mail e visualizadores de PDF, que não enviam Referer, continuam carregando-a. Revogar a chave invalida todas as URLs que ela gerou.
import { CarImageClient, type ImageParams } from "@meterapp/car-image-sdk";
const client = new CarImageClient({ apiKey: process.env.CAR_IMAGE_API_KEY });
// Quote or policy intake: the VIN in, the vehicle id and the decoded words on the record. Free.
const { data: decoded } = await client.decodeVin(policy.vin);
policy.vehicleId = decoded.vehicle?.id ?? null; // null: show the decoded text and no picture
policy.trimText = decoded.trim; // "Carrera, Carrera T, Carrera 4": words, never the picture
if (policy.vehicleId) {
// One view, framed once, for every screen and document that shows this policy's car.
const view: ImageParams = {
vehicle: policy.vehicleId, view: "front-3-4", color: policy.paintHex ?? "silver",
width: 640, height: 400, fit: "contain", trim: true, padding: 6,
};
// The claims workbench: a URL for this session, minted when the screen draws.
const { data: [workbench] } = await client.createImageUrls({ ...view, format: "auto" });
// The quote PDF: the HTML-to-PDF renderer loads the URL once and embeds the picture.
const { data: [pdf] } = await client.createImageUrls({ ...view, format: "jpg" });
// The policy portal and the renewal email: one URL that keeps working for the term.
const { data: [portal] } = await client.createImageUrls(
{ ...view, format: "auto" },
{ ttlSeconds: 604800, renew: true, renewDays: 365, idempotencyKey: `policy:${policy.id}:image` }
);
}Etapa 4: identifique como o modelo, nunca como o carro segurado
Coloque o aviso onde está a imagem, não apenas em uma nota de rodapé: no texto alternativo e em uma legenda abaixo da imagem. A renderização mostra a marca, o modelo e o ano em uma pintura que você escolhe, e color pode seguir a cor informada na apólice (um nome de cor predefinida ou qualquer hex). Ainda assim, é o modelo nessa pintura, não o carro do cliente.
<figure>
<img src="https://carimage.dev/api/v1/delivery/eyJhbGciOi…" width="640" height="400"
alt="Representative image of a 2024 Porsche 911, not a photo of the insured vehicle">
<figcaption>
2024 Porsche 911 · Coupe · Type 992 · trim on the VIN: Carrera, Carrera T or Carrera 4
<small>Representative image of the model. Not a photo of the insured vehicle.</small>
</figcaption>
</figure>Quanto custa e qual plano escolher
- Gratuito: a decodificação de VIN, o resolve, as consultas ao catálogo e todo carregamento de uma URL assinada dentro da sua validade.
- 1 crédito: cada imagem entregue ao seu servidor ou cada URL gerada, e cada semana adicional em que uma URL renovável é aberta.
- Veículos distintos: um funil de cotação recebe muitos veículos diferentes, e cada plano limita os veículos distintos por mês: Free 100, Pro 2.500 e Business 15.000; Enterprise não tem limite. Um veículo já atendido neste mês é sempre permitido, e uma solicitação acima do limite é recusada antes de qualquer cobrança; portanto, dimensione o plano pelos veículos que você cota, não pelos créditos.
Em um plano pago, a licença cobre uma renderização dentro do que o seu produto gera para os usuários dele, incluindo uma cotação ou um relatório, enquanto o plano estiver ativo; os detalhes estão na licença.
CLI, SDK e MCP
# decode for free and keep the id
npx @meterapp/car-image vin WP0AA2A96RS201834 --json | jq -r .data.vehicle.id
# one renewing URL for the policy's documents, minted once however often intake retries
npx @meterapp/car-image url --vehicle veh_78qtwrgh37bkr --view front-3-4 --width 640 --height 400 \
--fit contain --trim --padding 6 --format auto --ttl 604800 --renew --renew-days 365 \
--idempotency-key policy-88213-image- SDK:
client.decodeVin(vin, { year? })eclient.createImageUrls(…), como acima;client.resolve(query)para um veículo sem VIN. - MCP:
decode_vinecreate_car_image_urlsfazem parte do conjunto principal de ferramentas, então um assistente com o sinistro no contexto pode responder "mostre o modelo segurado" a partir do VIN registrado. A configuração está na página do MCP.
Perguntas frequentes
- A imagem pode substituir as fotos do veículo segurado?
- Não. É uma renderização de estúdio da marca, do modelo e do ano do catálogo, não uma fotografia, e não retrata nenhum veículo específico. Ela ajuda o cliente ou o regulador de sinistros a ver que o registro identifica o tipo certo de carro. Estado de conservação, danos, versão, opcionais e modificações vêm de fotos, vistorias e do texto decodificado, e a imagem deve informar que é ilustrativa.
- Quanto custa ter uma imagem em cada cotação?
- A decodificação do VIN é gratuita. A imagem custa 1 crédito quando sua URL assinada é gerada ou quando seus bytes são entregues ao seu servidor; carregar uma URL assinada é gratuito até ela expirar. Uma URL renovável custa 1 crédito a mais para cada semana em que é aberta, e nada nas semanas em que ninguém a visualiza.
- O VIN é decodificado, mas vehicle vem null. E agora?
- O decodificador reconheceu o veículo, mas o catálogo não tem uma entrada para essa marca, modelo e ano, o que acontece com reboques e alguns chassis comerciais. Mostre os campos decodificados sem imagem e nunca substitua por um carro parecido. Pesquise no catálogo, caso a grafia seja diferente, e, se o veículo realmente não estiver lá, solicite-o no quadro público de pedidos.
- A decodificação de VIN funciona para veículos de fora do mercado dos EUA?
- O decodificador usa os dados do vPIC da NHTSA, que cobrem veículos fabricados para o mercado dos EUA, então um VIN digitado corretamente de outro mercado pode retornar 404 ou ser decodificado sem modelo. Nesse caso, encontre o carro por marca, modelo e ano com o endpoint gratuito de resolve; o próprio catálogo cobre os modelos de outros mercados.
- Por quanto tempo um processo de sinistro pode manter a imagem?
- Enquanto o arquivo existir. Em um plano pago, a licença cobre um render dentro do que o seu produto gera, incluindo uma cotação ou um relatório, e um render entregue durante o plano mantém essa licença depois que o plano termina, inclusive em documentos armazenados. Os renders também podem ser aprimorados com o tempo, então um registro que precisa guardar exatamente o que o cliente viu deve armazenar o arquivo, e não uma URL.