Back to blog

Bulk Exporting Korean Used Car Data as NDJSON for Analytics

July 1, 2026·XAPI Korea Team

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.