encarapi-com Sync API

Business/Scale. Trials can test the change feed (last 7 days) and bulk lookups (1,000 ids per day), but not the full export. Hold a local copy of the catalog: one bulk export for the baseline, then incremental changes instead of re-pulling everything. Bulk endpoints fetch up to 500 vehicles, records or inspection reports per request for backfills; the vehicle bulk endpoint also takes KB Chachacha and K Car ids (kbc:/kcar:).

Operations 5

GET /api/catalog/export Full catalog export (CSV) - Business/Scale #
GET /api/catalog/changes Incremental catalog changes via cursor - Business/Scale #
POST /api/vehicle/bulk Bulk vehicle detail (up to 500 ids) - Business/Scale #
POST /api/inspection/bulk Bulk inspection reports (up to 500 ids) - Business/Scale #
POST /api/record/bulk Bulk insurance records (up to 500 ids) - Business/Scale #

Work with this as data

Every API here is available over the APIs.io API and to AI agents over MCP.

MCP server

One button, every client — Claude, Cursor, VS Code and the rest.

https://apis.io/mcp

Tools for apis

7 MCP tools reach this
  • find_apisBrowse and filter every API in the catalog.
  • get_api_artifactsOne API's artifacts, grouped by type.
  • get_openapiThe primary OpenAPI for this API.
  • find_similar_apisAPIs that look like this one.
  • apis_io_searchSTART HERE — APIs, providers and tags for one query, each with its total.
  • resolveTurn a domain, URL or GitHub org into the provider it belongs to.
  • find_cohortsEvery scored population of providers in the catalog.
All 92 tools →

Call it yourself

curl for this page
This API
curl "https://apis.io/api/v1/apis/encarapi-com:encarapi-com-sync-api"
All apis
curl "https://apis.io/api/v1/apis?limit=25"

Discovery needs no key. Ratings and market analysis are Pro.

Get an API key

Free tier, no form to fill in. Signing in shares your email address with us — we store it to create your key and to recognise you if you sign in with another provider. See our Privacy Policy and Terms.

A second provider on the same verified email joins the account you already have.

OpenAPI Specification

encarapi-com-sync-api-openapi.yml Raw ↑
openapi: 3.2.0
info:
  title: encarapi Sync 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: Sync
  description: 'Business/Scale. Trials can test the change feed (last 7 days) and bulk lookups (1,000 ids per day), but not the full export. Hold a local copy of the catalog: one bulk export for the baseline, then incremental changes instead of re-pulling everything. Bulk endpoints fetch up to 500 vehicles, records or inspection reports per request for backfills; the vehicle bulk endpoint also takes KB Chachacha and K Car ids (kbc:/kcar:).'
paths:
  /api/catalog/export:
    get:
      tags:
      - Sync
      summary: Full catalog export (CSV) - Business/Scale
      description: 'The full active catalog as a single CSV download - the baseline for a local copy. Regenerated once a day (if a rebuild fails, the previous file is served for up to 24 more hours - the `X-Encarapi-Generated-At` header always names the snapshot of the file you got); does NOT count against the daily catalog-row cap, unlike paginating /api/catalog to the same effect would. Requires a Business or Scale plan (403 on Starter and trials). Save the response `X-Encarapi-Generated-At` header - pass it as `since` to /api/catalog/changes for your first sync. The header is set a few minutes before the data snapshot, so that first call can repeat a few events (apply them idempotently) but never misses one. Includes an `is_duplicate`/`duplicate_of` column pair - see "Duplicate listings" above - and four lifecycle columns at the end: `first_seen_at`, `last_seen_at`, `removed_at`, `detail_fetched_at` (ISO 8601). After those, six seller/engagement columns (empty while not available yet): `seller_type`, `seller_region`, `seller_company`, `seller_id`, `view_count`, `subscribe_count` - see "Seller and engagement" above. Accepts ?source= (default encar). With ?source= set, the listing_id column carries the customer-facing ids (bare numeric for Encar, prefixed kcar:... / kbc:... otherwise) and a new column `source` is added after updated_at; rows are sorted by source, then source id. Appended after all of the above (both variants, 2026-10): with ?source= set, the duplicate and seller/engagement columns (KB Chachacha rows: Encar-duplicate flag, `seller_type`, province `seller_region`, `seller_id`; K Car rows empty); then `sell_type` (`sale` / `lease` / `rental`), `month_lease_price`, `acceptance_charge` (10,000 KRW) and `month_lease_rest` (months; the three lease columns only on lease/rental rows), then `region` and `city` (see "Region and city"). Last come `vin` and `vehicle_no` (Korean plate number; K Car rows: VIN only, KB Chachacha rows: plate only where published). Without ?source=, the Encar export then ends with `displacement_cc` (engine displacement in cc, empty when unknown). Last (both variants, 2026-10-22): `accident`, `simple_repair`, `inspection_available` - the accident status from Encar''s performance inspection (성능점검, not the insurance history), Encar rows only, empty on K Car / KB Chachacha rows. Three states: all three empty = we have not stored the listing''s detail yet (usually within an hour of `first_seen_at`, in rare cases longer); `inspection_available=false` = no inspection report at our last detail fetch (`accident`/`simple_repair` empty; can still turn true later); `true` = `accident` (frame/structural damage per the inspection) and `simple_repair` (only simple repairs such as panel/paint work) filled. Last with ?source= set (2026-10-26): `insurance_claims` - the number of insurance accident records on KB Chachacha rows ("보험이력 N건" on the listing page), empty on Encar / K Car rows and while not known. Already have a local copy? Pull this export once to fill the new columns for existing listings, then continue the change feed from its header. Columns are only ever appended, never moved. Add `compress=true` to receive the file gzip/brotli-compressed (about 6x smaller, faster download) - send `Accept-Encoding: gzip` and let your HTTP client decompress.'
      parameters:
      - name: source
        in: query
        schema:
          type: string
          default: encar
        example: all
        description: 'Data source(s): `encar` (default), `kcar`, `kbc`, a comma-separated list (`encar,kbc`), or `all`. Omitted = Encar only, byte-identical to pre-1.1.0 responses. When set, each item carries a `Source` field (plus `Url`, `Transmission`, `Color`, `Options`, `SeatCount` on K Car / KB Chachacha items). Filtering on a field a source does not provide excludes that source''s vehicles (see "Data sources" above).'
      - name: sell_type
        in: query
        schema:
          type: string
          default: sale
        example: lease,rental
        description: 'Which listings: `sale` / `일반` (standard sales, default - the pre-existing file), `lease` / `리스` (lease takeover), `rental` / `렌트`, a comma list, or `all`. Lease and rental listings exist on Encar only. Use `export?sell_type=lease,rental` + `/api/catalog/changes?sell_type=lease,rental` to keep a complete local copy of the lease/rental inventory.'
      - name: compress
        in: query
        schema:
          type: boolean
        example: true
        description: true = compressed transfer (gzip or brotli, per your Accept-Encoding). Off by default so existing integrations that store the raw bytes keep working.
      - name: lang
        in: query
        schema:
          type: string
          enum:
          - ru
          - de
        description: 'ru = the same file (catalog_export_ru.csv) with the label columns in Russian (de = catalog_export_de.csv, German; city stays English): model_group, model, badge_group, badge, fuel, transmission, drivetrain, color, seat_color, category, sell_type, region, city. Column order and every other column stay exactly as in the default file. Without lang, model and badge carry the Korean names (English: model_group, badge_group); the coded columns carry English codes.'
      responses:
        '200':
          description: CSV file
          content:
            text/csv:
              schema:
                type: string
        '401':
          $ref: '#/components/responses/Unauthorized'
        '403':
          description: Plan does not include the sync features. Upgrade to Business or Scale.
      operationId: getApiCatalogExport
      x-operation-id-source: derived
  /api/catalog/changes:
    get:
      tags:
      - Sync
      summary: Incremental catalog changes via cursor - Business/Scale
      description: 'Everything that changed, grouped into added / updated / reappeared / removed. Backed by an append-only event log, not a point-in-time diff - `nextCursor` is a monotonic position, so paging with it can never skip or duplicate an event, including when a response is `truncated`. Order: events are logged in the order we observe the changes (catalog passes several times a day), not by the source''s own change time; several changes between two passes arrive as one event. Every entry (also in `removed`) carries `eventId` (its position in the log, a numeric string on the same scale as `nextCursor`) and `occurredAt` (when we recorded the change). Items show the listing''s current state at the time of your request, not a snapshot of the event: if a listing has several entries on one page, the one with the highest `eventId` is the latest (e.g. `removed` after `updated`). An event enters the feed once the database transaction that recorded it has finished, usually within seconds of `occurredAt`; positions never go backwards. First call: pass `since` (from your /api/catalog/export baseline''s `X-Encarapi-Generated-At` header) or `cursor=0` for the full log. Every following call: pass the previous response''s `nextCursor`. `updated` items carry `changedFields` (which columns actually changed: price, mileage, condition, trust, record, inspection, accident, description, duplicate, ...) and `firstSeenAt`. Encar items also carry `Accident`, `SimpleRepair` and `InspectionAvailable` (same meaning as the export columns; `null` = detail not stored yet). When a listing''s detail is stored for the first time, it arrives once more as `updated` with `changedFields` containing `inspection` - from then on the three fields are known (check `InspectionAvailable` before calling /api/inspection/{id}: about one in five new listings has no report). Later changes arrive with `inspection` (report appeared/disappeared) or `accident` (accident status, simple repair or insurance-history counts changed). KB Chachacha items carry `InsuranceClaims` (number of insurance accident records, `null` = not known); a change arrives as `updated` with `accident` in `changedFields`. The count was added on 2026-10-26 without events for existing listings - pull the export once (?source=kbc) to fill it in a local copy. Every item also carries `IsDuplicate`/`DuplicateOf` - see "Duplicate listings" above (on KB Chachacha items: duplicate of an Encar listing, see "Deduplication" in the multi-source notes; drop those to stay consistent with /api/catalog) - and `Region`/`City`. `removed` entries are `{listingId, removedAt, removalReason}`: `removalReason` is `sold` when Encar still showed the listing as sold / under contract when it left the catalog, otherwise `unknown` - most Encar listings are deleted outright, which does not tell a sale from a withdrawal; always `unknown` for KB Chachacha and K Car. Requires a Business or Scale plan (403 on Starter); trials can read the last 7 days (older cursors or `since` values answer 403).'
      parameters:
      - name: cursor
        in: query
        schema:
          type: integer
        example: 0
        description: 'Resume point: the `nextCursor` from a previous response, or 0 for the full log. Takes precedence over `since` if both are given.'
      - name: since
        in: query
        schema:
          type: string
          format: date-time
        example: '2026-08-24T00:00:00Z'
        description: ISO 8601 timestamp, only for the first call after a fresh /api/catalog/export - resolved once to a cursor. Ignored if `cursor` is also given.
      - name: source
        in: query
        schema:
          type: string
          enum:
          - encar
          - kbc
          - kcar
          - truck
          - equipment
          default: encar
        description: One source per call (no lists, no `all`); `truck` = trucks and buses, `equipment` = excavators (both Business/Scale). Each source has its own cursor. KB Chachacha and K Car need a plan that includes them - see "Data sources" above.
      - name: sell_type
        in: query
        schema:
          type: string
        example: lease,rental
        description: Defaults to `sale` / `일반` (standard sale, matches /api/catalog). Pass `lease` / `리스`, `rental` / `렌트`, a comma list, or `all`. Items carry `SellType` (Korean value) from the catalog item. With `sell_type` set, sell-type transitions in both directions are included as well (e.g. a lease listing that became a standard sale arrives in a lease/rental feed with `changedFields` containing `sell_type` and the new `SellType`), so a filtered local copy can reclassify or drop it. Unknown values answer 400.
      - name: limit
        in: query
        schema:
          type: integer
          default: 10000
        description: Max events per call, max 50000. `hasMore`/`truncated` = true means more are available immediately - call again with `nextCursor`, no data is lost.
      - name: lang
        in: query
        schema:
          type: string
          enum:
          - en
          - ru
          - de
        description: lang=en returns English values, lang=ru Russian ones, lang=de German ones, like /api/catalog.
      responses:
        '200':
          description: OK
          content:
            application/json:
              schema:
                type: object
        '400':
          description: Missing/invalid `cursor` or `since` (one of the two is required), or an unknown `sell_type`.
        '401':
          $ref: '#/components/responses/Unauthorized'
        '403':
          description: Plan does not include the sync features. Upgrade to Business or Scale.
        '410':
          description: Cursor older than the 6-month retention window. Pull a fresh /api/catalog/export and restart from its generation timestamp.
      operationId: getApiCatalogChanges
      x-operation-id-source: derived
  /api/vehicle/bulk:
    post:
      tags:
      - Sync
      summary: Bulk vehicle detail (up to 500 ids) - Business/Scale
      description: 'Detail payloads for up to 500 ids in one request - for backfills. Same payload per id as /api/vehicle/{id}, including the `lifecycle`, `priceHistory`, `seller`, `engagementHistory` and `conditionReport` blocks. Removed listings are included (archive). Body: `{"ids": ["41750159", ...]}`. Response: `results` (id -> payload, ids echoed as sent; each Encar payload also carries `listingId`, `canonicalListingId` and `isCopyListing` - see /api/vehicle/{id}), `pending` (known listing, payload not available yet), `notFound`, `counts`. Requires a Business or Scale plan; trials can look up 1,000 ids per day, and removed listings count against the trial''s archive preview (100 per day) - beyond it they are listed under `archived`.


        **KB Chachacha and K Car ids.** The list may mix bare numeric Encar ids (listing or vehicle ids) with prefixed ids - `{"ids": ["41750159", "kbc:27400001", "kcar:EC61200001"]}`. Each prefixed id counts like an Encar id (500 per request, trial budget) and returns exactly the payload of /api/vehicle/{id} for that id: K Car = the detail payload (the catalog item until the detail is available), KB Chachacha = the catalog item plus the `History` block, both with `Source`, `Url`, `lifecycle` and `priceHistory`; the Encar-only blocks (`seller`, `engagementHistory`, `conditionReport`) are not part of them. Add `?lang=en` to the request URL for English values on KB Chachacha payloads, or `?lang=ru` / `?lang=de` for Russian / German values on KB Chachacha and Encar payloads, as on /api/vehicle/{id}. Prefixed ids are never `pending`: an unknown id or prefix is listed under `notFound`. If the key is not entitled to KB Chachacha / K Car data, the request still succeeds: those ids are listed under `notEntitled` (with `entitlementHint` and `counts.notEntitled`) and the Encar ids are answered as usual. An Encar-only id list returns the same response as before.'
      requestBody:
        required: true
        content:
          application/json:
            schema:
              type: object
              required:
              - ids
              properties:
                ids:
                  type: array
                  maxItems: 500
                  items:
                    type: string
      responses:
        '200':
          description: OK
          content:
            application/json:
              schema:
                type: object
        '400':
          description: Missing/invalid body, more than 500 ids, or ids that are neither bare numeric nor prefixed (kcar:/kbc:).
        '401':
          $ref: '#/components/responses/Unauthorized'
        '403':
          description: Plan does not include the sync features.
      operationId: postApiVehicleBulk
      x-operation-id-source: derived
  /api/inspection/bulk:
    post:
      tags:
      - Sync
      summary: Bulk inspection reports (up to 500 ids) - Business/Scale
      description: 'Inspection reports for up to 500 Encar ids in one request - same payload per id as /api/inspection/{id}, same body and response envelope as /api/vehicle/bulk. `pending` = the listing is known but no report is available (Encar has not published one, or it is not available yet) - this is how "no report" is told apart from a clean report. Encar listings only: prefixed ids (kcar:/kbc:) do not fail the request, they are listed under `encarOnly` (with `encarOnlyHint` and `counts.encarOnly`).'
      requestBody:
        required: true
        content:
          application/json:
            schema:
              type: object
              required:
              - ids
              properties:
                ids:
                  type: array
                  maxItems: 500
                  items:
                    type: string
      responses:
        '200':
          description: OK
          content:
            application/json:
              schema:
                type: object
        '400':
          description: Invalid body.
        '403':
          description: Plan does not include the sync features.
      operationId: postApiInspectionBulk
      x-operation-id-source: derived
  /api/record/bulk:
    post:
      tags:
      - Sync
      summary: Bulk insurance records (up to 500 ids) - Business/Scale
      description: 'Insurance-history records for up to 500 Encar ids in one request - same payload per id as /api/record/{id}, same body and response envelope as /api/vehicle/bulk. Encar listings only: prefixed ids (kcar:/kbc:) do not fail the request, they are listed under `encarOnly` (with `encarOnlyHint` and `counts.encarOnly`).'
      requestBody:
        required: true
        content:
          application/json:
            schema:
              type: object
              required:
              - ids
              properties:
                ids:
                  type: array
                  maxItems: 500
                  items:
                    type: string
      responses:
        '200':
          description: OK
          content:
            application/json:
              schema:
                type: object
        '400':
          description: Invalid body.
        '403':
          description: Plan does not include the sync features.
      operationId: postApiRecordBulk
      x-operation-id-source: derived
components:
  responses:
    Unauthorized:
      description: Missing or invalid API key.
  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).