# Sold Vehicles Summary

> Get monthly sold-vehicle statistics for US dealer sales since January 2021, grouped by geography and vehicle attributes and ranked by any measure.

Use the Sold Vehicles Summary API to see how many vehicles sold in a market, at what price, with what mileage, and how long they were for sale. One call returns ranked rows with the sold count, price, mileage, and days-on-market statistics (including percentiles), and MSRP averages, grouped by month, geography, and the vehicle attributes you choose.

The Sold Vehicles Summary API aggregates US dealer sales by month. You can summarize at state, city, or national level, filter by vehicle, dealer, and website attributes, and rank groups by any measure in the response.

This enables dealers, dealership groups, manufacturers, lenders, insurers, and market analysts to see which vehicles sell where, at what price, and how quickly.



## Overview

- Statistics on US dealer sales from January 2021 through the latest complete month, refreshed monthly
- Sales are inferred from listings that disappear from dealer websites. Read more about [Inferred Sales](/docs/guides/data/cars/inventory/key-concepts#inferred-sales)
- Prices are advertised asking prices at the time of sale, not negotiated transaction prices
- Results are aggregated rows only, never individual listings or VINs. Auction and private-seller listings are excluded

**Measures & Definitions:**

- **Counts**: Each statistic covers only vehicles with a value, shown in its `count` field
- **Days on Site**: `dos_active` counts days on the website domain the vehicle sold on
- **MSRP on Used Vehicles**: Compare prices with `mc_msrp`, not the listing `msrp`
- **Mileage**: Excludes readings over 500,000, kilometer readings, and readings of 0 on used vehicles



## How It Works

Each row in the response is one group: a month, a geography, the inventory type (unless `inventory_type=all` combines new and used), and the values of the ranking dimensions you request. A ranking dimension is a field that defines a group, such as `make` or `model`. A measure is a statistic in a row, such as `sold_count`, `price.mean`, or `miles.p50`.

Percentile measures are named `pNN` in parameters and read from `percentiles` in the row, so `price.p50` is `price.percentiles["50.0"]`. Other measure names match their path in the row, such as `price.mean`.

Within each month and geography, the API ranks the groups by `ranking_measure` and returns the top `top_n` ranks.

- Month is part of every group, including at the national level. A twelve-month request returns up to one row per month for each group
- Rows with no value for the geography or a requested dimension are excluded. Use `ranking_dimensions=none` to get one totals row per month and geography, with no rows excluded

Filters work at two stages. Row filters, such as `make`, `state`, and `year_range`, act on vehicles. Measure filters, such as `price.mean` and `sold_count`, act on whole groups:

| Behavior        | Row Filters     | Measure Filters |
|-----------------|-----------------|-----------------|
| Applied | Before statistics are computed | After statistics are computed |
| Removes | Vehicles | Whole groups |
| Effect on statistics in a remaining row | Changes them | Leaves them unchanged |




## Base Path

```http
GET https://api.marketcheck.com/v2/sold-vehicles/summary
```

The following example demonstrates a basic request that returns statistics for used Toyota RAV4s sold in Rhode Island in the latest complete month:

```bash
curl --request GET \
  --url https://api.marketcheck.com/v2/sold-vehicles/summary
```

Explore the full range of parameters available for filtering, grouping, and ranking results in the [Parameters](#parameters) section below.



## Request

The Sold Vehicles Summary API requires `api_key` and `inventory_type` on every request. All other parameters are optional and let you narrow, group, and rank the results.

> **IMPORTANT**: 
> `inventory_type` has no default, and a request without it returns `422`. An invalid value (including a differently cased value such as `Used`), or an unknown, repeated, or empty parameter, also returns `422`.

Send multiple values for a parameter as a comma-separated list (e.g., `make=Ford,Toyota`), and send each parameter only once. Parameters such as `inventory_type`, `summary_by`, `dealer_type`, `ranking_order`, `year_range`, and `miles_range` accept only one value. Values from a fixed list, such as those for `inventory_type`, `dealer_type`, `summary_by`, `ranking_order`, and `fuel_type_category`, must be lowercase.

Other filter values are matched case-insensitively and literally, without wildcards or negation. Free-text values are not validated, so a misspelled value (e.g., `state=Californ`) returns `200` with an empty `data` array. Check `applied` in the response to see how the API interpreted the request. `dealership_group_name` is also matched case-insensitively, but it is validated: an unrecognized name returns `422`.

To see the values the API uses for a field, request it as a ranking dimension with a high `top_n` (e.g., `inventory_type=used&summary_by=national&make=Kia&ranking_dimensions=model&top_n=500`). Only values with sales in the date window are returned.



### Parameters

Available parameters for filtering, grouping, and ranking results:

| Parameter   | Type        | Required    | Description |
|-------------|-------------|-------------|-------------|
| `api_key` | string | Yes | Your MarketCheck API authentication key. Required for every request, unless OAuth is used. |
| `base_exterior_color` | string | No | Filters sold vehicles by base exterior color (e.g., `White`, `Black`, `Gray`, `Silver`). Accepts multiple values separated by commas. |
| `base_interior_color` | string | No | Filters sold vehicles by base interior color (e.g., `Black`, `Gray`, `Beige`, `Brown`). Accepts multiple values separated by commas. |
| `body_subtype` | string | No | Filters sold vehicles by pickup cab configuration (e.g., `Crew`, `Extended`, `Regular`). Accepts multiple values separated by commas. |
| `body_type` | string | No | Filters sold vehicles by body type (e.g., `SUV`, `Pickup`). Accepts multiple values separated by commas. |
| `city` | string | No | Filters sold vehicles by city name (e.g., `Austin`, `Los Angeles`). Accepts multiple values separated by commas. Send with `state`. |
| `date_from` | string | No | Start of the sale-date window, as the first day of a month. Specify as `YYYY-MM-DD` (e.g., `2026-01-01`) and send with `date_to`. Default — first day of the latest complete month. |
| `date_to` | string | No | End of the sale-date window, as the last day of a month. Specify as `YYYY-MM-DD` (e.g., `2026-06-30`) and send with `date_from`. Default — last day of the latest complete month. |
| `dealer_type` | string | No | Filters sold vehicles by dealer type. Allowed values — `all`, `franchise`, `independent`. Default — `all`. |
| `dealership_group_name` | string | No | Filters sold vehicles by dealership group name (e.g., `AutoNation Inc.`), matched case-insensitively. Accepts multiple values separated by commas. Get accepted names from the Sold Vehicles Dealership Groups API. |
| `dom_active.count` | string | No | Filters groups by the number of vehicles with a `dom_active` value, with an optional comparison operator (e.g., `>=10`). |
| `dom_active.mean` | string | No | Filters groups by mean days on market, with an optional comparison operator (e.g., `<30`). |
| `dom_active.p50` | string | No | Filters groups by median days on market, with an optional comparison operator (e.g., `<30`). |
| `dos_active.count` | string | No | Filters groups by the number of vehicles with a `dos_active` value, with an optional comparison operator (e.g., `>=10`). |
| `dos_active.mean` | string | No | Filters groups by mean days on site, with an optional comparison operator (e.g., `<30`). |
| `dos_active.p50` | string | No | Filters groups by median days on site, with an optional comparison operator (e.g., `<30`). |
| `drivetrain` | string | No | Filters sold vehicles by drivetrain (`4WD`, `FWD`, `RWD`). Accepts multiple values separated by commas. |
| `fuel_type_category` | string | No | Filters sold vehicles by fuel type category. Allowed values — `ice`, `ev`, `hybrid`, `unknown`, `other`. Accepts multiple values separated by commas. |
| `inventory_type` | string | Yes | Inventory type of the sold vehicles. Allowed values — `new`, `used`, `certified`, `all`. `used` includes certified pre-owned vehicles, `certified` returns them only, and `all` combines new and used (certified included) into one row unless `ranking_dimensions` includes `inventory_type`. Accepts one value. Required. |
| `limit` | integer | No | Maximum number of rows to return. Default — 20000. Maximum — 20000. |
| `make` | string | No | Filters sold vehicles by make (e.g., `Toyota`, `Ford`). Accepts multiple values separated by commas. |
| `mc_msrp.count` | string | No | Filters groups by the number of vehicles with a MarketCheck MSRP, with an optional comparison operator (e.g., `>=10`). |
| `mc_msrp.mean` | string | No | Filters groups by mean MarketCheck MSRP, with an optional comparison operator (e.g., `>40000`). |
| `miles.count` | string | No | Filters groups by the number of vehicles with a valid odometer reading, with an optional comparison operator (e.g., `>=10`). |
| `miles.mean` | string | No | Filters groups by mean mileage, with an optional comparison operator (e.g., `<30000`). |
| `miles.p25` | string | No | Filters groups by 25th percentile mileage, with an optional comparison operator (e.g., `<30000`). |
| `miles.p50` | string | No | Filters groups by median mileage, with an optional comparison operator (e.g., `<30000`). |
| `miles.p75` | string | No | Filters groups by 75th percentile mileage, with an optional comparison operator (e.g., `<60000`). |
| `miles.p95` | string | No | Filters groups by 95th percentile mileage, with an optional comparison operator (e.g., `<100000`). |
| `miles_range` | string | No | Filters sold vehicles by odometer reading. Specify as `min-max` miles (e.g., `30000-60000`). |
| `min_sold_count` | integer | No | Filters groups by a minimum number of vehicles sold (e.g., `30`). Shorthand for `sold_count=>=n`. Cannot be combined with `sold_count`. |
| `model` | string | No | Filters sold vehicles by model (e.g., `RAV4`, `F-150`). Accepts multiple values separated by commas. |
| `msrp.count` | string | No | Filters groups by the number of vehicles with a listing MSRP, with an optional comparison operator (e.g., `>=10`). |
| `msrp.mean` | string | No | Filters groups by mean listing MSRP, with an optional comparison operator (e.g., `>40000`). |
| `msrp_label` | string | No | Filters sold vehicles by the source of the MarketCheck MSRP (e.g., `oem_msrp`, `build_specs_msrp`). Accepts multiple values separated by commas. |
| `powertrain_type` | string | No | Filters sold vehicles by powertrain type (e.g., `Combustion`, `BEV`, `HEV`, `PHEV`). Accepts multiple values separated by commas. |
| `price.count` | string | No | Filters groups by the number of vehicles with a price, with an optional comparison operator (e.g., `>=10`). |
| `price.max` | string | No | Filters groups by highest price, with an optional comparison operator (e.g., `<50000`). |
| `price.mean` | string | No | Filters groups by mean price, with an optional comparison operator (e.g., `>20000`). |
| `price.min` | string | No | Filters groups by lowest price, with an optional comparison operator (e.g., `>5000`). |
| `price.p25` | string | No | Filters groups by 25th percentile price, with an optional comparison operator (e.g., `>20000`). |
| `price.p50` | string | No | Filters groups by median price, with an optional comparison operator (e.g., `<=35000`). |
| `price.p75` | string | No | Filters groups by 75th percentile price, with an optional comparison operator (e.g., `>20000`). |
| `price.p95` | string | No | Filters groups by 95th percentile price, with an optional comparison operator (e.g., `>20000`). |
| `price.stddev` | string | No | Filters groups by the standard deviation of price, with an optional comparison operator (e.g., `<5000`). |
| `price.sum` | string | No | Filters groups by the total of all prices, with an optional comparison operator (e.g., `>1000000`). |
| `price_over_mc_msrp_percentage` | string | No | Filters groups by the percentage difference between mean price and mean MarketCheck MSRP, with an optional comparison operator (e.g., `<-5`). |
| `price_over_msrp_percentage` | string | No | Filters groups by the percentage difference between mean price and mean MSRP, with an optional comparison operator (e.g., `<0`). |
| `rank_after_filters` | boolean | No | If `true`, applies measure filters before ranking, so removed groups leave no gaps in the ranks. Default — false. |
| `ranking_dimensions` | string | No | Comma-separated list of fields to group and rank by (e.g., `make,model`), or `none` for totals. Default — `make,model,body_type`. |
| `ranking_measure` | string | No | Measure to rank groups by: `sold_count`, `price_over_msrp_percentage`, `price_over_mc_msrp_percentage`, or a dotted measure name (e.g., `price.mean`). `min_sold_count` is not a ranking measure. Default — `sold_count`. |
| `ranking_order` | string | No | Specifies ranking order. Allowed values — `asc` or `desc`. Default — `desc`. |
| `sold_count` | string | No | Filters groups by the number of vehicles sold, with an optional comparison operator (e.g., `>100`). Cannot be combined with `min_sold_count`. |
| `source` | string | No | Filters sold vehicles by website domain (e.g., `carmax.com`). Accepts multiple values separated by commas. |
| `state` | string | No | Filters sold vehicles by US state code, including DC and US territories (e.g., `CA`, `TX`). Accepts multiple codes separated by commas. |
| `summary_by` | string | No | Geographic level of the result rows. Allowed values — `state`, `city_state`, `national`. Default — `state`. |
| `top_n` | integer | No | Number of ranks to return within each month and geography. Default — 10. |
| `transmission` | string | No | Filters sold vehicles by transmission (`Automatic`, `CVT`, `Manual`). Accepts multiple values separated by commas. |
| `trim` | string | No | Filters sold vehicles by trim (e.g., `XLE`, `EX`). Accepts multiple values separated by commas. |
| `year` | string | No | Filters sold vehicles by model year (e.g., `2022`). Accepts multiple years separated by commas. Cannot be combined with `year_range`. |
| `year_range` | string | No | Filters sold vehicles by model year range. Specify as `min-max` (e.g., `2020-2024`), with either end optional (e.g., `2020-`). Cannot be combined with `year`. |




### Defaults

| Parameter     | Default Value | Description   |
|---------------|---------------|---------------|
| `date_from`, `date_to` | Latest complete month | The request covers one month. Send both to set a window of up to 365 days |
| `dealer_type` | `all` | Franchise and independent dealers are both counted |
| `limit` | `20000` | Maximum total rows in the response |
| `rank_after_filters` | `false` | Groups are ranked before measure filters are applied |
| `ranking_dimensions` | `make,model,body_type` | Each group is one make, model, and body type |
| `ranking_measure` | `sold_count` | Groups are ranked by units sold |
| `ranking_order` | `desc` | Highest value ranks first |
| `summary_by` | `state` | Rows are returned per state |
| `top_n` | `10` | Ten ranks within each month and geography |


Check `top_n_source` and `date_window_source` in the response's `applied` object to see whether `top_n` and the date window came from your request (`"request"`) or a default (`"default"`).



### Required Parameters



#### inventory_type

- **Required parameter** that sets which sold vehicles are counted. Accepts one value
- Supported values: `new`, `used` (includes certified pre-owned vehicles), `certified` (certified pre-owned only), and `all` (new and used combined, so certified vehicles are included)
- Any other value, including a differently cased one such as `Used`, returns `422`
- Example: `inventory_type=used`

> **WARNING**: 
> `inventory_type=all` combines new and used vehicles into one row per group, with no `inventory_type` key, and returns a `pooled_populations` warning. Counts and sums (`sold_count`, `price.sum`, and each `count`) stay exact, but means and percentiles mix the two populations. To get separate new and used rows, add `inventory_type` to `ranking_dimensions` (e.g., `inventory_type=all&ranking_dimensions=inventory_type,make`); new and used groups are then ranked together, so `top_n` applies across both.

Rows report the inventory type as `new` or `used` only. With `inventory_type=certified`, each row shows `"used"`, and `applied.inventory_type` shows `"certified"`.



### Geographic Parameters



#### summary_by

- Use `summary_by` to set the level of the result rows: `state`, `city_state`, or `national`
- `state` and `city` filter the rows. For example, `summary_by=city_state&state=TX` returns every city in Texas, and adding `city=Austin` returns Austin only
- Example: `summary_by=national`



#### city

- Use `city` to filter by city name at any `summary_by` level
- Send `state` with `city`. Without it, cities with the same name in different states are combined, and the API returns a `city_filter_without_state` warning
- Example: `summary_by=city_state&state=TX&city=Austin`

> **NOTE**: 
> City is the finest geography available. Metro, DMA, and ZIP code levels are not supported.



### Special Parameters



#### date_from & date_to

- Use `date_from` (the first day of a month) and `date_to` (the last day of a month) in `YYYY-MM-DD` format to set the sale-date window
- Send both or neither. Without them, the request covers the latest complete month
- The window can span up to 365 days, and any single calendar year is accepted. A longer window returns `422`, and a window outside the available history returns a `window_outside_available_history` warning
- Example: `date_from=2026-01-01&date_to=2026-06-30`



#### year_range

- Use `year_range` to filter by model year range in `min-max` format. Both ends are inclusive
- Leave either end open: `year_range=2020-` (or `2020-*`) means 2020 and later, and `year_range=-2024` (or `*-2024`) means 2024 and earlier
- `year_range=-`, `year_range=*-*`, and a minimum above the maximum return `422`. Do not combine `year_range` with `year`
- Example: `year_range=2020-2023`



#### miles_range

- Use `miles_range` to filter by odometer reading in `min-max` format. Both ends are inclusive
- Leave either end open, as in `miles_range=30000-`
- Example: `miles_range=30000-60000`



### Sorting & Ranking

The Sold Vehicles Summary API ranks groups within each month and geography, and returns rows in a fixed order.

**Ranking Parameters:**

- `ranking_dimensions` - Fields that define each group (e.g., `make,model`), or `none` for one totals row per month and geography. Do not combine `none` with other fields
- `ranking_measure` - Measure to rank by: `sold_count`, `price_over_msrp_percentage`, `price_over_mc_msrp_percentage`, or a dotted measure such as `price.p50`, all listed in [Parameters](#parameters). `min_sold_count` is not a ranking measure
- `ranking_order` - Ranking direction (`asc` or `desc`)
- `top_n` - Number of ranks returned within each month and geography

**Default Behavior:**

- Within each month and geography, each group is one make, model, and body type, groups are ranked by `sold_count` in descending order, and the top 10 ranks are returned
- Groups that tie share a rank and are all returned. A response can contain more rows than `top_n` suggests
- Rows are sorted by month and geography in descending order, then by `rank`

**Available Ranking Dimensions**

Fields are listed in the order they appear in each row.

| Field       | Description |
|-------------|-------------|
| inventory_type | Inventory type of the row: `new` or `used` (certified vehicles show as `used`). Use it to split rows when `inventory_type=all` |
| year | Model year |
| make | Vehicle make |
| model | Vehicle model, in the source's spelling (casing can differ, e.g., `Forte` and `FORTE`) |
| trim | Trim level |
| body_type | Body type |
| body_subtype | Pickup cab configuration |
| drivetrain | Drivetrain |
| transmission | Transmission |
| powertrain_type | Powertrain type, recommended for electrification analysis |
| fuel_type_category | Fuel type category (can classify mild hybrids as `ice`) |
| base_exterior_color | Base exterior color |
| base_interior_color | Base interior color |
| msrp_label | Source of the MarketCheck MSRP |
| dealership_group_name | Dealership group name |
| source | Website domain the vehicle sold on |


`body_subtype`, `powertrain_type`, `base_exterior_color`, `base_interior_color`, and `dealership_group_name` have no value on many rows. Requesting any of them returns a `sparse_dimension_rows_excluded` warning.

**Limits:**

- `limit` caps the total rows in the response, up to 20,000. When rows are removed, `truncated` is `true`
- Rows are removed from the end of the sort order: the earliest months first and, within a month, the alphabetically first states (or cities, at `city_state` level)
- There is no pagination. To get the removed rows, narrow the filters or the date window

> **CAUTION**: 
> With `ranking_order=asc`, groups whose ranking measure is `null` rank first. To keep them out of the ranking, set a minimum on the matching count and `rank_after_filters=true` (e.g., `ranking_measure=price.mean&ranking_order=asc&price.count=%3E%3D1&rank_after_filters=true`).



### Measure Filters

Measure filters remove whole groups after the statistics are computed (e.g., groups with fewer than 30 sales), and do not change the numbers inside a remaining group. The measure filter parameters are `sold_count`, the two `price_over_*_percentage` parameters, and the dotted parameters such as `price.mean`, all listed in [Parameters](#parameters).

**Parameters and Syntax**

- Each measure filter accepts an optional operator (`>`, `<`, `>=`, `<=`, `=`) followed by a number. A bare number means `=`, and negative and decimal numbers are accepted

  - Example: `price.p50=<=35000` (sent as `price.p50=%3C%3D35000`) keeps groups whose median price is at most 35,000
  - Example: `price_over_mc_msrp_percentage=<-5` (sent as `price_over_mc_msrp_percentage=%3C-5`) keeps groups whose mean price is more than 5% below the mean MarketCheck MSRP
- `min_sold_count=<n>` is shorthand for `sold_count=>=<n>`. Sending both returns `422`
  - Example: `min_sold_count=30` keeps groups with at least 30 sales
- `rank_after_filters` sets the order of ranking and filtering. With the default `false`, groups are ranked first and then filtered, and ranks can have gaps. With `true`, groups are filtered first, so removed groups leave no gaps in the ranks
- If every ranked group is removed, `data` is empty and the API returns a `measure_filter_removed_all_ranked_rows` warning

> **IMPORTANT**: 
> URL-encode the operators in your HTTP requests (e.g., `>` as `%3E`, `<` as `%3C`, and `>=` as `%3E%3D`).

**Example**

Here in this example, we are finding used models in Texas with a median mileage under 30,000 in July 2026, ranked by units sold among the groups that pass the filter:

```bash
curl --request GET \
  --url https://api.marketcheck.com/v2/sold-vehicles/summary
```



## Response

The Sold Vehicles Summary API returns a JSON object containing the request as the API interpreted it (`applied`), any warnings, and one row of statistics per group.



### Schema

```typescript
interface SoldSummaryResponse {
  success: boolean; // true when the query ran, even if it matched no groups
  result_count: number; // Number of rows in data
  limit: number; // Row limit the query ran with
  truncated: boolean; // true when limit removed rows
  warnings: Warning[]; // Always present; [] when there is nothing to report
  applied: object; // The request as the API interpreted it, including defaults
  data: SummaryRow[]; // One object per group
}

interface Warning {
  code: string; // Warning code (see Warnings below)
  message: string; // Human-readable explanation
  detail: object; // Warning-specific context
}

interface SummaryRow {
  month: string; // "YYYY-MM"
  inventory_type?: string; // "new" or "used" (certified vehicles show as "used"); absent when inventory_type=all and inventory_type is not in ranking_dimensions
  city?: string; // Present only when summary_by=city_state
  state?: string; // Present when summary_by=state or city_state
  // ...one key per requested ranking dimension, for example make, model
  rank: number; // Rank within the month and geography
  sold_count: number; // Number of vehicles sold
  price: PriceStats; // Advertised asking price at the time of sale
  miles: MilesStats; // Odometer reading
  dom_active: DaysStats; // Days for sale on any website
  dos_active: DaysStats; // Days for sale on the website it sold on
  msrp: MsrpStats; // MSRP shown on the listing
  mc_msrp: MsrpStats; // MarketCheck MSRP
  price_over_msrp_percentage: number | null; // (mean price - mean msrp) / mean msrp x 100
  price_over_mc_msrp_percentage: number | null; // Same, against mc_msrp
}

interface PriceStats {
  count: number; // Vehicles with a price
  mean: number | null;
  sum: number | null;
  min: number | null;
  max: number | null;
  stddev: number | null; // Sample standard deviation; null when count is 1
  percentiles: { "25.0": number | null; "50.0": number | null; "75.0": number | null; "95.0": number | null };
}

interface MilesStats {
  count: number; // Vehicles with a valid odometer reading
  mean: number | null;
  percentiles: { "25.0": number | null; "50.0": number | null; "75.0": number | null; "95.0": number | null };
}

interface DaysStats {
  count: number; // Vehicles with a value
  mean: number | null;
  percentiles: { "50.0": number | null };
}

interface MsrpStats {
  count: number; // Vehicles with a value
  mean: number | null;
}
```



### Warnings

Each warning in the `warnings` array has a `code`, `message`, and `detail`. Use `code`, not `message`, when you handle warnings. A warning does not change the status code or the data returned.

| Code          | Returned When |
|---------------|---------------|
| `city_filter_without_state` | `city` is sent without `state` |
| `measure_filter_removed_all_ranked_rows` | `data` is empty and measure filters were applied |
| `pooled_populations` | `inventory_type=all` is sent and `inventory_type` is not in `ranking_dimensions`. `detail.affected_measures` names the affected measure objects, such as `price` and `miles` |
| `ranking_parameters_ignored` | `ranking_dimensions=none` is sent, and you explicitly sent `top_n`, `ranking_measure`, or `ranking_order` |
| `result_truncated` | `limit` removed rows |
| `sparse_dimension_rows_excluded` | A requested ranking dimension has no value on many rows |
| `window_outside_available_history` | The date window falls wholly or partly outside the available history |




### Success Response

- `200 OK` - Returns JSON object with grouped sold-vehicle statistics, or an empty `data` array (with `success: true`) when no groups match
- Percentile keys are strings such as `"50.0"`. Counts and `rank` are integers, and other statistics are floats rounded to 2 decimal places
- Mileage values are in miles, `dom_active` and `dos_active` values are in days, and `price_over_*_percentage` values are percentages (`-5` means 5% below MSRP)
- Keys that do not apply to a row are omitted (e.g., `city` at `state` level, or `inventory_type` when `inventory_type=all` is sent without `inventory_type` in `ranking_dimensions`), and a statistic is `null` when its `count` is 0

`applied` echoes the request as the API interpreted it, including defaults, `inventory_type` as sent (e.g., `"certified"`), the canonical spellings of any `dealership_group_name` values, and `available_history` (the first and latest complete months).

The request under [Base Path](#base-path) returns a response like the following, captured when July 2026 was the latest complete month (`applied` is abridged):

```json
{
  "success": true,
  "result_count": 1,
  "limit": 20000,
  "truncated": false,
  "warnings": [],
  "applied": {
    "summary_by": "state",
    "ranking_dimensions": ["make", "model"],
    "ranking_measure": "sold_count",
    "ranking_order": "desc",
    "top_n": 1,
    "top_n_source": "request",
    "limit": 20000,
    "date_from": "2026-07-01",
    "date_to": "2026-07-31",
    "date_window_source": "default",
    "available_history": {
      "first_month": "2021-01",
      "latest_complete_month": "2026-07"
    },
    "inventory_type": "used",
    "state": ["RI"],
    "make": ["Toyota"],
    "model": ["RAV4"],
    "semantics": {
      "drop_null_dimensions": true,
      "rank_after_filters": false
    }
  },
  "data": [
    {
      "month": "2026-07",
      "inventory_type": "used",
      "state": "RI",
      "make": "Toyota",
      "model": "RAV4",
      "rank": 1,
      "sold_count": 125,
      "price": {
        "count": 111,
        "mean": 26470.85,
        "sum": 2938264.0,
        "min": 4499.0,
        "max": 43708.0,
        "stddev": 9521.45,
        "percentiles": {
          "25.0": 18998.0,
          "50.0": 27419.0,
          "75.0": 34608.0,
          "95.0": 39876.5
        }
      },
      "miles": {
        "count": 124,
        "mean": 75611.2,
        "percentiles": {
          "25.0": 25119.25,
          "50.0": 62588.0,
          "75.0": 116009.0,
          "95.0": 184984.3
        }
      },
      "dom_active": {
        "count": 125,
        "mean": 31.1,
        "percentiles": { "50.0": 21.0 }
      },
      "dos_active": {
        "count": 125,
        "mean": 29.77,
        "percentiles": { "50.0": 20.0 }
      },
      "msrp": { "count": 111, "mean": 26697.7 },
      "mc_msrp": { "count": 125, "mean": 33264.46 },
      "price_over_msrp_percentage": -0.85,
      "price_over_mc_msrp_percentage": -20.42
    }
  ]
}
```

Here, 125 vehicles sold and 111 had a price, and `price.mean` is the mean over those 111 vehicles. The mean price is 0.85% below the mean `msrp` and 20.42% below the mean `mc_msrp`. This gap is why `mc_msrp` is the better reference on used vehicles.



### Error Response

| Status Code   | Description   | Common Causes |
|---------------|---------------|---------------|
| 401 | Unauthorized | Missing/invalid API key |
| 403 | Forbidden | Access denied to resource |
| 405 | Method Not Allowed | A method other than `GET` or `OPTIONS` |
| 422 | Unprocessable Entity | Missing `inventory_type`, an invalid value or combination, or an unknown, repeated, or empty parameter |
| 429 | Too Many Requests | Rate limit exceeded |
| 500 | Internal Server Error | Temporary server issues, or a request that did not complete in time |
| 502 | Bad Gateway | Issues with upstream services |
| 503 | Service Unavailable | Data temporarily unavailable, or the request was too large to process |


**Error Response Format**

Most error responses follow this structure. `message` is usually a string, but it can be an object, as in a `422` response, which contains a `detail` array (shown below), and in some `5xx` responses. A `429` response contains only `message` (see [Quota and Rate Limits](/docs/get-started/api/quota-and-rate-limits)), and some `502` and `503` responses may not follow this structure:

```json
{
  "code": <HTTP status code>,
  "message": "<Error message describing the issue>"
}
```

**Example Error Response:**

Unrecognized parameter (422):

```json
{
  "code": 422,
  "message": {
    "detail": [
      {
        "type": "extra_forbidden",
        "loc": ["query", "bogus"],
        "msg": "Extra inputs are not permitted",
        "input": "1"
      }
    ]
  }
}
```

In a `422` response, `message.detail` has one entry for each invalid parameter. Use `type` and `loc`, not `msg`, in your error handling, since `msg` text can change:

| Type         | Returned For |
|--------------|--------------|
| `enum` | An invalid value for `inventory_type`, `dealer_type`, `summary_by`, or `ranking_order`, including a differently cased value |
| `extra_forbidden` | An unrecognized parameter |
| `greater_than_equal`, `less_than_equal` | `top_n` below 1, or `limit` below 1 or above 20000 |
| `missing` | `inventory_type` not sent |
| `value_error` | A repeated or empty parameter, or an invalid `fuel_type_category`, `ranking_measure`, `year`, `year_range`, `miles_range`, `dealership_group_name`, or measure filter |


**Best Practices**

- Always check HTTP status codes
- Log the full `422` body. `msg` explains how to fix the request, but match on `type` and `loc` in code
- Read `applied` when `data` is empty
- Retry `502` and `503` with exponential backoff. If a `500` or `503` repeats for the same request, narrow the date window or filters instead. On `429`, wait for the time in the `Retry-After` header (see [Quota and Rate Limits](/docs/get-started/api/quota-and-rate-limits))



## Use Cases & Examples

Each example sets `date_from` and `date_to`. Change them to the months you need.



### Get Totals for a Model in a State

Get the full set of statistics for one model in one market, such as the price range and typical days on market. This is useful for shoppers and dealers who need a market reference for a specific vehicle.

Use `ranking_dimensions=none` to get one totals row per month. With one row per month and geography, ranking has no effect, and `applied.ranking_ignored` is `true` in the response.

**Example:**

Here in this example, we are retrieving totals for used Subaru Crosstreks sold in Colorado in July 2026:

```bash
curl --request GET \
  --url https://api.marketcheck.com/v2/sold-vehicles/summary
```



### Find the Top-Selling Models in a State

Find which models sold the most in a state to guide stocking decisions. Use `ranking_dimensions=make,model`, and compare `price.mean` with `price.percentiles["50.0"]` to see how much high-priced outliers raise the mean.

**Example:**

Here in this example, we are ranking the top 15 used makes and models in Texas by units sold in July 2026:

```bash
curl --request GET \
  --url https://api.marketcheck.com/v2/sold-vehicles/summary
```



### Find the Top-Selling Certified Pre-Owned Models

Find which certified pre-owned models sell the most with `inventory_type=certified`. The statistics cover certified vehicles only, and each row shows `inventory_type` as `"used"`. Compare the results with an `inventory_type=used` request to see the certified share of used sales.

**Example:**

Here in this example, we are ranking the top 3 certified pre-owned Toyota models nationally by units sold in July 2026:

```bash
curl --request GET \
  --url https://api.marketcheck.com/v2/sold-vehicles/summary
```



### Find the Fastest-Selling Models

Find the models that sold fastest with `ranking_measure=dom_active.mean&ranking_order=asc`. Use `min_sold_count` to require a minimum number of sales, and `rank_after_filters=true` to apply that minimum before ranking, so the top 10 come from models that meet it.

**Example:**

Here in this example, we are ranking used models in Ohio by mean days on market for each month from May through July 2026, keeping only models with at least 30 sales:

```bash
curl --request GET \
  --url https://api.marketcheck.com/v2/sold-vehicles/summary
```



### Estimate a Price Band for a Specific Vehicle

Estimate the advertised price band for a specific vehicle by filtering to one year, make, model, and trim. The response has one row per month. Read the band from `price.percentiles`, and check `price.count` to see how many sales each band is based on.

**Example:**

Here in this example, we are retrieving monthly price distributions for used 2023 Honda Civic EX vehicles sold in Pennsylvania from May through July 2026:

```bash
curl --request GET \
  --url https://api.marketcheck.com/v2/sold-vehicles/summary
```



### Find the Top-Selling Websites in a City

Find which dealer websites sell the most vehicles in a city. Use `summary_by=city_state` with `state` and `city`, and set `ranking_dimensions=source`. `source` is the website domain, the closest available match to an individual dealer.

**Example:**

Here in this example, we are ranking the websites with the most used-vehicle sales in Austin, Texas, in July 2026:

```bash
curl --request GET \
  --url https://api.marketcheck.com/v2/sold-vehicles/summary
```



### Analyze a Mileage Band

Analyze prices for vehicles within a mileage band, for example to support lending decisions. Use `miles_range` to filter vehicles before statistics are computed, so every statistic describes only the vehicles inside the band.

**Example:**

Here in this example, we are retrieving statistics for used 2020 to 2023 model-year vehicles with 30,000 to 60,000 miles sold in Texas in July 2026:

```bash
curl --request GET \
  --url https://api.marketcheck.com/v2/sold-vehicles/summary
```



### Track a Monthly Trend

Track how volume, price, and mileage change month by month with a single twelve-month request. To combine months yourself, use `price.sum` and `price.count` rather than averaging the monthly means.

**Example:**

Here in this example, we are retrieving national used-vehicle totals for each month from August 2025 through July 2026:

```bash
curl --request GET \
  --url https://api.marketcheck.com/v2/sold-vehicles/summary
```



### Find Where a Make Sells Below MSRP

Find the states where a make sells below MSRP. Use `price_over_msrp_percentage=%3C0` to keep only groups that sold below MSRP on average, and `min_sold_count` to remove groups with too few sales to compare.

**Example:**

Here in this example, we are finding the states where new Nissans sold below MSRP on average in July 2026, with at least 50 sales:

```bash
curl --request GET \
  --url https://api.marketcheck.com/v2/sold-vehicles/summary
```



### Rank Models by Median Price

Rank models by a percentile instead of a count, for example with `ranking_measure=price.p50` to find the highest-priced models. Pair it with `min_sold_count` and `rank_after_filters=true` to keep small groups out of the ranking.

**Example:**

Here in this example, we are ranking the top 8 used models nationally by median price in July 2026, keeping only models with at least 250 sales:

```bash
curl --request GET \
  --url https://api.marketcheck.com/v2/sold-vehicles/summary
```



### Rank Dealership Groups by Sales

Rank dealership groups to compare their sales volume in a region. Use `ranking_dimensions=dealership_group_name`. Rows without a dealership group are excluded, and the response includes a `sparse_dimension_rows_excluded` warning.

**Example:**

Here in this example, we are ranking the top 10 dealership groups by used-vehicle sales in each of Illinois, Indiana, and Wisconsin in July 2026:

```bash
curl --request GET \
  --url https://api.marketcheck.com/v2/sold-vehicles/summary
```



### Compare Specific Dealership Groups

Compare named dealership groups by passing their names as `dealership_group_name` and ranking by `dealership_group_name`. Each row describes one dealership group, so you can compare their volume, prices, and days on market side by side.

**Example:**

Here in this example, we are comparing used-vehicle sales for six dealership groups nationally in July 2026:

```bash
curl --request GET \
  --url https://api.marketcheck.com/v2/sold-vehicles/summary
```



### Compare New and Used Sales

Compare new and used sales in one request with `inventory_type=all` and `inventory_type` in `ranking_dimensions`. Each row then describes one inventory type, so means and percentiles stay accurate and no `pooled_populations` warning is returned. New and used groups are ranked together, so the top ranks can mix both. To rank each inventory type separately, send one request per type.

**Example:**

Here in this example, we are comparing new and used sales for four dealership groups nationally in July 2026:

```bash
curl --request GET \
  --url https://api.marketcheck.com/v2/sold-vehicles/summary
```



## Performance Considerations

Request time grows with the width of the date window, not with the size of the result. Twelve-month requests can take tens of seconds, while single-month requests return faster.

**Optimal Request Patterns**

1. **Narrow the date window first** - `limit` and `top_n` reduce the response size, not the request time
2. **Set a generous client timeout** - twelve-month requests can take tens of seconds. See [Request Timeout](/docs/get-started/api/quota-and-rate-limits#request-timeout) for the gateway limit
3. **Cache long series** - the data changes monthly, so you can reuse a series instead of requesting it again



## See Also

- [Inferred Sales Stats](/docs/api/cars/market-insights/inferred-sales-stats)
- [Popular Cars](/docs/api/cars/market-insights/popular-cars)
- [Past Inventory Search](/docs/api/cars/inventory/past-inventory-search)
