Every API here is available over the APIs.io API and to AI agents over MCP.
openapi: 3.2.0
info:
title: encarapi Leasing 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: Leasing
description: Lease-takeover (리스) and rental (렌트) listings - same shape and filters as /api/catalog, kept separate because these price by monthly payment, not a purchase price.
paths:
/api/catalog/leasing:
get:
tags:
- Leasing
summary: Lease-takeover and rental listings
description: 'Same filters and response shape as /api/catalog, scoped to 리스 (lease-takeover) and 렌트 (rental) listings instead of standard sales. `Price` here is the lease/rental vehicle value, not a purchase price - use the lease-specific fields on each item for the actual terms: `MonthLeasePrice` (monthly payment, 만원), `AcceptanceCharge` (takeover fee, 만원), `MonthLeaseRest` (months remaining), `Lease` (flag). Available on every plan; not subject to the catalog daily volume cap (on a trial, these rows count toward the trial''s catalog allowance). Encar-only: lease-takeover and rental listings exist only on Encar, so this endpoint does not accept ?source=.'
parameters:
- name: manufacturer
in: query
description: Brand. Comma-separated = OR.
schema:
type: string
example: bmw
- name: model_group
in: query
description: Model line (English name or Korean token).
schema:
type: string
example: 3-series
- name: model
in: query
description: Specific generation.
schema:
type: string
- name: fuel
in: query
description: Fuel type.
schema:
type: string
enum:
- gasoline
- diesel
- hybrid
- diesel-hybrid
- lpg-hybrid
- gasoline-lpg
- cng
- electric
- lpg
- hydrogen
- other
example: diesel
- name: transmission
in: query
description: Transmission type.
schema:
type: string
enum:
- automatic
- manual
- cvt
- semi-automatic
- other
example: automatic
- name: color
in: query
description: Exterior / paint color.
schema:
type: string
enum:
- white
- black
- gray
- blue
- silver
- silver-gray
- pearl
- red
- sky-blue
- green
- dark-green
- light-green
- brown
- yellow
- orange
- purple
- maroon
- turquoise
- gold
- pink
example: black
- name: seat_color
in: query
description: Interior / seat color.
schema:
type: string
enum:
- black
- brown
- beige
- gray
- red
- white
- blue
- green
- orange
- yellow
example: beige
- name: category
in: query
description: Body category.
schema:
type: string
enum:
- suv
- rv
- large
- midsize
- compact
- small
- kei
- van
- light-van
- truck
- sports
- other
example: suv
- name: seats
in: query
description: Number of seats. Comma = OR (e.g. 5,7).
schema:
type: string
example: 7,9
- name: min_seats
in: query
description: Minimum seats.
schema:
type: integer
- name: max_seats
in: query
description: Maximum seats.
schema:
type: integer
- name: options
in: query
description: Equipment codes; the car must have all listed. Comma-separated.
schema:
type: string
example: 001,024
- name: min_price
in: query
description: Min price in 만원 (1 = 10,000 KRW).
schema:
type: integer
example: 2000
- name: max_price
in: query
description: Max price in 만원 (1 = 10,000 KRW).
schema:
type: integer
example: 5000
- name: min_year
in: query
description: Min model year (4-digit).
schema:
type: integer
example: 2021
- name: max_year
in: query
description: Max model year (4-digit).
schema:
type: integer
- name: min_mileage
in: query
description: Min mileage in km.
schema:
type: integer
- name: max_mileage
in: query
description: Max mileage in km.
schema:
type: integer
example: 100000
- name: lang
in: query
description: Set to 'en' for English values, 'ru' for Russian or 'de' for German ones (English where no Russian or German label exists).
schema:
type: string
enum:
- en
- ru
- de
example: en
- name: q
in: query
description: Advanced query syntax (alternative to the flat parameters above).
schema:
type: string
- name: badge_group
in: query
schema:
type: string
example: c43-amg-4matic-coupe
description: Badge / trim group - this is where the body-style split lives (Coupe vs Sedan vs Cabriolet). Use a value from /api/taxonomy/badges.csv or /api/nav; filter on this instead of parsing the title.
- name: badge
in: query
schema:
type: string
description: Exact badge (finest trim level), value from /api/nav.
- name: drivetrain
in: query
schema:
type: string
example: 4wd
description: Drivetrain (e.g. 2wd / 4wd). Values from /api/nav.
- name: model_search
in: query
schema:
type: string
example: s63 coupe
description: Cross-brand free-text model search. ";"-separated phrases are OR-combined (e.g. "s63 coupe;m5"). Matches make/model/badge names. See also GET /api/model-search for autocomplete.
- name: min_ps
in: query
schema:
type: integer
description: Minimum engine power in PS.
- name: max_ps
in: query
schema:
type: integer
description: Maximum engine power in PS.
- name: max_owners
in: query
schema:
type: integer
example: 1
description: Maximum number of previous owners.
- name: frame_clean
in: query
schema:
type: boolean
example: true
description: true = only accident-free cars (clean chassis frame).
- name: no_damage_cost
in: query
schema:
type: boolean
description: true = only cars with zero insurance-reported repair cost. A missing insurance record counts as zero - combine with has_record=true to drop cars whose history is unknown.
- name: max_damage_eur
in: query
schema:
type: integer
example: 3000
description: Maximum insurance-reported repair cost in EUR (own + caused). A missing insurance record counts as zero - combine with has_record=true to drop cars whose history is unknown.
- name: no_repairs
in: query
schema:
type: boolean
description: true = only cars with no recorded panel repairs. A missing inspection report counts as zero repairs - combine with has_inspection=true to drop cars without a report.
- name: exclude_prices
in: query
schema:
type: string
example: 1111,9999
description: Comma-separated prices (in 10,000 KRW) to exclude. Korean dealers mark reserved cars with placeholder prices such as 1111 or 9999; pass them here to hide those listings server-side so Count and paging stay correct. Max 50 values.
- name: has_record
in: query
schema:
type: boolean
description: true = only cars with an insurance history record (GET /api/record/{id} available). Encar sellers can withhold the record; those cars have unknown damage cost and are otherwise included by no_damage_cost / max_damage_eur.
- name: has_inspection
in: query
schema:
type: boolean
description: true = only cars with an official inspection report (GET /api/inspection/{id} available). Encar listings only.
- name: usage_change
in: query
schema:
type: string
example: rental,commercial
description: 'Comma-separated usage changes recorded on the official inspection report (용도변경): `rental` (렌트), `commercial` (영업용), `government` (관용). Returns cars with ANY of the listed changes. Source field: `master.detail.usageChangeTypes` in GET /api/inspection/{id}. Encar listings only - K Car and KB Chachacha listings drop out when this filter is set.'
- name: no_usage_change
in: query
schema:
type: boolean
description: true = only cars whose inspection report lists no usage change (never a rental, commercial or government vehicle). Cars without an inspection report are excluded. Encar listings only.
- name: has_photos
in: query
schema:
type: boolean
description: true = only listings that have photos.
- name: min_first_seen
in: query
schema:
type: string
format: date-time
example: '2026-09-01T00:00:00Z'
description: Only listings we have known about since this ISO 8601 timestamp or later - filter the live catalog by discovery date without calling /api/catalog/changes.
- name: exclude_duplicates
in: query
schema:
type: boolean
description: true = exclude listings we have detected as a duplicate of another listing (see the "Duplicate listings" section above). Off by default - duplicates are flagged, not hidden, unless you opt in.
- name: region
in: query
schema:
type: string
example: gyeonggi,seoul
description: 'Comma-separated region codes (also accepts the English or Korean name): seoul, gyeonggi, incheon, busan, daegu, daejeon, ulsan, gwangju, sejong, gangwon, chungbuk, chungnam, jeonbuk, jeonnam, gyeongbuk, gyeongnam, jeju. Works on Encar (no ?source=) and on one single source (?source=kbc or ?source=kcar); a mix of sources (e.g. encar,kbc or all) answers 400. Unknown values answer 400. See "Region and city" above.'
- name: city
in: query
schema:
type: string
example: suwon
description: 'Comma-separated cities: the `value` from /api/enums -> city (e.g. `suwon`, `gangnam`), the English name (`Suwon-si`) or the Korean name (`수원시`). Encar listings only (KB Chachacha and K Car publish the province only; with ?source= set the filter answers 400 - use ?region= there). Names shared by several cities (e.g. `jung` = every Jung-gu) match all of them - combine with ?region= to pick one.'
- name: sort
in: query
schema:
type: string
enum:
- newest
- price_asc
- price_desc
- mileage_asc
- mileage_desc
- year_desc
- year_asc
- id
default: newest
example: price_asc
description: Sort order. `newest` (default) = most recently changed first; any change moves a listing to the top, so offset paging over a changing catalog can repeat or skip listings at page boundaries. For a complete traversal use `sort=id` (immutable listing id ascending) with `after` = the previous response's `nextAfter` until `hasMore` is false; listings added during the traversal are covered by /api/catalog/changes.
- name: after
in: query
schema:
type: string
example: '41234567'
description: 'Keyset cursor for `sort=id`: pass the `nextAfter` value of the previous response to get the next page (ignores page/offset). Use this for complete traversals - see `sort`.'
- name: page
in: query
description: Page number (1-based).
schema:
type: integer
default: 1
example: 1
- name: limit
in: query
description: Results per page (1-1000).
schema:
type: integer
default: 20
example: 25
- name: count
in: query
description: Include the total match count.
schema:
type: boolean
example: true
responses:
'200':
description: OK
content:
application/json:
schema:
$ref: '#/components/schemas/CatalogResponse'
'401':
$ref: '#/components/responses/Unauthorized'
operationId: getApiCatalogLeasing
x-operation-id-source: derived
components:
responses:
Unauthorized:
description: Missing or invalid API key.
schemas:
CatalogResponse:
type: object
properties:
Count:
type: integer
description: Total matches (only when count=true). Calculated from a periodically refreshed snapshot and cached - it can lag the live rows by up to about 20 minutes. Do not use it as a completeness check.
example: 687
SearchResults:
type: array
items:
$ref: '#/components/schemas/CatalogItem'
nextAfter:
type:
- string
- 'null'
description: 'Only with sort=id: pass as ?after= for the next page; null on the last page.'
example: '41234567'
hasMore:
type: boolean
description: 'Only with sort=id: true while more pages follow.'
example: true
CatalogItem:
type: object
description: Raw Korean fields are always present; the *English companions give the English value. With lang=en the main fields are English and the *English duplicates are omitted.
properties:
Id:
type: string
example: '39781121'
Manufacturer:
type: string
example: BMW
ManufacturerEnglish:
type: string
example: BMW
Model:
type: string
example: 5시리즈
ModelEnglish:
type: string
example: 5-Series
Badge:
type: string
example: 520d
BadgeEnglish:
type: string
example: 520d
FuelType:
type: string
example: 디젤
FuelTypeEnglish:
type: string
example: diesel
Year:
type: integer
description: YYYYMM
example: 202105
Price:
type: integer
description: In 만원 (10,000 KRW).
example: 4890
Mileage:
type: integer
description: km
example: 38200
PowerPs:
type:
- integer
- 'null'
description: Engine power in PS (absent when not available for this listing).
example: 245
PowerKw:
type:
- integer
- 'null'
description: Engine power in kW (absent when not available for this listing).
example: 180
DisplacementCc:
type:
- integer
- 'null'
description: Engine displacement in cc (absent when not available for this listing).
example: 2993
IsDuplicate:
type: boolean
description: true when this listing is an extra copy of another listing (same car, cross-posted by the dealer). Only present when true. See "Duplicate listings" above.
example: true
DuplicateOf:
type: string
description: The listing_id this is a duplicate of (numeric string). Only present when IsDuplicate is true.
example: '39781100'
Photos:
type: array
items:
type: object
properties:
location:
type: string
Source:
type: string
enum:
- encar
- kcar
- kbc
description: Which platform this listing comes from. Only present when the request sets ?source= - default (Encar-only) responses are unchanged.
example: kbc
Url:
type: string
description: Public listing page on the source platform. Only on K Car / KB Chachacha items (?source= set).
example: https://m.kbchachacha.com/public/web/car/detail.kbc?carSeq=27617411
Transmission:
type: string
description: Gearbox (Korean raw value; with ?lang=en the English code, with ?lang=ru / de the Russian / German label). On Encar items as delivered by Encar; on K Car / KB Chachacha items filled from our normalized data.
example: 오토
Color:
type: string
description: Exterior color (with ?lang=en the English code, with ?lang=ru / de the Russian / German label). Only on K Car / KB Chachacha items (?source= set) - Encar carries color in /api/vehicle/{id} only.
example: 흰색
Options:
type: array
items:
type: string
description: Equipment codes. Only on K Car / KB Chachacha items (?source= set). K Car codes are mapped to Encar codes; KB Chachacha uses its own codes - resolve them with /api/taxonomy/kbc_options.csv.
example:
- '100100'
- '100110'
SeatCount:
type: integer
description: Seats. Only on K Car / KB Chachacha items (?source= set), where the platform publishes it.
example: 5
Region:
type:
- string
- 'null'
description: Normalized region (province) code of the seller, on every source; with ?lang=ru the Russian region name, with ?lang=de the region name. See "Region and city".
example: gyeonggi
City:
type:
- string
- 'null'
description: English city / district name of the seller (Russian with ?lang=ru). Encar listings only (null on KB Chachacha / K Car).
example: Suwon-si
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).