Vấn đề: bản ghi có VIN nhiều tháng trước khi có ảnh
Một bản ghi xe tồn kho trong CRM, ERP hay hệ thống quản lý đại lý (DMS) ban đầu chỉ có số VIN, mã tồn kho và giá. Ảnh chỉ có khi thợ chụp ảnh của bãi xe đến, và với một số xe thì không bao giờ có: xe đang trên đường vận chuyển, xe thu đổi còn đang được tân trang, xe nhập khẩu có tên mẫu không khớp với bất kỳ mục nào trong nguồn ảnh của DMS, hay một chiếc xe thập niên 1990 mà chẳng ai mua bản quyền ảnh báo chí. Mọi màn hình hiển thị bản ghi đó, từ danh sách của nhân viên bán hàng, phiếu định giá của người thu mua đến báo giá cho khách hàng, đều hiện một ô giữ chỗ màu xám.
Các công cụ cho đại lý và nhập khẩu xe trên API điền vào chỗ trống đó từ dữ liệu bản ghi đã có. Nếu có VIN, ảnh chỉ cách một lần giải mã miễn phí. Nếu chỉ có một dòng trong bảng kê kho xe, tính năng resolve văn bản tự do sẽ tìm ra. Dù bằng cách nào, bản ghi cuối cùng cũng lưu một vehicle id ổn định, và mọi màn hình đều render cùng một chiếc xe theo cùng một cách.
Một tích hợp cho đại lý trông như thế nào
- Giải mã khi tiếp nhận. VIN được giải mã một lần, khi tạo bản ghi, và vehicle id trong danh mục được lưu ngay bên cạnh. Không khâu nào phía sau phải viết tên hãng hay mẫu xe.
- Một góc cho danh sách, một góc cho trang chi tiết. Góc
sidethẳng trong khung rộng cho danh sách xe tồn kho;front-3-4cho trang chi tiết và báo giá. - Trải dài nhiều năm. Xe nhập khẩu và xe đã qua sử dụng có thể từ những năm 1990, và chúng được render giống như xe mới về: danh mục trải dài từ 1990 đến năm mẫu xe hiện tại, bao gồm cả các dòng xe nội địa Nhật Bản.
- URL đã ký ngay trong ứng dụng. CRM chạy trên trình duyệt, nên nó tải các URL đã ký không chứa khóa do máy chủ tạo, tối đa năm mươi URL mỗi lần gọi, và gia hạn cho những bản ghi tồn tại lâu hơn một tuần.
Bước 1: giải mã VIN, miễn phí
GET /api/v1/vin/{vin} hoàn toàn miễn phí và chỉ cần một API key. Nó trả về năm, hãng, mẫu xe, phiên bản, kiểu thân xe, động cơ đã giải mã và mọi thuộc tính khác có trong dữ liệu vPIC của NHTSA, và khi danh mục có chiếc xe đó, thêm một đối tượng vehicle với id ổn định và một image_path sẵn dùng. VIN không đầy đủ cũng được: tối thiểu năm ký tự, * cho mỗi vị trí chưa biết, kèm gợi ý year tùy chọn.
curl -s -H "Authorization: Bearer $CAR_IMAGE_API_KEY" \
"https://carimage.dev/api/v1/vin/1HGCM82633A004352"{
"data": {
"vin": "1HGCM82633A004352",
"valid": true,
"year": 2003,
"make": "Honda",
"model": "Accord",
"trim": "EX-V6",
"body_class": "Coupe",
"vehicle": {
"id": "veh_3qfyk22gfhsx3",
"make": "Honda",
"model": "Accord",
"year": 2003,
"image_path": "/api/v1/images/car?vehicle=veh_3qfyk22gfhsx3"
}
},
"request_id": "req_01j9x…"
}trim và body_class dưới dạng văn bản trong bản ghi và hiển thị chúng cạnh hình ảnh, thay vì khẳng định rằng hình ảnh thể hiện chúng. VIN có lỗi chữ số kiểm tra vẫn được giải mã, với valid: false và lỗi được liệt kê, nên một bảng kê tồn kho bị gõ sai không phải là ngõ cụt.Bước 1b: khi chỉ có một dòng trong bảng kê xe tồn kho
Dữ liệu xe nhập khẩu thường được gửi đến dưới dạng bảng tính: năm, hãng, tên mẫu xe theo bất kỳ cách viết nào mà nhà đấu giá dùng, cùng mã cấp độ hoặc phiên bản. POST /api/v1/images/resolve miễn phí và cho kết quả nhất quán: endpoint này tách các từ chỉ năm, màu và góc nhìn ra khỏi cụm từ, tìm trong danh mục bằng phần còn lại, rồi trả về tham số chính xác kèm mức độ tin cậy để quý vị dựa vào đó xử lý.
curl -s -X POST https://carimage.dev/api/v1/images/resolve \
-H "Authorization: Bearer $CAR_IMAGE_API_KEY" \
-H "Content-Type: application/json" \
-d '{"query": "2019 toyota voxy zs side"}'{
"data": {
"params": {
"vehicle_id": "veh_9w0nvw7jphp6r",
"make": "toyota",
"model": "voxy",
"year": 2019,
"view": "side",
"color": "silver"
},
"display": {
"make_name": "TOYOTA",
"model_name": "VOXY"
},
"confidence": "low",
"image_path": "/api/v1/images/car?make=toyota&model=voxy&year=2019&view=side&color=silver"
},
"request_id": "req_01j9x…"
}Xe được xác định đúng (Toyota Voxy 2019) nhưng độ tin cậy là low, vì "ZS" là một cấp phiên bản mà danh mục không biết nên phải so khớp vòng qua nó. Khi nhập hàng loạt, hãy coi high là xong, còn medium và low thì chuyển cho người kiểm tra kèm danh sách candidates. Khi bảng kê đã có năm và hãng xe ở các cột riêng, hãy gửi chúng qua các trường year và make và chỉ để mẫu xe trong query; kết quả khớp sẽ chính xác hơn nhiều. Một cụm từ không chứa từ nào liên quan đến xe sẽ trả về 400, và một hãng xe không có mẫu nào khớp sẽ trả về 404 kèm danh sách các năm của hãng đó để bạn có thể hỏi lại mẫu xe.
Bước 2: lưu id xe vào bản ghi
Dù đi theo cách nào, hãy lưu vehicle.id (hoặc params.vehicle_id) vào bản ghi hàng tồn kho dưới dạng một cột chuỗi thông thường. Giá trị này mang tính xác định và vĩnh viễn: cùng một xe luôn có cùng id ở mọi lần triển khai và sau mọi bản phát hành danh mục, nên có thể dùng an toàn làm khóa ngoại. Từ đó trở đi, mọi yêu cầu hình ảnh đều là vehicle=veh_…, không thể viết sai chính tả, và việc một hãng xe bị nhà sản xuất đổi tên hay bị một nguồn phân loại lại sẽ không bao giờ làm hỏng URL đã lưu.
Bước 3: một góc nhìn cho trang danh sách, một góc nhìn cho trang chi tiết
Danh sách hàng tồn kho thường rộng và thấp, nên góc nhìn ngang thẳng trong khung 2:1 là lựa chọn phổ biến: mọi xe đều quay cùng một hướng và nằm trên cùng một đường nền. trim=1&padding=6 cắt sát theo xe trước khi căn khung, nên một chiếc Hilux và một chiếc Yaris lấp đầy hàng theo cùng một cách; fit=contain giữ khung ảnh đúng 640×320 với lề trong suốt. Trang chi tiết dùng front-3-4 ở 1024, và cả hai dùng chung bộ nhớ đệm: màu sơn bạn không chỉ định sẽ là màu bạc ở cả hai nơi.
curl --fail-with-body -H "Authorization: Bearer $CAR_IMAGE_API_KEY" \
"https://carimage.dev/api/v1/images/car?vehicle=veh_3qfyk22gfhsx3&view=side&w=640&h=320&fit=contain&trim=1&padding=6&format=webp" \
-o stock-4471.webpBước 4: hiển thị trong CRM qua signed URL
CRM chạy trên trình duyệt, và trình duyệt tuyệt đối không được giữ khóa API. Khi một màn hình liệt kê một trang xe tồn kho, máy chủ sẽ tạo một URL có chữ ký cho mỗi bản ghi bằng POST /api/v1/image-urls (tối đa năm mươi URL mỗi lần gọi; ảnh của mỗi URL được tính là một ảnh xe của tháng) và trang tải chúng như mọi ảnh khác. Có hai thiết lập quan trọng đối với bản ghi nằm trong kho nhiều tháng:
ttl_seconds: 604800vớirenew: true: URL vẫn hoạt động sau TTL bảy ngày, và mỗi lần gia hạn tính hình ảnh một lần trong tháng diễn ra gia hạn, không tính thêm nếu hình đã được tính trong tháng đó. Những tháng không ai xem xe thì không tính gì.- Mỗi trang đồng bộ dùng một
Idempotency-Key: yêu cầu được thử lại sẽ phát lại phản hồi đầu tiên và không tạo trùng bất cứ thứ gì.
Giới hạn khóa tạo URL ở origin của CRM trên bảng điều khiển, khi đó URL bị lộ sang trang khác sẽ trả về 403. Thu hồi khóa sẽ vô hiệu hóa mọi URL mà khóa đó đã tạo. Nếu hình ảnh xe của gói trong tháng đã dùng hết, lượt gia hạn sẽ trả về 402 và cùng URL đó sẽ hoạt động trở lại khi hạn mức được đặt lại hoặc gói được nâng cấp. Toàn bộ vòng đời có trong tài liệu về URL có chữ ký.
import { CarImageClient } from "@meterapp/car-image-sdk";
const client = new CarImageClient({ apiKey: process.env.CAR_IMAGE_API_KEY });
// On intake: VIN in, vehicle id on the record. Free.
const { data: decoded } = await client.decodeVin(stock.vin);
if (decoded.vehicle) {
stock.vehicleId = decoded.vehicle.id; // veh_…, permanent; the record never spells a car again
stock.trim = decoded.trim; // shown next to the image, never claimed by it
}
// When the CRM draws the stock list: one signed URL per record, up to fifty per call.
// The browser loads them; the key never leaves the server.
const { data: urls } = await client.createImageUrls(
page.map((row) => ({
vehicle: row.vehicleId, view: "side",
width: 640, height: 320, fit: "contain", trim: true, padding: 6, format: "auto",
})),
{ ttlSeconds: 604_800, renew: true, renewDays: 365, idempotencyKey: `stock-list:${syncRunId}:${pageIndex}` }
);CLI, SDK và MCP
# decode for free; the output names the vehicle id and a ready-to-run image command
npx @meterapp/car-image vin 1HGCM82633A004352
npx @meterapp/car-image vin 1HGCM82633A004352 --json | jq -r .data.vehicle.id
# a partial VIN from a faded door sticker: at least five characters, * for each unknown position
npx @meterapp/car-image vin "1HGCM826*3A" --year 2003
# the list image for one record
npx @meterapp/car-image get --vehicle veh_3qfyk22gfhsx3 --view side --width 640 --height 320 --fit contain --trim --padding 6 --format webp --out stock-4471.webp- SDK:
client.decodeVin(vin, { year? }),client.resolve(query),client.getImage({ vehicle, … })vàclient.createImageUrls(…), như trên. - MCP:
decode_vin,resolve_vehicle,get_car_imagevàcreate_car_image_urlsnằm trong bộ công cụ cốt lõi, nên một trợ lý có sẵn hệ thống hàng tồn kho trong ngữ cảnh có thể trả lời "ảnh cho xe tồn kho 4471" từ số VIN trong hồ sơ. Hướng dẫn thiết lập có trên trang MCP; các trường và lỗi của bộ giải mã có trong tài liệu VIN.
Câu hỏi thường gặp
- Chi phí để có ảnh cho mọi bản ghi xe tồn kho là bao nhiêu?
- Giải mã VIN là miễn phí. Mỗi xe ở mỗi màu sơn và góc nhìn là một hình ảnh xe, được tính một lần mỗi tháng dù hiển thị bao nhiêu lần và ở bất kỳ kích thước nào; kiểm tra lại bằng If-None-Match là miễn phí. URL đã ký tính hình ảnh khi được tạo và, với renew: true, tính thêm một lần trong mỗi tháng sau đó mà URL được mở. Một tập đoàn đại lý có vài nghìn xe trong kho sẽ hiển thị vài nghìn hình ảnh xe mỗi tháng, vì vậy hãy chọn gói theo số xe đang được trưng bày.
- VIN giải mã được nhưng vehicle là null. Giờ phải làm sao?
- Bộ giải mã đã biết hãng, mẫu xe và năm nhưng danh mục không có mục nào cho tổ hợp đó: rơ-moóc, một số khung gầm xe thương mại, hoặc một tên mẫu xe mà các nguồn chưa ghi nhận. Hãy hiển thị các trường đã giải mã, tìm trong danh mục bằng GET /api/v1/vehicles?q= phòng khi cách viết khác, và yêu cầu bổ sung xe trên bảng yêu cầu; POST /api/v1/requests sẽ bình chọn cho yêu cầu đang mở thay vì tạo bản trùng lặp.
- Giải mã VIN có hỗ trợ xe nhập khẩu và xe chưa từng bán tại Mỹ không?
- Bộ giải mã dùng dữ liệu vPIC của NHTSA, nên VIN của nhà sản xuất có đăng ký với NHTSA sẽ được giải mã đầy đủ. Xe chưa từng được chứng nhận cho thị trường Mỹ thường chỉ giải mã ra nhà sản xuất và năm mà không có mẫu xe, và một số xe hoàn toàn không giải mã được. Với những xe đó, hãy xác định xe từ giấy đăng ký: bản thân danh mục bao phủ toàn cầu, từ năm 1990, và có cả các mẫu xe dành cho thị trường nội địa Nhật như Toyota Voxy.
- Ảnh render có thể hiện phiên bản (trim) ghi trong bản ghi không?
- Không. Danh mục được xác định theo hãng, mẫu xe và năm, nên một chiếc coupe EX-V6 và một chiếc sedan LX đều được render thành cùng một chiếc Accord 2003. Hãy giữ trim và body_class từ kết quả giải mã dưới dạng văn bản cạnh hình ảnh, và tuyệt đối không mô tả ảnh render là chính chiếc xe cụ thể đó.
- Website của đại lý có dùng được chính các URL giống như CRM không?
- Hãy tạo chúng từ một khóa có danh sách nguồn được phép (allowed origins) bao gồm trang web, khi đó URL nào được trình duyệt tải từ bất kỳ trang nào khác sẽ trả về 403 origin_not_allowed. Các lượt tải không có Referer, chẳng hạn từ ứng dụng email, vẫn được chấp nhận. CRM và trang web có thể dùng chung một khóa và một bộ URL, hoặc mỗi bên dùng một khóa riêng để có thể thu hồi riêng từng bên.