Bulk Exporting Korean Used Car Data as NDJSON for Analytics
Paging through /v1/search one request at a time works fine for a search UI, but it is cumbersome if you're preparing data for your own pricing model, market research, or a car import catalog. GET /v1/export/cars streams matching listings as newline-delimited JSON (NDJSON), one search-result summary row per line.
Each successful listing row has the CarListing summary shape used by /v1/search: identity, model, year, mileage, price, thumbnail and other grid fields. It is not a full vehicle-detail record and does not include the detail photo gallery or inspection payload. Fetch /v1/cars/{car_id} and its related endpoints separately when you need those fields.
Why NDJSON
Each line is an independently parseable JSON object:
{"id":40907726,"manufacturer":"Hyundai","model":"Tucson","price_krw":23500000,...}
{"id":40907727,"manufacturer":"Hyundai","model":"Sonata","price_krw":18200000,...}
That means you can start processing records as they arrive instead of waiting for the entire response to download and parse, which matters when max_records is in the tens of thousands. Every major language handles this the same way: read line by line, JSON.parse/json.loads each one.
Requesting an export
curl "https://api.xapikorea.com/v1/export/cars?brand=hyundai&year_from=2022&car_type=Y&lang=en&max_records=5000" \
-H "X-API-Key: enc_your_key_here" \
-o hyundai_2022.ndjson
The export endpoint accepts this filter subset: brand, year_from, year_to, price_min, price_max, fuel_type and car_type. It does not accept search-only controls such as model, transmission, body_style, is_accident_free or sort. lang controls the response language, and max_records caps the stream at 200,000 rows (default 10,000).
car_type defaults to Y, so omitting it exports domestic cars only. Use N for imported cars; request the two types separately if you need both.
Reading it in Python:
import json
import httpx
with httpx.stream(
"GET",
"https://api.xapikorea.com/v1/export/cars",
params={"brand": "hyundai", "year_from": 2022, "car_type": "Y", "lang": "en", "max_records": 5000},
headers={"X-API-Key": "enc_your_key_here"},
) as response:
for line in response.iter_lines():
if not line:
continue
record = json.loads(line)
if "error" in record:
raise RuntimeError(record["error"])
print(record["model"], record["price_krw"])
What people actually build with this
A few patterns come up repeatedly among API users:
- Pricing models: pulling a brand/year slice regularly to track how asking prices move over time, or to spot listings priced well below comparable cars.
- Import marketplace catalogs: seeding and refreshing a storefront of Korean-market cars for buyers overseas, without hand-copying listings.
- Market research: analyzing fuel type mix, average mileage by year, or regional price spread across the Korean used car market as a whole.
The endpoint supplies summary rows for your own downstream processing; it does not calculate market analytics. Because listings can change while a long stream is running, treat an export as a streamed collection rather than a transactionally consistent market snapshot. If the upstream provider fails after the HTTP stream has already begun, the endpoint emits a final {"error":"..."} NDJSON record and closes the stream, so consumers should check for that key before treating a line as a car.
Availability
Bulk export is restricted to Pro and Enterprise accounts (403 on Free or Starter).
Export quota is charged up front from the requested max_records, not the number of rows ultimately returned: each started block of 1,000 requested rows costs one monthly quota unit. For example, max_records=5,000 costs five units even when the filters return fewer than 5,000 rows.
