Car Image API

활용 사례 · 경매

경매 매물용 자동차 이미지

사진이 도착하기 전에 경매 로트를 게시하세요. 각 로트에는 해당 모델 연식의 스튜디오 이미지를 카탈로그 렌더링임을 표시해 넣고, 경매와 함께 만료되는 서명된 URL로 제공합니다.

API의 문서화된 동작을 바탕으로 작성된 구축 가이드이며, 특정 고객을 언급하지 않습니다. 게시.

문제: 사진보다 경매가 먼저 시작됩니다

경매 카탈로그는 위탁 차량이 모이는 즉시 게시되며, 차량마다 VIN, 로트 번호, 경매 일자가 표시됩니다. 사진은 차량이 야드에 도착하고 사진작가가 그 차량을 촬영한 뒤에야 나오는데, 경매 차량 중 일부는 입찰이 시작된 이후가 됩니다. 그때까지 해당 로트는 텍스트 한 줄 옆의 회색 상자로만 남습니다.

카탈로그 렌더는 올바른 연식으로 빈자리를 채워 줍니다. 하지만 경매는 렌더가 실제 차량으로 오인되어서는 절대 안 되는 곳이기도 합니다. 입찰자는 차량 상태를 보고 가격을 매기는데, 렌더는 특정 실물 차량을 묘사하지 않으므로 상태를 전혀 보여 주지 않습니다. 아래 내용은 모두 이 두 가지를 동시에 고려한 결과입니다.

연동 구조 한눈에 보기

  • VIN으로 매물별 렌더를 생성하고, 매물 자체 사진이 도착할 때까지만 표시합니다.
  • 카탈로그 선택기: VIN이 디코딩되지 않는 출품 차량용.
  • 이미지 위 라벨: "카탈로그 렌더 이미지, 실제 출품 차량 아님".
  • Idempotency-Key로 출품 차량당 URL을 한 번만 발급하며, 이 URL은 경매가 끝날 때까지 유지됩니다.

1단계: 출품 차량의 VIN에서 차량 ID 얻기

GET /api/v1/vin/{vin}는 무료입니다. 카탈로그에 해당 차량이 있으면 응답에 매물에 저장할 고정 ID인 data.vehicle.id가 포함되며, 디코딩된 트림, 차체, 엔진 정보는 매물 텍스트에 둡니다. 카탈로그는 1990년부터 2027년까지를 포괄하므로 경매의 오래된 재고도 최신 차량처럼 렌더링됩니다. 보험 가이드에서 디코딩 결과를 필드별로 살펴볼 수 있으며, VIN 문서에서 부분 VIN과 오류를 다룹니다.

입고 시 VIN 디코딩
# the lot's VIN to the vehicle id the lot stores (free); nothing printed means no catalog match
npx @meterapp/car-image vin "$LOT_VIN" --json | jq -r '.data.vehicle.id // empty'

2단계: 디코딩할 수 있는 VIN이 없나요? 카탈로그에서 차량을 선택하세요

일부 출품 차량은 디코딩되는 VIN 없이 들어옵니다. 다른 시장용으로 생산된 차량, 출처에서 잘못 입력한 VIN, 연식·제조사·모델 외에는 아무 정보도 없는 위탁 시트 등이 그렇습니다. 무료 공개 API인 GET /api/v1/vehicles로 채워지는 드롭다운 세 개를 위탁 양식에 추가하세요. ?year=는 해당 연식에 모델이 있는 제조사 목록을, ?year=&makeId=는 해당 제조사의 모델 목록을 각 모델 연식의 차량 id와 함께 반환합니다.

연식, 제조사, 모델 순서로 선택
# every make with a 2006 model year (free, public)
curl -s "https://carimage.dev/api/v1/vehicles?year=2006"
# {"data":{"year":2006,"makes":[…,{"id":476,"name":"DODGE","slug":"dodge"},…]},…}

# that make's 2006 models, each with the id of its 2006 model year
curl -s "https://carimage.dev/api/v1/vehicles?year=2006&makeId=476"
200 OK (일부 생략)
{
  "data": {
    "year": 2006,
    "make_id": 476,
    "models": [
      {
        "name": "Caliber",
        "slug": "caliber",
        "vehicle_type": "Passenger Car",
        "id": "veh_294vq81yq0d3y"
      },
      {
        "name": "Charger",
        "slug": "charger",
        "vehicle_type": "Passenger Car",
        "id": "veh_96j8z47jqfd4r"
      },
      "…"
    ]
  }
}

같은 카탈로그가 오픈 @meterapp/vehicle-db 패키지로 공개되어 있으므로, 드롭다운을 동일한 목록으로 오프라인에서도 실행할 수 있습니다. 어느 방식이든 출품 차량에는 디코딩된 VIN과 같은 종류의 ID가 저장되며, 이후 단계에서 차량 이름을 직접 문자열로 다루는 곳은 없습니다.

위탁 목록 전체가 한 번에 들어오면 POST /api/v1/vehicles/check가 호출당 최대 2,000개 항목을 읽습니다. 각 항목을 목록에 적힌 그대로 보내고 출품 번호를 ref로 지정하면, 모든 항목에 대해 저장할 id가 포함된 일치, 제안, 불일치 또는 잘못된 행으로 응답합니다. 렌더링도 과금도 발생하지 않으며, 자세한 내용은 vehicles 문서를 참조하세요.

3단계: 렌더 이미지임을 표시하기

라벨은 아래 설명란에만 넣지 말고, 입찰자의 시선이 닿는 이미지 자체와 대체 텍스트에도 넣으세요. 차량 상태, 주행거리, 손상, 옵션, 실제 차량의 도장 색상은 출품 설명에, 그리고 사진이 준비되면 사진에 담아야 합니다. 사진이 도착하면 렌더링 이미지는 내립니다.

실사진이 도착하기 전까지 사용할 출품 차량 이미지
<figure class="lot-image">
  <img src="https://carimage.dev/api/v1/delivery/eyJhbGciOi…" width="800" height="450"
       alt="Catalog render of a 2006 Dodge Charger, not a photo of lot 117">
  <span class="lot-image__badge">Catalog render, not this lot</span>
</figure>
<p>Photos of this lot are on their way. Condition, mileage and damage are in the report.</p>

4단계: 로트당 URL 하나, 한 번만 발급

출품 접수 시 POST /api/v1/image-urls와 경매 및 출품 건으로 만든 Idempotency-Key로 해당 출품 건의 URL을 발급하세요. 키에는 문자, 숫자, ., _, :, -를 사용할 수 있습니다. URL은 발급될 때 해당 이미지를 이번 달 차량 이미지로 집계하므로, 키가 없으면 접수를 재시도할 때 두 번째 URL이 발급됩니다. 키를 사용하면 다음과 같습니다:

  • 같은 키와 같은 본문으로 24시간 이내에 다시 요청하면 동일한 URL을 포함한 첫 번째 응답이 Idempotent-Replayed: true와 함께 그대로 반환되며, 요금은 다시 청구되지 않습니다.
  • 같은 키에 다른 본문을 보내면 422가 되고, 첫 요청보다 먼저 처리된 재시도는 Retry-After와 함께 409가 됩니다. 따라서 매물을 생성할 때 유효 기간을 포함한 본문 전체를 확정하고 매물과 함께 저장하세요.
  • URL도 출품 차량 레코드에 저장하세요. 키는 재시도를 안전하게 보호하고, 저장된 URL은 경매가 끝날 때까지 페이지에서 읽어 오는 값입니다.

카탈로그 전체를 한 번에 가져올 때는 호출당 최대 50개 출품 차량의 URL을 발급할 수 있으며, 배치마다 키를 하나씩 사용합니다. 응답의 각 URL에는 해당 URL이 발급된 차량과 옵션이 함께 표시됩니다.

출품 번호 117의 URL
curl --fail-with-body -X POST https://carimage.dev/api/v1/image-urls \
  -H "Authorization: Bearer $CAR_IMAGE_API_KEY" \
  -H "Content-Type: application/json" \
  -H "Idempotency-Key: sale-2026-10-14:lot-117" \
  -d '{"images":[{"vehicle":"veh_96j8z47jqfd4r","view":"side","width":800,"height":450,"fit":"contain","trim":true,"padding":6,"format":"auto"}],"ttl_seconds":259200}'
# run it again: the same URL comes back with Idempotent-Replayed: true, and nothing more is charged

5단계: URL 유효 기간을 경매 일정에 맞추기

ttl_seconds는 최대 604800(7일)까지 설정할 수 있으며, 더 긴 값은 이 값으로 제한됩니다. 일주일 안에 마감되는 경매라면 마감까지 남은 시간으로 설정하세요. 그러면 입찰이 끝날 때 이미지도 작동을 멈추고, 이후 URL은 403을 반환합니다.

  • 7일보다 긴 기간 한정 경매: renew: true, 최대값의 ttl_seconds, 경매 기간을 포괄하는 renew_days로 발급하세요. 갱신 시 갱신이 이루어진 달에 이미지가 한 번 집계되며 그달에 이미 집계되었다면 추가로 집계되지 않습니다. 아무도 출품 차량을 열지 않은 주에는 집계되지 않으며, 갱신은 renews_until에서 중단됩니다.
  • max_uses는 기본값인 0으로 두세요. 무제한 URL은 유효 기간 동안 공개 캐시가 가능하지만, 사용 횟수가 제한된 URL은 private, no-store로 처리되어 모든 로드가 오리진 서버로 전달됩니다.
  • 대시보드에서 발급용 키를 경매 사이트 도메인으로 제한하세요. 다른 사이트에 복사된 출품 차량 이미지는 403을 반환합니다.
TypeScript SDK로 출품 차량 등록하기
import { CarImageClient, type ImageParams } from "@meterapp/car-image-sdk";

const client = new CarImageClient({ apiKey: process.env.CAR_IMAGE_API_KEY });

const lotImage = (vehicle: string): ImageParams => ({
  vehicle, view: "side", width: 800, height: 450, fit: "contain", trim: true, padding: 6, format: "auto",
});

// How long the lot's URL lives, decided once from the sale's close.
function lifetime(closesAt: Date) {
  const seconds = secondsUntil(closesAt);
  return seconds <= 604800
    ? { ttlSeconds: Math.max(seconds, 60) } // closes within the week
    : { ttlSeconds: 604800, renew: true, renewDays: Math.min(daysUntil(closesAt), 365) }; // a longer timed sale
}

// At intake, once per lot. The lifetime is stored with the lot, so a retry sends
// the same body and replays the first answer instead of minting a second URL.
lot.imageLifetime ??= lifetime(sale.closesAt);
const { data: [placeholder] } = await client.createImageUrls(lotImage(lot.vehicleId), {
  ...lot.imageLifetime,
  idempotencyKey: `${sale.id}:lot-${lot.number}`,
});
lot.placeholderUrl = placeholder.url; // replaced by the lot's own photos when they arrive

경매 규모에 맞춰 플랜 정하기

각 출품 차량은 하나의 차량 이미지(해당 차량의 도색과 뷰)이며, 두 출품 차량이 세 가지가 모두 같은 경우는 예외입니다. 각 요금제에는 월별 차량 이미지 수가 포함됩니다: Free 100개, Pro 2,500개, Business 10,000개이며 Enterprise는 협의로 정해집니다. 이번 달에 이미 집계된 이미지는 항상 제공되며, 한도를 초과하는 배치는 집계 전에 전체가 거부되고 응답에 요금제와 한도가 포함됩니다. 한 달에 등록하는 출품 차량 수에 맞춰 요금제를 선택하세요. 마켓플레이스 사례에서 요청 및 렌더 한도 내에서 대규모 가져오기 속도를 조절하는 방법을 다룹니다.

자주 묻는 질문

출품 차량의 사진이 도착한 후에도 렌더를 계속 게시할 수 있나요?
교체하세요. 렌더는 해당 모델 연식을 대신하는 임시 이미지이므로, 입찰자가 어떤 사진이 판매 중인 차량인지 헷갈리는 일이 없어야 합니다. 페이지에 참고용으로 남겨 둔다면 라벨도 함께 표시하세요.
경매가 끝난 후 URL은 어떻게 되나요?
유효 기간이 끝나거나, 갱신형 URL의 경우 갱신 기간이 끝나면 만료되며 이후에는 403을 반환합니다. 그 시점에는 로트에 자체 사진이나 낙찰 결과가 있을 것이며, 경매 아카이브에는 실제 사진을 표시해야 합니다. URL을 발급한 키를 폐기하면 모든 URL이 한 번에 만료됩니다.
재시도 요청에 422가 반환되었습니다. 이유가 무엇인가요?
동일한 Idempotency-Key가 다른 본문과 함께 다시 전송되었습니다. 흔한 원인은 재시도 시점의 시각을 기준으로 유효 기간을 다시 계산하는 것입니다. 로트를 생성할 때 유효 기간을 확정해 저장해 두면 재시도 시 같은 본문이 전송되고 첫 번째 응답이 그대로 재현됩니다.
렌더링에 해당 로트 차량의 도장 색상을 반영할 수 있나요?
예. color에는 사전 설정된 색상 이름이나 hex를 지정할 수 있으므로 추가 비용 없이 위탁 명세서의 도색과 이미지를 맞출 수 있습니다. 그래도 이는 해당 도색의 모델일 뿐 해당 출품 차량은 아니므로 라벨은 그대로 유지합니다.
400개 로트 경매의 비용은 얼마인가요?
이번 달 차량 이미지 400개: URL이 발급될 때 출품 건당 1개가 집계되며, 발급을 재시도해도 다시 집계되지 않습니다. URL 유효 기간 내의 모든 로드는 무료입니다. 플랜에는 월 Free 100개, Pro 2,500개, Business 10,000개의 차량 이미지가 포함되며, 차량, 도색, 뷰가 같은 출품 건은 한 번만 집계됩니다.

계속 읽기

고객 사례 · 자동차 마켓플레이스모든 마켓플레이스 매물에 스튜디오 차량 이미지를 넣는 방법판매자가 사진을 올리기 전에도 매물에는 이미지가 필요합니다. 마켓플레이스는 하나의 앵글과 하나의 도색으로 전체 카탈로그를 채운 뒤, 새 연식이 나올 때마다 같은 요청 형태를 그대로 사용합니다.