Migration

How to migrate from MarketCheck to Cardog

Last updated:

Move your MarketCheck inventory search to Cardog listings: the field map, ref and spec filters, and an adapter you run in your own code.

If you call MarketCheck's Inventory Search today, the Cardog equivalent is GET /v2/listings/search, plus GET /v2/listings/facets for facets and the total (or GET /v2/listings/count for the total alone). The core vehicle and price fields carry over, and every filter becomes an entity ref or a spec filter, so a search can ask for exact equipment and an unknown value is a 400 that names it, never an empty page. The tables below map each field.

This guide is written by Cardog. Every claim about MarketCheck links to MarketCheck's own public documentation, and every claim was checked on 2026-10-26.

The short version

  1. Get a Cardog API key and send it as the x-api-key header (MarketCheck uses an api_key query parameter). Base URL: https://api.cardog.app.
  2. Swap GET /v2/search/car/active for GET /v2/listings/search. Translate filters: make and model become entity refs (make=make:toyota, model=model:toyota/rav4), price_range=10000-30000 becomes price.min=10000&price.max=30000, rows/start become limit/page, and radius (with lat and lng) is in kilometres, not miles.
  3. If you read num_found, facets or range_facets, call GET /v2/listings/facets with the same filters. It returns totalCount along with the facets. If you only need the total, GET /v2/listings/count returns count.
  4. If you read msrp, mpg, dimensions or seating, call GET /v2/listings/vin/{vin} for the listing's variant and full spec.
  5. Rename fields using the table below, or use the adapter and keep your existing parsing code.
  6. Diff a sample of searches and VINs between the two before you cut over.

How their fields map to ours

MarketCheck's fields are from its Inventory Search reference. Cardog paths are from our published contract. A listing row in that contract has id, vin, price, currency, odometer, year, make, model, trim, makeRef, modelRef, nano and media. Those are the fields this guide maps.

Response envelope

MarketCheckCardogNote
num_foundtotalCount from GET /v2/listings/facets, or count from GET /v2/listings/countSeparate call. Both count distinct VINs with the same filters as search. For a very broad search the number can be a planner estimate, flagged by countIsApproximate (or totalCountIsApproximate on facets).
listingslistingsSame
facetsGET /v2/listings/facets (makes, models, bodyStyles, fuelTypes, ...)Separate call. Buckets are { ref, name, count } instead of { item, count }.
statsNot mappedFacets return min and max for year, price and odometer.
range_facetspriceHistogram from GET /v2/listings/facetsPrice, about 20 buckets.
(none)pagination, filtersCardog echoes the page and the filters it applied.

Listing

MarketCheckCardogNote
ididSame name, different ids.
vinvinSame
headingNot mappedBuild it from year, make, model, trim.
pricepriceSame name. Read currency with it (default CAD).
msrpvariant.msrp on GET /v2/listings/vin/{vin}Detail call only. variant is null when the VIN has no variant link yet.
milesodometerUnit change: kilometres. Miles = km / 1.609344.
media.photo_linksmedia[].urlmedia is an array of objects, at most 5 per row on search.
alternate_vin, data_source, source, vdp_url, stock_no, model_code, seller_type, inventory_type, is_certified, in_transit, vehicle_status, availability_statusNot mapped
fees, price_includes_fees, buy_now_price, ref_price, ref_price_dt, price_change_percent, ref_miles, ref_miles_dtNot mapped
exterior_color, interior_color, base_ext_color, base_int_colorFilters and facetsFilter by exteriorColor and interiorColor; facets count exterior colours.
dom, dom_180, dom_active, dos_active, first_seen_at*, last_seen_at*, scraped_at*Not mappedcreatedAfter and updatedAfter filter on freshness.
distNot mappedFilter by radius with lat, lng and radius (kilometres).
financing_options, leasing_optionsNot mapped
media.photo_links_cachedNot mapped

Dealer

MarketCheckCardogNote
dealer.*, mc_dealership.*Not mappedFilter by seller id (seller=) and by location (lat, lng, radius).

Build

MarketCheckCardogNote
build.year, make, model, trimyear, make, model, trimFlattened onto the row. Cardog also returns makeRef, modelRef and nano.
build.body_type, vehicle_type, transmission, drivetrain, fuel_type, powertrain_typeFilters and facets, not row fieldsFilter with bodyStyle=, vehicleType=, transmission=, driveType=, fuelType=, electrification= refs. For one vehicle, GET /v2/listings/vin/{vin} returns the full spec.
build.engine_size, cylinders, doorsspec.displacementL, spec.cylinders, spec.doors on GET /v2/listings/vin/{vin}Detail call only. cylinders and doors are also search filters.
build.highway_mpg, build.city_mpgspec.fuelEconomyHighway, spec.fuelEconomyCity on GET /v2/listings/vin/{vin}Detail call only. Litres per 100 km, so lower is better. US mpg = 235.215 / value.
build.overall_height, overall_length, overall_widthspec.height, spec.length, spec.width on GET /v2/listings/vin/{vin}Detail call only. Millimetres.
build.std_seatingspec.seatingCapacity on GET /v2/listings/vin/{vin}Detail call only. spec is null when the VIN has no variant link yet.
build.version, engine, engine_block, made_inNot mapped

Spec key names and units are listed by GET /v2/specs/catalog.

An adapter for your code

This calls Cardog and returns an object in MarketCheck's documented Inventory Search shape, for the fields that map. Everything else is left undefined. Cardog does not serve a MarketCheck-shaped response. This adapter runs in your code.

const CARDOG = "https://api.cardog.app";
const KM_PER_MILE = 1.609344;

/**
 * cardogQuery uses Cardog filter names, e.g.
 * "make=make:toyota&model=model:toyota/rav4&price.max=30000&limit=50&page=1"
 * Note: this makes two metered calls (search + count).
 */
export async function searchActiveMarketCheckShape(cardogQuery: string, apiKey: string) {
  const headers = { "x-api-key": apiKey };
  const [search, count] = await Promise.all([
    fetch(`${CARDOG}/v2/listings/search?${cardogQuery}`, { headers }).then((r) => r.json()),
    fetch(`${CARDOG}/v2/listings/count?${cardogQuery}`, { headers }).then((r) => r.json()),
  ]);

  return {
    num_found: count.count,
    listings: search.listings.map((l: any) => ({
      id: l.id,
      vin: l.vin,
      heading: [l.year, l.make, l.model, l.trim].filter(Boolean).join(" "),
      price: l.price, // in l.currency (default CAD)
      miles: l.odometer != null ? Math.round(l.odometer / KM_PER_MILE) : undefined, // odometer is km
      media: { photo_links: (l.media ?? []).map((m: any) => m.url) },
      build: {
        year: l.year,
        make: l.make,
        model: l.model,
        trim: l.trim ?? undefined,
      },
      // msrp, mpg, dimensions, seating, engine size, cylinders and doors
      // come from the detail call, GET /v2/listings/vin/{vin}.
    })),
    // facets / range_facets: call GET /v2/listings/facets.
  };
}

Verify before you switch

  1. Pick five to ten searches you run often (one make, one make plus model, a price band, a radius search around a Canadian location you can geocode to lat and lng).
  2. Run each against MarketCheck with country=ca and against Cardog with the translated filters.
  3. Compare totals (num_found against count), then pick ten VINs that appear in both and diff price, odometer (after converting miles to kilometres) and trim.
  4. Look at VINs that appear only on one side. Cardog serves verified listings by default; pass verified=false to see the rest.
  5. Note which fields your product reads that sit in the "Not mapped" rows above, and decide before cut-over whether to compute, drop or keep a second source for them.

What Cardog adds

  • Filters that cannot silently miss. Make, model, body style, fuel type and the rest are entity refs. An unknown ref returns a 400 that names it, never a fuzzy match or an empty page.
  • Spec filters. Filter on canonical specs and equipment availability with spec.{attributeId}, for example spec.fuelEconomyCombined.max=8 (litres per 100 km) or spec.heatedSeatsFront=standard.
  • Feature facets. Facets include equipment counts (featureFacets) and spec slider ranges (specRanges) over the same filtered set.
  • Full spec on detail. GET /v2/listings/vin/{vin} returns the listing, its variant and the full canonical spec in one call.
  • A build key on every row. nano groups listings of the same build, for deduplication and comparables, and is also a filter.
  • Transport Canada recalls. GET /v2/vin/{vin}/recalls lists the campaigns for the VIN's model year, tagged with their issuing authority, Transport Canada (tc) or NHTSA (nhtsa).
  • Metric and Canadian by default. Radius and odometer in kilometres, prices with an explicit currency (default CAD), and up to 250 rows per page against MarketCheck's 50.

FAQ

Can I keep my MarketCheck parsing code? Yes, for the fields that map. Use the adapter above. Fields with no mapping come back undefined.

Do I still pass make=Toyota? No. Cardog filters on refs: make=make:toyota. Free text returns a 400. Use GET /v2/entities/resolve to look up a ref.

Why is the total a separate call? The search response carries listings and pagination only. GET /v2/listings/facets (as totalCount) and GET /v2/listings/count (as count) take the same filters and return distinct VINs.

Are odometer and radius in miles? No. Both are in kilometres. MarketCheck's miles, radius and dist are in miles.

How is it billed? Search, count, facets and detail are one credit per request each, so the adapter above costs two. See /pricing.

Sources

Checked on 2026-10-26:

If something here is wrong, tell us and we will fix it.