Every API here is available over the APIs.io API and to AI agents over MCP.
openapi: 3.2.0
info:
title: encarapi Vehicle API
version: 1.3.0
description: 'Real-time Korean used-car data from the full Encar inventory, served as clean JSON. Filter the whole catalog with simple **English** query parameters (or the advanced `q` query syntax). Add `lang=en` to receive every value in English. Discover all valid filter values at `/api/enums`. ## SDKs & AI agents
- Node.js: `npm install encarapi`
- Python: `pip install encarapi`
- AI agents (Claude, ChatGPT, Cursor, VS Code): add the MCP server `https://mcp.encarapi.com/mcp` and sign in with your API key in the browser. Claude Code: `claude mcp add --transport http encarapi https://mcp.encarapi.com/mcp`
## Catalog scope
`/api/catalog` covers standard-sale listings only (Encar''s "일반" sell type). Lease-takeover ("리스") and rental ("렌트") listings are a separate endpoint, `/api/catalog/leasing` - they price by monthly payment rather than a purchase price, so mixing them into `/api/catalog` would distort `Price`. For a brand with e.g. 16,000 total Encar listings, expect roughly 5-10% to be lease/rental. ## Caching
Recommended cache times:
- `/api/enums`, the taxonomy CSVs and `/api/nav`: 24 hours (makes, models, badges and filter values barely change)
- `/api/catalog` listings: 4 to 6 hours
- `/api/vehicle/{id}` details: 24 hours (a listing''s specs change rarely; it only drops out when sold)
Serve listings from your own database and refresh periodically rather than calling live on every user click. Fair use applies. ## Live queries vs. a local copy
There are two supported ways to use this API - pick the one that matches what you are building:
- **Starter - live queries.** Call `/api/catalog` with the filters your users actually search for and cache each response for the times above. This is the default, and it is what the per-key daily catalog-row cap protects (re-pulling the entire catalog on this plan will eventually hit it). - **Business / Scale - a local copy.** Pull `/api/catalog/export` once for a full baseline (does not count against the daily cap), then keep it current with `/api/catalog/changes?since=` instead of re-dumping the whole catalog. Scale additionally has no daily catalog-row cap. Both are 403 on Starter. ## Duplicate listings
Korean dealers commonly list the same physical car twice (sometimes more) under different listing IDs for extra visibility. We detect these and flag the extra copies with `IsDuplicate: true` and `DuplicateOf: ` on the catalog item; the original listing is left unflagged. Duplicates are flagged, not removed, so you can decide how to treat them. `/api/catalog` and `/api/catalog/leasing` accept `exclude_duplicates=true` to filter them out server-side. `/api/catalog/changes` stays a complete, lossless event log (no filtering there) - it still carries `IsDuplicate`/`DuplicateOf` on every item, so filter client-side if you keep a local copy of the catalog. ## Data sources - Encar, KB Chachacha and K Car
The API serves listings from three Korean platforms:
| Source | Platform | Live listings | Depth |
|---|---|---|---|
| `encar` | Encar (encar.com) | 190,000+ | full detail, inspection and insurance reports (default) |
| `kbc` | KB Chachacha (kbchachacha.com) | 110,000+ | catalog plus public history block |
| `kcar` | K Car (kcar.com, direct-sale channel) | 5,000+ | full detail incl. VIN and accident history |
**Plans.** Encar is part of every plan. KB Chachacha and K Car are included in Business and Scale and in the 5-day trial, and are an add-on for Starter. A key without them gets 403 with a hint on `source=kbc`, `kcar` or `all`. **Trial.** The trial includes 100,000 catalog rows and 2,000 detail lookups in total, with at most 1,000 detail lookups per day. Catalog rows are counted over the whole trial across `/api/catalog`, `/api/catalog/leasing` and the items of `/api/catalog/changes`, with at most 100 items per request; detail lookups are `/api/vehicle/{id}`, `/api/inspection/{id}` and `/api/record/{id}` together - the daily budget resets at 00:00 UTC, the totals do not.'
contact:
name: encarapi
url: https://encarapi.com
servers:
- url: https://api.encarapi.com
description: Production
security:
- ApiKeyHeader: []
- ApiKeyQuery: []
tags:
- name: Vehicle
description: Per-vehicle detail, history & inspection
paths:
/api/vehicle/{id}/refresh:
post:
tags:
- Vehicle
summary: Request a refresh of one listing
description: 'Encar (bare numeric id): queues the listing''s detail bundle (vehicle, insurance record, inspection report) for a priority update; compare `lifecycle.detailFetchedAt` on /api/vehicle/{id} to see when it is done. Active Encar listings only (409 for removed ones). Daily quota per key: Starter 10, Business and trials 100, Scale 1000 (429 when used up, resets 00:00 UTC). A listing that is already queued answers 202 with `alreadyQueued: true` and does not count against the quota.
K Car (`kcar:EC`, same entitlement as K Car data: Business, Scale, trials or the multi-source add-on): the listing is updated from K Car right away and the answer is 200 with `queued: false`, `refreshed: true` and `collectedAt` - /api/vehicle/{id} returns the fresh state immediately. It refreshes the detail payload (specification, accident and ownership history, options, photos); the catalog fields price and mileage keep following the regular catalog updates. A K Car refresh counts against the same daily quota as an Encar refresh. Not counted: a listing updated less than 10 minutes ago (200 with `alreadyFresh: true`, nothing is fetched), a refresh of the same listing that is still running (202 with `alreadyQueued: true`) and every failed attempt (502 when K Car does not answer, 503 with `Retry-After` when too many refreshes run at once). 409 when the listing is removed or K Car no longer serves it.
KB Chachacha (`kbc:` ids) has no refresh: the request answers 400 with a hint. Those listings follow the regular updates only.'
parameters:
- name: id
in: path
required: true
schema:
type: string
description: Encar listing id (bare numeric) or a K Car id from a multi-source catalog response ("kcar:EC1234567").
example: '39781121'
responses:
'200':
description: 'K Car: updated right away (`refreshed: true`) or updated less than 10 minutes ago (`alreadyFresh: true`).'
'202':
description: 'Encar: queued. K Car: a refresh of this listing is already running.'
'400':
description: KB Chachacha or unknown id prefix - refresh not available.
'403':
description: Key not entitled to K Car data.
'404':
$ref: '#/components/responses/NotFound'
'409':
description: Listing removed.
'429':
description: Daily refresh quota reached.
'502':
description: K Car did not answer - not counted against the quota.
'503':
description: Too many K Car refreshes right now - retry after the `Retry-After` interval. Not counted against the quota.
operationId: postApiVehicleByIdRefresh
x-operation-id-source: derived
/api/vehicle/by-vin/{vin}:
get:
tags:
- Vehicle
summary: Look up a vehicle by VIN - Business/Scale
description: 'Every listing that carries this VIN, active and removed, on Encar and K Car (KB Chachacha publishes no VIN). A car is often listed more than once (relists, cross-posts), so this is also the listing history of one vehicle. Each result: `id` (pass to /api/vehicle/{id} for the full detail), `source`, `status`, `manufacturer`, `model`, `badge`, `year` (YYYYMM), `mileage`, `price` (10,000 KRW), `firstSeenAt`, `removedAt`, `url`. Active listings first, newest first. VIN coverage: most Encar listings and practically all K Car listings. Business / Scale (and trials).'
parameters:
- name: vin
in: path
required: true
schema:
type: string
example: KMHFG41EBBA058518
description: 17-character VIN (case-insensitive).
responses:
'200':
description: OK (count 0 = no listing with this VIN)
content:
application/json:
schema:
type: object
'400':
description: Not a valid 17-character VIN.
'403':
description: Business or Scale only.
operationId: getApiVehicleByVinByVin
x-operation-id-source: derived
/api/vehicle/{id}:
get:
tags:
- Vehicle
summary: Vehicle detail
description: 'Full specification, photos and equipment for one listing. `{id}` is the `Id` from the catalog. Also includes `spec.powerPs` / `spec.powerKw` (engine power) and `spec.displacementCc` (engine displacement) when available for the listing - they may be absent for some vehicles. Catalog items carry the same figures as `PowerPs`, `PowerKw` and `DisplacementCc`; the CSV export has `power_ps`, `power_kw` and `displacement_cc`. **Multi-source ids.** `kcar:{id}` returns K Car''s full detail plus `Source` and `Url`. `kbc:{id}` returns the enriched catalog item plus `Source`, `Url` (the public listing page), `ListingStatus`, `InsuranceClaims` (number of insurance accident records, as on the catalog item), `AccidentReported` (KB Chachacha''s own accident flag) and `History` - the public history block (licensePlate, displacementCc, seatColor, unpaidTax, seizure, lien, totalLoss, floodDamage, commercialUse, ownershipChanges, frameDiagnosis, panelDiagnosis, collectedAt), or `null` while it is not available for that listing yet. The KB Chachacha detail page itself is not included - see "Data sources" above. **Lifecycle and price history.** Every detail response (Encar, kcar:, kbc:) carries two extra blocks: `lifecycle` (`status`, `firstSeenAt`, `lastSeenAt`, `removedAt`, `detailFetchedAt` - ISO 8601) and `priceHistory` (every observed asking price, oldest first: `{price, observedAt}`, same unit as Price in the catalog). History is available from the date we first observed the listing. **Seller and engagement (Encar only).** Encar detail responses (/api/vehicle/{id}, /api/vehicle/bulk) also carry `seller` and `engagementHistory`. `seller` = `{type, region, company, id}`: `type` is `dealer`, `private` or another seller category exactly as Encar reports it, lowercased (e.g. `repeat` - a non-dealer who lists repeatedly);`region` is the seller''s location at city/district level (e.g. `경기 수원시`), never a street address; `company` is the dealership name (dealers only); `id` is a stable seller code (dealers only, the same dealer always gets the same id - use it to group listings and spot relists). No personal names or phone numbers. `seller` is `null` while it is not available for a listing yet. `engagementHistory` lists every observed change of Encar''s view and favorite counters, oldest first: `{viewCount, subscribeCount, observedAt}`; points are not evenly spaced. History is available from the date we first observed the listing. The same seller fields plus the latest `view_count`/`subscribe_count` are appended to /api/catalog/export (with and without `source`). KB Chachacha detail responses (/api/vehicle/kbc:{id}) carry the same `seller` block: `type` `dealer` or `private` (direct owner sale), `region` at province level only (KB Chachacha publishes no city), `company` always `null`, `id` a stable dealership code (prefixed `k_`, never equal to an Encar id). **Region and city.** Every catalog item carries `Region` (normalized province code: `seoul`, `gyeonggi`, `incheon`, `busan`, `daegu`, `daejeon`, `ulsan`, `gwangju`, `sejong`, `gangwon`, `chungbuk`, `chungnam`, `jeonbuk`, `jeonnam`, `gyeongbuk`, `gyeongnam`, `jeju`) on every source, and `City` (English name, e.g. `Suwon-si`, `Gangnam-gu`) on Encar listings - KB Chachacha and K Car only publish the province, so `City` is `null` there. Filter with `?region=` and `?city=` on /api/catalog, /api/catalog/leasing, /api/nav and /api/model-search - on Encar (no `?source=`) or on one single other source (`?source=kbc` or `?source=kcar`, region only); a mix of sources answers 400. /api/enums lists every region and city with Encar counts. Both are also the last two columns (`region`, `city`) of /api/catalog/export. **Condition report (Encar only).** Encar detail responses (/api/vehicle/{id}, /api/vehicle/bulk) also carry `conditionReport`: the car-condition check done at an Encar center (not every listing has one; `null` when Encar has no report for the car or it is not available yet).'
parameters:
- name: id
in: path
required: true
schema:
type: string
description: The Id from the catalog response. Bare numeric = Encar. K Car and KB Chachacha ids from multi-source catalog responses are prefixed ("kcar:EC1234567", "kbc:987654") - pass them unchanged.
example: '39781121'
- name: lang
in: query
schema:
type: string
enum:
- en
- ru
- de
example: en
description: 'en: only affects kbc:{id} responses (English names and codes in the catalog-item fields, like /api/catalog?lang=en); Encar detail payloads are returned as-is. ru: Russian values on kbc:{id} responses and on Encar detail payloads (`spec` fuelName / transmissionName / colorName / bodyName, the `category` names, the `optionsDecoded` names). de: German values, the same fields as ru. K Car detail payloads are returned as-is with any value.'
responses:
'200':
description: OK
content:
application/json:
schema:
type: object
'404':
$ref: '#/components/responses/NotFound'
operationId: getApiVehicleById
x-operation-id-source: derived
/api/record/{id}:
get:
tags:
- Vehicle
summary: Accident & ownership record
description: 'Full insurance accident and ownership history for one vehicle. Includes accident counts and repair costs for damage to this car and for damage it caused to others, the number of owner and plate changes, total-loss, flood and theft events, and a dated list of every insurance claim. `{id}` is the `Id` from the catalog.
Encar listings only. Prefixed multi-source ids (kcar:..., kbc:...) return 404 with a hint. For K Car listings, accident counts, insurance payouts and ownership history are embedded in /api/vehicle/{id} instead; for KB Chachacha, the public history block is embedded there as `History`.
Removed listings: returned on Business and Scale (archive; trials: 100 per day); other plans get 403 with `listingStatus: "removed"`, `removedAt` and `archive: true`. Earlier versions of a report: /api/inspection/{id}/versions and /api/record/{id}/versions.'
parameters:
- name: id
in: path
required: true
schema:
type: string
description: The Id from the catalog response.
example: '39781121'
responses:
'200':
description: OK
content:
application/json:
schema:
$ref: '#/components/schemas/RecordResponse'
'404':
$ref: '#/components/responses/NotFound'
operationId: getApiRecordById
x-operation-id-source: derived
/api/price-check/{id}:
get:
tags:
- Vehicle
summary: 'Price check (beta): is this listing priced below, in line with or above the…'
description: '**Beta - Scale plan** (trials: 10 lookups per day; Starter/Business: 403 with upgrade hint).
For an active Encar or K Car listing, returns a model-based market estimate with an honest 80% range and where the asking price sits relative to it (`position` in percent, `verdict` = `below_market` / `in_line` / `above_market`).
**How it works.** A statistical model compares the listing with comparable cars and returns an estimate with an 80% range.
**Confidence.** `high` = range within ±10%, `medium` = within ±15%. When comparable cars vary more than ±15% the response says `insufficient_confidence` and gives no estimate rather than a misleading one (about a third of listings today, mostly older, cheaper and rarer cars).
**Accuracy today** (Sept 2026): median deviation about 6%; Mercedes-Benz about 6%, BMW about 6.5%; more accurate than Encar''s own price indicator on the same cars in our comparison. K Car listings: about 5.5%.
**Limits of the beta.** Estimates are based on asking prices, not transaction prices. Covered: Encar (bare numeric id) and K Car (`kcar:`); KB Chachacha listings are not covered yet (the request answers 404 with a hint). No price check for K Car listings that are flagged as a duplicate of a listing on another marketplace, no lease/rental listings, no listings added today. Accuracy and coverage improve over time. Fields may still be added; existing fields will not be renamed.'
parameters:
- name: id
in: path
required: true
schema:
type: string
example: '42800003'
description: 'Encar listing id (bare numeric) or a prefixed id: `kcar:<id>` (K Car).'
responses:
'200':
description: OK
content:
application/json:
schema:
type: object
properties:
listingId:
type: string
example: '42800003'
source:
type: string
enum:
- kcar
description: Only present for prefixed ids; Encar answers are unchanged.
beta:
type: boolean
example: true
askingPrice:
type: integer
description: Current asking price, 10,000 KRW.
example: 1850
currency:
type: string
example: KRW_10K
confidence:
type: string
enum:
- high
- medium
- low
example: high
estimate:
type:
- integer
- 'null'
description: Market estimate, 10,000 KRW. null when confidence is low.
example: 1790
range:
type:
- object
- 'null'
properties:
low:
type: integer
example: 1650
high:
type: integer
example: 1940
coverage:
type: number
example: 0.8
position:
type:
- number
- 'null'
description: Asking price vs estimate in percent (+3.4 = 3.4% above).
example: 3.4
verdict:
type: string
enum:
- below_market
- in_line
- above_market
- insufficient_confidence
example: in_line
segment:
type: string
enum:
- domestic
- german
- other_import
modelVersion:
type: string
example: pc-20261004
computedAt:
type: string
format: date-time
note:
type: string
'403':
description: Plan does not include the price check (Scale only).
'404':
description: 'No price check for this listing (not active, lease/rental, no asking price, added today, flagged as a duplicate of a listing on another marketplace, or a source that is not covered: KB Chachacha).'
'429':
description: Trial daily preview used up.
operationId: getApiPriceCheckById
x-operation-id-source: derived
/api/inspection/{id}:
get:
tags:
- Vehicle
summary: Inspection report
description: 'Official pre-sale inspection report for one vehicle. `master` holds the certified summary (VIN, mileage, accident and simple-repair flags, tuning, recall, engine and transmission checks), while `outers` and `inners` list per-panel condition codes and `images` the inspection photos. `{id}` is the `Id` from the catalog.
Encar listings only. Prefixed multi-source ids (kcar:..., kbc:...) return 404 with a hint. For K Car listings, accident counts, insurance payouts and ownership history are embedded in /api/vehicle/{id} instead; for KB Chachacha, the public history block is embedded there as `History`.
Removed listings: returned on Business and Scale (archive; trials: 100 per day); other plans get 403 with `listingStatus: "removed"`, `removedAt` and `archive: true`. Earlier versions of a report: /api/inspection/{id}/versions and /api/record/{id}/versions.'
parameters:
- name: id
in: path
required: true
schema:
type: string
description: The Id from the catalog response.
example: '39781121'
responses:
'200':
description: OK
content:
application/json:
schema:
$ref: '#/components/schemas/InspectionResponse'
'404':
$ref: '#/components/responses/NotFound'
operationId: getApiInspectionById
x-operation-id-source: derived
components:
responses:
NotFound:
description: Listing not found (sold or removed).
schemas:
RecordResponse:
type: object
description: Official insurance accident and ownership history for one vehicle.
properties:
accidentCnt:
type: integer
description: Total number of insurance-reported accidents.
example: 2
myAccidentCnt:
type: integer
description: Insurance claims for damage to THIS vehicle.
example: 1
myAccidentCost:
type: integer
description: Total repair payout for damage to this vehicle, KRW.
example: 1748300
otherAccidentCnt:
type: integer
description: Claims where this vehicle damaged another party.
example: 1
otherAccidentCost:
type: integer
description: Total payout for damage this vehicle caused to others, KRW.
example: 273719
ownerChangeCnt:
type: integer
description: Number of ownership changes.
example: 2
ownerChanges:
type: array
items:
type: string
format: date
description: Date of each ownership change (newest first).
example:
- '2026-02-19'
- '2021-07-08'
carNoChangeCnt:
type: integer
description: Number of license-plate changes.
example: 0
totalLossCnt:
type: integer
description: Times the vehicle was written off as a total loss.
example: 0
totalLossDate:
type:
- string
- 'null'
description: Date of the total-loss event, if any.
floodTotalLossCnt:
type: integer
description: Flood total-loss events.
example: 0
floodPartLossCnt:
type:
- integer
- 'null'
description: Flood partial-loss events.
example: null
floodDate:
type:
- string
- 'null'
description: Date of the flood-damage event, if any.
robberCnt:
type: integer
description: Number of recorded theft events.
example: 0
robberDate:
type:
- string
- 'null'
description: Date of the theft event, if any.
use:
type: string
description: Usage code ('1' = private, '2' = commercial/business, '3' = government).
example: '2'
business:
type: integer
description: Whether the car was ever used commercially (1) or not (0).
example: 0
firstDate:
type: string
format: date
description: First registration date of the vehicle.
example: '2017-07-31'
regDate:
type: string
description: Timestamp when this insurance record was generated.
accidents:
type: array
description: Dated list of every insurance claim with itemized costs.
items:
$ref: '#/components/schemas/AccidentEvent'
InspectionMaster:
type: object
description: Certified summary of the official government inspection.
properties:
accdient:
type: boolean
description: 'Whether the inspection flags accident history (note: the Encar field is misspelled "accdient").'
example: false
simpleRepair:
type: boolean
description: Whether only simple repairs (e.g. paint) were found.
example: false
supplyNum:
type: string
description: Inspection certificate number.
registrationDate:
type: string
description: Date the inspection was registered.
detail:
type: object
description: 'Full inspection detail: vin, mileage, waterlog, tuning, recall, engine and transmission checks, serious-damage types, painted panels, main options, validity dates, usage changes (`usageChangeTypes`) and the inspector''s free-text remarks (`comments`).'
properties:
usageChangeTypes:
type: array
description: Usage changes in the vehicle's history (용도변경). Empty array = none. Filter the catalog with `usage_change` / `no_usage_change`.
items:
type: object
properties:
code:
type: string
example: '1'
title:
type: string
description: 렌트 = rental, 영업용 = commercial, 관용 = government.
example: 렌트
comments:
type:
- string
- 'null'
description: Free-text remarks of the inspection center or dealer (Korean), exactly as published.
InspectionResponse:
type: object
description: Official pre-sale inspection report for one vehicle.
properties:
vehicleId:
type: string
description: Encar vehicle id this report belongs to.
master:
$ref: '#/components/schemas/InspectionMaster'
outers:
type: array
description: Exterior panel condition codes (paint, dent, replacement). Empty when no exterior issues.
items:
type: object
inners:
type: array
description: Interior / structural frame panel condition codes.
items:
type: object
images:
type: array
description: Inspection photo references.
items:
type: object
price:
type:
- object
- 'null'
description: Assessed-value data, when provided by the inspector.
etcs:
type: array
description: Additional inspector notes.
items:
type: object
formats:
type: array
description: Report format metadata.
items:
type: object
inspectionSource:
type: string
description: Origin of the inspection report.
directManagement:
type: boolean
description: Whether the listing is directly managed by Encar.
AccidentEvent:
type: object
description: A single insurance-reported repair event. All costs are in KRW.
properties:
date:
type: string
format: date
description: Date of the claim.
example: '2024-01-23'
type:
type: string
description: Claim type code (1 = damage to own car, 2 = damage caused to others, etc.).
example: '3'
partCost:
type: integer
description: Parts cost, KRW.
example: 0
laborCost:
type: integer
description: Labor cost, KRW.
example: 72630
paintingCost:
type: integer
description: Painting cost, KRW.
example: 201089
insuranceBenefit:
type: integer
description: Total insurance payout for this event, KRW.
example: 300000
securitySchemes:
ApiKeyHeader:
type: apiKey
in: header
name: x-api-key
description: Your API key.
ApiKeyQuery:
type: apiKey
in: query
name: api_key
description: Your API key (alternative to the header).