<Note variant="warning">
  The Ownership API is available on **Enterprise plans only**. If you're interested in access, [contact us](/contact)
  and we'll walk you through your options.
</Note>

The Ownership API answers one core question from four different starting points: **who is connected to this vehicle or place?** You always have something to start from — a VIN, a name and address, just an address, or a ZIP code — and the API resolves the rest: a registered owner, a resident, or a pool of people matching a set of filters.

All four lookup types are gated behind a single `ownership` entitlement on your API key and billed the same way: you're only ever charged when a match is found.

| You have…             | You call…                   | You get back…                                                        |
| :-------------------- | :-------------------------- | :------------------------------------------------------------------- |
| A 17-character VIN    | `GET /v1/ownership/vin`     | The vehicle's registered owner(s), contact info, and vehicle history |
| A full name + address | `GET /v1/ownership/person`  | Contact details and any vehicle linked to that identity              |
| Just a street address | `GET /v1/ownership/address` | Everyone on file at that address, contact info, and vehicle history  |
| A ZIP code + filters  | `GET /v1/ownership/zip`     | A page of matching people in that area                               |

<Note>
  Every response follows a strict **"charge only on non-empty results"** rule: if there's no match, you get a **404**
  with `error: "no_data"`, your usage counter doesn't move, and nothing is billed. When there is a match, billing scales
  with how many records come back — **not a flat rate per request**: the billed quantity is exactly the number of
  entries in `owners`/`matches`/`records`, so a 3-owner VIN response bills 3 units, not 1. ZIP is the one to watch here
  — it can return dozens of records in a single page, so one call there can consume far more quota than a typical
  VIN/Person/Address lookup. Across all four lookup types, `include` (and, on Address and ZIP, the legacy `variant`)
  only shapes which sections of the response are shown — everything is fetched, and billed, as a single base call.
</Note>

---

## VIN → Owner

<Row>
  <Col>
    Look up the registered owner(s) of a vehicle by VIN, along with vehicle attributes, vehicle history, and contact details.

    ### Required attributes

    <Properties>
      <Property name="key" type="string">
        Your CarsXE API key.
      </Property>
      <Property name="vin" type="string">
        The 17-character vehicle identification number.
      </Property>
    </Properties>

    ### Optional attributes

    <Properties>
      <Property name="include" type="string">
        Comma-separated subset of `demographics,emails,phones,vehicle_history`. Omit it to get everything.
      </Property>
    </Properties>

    <Note>
      `demographics`, `vehicle_history`, `emails`, and `phones` all come from the same single call — nothing about `include` changes what's fetched or billed, only which sections appear in the response. Omit `include` to get everything back by default.
    </Note>

    ---

    ### Response attributes

    <Properties>
      <Property name="success" type="boolean">
        Whether the request was processed successfully.
      </Property>
      <Property name="vin" type="string">
        The VIN you queried.
      </Property>
      <Property name="include" type="string">
        Echoes the `include` value you passed. Omitted entirely when you didn't pass one.
      </Property>
      <Property name="vehicle" type="object">
        Attributes for the queried vehicle. See the table below.
      </Property>
      <Property name="owners" type="array">
        One entry per person linked to this VIN, each billed as a separate unit (see the billing note above). Listed in order of recency — the most recent owner is first. See the table below.
      </Property>
      <Property name="error" type="string">
        Machine-readable error code, or `""` on success.
      </Property>
    </Properties>

    #### `vehicle` object

    | Field | Type | Description |
    | :--- | :--- | :--- |
    | `make`, `model` | string | Vehicle make and model. |
    | `year` | number \| null | Model year. |
    | `manufacturer` | string | Full legal manufacturer name. |
    | `fuel_type`, `drive_type`, `transmission_type` | string | e.g. `Diesel`, `4WD`, `A`. |
    | `body_type`, `body_subtype` | string | e.g. `PICKUP`, `Crew Cab`. |
    | `doors`, `engine_cylinders` | number \| null | |
    | `vehicle_class`, `size`, `vehicle_type` | string | e.g. `Mainstream`, `Full-Size`, `TRUCK`. |

    #### `owners[]` object

    | Field | Type | Description |
    | :--- | :--- | :--- |
    | `record_id` | string | Internal identity ID for this person. |
    | `first_name`, `last_name` | string | |
    | `age`, `gender` | string | Empty when not on file. |
    | `address` | object | `{ street, city, state, zip }`. |
    | `first_observed`, `last_observed` | string | `YYYY-MM-DD`. The date range this VIN-to-person link has been on file — how long it's been known, and how recently it was reconfirmed. Empty when not on file. |
    | `source_count` | number \| null | How many independent sources confirm this link. `null` when not on file. |
    | `demographics` | object | `marital_status`, `home_owner`, `children_in_household`, `veteran_in_household`, `occupation`, `income_range`, `net_worth_range`, `credit_range` — all raw string values, empty unless on file. |
    | `emails[]` | array | `{ address, last_seen }`. |
    | `phones[]` | array | `{ number, type, dnc }`. |
    | `vehicle_history[]` | array | Up to 3 other vehicles linked to this owner: `{ make, model, year, vin }`. |

    ### Errors

    | Status | `error` | Cause |
    | :--- | :--- | :--- |
    | 400 | `invalid_inputs` | Missing `vin`. |
    | 400 | `invalid_vin` | Not a well-formed 17-character VIN. |
    | 404 | `no_data` | No match — not billed. |

  </Col>
  <Col sticky>
    <CodeGroup title="Request" tag="GET" label="/v1/ownership/vin">
      ```bash
      curl -G https://api.carsxe.com/v1/ownership/vin \
        -d key=CARSXE_API_KEY \
        -d vin=1FT8X3BT0BEA61538
      ```
    </CodeGroup>

    <CodeGroup title="Request — narrowing the response with include" tag="GET" label="/v1/ownership/vin">
      ```bash
      curl -G https://api.carsxe.com/v1/ownership/vin \
        -d key=CARSXE_API_KEY \
        -d vin=1FT8X3BT0BEA61538 \
        -d include=demographics
      ```
    </CodeGroup>

    <CodeGroup title="Response — documentation sample VIN (includes populated demographics)">
      ```json showLineNumbers
      {
        "success": true,
        "vin": "1FT8X3BT0BEA61538",
        "vehicle": {
          "make": "Ford",
          "model": "F-350",
          "year": 2011,
          "manufacturer": "Ford Motor Company",
          "fuel_type": "Diesel",
          "drive_type": "4WD",
          "transmission_type": "A",
          "body_type": "PICKUP",
          "body_subtype": "Crew Cab",
          "doors": 4,
          "engine_cylinders": 8,
          "vehicle_class": "Mainstream",
          "size": "Full-Size",
          "vehicle_type": "TRUCK"
        },
        "owners": [
          {
            "record_id": "2074367570",
            "first_name": "Mark",
            "last_name": "Spence",
            "age": "57",
            "gender": "Male",
            "address": {
              "street": "910 Lucabaugh Mill Rd",
              "city": "Westminster",
              "state": "MD",
              "zip": "21157"
            },
            "first_observed": "2019-11-04",
            "last_observed": "2026-07-30",
            "source_count": 4,
            "demographics": {
              "marital_status": "Married",
              "home_owner": "Home Owner",
              "children_in_household": "",
              "veteran_in_household": "",
              "occupation": "President",
              "income_range": "$100,000 - $149,999",
              "net_worth_range": "$250,000 - $499,999",
              "credit_range": "700 - 749"
            },
            "emails": [{ "address": "mspence32@gmail.com", "last_seen": "2026-03-08" }],
            "phones": [{ "number": "4437890815", "type": "mobile", "dnc": true }],
            "vehicle_history": [{ "make": "Ford", "model": "Explorer", "year": 2015, "vin": "1FM5K8D84FGA12345" }]
          }
        ],
        "error": ""
      }
      ```
    </CodeGroup>

    <Note>
      The sample VIN above returns a canned documentation response (before auth) with fully populated demographics so the complete shape is visible. Demographics come back by default for any other VIN too — the second request example just narrows the response down to the `demographics` section alone.
    </Note>

  </Col>
</Row>

---

## Person → Contact Info

<Row>
  <Col>
    Resolve contact details for a specific person you already have a name and address for.

    ### Required attributes

    <Properties>
      <Property name="key" type="string">
        Your CarsXE API key.
      </Property>
      <Property name="first_name" type="string">
        Max 50 characters.
      </Property>
      <Property name="last_name" type="string">
        Max 50 characters.
      </Property>
      <Property name="address" type="string">
        Street address only (no city/state) — max 100 characters.
      </Property>
      <Property name="zip" type="string">
        5-digit US ZIP, optionally ZIP+4.
      </Property>
    </Properties>

    ### Optional attributes

    <Properties>
      <Property name="include" type="string">
        Comma-separated subset of `demographics,emails,phones,vehicle_history`. Omit it to get everything.
      </Property>
    </Properties>

    <Note>
      `demographics`, `vehicle_history`, `emails`, and `phones` all come from the same single call — nothing about `include` changes what's fetched or billed, only which sections appear in the response. Omit `include` to get everything back by default.
    </Note>

    ---

    ### Response attributes

    <Properties>
      <Property name="success" type="boolean">
        Whether the request was processed successfully.
      </Property>
      <Property name="input" type="object">
        Echo of the query you made — `first_name`, `last_name`, `address`, `zip`, plus `include` when you passed one.
      </Property>
      <Property name="count" type="number">
        Number of matches found — this is exactly what's billed (see the billing note above).
      </Property>
      <Property name="matches" type="array">
        One entry per matched person. See the table below.
      </Property>
      <Property name="error" type="string">
        Machine-readable error code, or `""` on success.
      </Property>
    </Properties>

    #### `matches[]` object

    | Field | Type | Description |
    | :--- | :--- | :--- |
    | `record_id` | string | Internal identity ID for this person. |
    | `first_name`, `last_name` | string | |
    | `age`, `gender` | string | Empty when not on file. |
    | `address` | object | `{ street, city, state, zip }` — `city`/`state` are the canonical values for the address, which may differ in formatting from what you sent. |
    | `vin` | string | A vehicle linked to this identity, or `""` when none. |
    | `emails[]` | array | `{ address, last_seen }`. Can be empty. |
    | `phones[]` | array | `{ number, type, dnc }`. Can be empty — don't assume a match has both emails and phones. |
    | `demographics` | object | `marital_status`, `home_owner`, `children_in_household`, `veteran_in_household`, `occupation`, `income_range`, `net_worth_range`, `credit_range` — all raw string values, empty unless on file. |
    | `vehicle_history[]` | array | Up to 3 other vehicles linked to this identity: `{ make, model, year, vin }`. |

    ### Errors

    | Status | `error` | Cause |
    | :--- | :--- | :--- |
    | 400 | `invalid_inputs` | Missing or oversized name/address. |
    | 400 | `invalid_zip` | Not a valid 5-digit (or ZIP+4) US ZIP. |
    | 404 | `no_data` | No match — not billed. |

  </Col>
  <Col sticky>
    <CodeGroup title="Request" tag="GET" label="/v1/ownership/person">
      ```bash
      curl -G https://api.carsxe.com/v1/ownership/person \
        -d key=CARSXE_API_KEY \
        -d first_name=John \
        -d last_name=Sample \
        -d address="123 Example St" \
        -d zip=90210
      ```
    </CodeGroup>

    <CodeGroup title="Response">
      ```json showLineNumbers
      {
        "success": true,
        "input": {
          "first_name": "John",
          "last_name": "Sample",
          "address": "123 Example St",
          "zip": "90210"
        },
        "count": 1,
        "matches": [
          {
            "record_id": "2074367570",
            "first_name": "John",
            "last_name": "Sample",
            "age": "45",
            "gender": "Male",
            "address": {
              "street": "123 Example St",
              "city": "Beverly Hills",
              "state": "CA",
              "zip": "90210"
            },
            "vin": "1FT8X3BT0BEA61538",
            "emails": [
              { "address": "john.sample@gmail.com", "last_seen": "2026-03-08" },
              { "address": "jsample@msn.com", "last_seen": "" }
            ],
            "phones": [
              { "number": "3105551901", "type": "", "dnc": false },
              { "number": "3105558018", "type": "", "dnc": false }
            ],
            "demographics": {
              "marital_status": "Married",
              "home_owner": "Home Owner",
              "children_in_household": "",
              "veteran_in_household": "",
              "occupation": "President",
              "income_range": "$100,000 - $149,999",
              "net_worth_range": "$250,000 - $499,999",
              "credit_range": "700 - 749"
            },
            "vehicle_history": [{ "make": "Ford", "model": "F-350", "year": 2011, "vin": "1FT8X3BT0BEA61538" }]
          }
        ],
        "error": ""
      }
      ```
    </CodeGroup>

  </Col>
</Row>

---

## Address → Residents

<Row>
  <Col>
    Find everyone on file at a street address.

    ### Required attributes

    <Properties>
      <Property name="key" type="string">
        Your CarsXE API key.
      </Property>
      <Property name="address" type="string">
        Street address only, max 100 characters.
      </Property>
      <Property name="zip" type="string">
        5-digit US ZIP, optionally ZIP+4.
      </Property>
    </Properties>

    ### Optional attributes

    <Properties>
      <Property name="include" type="string">
        Comma-separated subset of `demographics,emails,phones,vehicle_history`. Omit it to get everything.
      </Property>
      <Property name="variant" type="string">
        Legacy alias (`vehicle_history` or `compliance`) from before `include` existed — still accepted and echoed back, but no longer changes what's fetched or shown. Use `include` instead.
      </Property>
    </Properties>

    <Note>
      `demographics`, `vehicle_history`, `emails`, and `phones` all come from the same single call — nothing about `include` changes what's fetched or billed, only which sections appear in the response. Omit `include` to get everything back by default.
    </Note>

    ---

    ### Response attributes

    <Properties>
      <Property name="success" type="boolean">
        Whether the request was processed successfully.
      </Property>
      <Property name="input" type="object">
        Echo of the query you made — `address`, `zip`, plus `include`/`variant` when you passed them.
      </Property>
      <Property name="count" type="number">
        Number of matches found — this is exactly what's billed (see the billing note above).
      </Property>
      <Property name="matches" type="array">
        One entry per matched resident. See the table below.
      </Property>
      <Property name="error" type="string">
        Machine-readable error code, or `""` on success.
      </Property>
    </Properties>

    #### `matches[]` object

    | Field | Type | Description |
    | :--- | :--- | :--- |
    | `record_id` | string | Internal identity ID for this person. |
    | `first_name`, `last_name` | string | |
    | `age`, `gender` | string | Empty when not on file. |
    | `address` | object | `{ street, city, state, zip }` — `city`/`state` are the canonical values for the address, which may differ in formatting from what you sent. |
    | `vin` | string | A vehicle linked to this identity, or `""` when none. |
    | `emails[]` | array | `{ address, last_seen }`. Can be empty. |
    | `phones[]` | array | `{ number, type, dnc }`. Can be empty — don't assume a match has both emails and phones. |
    | `demographics` | object | `marital_status`, `home_owner`, `children_in_household`, `veteran_in_household`, `occupation`, `income_range`, `net_worth_range`, `credit_range` — all raw string values, empty unless on file. |
    | `vehicle_history[]` | array | Up to 3 other vehicles linked to this identity: `{ make, model, year, vin }`. |

    ### Errors

    | Status | `error` | Cause |
    | :--- | :--- | :--- |
    | 400 | `invalid_inputs` | Missing/oversized address, or invalid `variant`. |
    | 400 | `invalid_zip` | Not a valid 5-digit (or ZIP+4) US ZIP. |
    | 404 | `no_data` | No match — not billed. |

  </Col>
  <Col sticky>
    <CodeGroup title="Request" tag="GET" label="/v1/ownership/address">
      ```bash
      curl -G https://api.carsxe.com/v1/ownership/address \
        -d key=CARSXE_API_KEY \
        -d address="123 Example St" \
        -d zip=90210
      ```
    </CodeGroup>

    <CodeGroup title="Response">
      ```json showLineNumbers
      {
        "success": true,
        "input": {
          "address": "123 Example St",
          "zip": "90210"
        },
        "count": 2,
        "matches": [
          {
            "record_id": "2074367570",
            "first_name": "John",
            "last_name": "Sample",
            "age": "45",
            "gender": "Male",
            "address": { "street": "123 Example St", "city": "Beverly Hills", "state": "CA", "zip": "90210" },
            "vin": "1FT8X3BT0BEA61538",
            "emails": [{ "address": "john.sample@gmail.com", "last_seen": "2026-03-08" }],
            "phones": [{ "number": "3105551901", "type": "", "dnc": false }],
            "demographics": {
              "marital_status": "Married",
              "home_owner": "Home Owner",
              "children_in_household": "",
              "veteran_in_household": "",
              "occupation": "President",
              "income_range": "$100,000 - $149,999",
              "net_worth_range": "$250,000 - $499,999",
              "credit_range": "700 - 749"
            },
            "vehicle_history": [{ "make": "Ford", "model": "F-350", "year": 2011, "vin": "1FT8X3BT0BEA61538" }]
          },
          {
            "record_id": "7304690614",
            "first_name": "Jane",
            "last_name": "Sample",
            "age": "43",
            "gender": "Female",
            "address": { "street": "123 Example St", "city": "Beverly Hills", "state": "CA", "zip": "90210" },
            "vin": "",
            "emails": [{ "address": "jane.sample@yahoo.com", "last_seen": "" }],
            "phones": [{ "number": "3105558018", "type": "", "dnc": false }],
            "demographics": {
              "marital_status": "",
              "home_owner": "",
              "children_in_household": "",
              "veteran_in_household": "",
              "occupation": "",
              "income_range": "",
              "net_worth_range": "",
              "credit_range": ""
            },
            "vehicle_history": []
          }
        ],
        "error": ""
      }
      ```
    </CodeGroup>

  </Col>
</Row>

---

## ZIP → Area Search

<Row>
  <Col>
    Search a broader area for people matching optional gender, age, and income filters. This is the only one-to-many, paginated lookup in the product.

    ### Required attributes

    <Properties>
      <Property name="key" type="string">
        Your CarsXE API key.
      </Property>
      <Property name="zip" type="string">
        Exactly 5 digits.
      </Property>
    </Properties>

    ### Optional attributes

    <Properties>
      <Property name="gender" type="string">
        `M` or `F`, case-insensitive.
      </Property>
      <Property name="min_age" type="string">
        Whole number. Optional — only forwarded upstream when provided (CarsXE does not apply a default).
      </Property>
      <Property name="max_age" type="string">
        Whole number. Optional — only forwarded upstream when provided (CarsXE does not apply a default).
      </Property>
      <Property name="income" type="string">
        Full label, letter code, or a loose case/whitespace variant of either. See the table below.
      </Property>
      <Property name="page" type="string">
        Default `1`.
      </Property>
      <Property name="limit" type="string">
        Default `15`, max `100`. Each record returned is billed individually, so a full page at `limit=100` bills up to 100 units in one call.
      </Property>
      <Property name="include" type="string">
        Comma-separated subset of `demographics,emails,phones,vehicle_history`. Omit it to get everything — same behavior as VIN/Person.
      </Property>
      <Property name="variant" type="string">
        Legacy, deprecated. `vehicle_history` is accepted and echoed back for backward compatibility, but no longer changes the response — use `include` instead.
      </Property>
    </Properties>

    #### Valid `income` values

    Pass the full string, the letter code alone, or a sloppy variant of either — `f`, `F. $50,000-$59,999`, and `  f  ` all resolve to the same bucket.

    | Code | Full value |
    | :--- | :--- |
    | — | `Unknown` |
    | `A` | Under $10,000 |
    | `B` | $10,000–$19,999 |
    | `C` | $20,000–$29,999 |
    | `D` | $30,000–$39,999 |
    | `E` | $40,000–$49,999 |
    | `F` | $50,000–$59,999 |
    | `G` | $60,000–$74,999 |
    | `H` | $75,000–$99,999 |
    | `K` | $100,000–$149,999 |
    | `L` | $150,000–$174,999 |
    | `M` | $175,000–$199,999 |
    | `N` | $200,000–$249,999 |
    | `O` | $250K + |

    ---

    ### Response attributes

    <Properties>
      <Property name="success" type="boolean">
        Whether the request was processed successfully.
      </Property>
      <Property name="zip" type="string">
        The ZIP you queried.
      </Property>
      <Property name="filters" type="object">
        Only the filters you actually set — not the resolved defaults.
      </Property>
      <Property name="page" type="number">
        Current page.
      </Property>
      <Property name="limit" type="number">
        Page size.
      </Property>
      <Property name="count" type="number">
        Number of records on this page — this is exactly what's billed for this call (see the billing note above).
      </Property>
      <Property name="records" type="array">
        One entry per matched person. See the table below.
      </Property>
      <Property name="include" type="string">
        Echoes the `include` value you passed. Omitted entirely when you didn't pass one.
      </Property>
      <Property name="variant" type="string">
        Echoes the (legacy) `variant` value you passed. Omitted entirely when you didn't pass one.
      </Property>
      <Property name="error" type="string">
        Machine-readable error code, or `""` on success.
      </Property>
    </Properties>

    #### `records[]` object

    | Field | Type | Description |
    | :--- | :--- | :--- |
    | `record_id` | string | |
    | `first_name`, `last_name` | string | |
    | `age`, `gender` | string | Each record's own values, same as VIN/Person/Address — unrelated to the `gender`/`min_age`/`max_age` filter params (those only narrow which records match, they don't determine what's shown per record). |
    | `address` | object | `{ street, city, state, zip }`. |
    | `vin` | string | Linked VIN, or `""` when none. |
    | `vehicle` | object \| null | `{ make, model, year }`, or `null` when no vehicle is linked. |
    | `emails[]` | array | `{ address, last_seen }`. Included by default; narrow with `include`. |
    | `phones[]` | array | `{ number, dnc }`. Included by default; narrow with `include`. |
    | `demographics` | object | `marital_status`, `home_owner`, `children_in_household`, `veteran_in_household`, `occupation`, `income_range`, `net_worth_range`, `credit_range` — same shape as VIN/Person/Address, all raw string values. Frequently blank — this is a broad-search endpoint, not every record has every attribute on file. Included by default; narrow with `include`. |
    | `vehicle_history[]` | array | Up to 3 other vehicles linked to this person: `{ make, model, year, vin }`. Included by default; narrow with `include`. |

    ### Errors

    | Status | `error` | Cause |
    | :--- | :--- | :--- |
    | 400 | `invalid_zip` | Missing or not exactly 5 digits. |
    | 400 | `invalid_gender` | Not `M`/`F` after normalization. |
    | 400 | `invalid_age` | `min_age`/`max_age` not a whole number. |
    | 400 | `invalid_income` | Doesn't match any known code or label. |
    | 400 | `invalid_variant` | Unrecognized `variant` value. `variant` is a legacy, inert alias — kept for backward compatibility, still validated, but no longer changes what's fetched or shown. |
    | 404 | `no_data` | No records match — not billed. |

  </Col>
  <Col sticky>
    <CodeGroup title="Request" tag="GET" label="/v1/ownership/zip">
      ```bash
      curl -G https://api.carsxe.com/v1/ownership/zip \
        -d key=CARSXE_API_KEY \
        -d zip=00000 \
        -d gender=f \
        -d min_age=45
      ```
    </CodeGroup>

    <CodeGroup title="Response">
      ```json showLineNumbers
      {
        "success": true,
        "zip": "00000",
        "filters": {},
        "page": 1,
        "limit": 15,
        "count": 1,
        "records": [
          {
            "record_id": "2104840276",
            "first_name": "Victoria",
            "last_name": "Rose",
            "age": "34",
            "gender": "F",
            "address": {
              "street": "141 Hardwood Ln SE",
              "city": "Kalkaska",
              "state": "MI",
              "zip": "49646"
            },
            "vin": "1HGBH41JXMN109186",
            "vehicle": { "make": "Honda", "model": "Civic", "year": 2021 },
            "emails": [
              { "address": "victoria.rose@example.com", "last_seen": "2026-07-11" },
              { "address": "vrose2@gmail.com", "last_seen": "" }
            ],
            "phones": [
              { "number": "2314567890", "dnc": false },
              { "number": "2319876543", "dnc": true }
            ],
            "demographics": {
              "marital_status": "Married",
              "home_owner": "Home Owner",
              "children_in_household": "1",
              "veteran_in_household": "",
              "occupation": "Professional",
              "income_range": "F. $50,000-$59,999",
              "net_worth_range": "D. $50,000-$99,999",
              "credit_range": "H. 700-749"
            },
            "vehicle_history": [{ "make": "Honda", "model": "Civic", "year": 2021, "vin": "1HGBH41JXMN109186" }]
          }
        ],
        "error": ""
      }
      ```
    </CodeGroup>

  </Col>
</Row>

---

## Shared behavior

**Billing.** All four lookups follow the same rule: zero records means a `404` with `error: "no_data"`, no usage increment, and no charge. When there is data, you're billed per record returned, not per request — the charged quantity is exactly the number of entries in the response (`owners`/`matches`/`records`), so a 3-owner VIN response or a 40-record ZIP page bills 3 or 40 units respectively. ZIP is the one to watch: it's paginated and can return far more records per call (up to `limit=100`) than VIN/Person/Address typically do, so a single ZIP request can consume noticeably more quota than expected.

**Every response tells you what request produced it.** Optional parameters that shape the response — `include` on all four endpoints, plus the legacy `variant` on Address and ZIP — are echoed back whenever they're set, and simply omitted when they're not.

**`include` is one concept everywhere now.** On VIN, Person, Address, and ZIP alike, it only decides which already-fetched fields to show — the full record is always fetched and billed as a single base call regardless of what you pass. An unrecognized `include` value is ignored and falls back to showing everything; it's never rejected with `400`. The `variant` param on Address and ZIP is a legacy, inert alias kept for backward compatibility — it no longer selects a different lookup.

---

## Error codes

| Status    | Meaning                                                                                                                                                    | Seen on  |
| :-------- | :--------------------------------------------------------------------------------------------------------------------------------------------------------- | :------- |
| 200       | Success — at least one match found.                                                                                                                        | All four |
| 400       | Malformed input — fix the request before retrying.                                                                                                         | All four |
| 401       | Missing/invalid API key, or an inactive account.                                                                                                           | All four |
| 403       | `api_not_enabled` — your key doesn't have the `ownership` entitlement.                                                                                     | All four |
| 404       | `no_data` — valid request, zero matches, not billed.                                                                                                       | All four |
| 429       | Usage limit reached for your plan.                                                                                                                         | All four |
| 503       | Kill-switch — Ownership temporarily unavailable. Body is `{ success: false, message: "The Ownership API is temporarily unavailable." }` (no `error` code). | All four |
| 408 / 500 | Upstream timeout or vendor error — safe to retry.                                                                                                          | All four |

<FAQ faqs={[
  { question: "What is the Ownership API?",
  answer: "One product with four lookup types — VIN, Person (name + address), Address, and ZIP — that all resolve people and contact details from CarsXE's identity graph. They share a single entitlement and billing model."},

{ question: "Which endpoint should I use?",
answer: <ul><li>Have a VIN? Use <code>VIN</code>.</li><li>Have a full name and address? Use <code>Person</code>.</li><li>Only have an address? Use <code>Address</code>.</li><li>Have a ZIP code and want a filtered list of people in that area? Use <code>ZIP</code>.</li></ul>},

{ question: "Do I get charged if there's no match?",
answer: "No. A 404 with error: \"no_data\" means the API correctly found nothing — it's not billed and doesn't count against your usage."},

{ question: "What's the difference between variant and include on the Address endpoint?",
answer: "There isn't one anymore in practice. variant is a legacy alias from before include existed — it's still accepted and echoed back for backward compatibility, but it no longer changes what's fetched or shown. Use include to pick which of demographics, emails, phones, and vehicle_history appear in the response; omit it to get everything."},

{ question: "Why is demographics empty even though I didn't pass include?",
answer: "demographics, like the rest of the response, comes back by default — you don't need to pass include to get it. An empty demographics object (or blank age/gender fields) just means that data isn't on file for that match, not that it was withheld."},

{ question: "Can a VIN or address resolve to more than one person?",
answer: "Yes — co-owners, prior owners still on file, roommates, or family members can all be legitimately linked to the same VIN or address. Always iterate the full owners/matches array rather than assuming the first entry is the only answer."},

{ question: "Why are age and gender blank on ZIP search results?",
answer: "On the ZIP endpoint, age and gender are filter inputs, not guaranteed per-record output fields. If you need a confirmed age or gender for a specific person, use VIN or Person instead."},

{ question: "Does this API require authentication?",
answer: "Yes. All four endpoints require your CarsXE API key as the key query parameter, and your key must have the ownership entitlement enabled."}
]} hidePadding />
