> ## Documentation Index
> Fetch the complete documentation index at: https://docs.autosnap.com/llms.txt
> Use this file to discover all available pages before exploring further.

# Semantic Search

> Vault retrieval endpoints that take shopper intent and return ranked in-stock vehicles, plus a match-score endpoint for re-ranking shortlists.

Vault is the AutoSnap vector layer for dealer inventory. Every active vehicle in the AutoSnap network is encoded as a vector and stored in Vault. Three endpoints sit on top of that store:

* **`POST /v2/search`**. Takes a natural-language question and returns ranked, in-stock vehicles at a dealer.
* **`GET /v2/vehicles/vin/{vin}/similar`**. Takes an anchor VIN and returns the closest in-stock alternatives at the same dealer.
* **`POST /v2/match-score`**. Takes a shopper intent plus a list of VINs and returns each VIN's score against the intent. Used to re-rank a shortlist when the shopper's question evolves.

The endpoints are tools. A customer's AI assistant decides when to call which one. Vault answers; the LLM running on the customer's side handles the conversation, the user, and the product surface. We do not run the chat.

## What vectors do, in plain terms

A vector is a list of numbers that encodes the meaning of a vehicle. Year, model, trim, body, options, description, and pricing context all collapse into a single point in a high-dimensional space. Vehicles that are conceptually similar end up close together in that space. A Buick Enclave and a Chevy Traverse, both three-row family SUVs, sit near each other regardless of whether they share any keywords.

Vault encodes shopper questions the same way. "Something that turns heads" becomes a point in the same space. The match is the geometric distance between the question's point and each vehicle's point. Closer is more relevant. This is one fast operation per vehicle, which is why the endpoints stay sub-second on inventories of two thousand vehicles or more.

The advantage over a SQL filter or keyword index is what gets matched. `body = SUV` returns every SUV in random order. "Something that turns heads" is not a column you can filter on. It is a direction in the vector space, and Vault finds the vehicles closest to that direction.

## What Vault is, what it is not

Vault is production vector infrastructure. The encoding pipeline runs continuously: when a dealer's scrape lands, new vehicles are encoded within seconds, updated vehicles are re-encoded, and sold vehicles are removed. The store reflects what is actually on the dealer's lot right now. You do not host an embedding model, manage a vector database, or run a nightly indexer.

Vault is not a chat backend. It does not generate text, route conversations, or hold user state. Those belong to the AI assistant on your side. Vault's endpoints are tools that an LLM calls during a conversation. The boundary is firm: your LLM owns the user experience, Vault owns the retrieval.

## A note on `score_threshold`

`POST /v2/search` accepts an optional `score_threshold` between 0.0 and 1.0. It is a relevance floor: results scoring below the threshold are dropped before being returned.

For natural-language shopper questions ("fun to drive", "good for my new dad", "I tow a boat on weekends"), set it to **0.20**. The endpoint defaults to `0.30`, which is stricter and works for narrower spec-style lookups (a specific model, a trim, a color). Every `POST /v2/search` example below sets `score_threshold: 0.20` explicitly.

<Note>
  All examples below use `dealership_id` for compactness. You can substitute `"dealership_url": "carlblackroswell.com"` if you'd rather scope by URL.
</Note>

<Note>
  The example VINs and result snippets reflect real, live inventory at the time of writing. Dealer lots rotate. Specific VINs may have sold and specific top-result rankings may have shifted by the time you run these requests. The request shapes and response schemas are stable; the data is not.
</Note>

***

## GET /v2/vehicles/vin/{vin}/similar

Takes a VIN. Returns the closest in-stock vehicles at the same dealer, ranked by similarity to the anchor's encoded vector. Three patterns the endpoint handles cleanly: the shopper's pick is over budget so they want the same model at a lower trim, the shopper wants a different model year of the same model, or the shopper's pick just sold and the LLM needs a near-alternative to keep the conversation alive.

Scores for `/similar` are high (typically 0.94 and above) because the comparison is between two rich vehicle vectors. Treat 0.94+ as "in the same conceptual neighborhood."

### 1. Same-model price ladder

> Shopper: *"I love this S-Class but it's a stretch for me."*
> Vault returns lower-priced in-stock S-Class alternatives.

<CodeGroup>
  ```bash cURL theme={null}
  curl "https://api.autosnap.com/v2/vehicles/vin/W1K6X7GB0TA372545/similar?api_key=$AUTOSNAP_API_KEY&limit=5"
  ```

  ```python Python theme={null}
  import os, requests

  r = requests.get(
      "https://api.autosnap.com/v2/vehicles/vin/W1K6X7GB0TA372545/similar",
      params={"api_key": os.environ["AUTOSNAP_API_KEY"], "limit": 5},
  )
  print(r.json())
  ```
</CodeGroup>

```json Response (abbreviated) theme={null}
{
  "success": true,
  "results": [
    {"year": 2026, "make": "Mercedes-Benz", "model": "S-Class", "price": 220235, "score": 0.988},
    {"year": 2026, "make": "Mercedes-Benz", "model": "S-Class", "price": 156700, "score": 0.964},
    {"year": 2026, "make": "Mercedes-Benz", "model": "S-Class", "price": 149910, "score": 0.964},
    {"year": 2026, "make": "Mercedes-Benz", "model": "S-Class", "price": 148900, "score": 0.960},
    {"year": 2026, "make": "Mercedes-Benz", "model": "S-Class", "price": 150650, "score": 0.960}
  ]
}
```

### 2. Same-model trim ladder

> Shopper: *"I like this Encore GX but it's just over what I want to spend."*
> Vault returns three trims of the same model at lower price points.

<CodeGroup>
  ```bash cURL theme={null}
  curl "https://api.autosnap.com/v2/vehicles/vin/KL4AMFSLXTB151160/similar?api_key=$AUTOSNAP_API_KEY&limit=5"
  ```

  ```python Python theme={null}
  r = requests.get(
      "https://api.autosnap.com/v2/vehicles/vin/KL4AMFSLXTB151160/similar",
      params={"api_key": os.environ["AUTOSNAP_API_KEY"], "limit": 5},
  )
  ```
</CodeGroup>

```json Response (abbreviated) theme={null}
{
  "success": true,
  "results": [
    {"year": 2026, "make": "Buick", "model": "Encore GX", "price": 30774, "score": 0.994},
    {"year": 2026, "make": "Buick", "model": "Encore GX", "price": 28679, "score": 0.983},
    {"year": 2026, "make": "Buick", "model": "Encore GX", "price": 32974, "score": 0.981},
    {"year": 2026, "make": "Buick", "model": "Encore GX", "price": 28679, "score": 0.975},
    {"year": 2026, "make": "Buick", "model": "Encore GX", "price": 32324, "score": 0.954}
  ]
}
```

### 3. Cross-year alternatives

> Shopper: *"This 2025 GLE is more than I want to spend. Anything similar but less?"*
> Vault returns same-model alternatives from earlier model years, ranked by similarity.

<CodeGroup>
  ```bash cURL theme={null}
  curl "https://api.autosnap.com/v2/vehicles/vin/4JGFB8KB4SB347545/similar?api_key=$AUTOSNAP_API_KEY&limit=5"
  ```

  ```python Python theme={null}
  r = requests.get(
      "https://api.autosnap.com/v2/vehicles/vin/4JGFB8KB4SB347545/similar",
      params={"api_key": os.environ["AUTOSNAP_API_KEY"], "limit": 5},
  )
  ```
</CodeGroup>

```json Response (abbreviated) theme={null}
{
  "success": true,
  "results": [
    {"year": 2026, "make": "Mercedes-Benz", "model": "GLE", "price": 149640, "condition": "New",  "score": 0.946},
    {"year": 2025, "make": "Mercedes-Benz", "model": "GLE", "price":  85775, "condition": "Used", "score": 0.945},
    {"year": 2026, "make": "Mercedes-Benz", "model": "GLE", "price": 142355, "condition": "New",  "score": 0.943},
    {"year": 2024, "make": "Mercedes-Benz", "model": "GLE", "price":  68323, "condition": "Used", "score": 0.939},
    {"year": 2023, "make": "Mercedes-Benz", "model": "GLE", "price":  70658, "condition": "Used", "score": 0.936}
  ]
}
```

<Tip>
  Replace the example VIN with any active VIN in your dealer's inventory. The endpoint returns in-stock alternatives from the same dealership by default.
</Tip>

***

## POST /v2/search

Takes a question and a dealer ID. Returns ranked, in-stock vehicles. The shopper's actual words are fine: they do not need to be reformatted into make and model terms. Vault encodes the question and ranks every vehicle in the dealer's inventory by relevance.

Scores for `/v2/search` are low (typically 0.20 to 0.40). That is expected. The comparison is between a short question vector and a full vehicle vector, which are different shapes of object. Do not interpret 0.30 as "weak." Read the relative ordering.

### 4. "I want my friends to be jealous"

> Shopper: *"I want my friends to be jealous when they see my new car."*
> Vault returns the dealer's headline-grabbing inventory.

<CodeGroup>
  ```bash cURL theme={null}
  curl -X POST "https://api.autosnap.com/v2/search" \
    -H "Content-Type: application/json" \
    -d '{
      "api_key": "'$AUTOSNAP_API_KEY'",
      "query": "I want my friends to be jealous when they see my new car",
      "dealership_id": 4,
      "score_threshold": 0.20,
      "limit": 5
    }'
  ```

  ```python Python theme={null}
  r = requests.post(
      "https://api.autosnap.com/v2/search",
      json={
          "api_key": os.environ["AUTOSNAP_API_KEY"],
          "query": "I want my friends to be jealous when they see my new car",
          "dealership_id": 4,
          "score_threshold": 0.20,
          "limit": 5,
      },
  )
  ```
</CodeGroup>

```json Top result theme={null}
{"year": 2026, "make": "Mercedes-Benz", "model": "AMG GT 55", "price": 160480, "score": 0.321}
```

### 5. "I haul construction materials for work"

> Shopper: *"I haul construction materials for work."*
> Vault returns work trucks and cargo vans across new and used inventory.

<CodeGroup>
  ```bash cURL theme={null}
  curl -X POST "https://api.autosnap.com/v2/search" \
    -H "Content-Type: application/json" \
    -d '{
      "api_key": "'$AUTOSNAP_API_KEY'",
      "query": "I haul construction materials for work",
      "dealership_id": 1,
      "score_threshold": 0.20,
      "limit": 5
    }'
  ```

  ```python Python theme={null}
  r = requests.post(
      "https://api.autosnap.com/v2/search",
      json={
          "api_key": os.environ["AUTOSNAP_API_KEY"],
          "query": "I haul construction materials for work",
          "dealership_id": 1,
          "score_threshold": 0.20,
          "limit": 5,
      },
  )
  ```
</CodeGroup>

```json Top results theme={null}
[
  {"year": 2025, "make": "GMC",       "model": "Savana Cargo Work Van", "price": 50474, "score": 0.304},
  {"year": 2025, "make": "GMC",       "model": "Savana Cargo Work Van", "price": 52743, "score": 0.301},
  {"year": 2025, "make": "GMC",       "model": "Savana Cargo Work Van", "price": 51878, "score": 0.301},
  {"year": 2025, "make": "Ram",       "model": "1500 Tradesman",       "price": 41784, "score": 0.300},
  {"year": 2025, "make": "GMC",       "model": "Savana Cargo Work Van", "price": 51878, "score": 0.300}
]
```

### 6. "Looks expensive but isn't"

> Shopper: *"I want something that looks expensive but isn't."*
> Vault returns value-luxury trims that feel premium without the price tag.

<CodeGroup>
  ```bash cURL theme={null}
  curl -X POST "https://api.autosnap.com/v2/search" \
    -H "Content-Type: application/json" \
    -d '{
      "api_key": "'$AUTOSNAP_API_KEY'",
      "query": "looks expensive but isn'\''t",
      "dealership_id": 1,
      "score_threshold": 0.20,
      "limit": 5
    }'
  ```

  ```python Python theme={null}
  r = requests.post(
      "https://api.autosnap.com/v2/search",
      json={
          "api_key": os.environ["AUTOSNAP_API_KEY"],
          "query": "looks expensive but isn't",
          "dealership_id": 1,
          "score_threshold": 0.20,
          "limit": 5,
      },
  )
  ```
</CodeGroup>

```json Top results theme={null}
[
  {"year": 2024, "make": "Lincoln",   "model": "Corsair Reserve",       "price": 36768, "score": 0.244},
  {"year": 2023, "make": "Kia",       "model": "Telluride SX Prestige", "price": 41687, "score": 0.241},
  {"year": 2025, "make": "Hyundai",   "model": "Palisade Calligraphy",  "price": 50687, "score": 0.239}
]
```

### 7. "Something that turns heads"

> Shopper: *"I want something that turns heads."*
> Vault returns the dealer's most visually striking inventory.

<CodeGroup>
  ```bash cURL theme={null}
  curl -X POST "https://api.autosnap.com/v2/search" \
    -H "Content-Type: application/json" \
    -d '{
      "api_key": "'$AUTOSNAP_API_KEY'",
      "query": "I want something that turns heads",
      "dealership_id": 4,
      "score_threshold": 0.20,
      "limit": 5
    }'
  ```

  ```python Python theme={null}
  r = requests.post(
      "https://api.autosnap.com/v2/search",
      json={
          "api_key": os.environ["AUTOSNAP_API_KEY"],
          "query": "I want something that turns heads",
          "dealership_id": 4,
          "score_threshold": 0.20,
          "limit": 5,
      },
  )
  ```
</CodeGroup>

```json Top results theme={null}
[
  {"year": 2026, "make": "Mercedes-Benz", "model": "AMG SL 55", "price": 161545, "score": 0.289},
  {"year": 2026, "make": "Mercedes-Benz", "model": "AMG GT 55", "price": 160480, "score": 0.284},
  {"year": 2026, "make": "Mercedes-Benz", "model": "AMG SL 63", "price": 211130, "score": 0.280}
]
```

### 8. "Boring but practical"

> Shopper: *"I want something boring but practical, just gets me there."*
> Vault returns dependable, no-drama daily drivers.

<CodeGroup>
  ```bash cURL theme={null}
  curl -X POST "https://api.autosnap.com/v2/search" \
    -H "Content-Type: application/json" \
    -d '{
      "api_key": "'$AUTOSNAP_API_KEY'",
      "query": "boring but practical, just gets me there",
      "dealership_id": 1,
      "score_threshold": 0.20,
      "limit": 5
    }'
  ```

  ```python Python theme={null}
  r = requests.post(
      "https://api.autosnap.com/v2/search",
      json={
          "api_key": os.environ["AUTOSNAP_API_KEY"],
          "query": "boring but practical, just gets me there",
          "dealership_id": 1,
          "score_threshold": 0.20,
          "limit": 5,
      },
  )
  ```
</CodeGroup>

```json Top results theme={null}
[
  {"year": 2025, "make": "Nissan", "model": "Versa SV", "price": 23944, "score": 0.270},
  {"year": 2024, "make": "Nissan", "model": "Versa S",  "price": 19789, "score": 0.260}
]
```

***

## POST /v2/search with hard filters

The endpoint accepts structured filters alongside the question: `condition`, `make`, `year_min`, `year_max`, `price_min`, `price_max`. The question controls ranking. The filters control the candidate pool. They compose: an LLM can pass a vague-sounding question and a hard budget cap in the same call.

### 9. "Fun to drive" under \$40,000

> Shopper: *"I want something fun to drive but I have to stay under forty grand."*
> Vault returns sport-trim and performance-oriented cars priced at or under \$40,000.

<CodeGroup>
  ```bash cURL theme={null}
  curl -X POST "https://api.autosnap.com/v2/search" \
    -H "Content-Type: application/json" \
    -d '{
      "api_key": "'$AUTOSNAP_API_KEY'",
      "query": "fun to drive",
      "dealership_id": 1,
      "price_max": 40000,
      "score_threshold": 0.20,
      "limit": 5
    }'
  ```

  ```python Python theme={null}
  r = requests.post(
      "https://api.autosnap.com/v2/search",
      json={
          "api_key": os.environ["AUTOSNAP_API_KEY"],
          "query": "fun to drive",
          "dealership_id": 1,
          "price_max": 40000,
          "score_threshold": 0.20,
          "limit": 5,
      },
  )
  ```
</CodeGroup>

```json Top results theme={null}
[
  {"year": 2024, "make": "Dodge",     "model": "Hornet R/T Plus", "price": 24944, "score": 0.354},
  {"year": 2021, "make": "BMW",       "model": "4 Series 430i",   "price": 39344, "score": 0.354},
  {"year": 2025, "make": "Chevrolet", "model": "Trax 2RS",        "price": 27953, "score": 0.351},
  {"year": 2025, "make": "Kia",       "model": "Soul LX",         "price": 23789, "score": 0.351},
  {"year": 2022, "make": "Subaru",    "model": "WRX GT",          "price": 37844, "score": 0.347}
]
```

### 10. "Luxury feel" GMC only

> Shopper: *"I want a luxury feel, but I'm a GMC person."*
> Vault returns the dealer's top-tier GMC trims (Denali Ultimate Sierra and Yukon).

<CodeGroup>
  ```bash cURL theme={null}
  curl -X POST "https://api.autosnap.com/v2/search" \
    -H "Content-Type: application/json" \
    -d '{
      "api_key": "'$AUTOSNAP_API_KEY'",
      "query": "luxury feel",
      "dealership_id": 2,
      "make": "GMC",
      "score_threshold": 0.20,
      "limit": 5
    }'
  ```

  ```python Python theme={null}
  r = requests.post(
      "https://api.autosnap.com/v2/search",
      json={
          "api_key": os.environ["AUTOSNAP_API_KEY"],
          "query": "luxury feel",
          "dealership_id": 2,
          "make": "GMC",
          "score_threshold": 0.20,
          "limit": 5,
      },
  )
  ```
</CodeGroup>

```json Top results theme={null}
[
  {"year": 2026, "make": "GMC", "model": "Sierra 1500 Denali Ultimate", "price": 76454, "score": 0.297},
  {"year": 2026, "make": "GMC", "model": "Yukon Denali Ultimate",       "price": 107690, "score": 0.296},
  {"year": 2026, "make": "GMC", "model": "Sierra 1500 Denali Ultimate", "price": 74839, "score": 0.295}
]
```

***

## POST /v2/match-score

Takes a question and a caller-supplied list of VINs (up to 25). Returns each VIN's score against the question, an `in_stock` flag, and an optional `price_fit` against `price_min` and `price_max`. The vehicles are not re-encoded: Vault reuses each one's already-stored vector. One embedding call for the question, one bulk vector retrieve, comparison in memory.

Why this endpoint exists separately from `/v2/search`: in an agentic flow, the customer's LLM often holds a shortlist from a prior turn (a `/v2/search` result, a previously-shown set, a hand-picked group) and wants to re-rank just that shortlist when the shopper adds a constraint. `/v2/match-score` is the right tool for that re-rank. `/v2/search` is the right tool when the candidate pool is the dealer's whole inventory.

Scores for `/v2/match-score` are in the same low natural-language range as `/v2/search` (typically 0.20 to 0.40). Same reason: question vector versus vehicle vector. Compare relative ordering, not absolute values.

### Same VINs, different intents, different ordering

The reason this endpoint belongs in the toolkit is that the score is a direct function of the intent. Hold the candidate set fixed; vary the intent; the ordering changes. The next two examples use the same five VINs to make that point explicit.

#### Intent A: "family friendly with good cargo space" (budget $20,000 to $40,000)

> The Encore GX, a compact crossover priced inside the budget, comes back at the top. The S-Class drops to fourth.

<CodeGroup>
  ```bash cURL theme={null}
  curl -X POST "https://api.autosnap.com/v2/match-score" \
    -H "Content-Type: application/json" \
    -d '{
      "api_key": "'$AUTOSNAP_API_KEY'",
      "intent": "family friendly with good cargo space",
      "vins": [
        "W1K6X7GB0TA372545",
        "KL4AMFSLXTB151160",
        "4JGFB8KB4SB347545",
        "1GTUUGEL3TZ376841",
        "INVALIDXXXXX00001"
      ],
      "price_min": 20000,
      "price_max": 40000
    }'
  ```

  ```python Python theme={null}
  r = requests.post(
      "https://api.autosnap.com/v2/match-score",
      json={
          "api_key": os.environ["AUTOSNAP_API_KEY"],
          "intent": "family friendly with good cargo space",
          "vins": [
              "W1K6X7GB0TA372545",
              "KL4AMFSLXTB151160",
              "4JGFB8KB4SB347545",
              "1GTUUGEL3TZ376841",
              "INVALIDXXXXX00001",
          ],
          "price_min": 20000,
          "price_max": 40000,
      },
  )
  ```
</CodeGroup>

```json Response theme={null}
{
  "success": true,
  "intent": "family friendly with good cargo space",
  "results": [
    {"vin": "KL4AMFSLXTB151160", "match_score": 0.3649, "vehicle": {"year": 2026, "make": "Buick", "model": "Encore GX", "price": 37680}, "price_fit": "within_range", "in_stock": true},
    {"vin": "4JGFB8KB4SB347545", "match_score": 0.3235, "vehicle": {"year": 2025, "make": "Mercedes-Benz", "model": "GLE", "price": 99953}, "price_fit": "over_range", "in_stock": true},
    {"vin": "1GTUUGEL3TZ376841", "match_score": 0.3163, "vehicle": {"year": 2026, "make": "GMC", "model": "Sierra 1500", "price": 79034}, "price_fit": "over_range", "in_stock": true},
    {"vin": "W1K6X7GB0TA372545", "match_score": 0.2961, "vehicle": {"year": 2026, "make": "Mercedes-Benz", "model": "S-Class", "price": 243640}, "price_fit": "over_range", "in_stock": true},
    {"vin": "INVALIDXXXXX00001", "match_score": null, "vehicle": null, "price_fit": "unknown", "in_stock": false}
  ],
  "count": 5,
  "search_time_ms": 34
}
```

#### Intent B: same VINs, "something that feels luxurious and turns heads" (budget $30,000 to $100,000)

> The S-Class comes back at the top. The Encore GX drops to second.

<CodeGroup>
  ```bash cURL theme={null}
  curl -X POST "https://api.autosnap.com/v2/match-score" \
    -H "Content-Type: application/json" \
    -d '{
      "api_key": "'$AUTOSNAP_API_KEY'",
      "intent": "something that feels luxurious and turns heads",
      "vins": [
        "W1K6X7GB0TA372545",
        "KL4AMFSLXTB151160",
        "4JGFB8KB4SB347545",
        "1GTUUGEL3TZ376841",
        "INVALIDXXXXX00001"
      ],
      "price_min": 30000,
      "price_max": 100000
    }'
  ```

  ```python Python theme={null}
  r = requests.post(
      "https://api.autosnap.com/v2/match-score",
      json={
          "api_key": os.environ["AUTOSNAP_API_KEY"],
          "intent": "something that feels luxurious and turns heads",
          "vins": [
              "W1K6X7GB0TA372545",
              "KL4AMFSLXTB151160",
              "4JGFB8KB4SB347545",
              "1GTUUGEL3TZ376841",
              "INVALIDXXXXX00001",
          ],
          "price_min": 30000,
          "price_max": 100000,
      },
  )
  ```
</CodeGroup>

```json Response (abbreviated) theme={null}
{
  "success": true,
  "intent": "something that feels luxurious and turns heads",
  "results": [
    {"vin": "W1K6X7GB0TA372545", "match_score": 0.3407, "vehicle": {"year": 2026, "make": "Mercedes-Benz", "model": "S-Class", "price": 243640}, "price_fit": "over_range", "in_stock": true},
    {"vin": "KL4AMFSLXTB151160", "match_score": 0.3045, "vehicle": {"year": 2026, "make": "Buick", "model": "Encore GX", "price": 37680}, "price_fit": "within_range", "in_stock": true},
    {"vin": "1GTUUGEL3TZ376841", "match_score": 0.2969, "vehicle": {"year": 2026, "make": "GMC", "model": "Sierra 1500", "price": 79034}, "price_fit": "within_range", "in_stock": true},
    {"vin": "4JGFB8KB4SB347545", "match_score": 0.2956, "vehicle": {"year": 2025, "make": "Mercedes-Benz", "model": "GLE", "price": 99953}, "price_fit": "within_range", "in_stock": true},
    {"vin": "INVALIDXXXXX00001", "match_score": null, "vehicle": null, "price_fit": "unknown", "in_stock": false}
  ],
  "count": 5,
  "search_time_ms": 31
}
```

<Note>
  The bad VIN (`INVALIDXXXXX00001`) appears in both responses with `match_score: null`, `vehicle: null`, and `in_stock: false`. The caller can rely on this shape to confirm a requested VIN is no longer available without parsing error fields.
</Note>

`price_fit` is an independent signal from `match_score`. The S-Class wins on luxury intent even though it is out of budget (`over_range`). The caller's LLM decides whether to surface, filter, or footnote the out-of-range result. Vault returns both signals; it does not make that decision for you.

***

## A worked flow: `/v2/search` then `/v2/match-score`

This is what an agentic chat looks like when the customer's LLM uses both endpoints in one conversation. The dealer here is Ewing Buick GMC (`dealership_id = 2`).

### Step 1. Shopper opens broad. The LLM calls `/v2/search`.

The shopper types something general into the on-site assistant. The LLM passes the question through to Vault, scoped to the dealer.

<CodeGroup>
  ```bash cURL theme={null}
  curl -X POST "https://api.autosnap.com/v2/search" \
    -H "Content-Type: application/json" \
    -d '{
      "api_key": "'$AUTOSNAP_API_KEY'",
      "query": "family friendly with good cargo space",
      "dealership_id": 2,
      "score_threshold": 0.20,
      "limit": 5
    }'
  ```
</CodeGroup>

Vault returns five ranked VINs. The LLM holds them in conversation memory:

```
["W1Y4KBHY8ST201689",
 "W1Y4KBHY2ST196456",
 "W1W4NCVY6ST195403",
 "W1Y4NBHY7RT186541",
 "5GAERAKS3TJ346737"]
```

### Step 2. The LLM shows the shortlist. The shopper adds a constraint.

The LLM renders the top three to five results in the chat. The shopper does not pick a single car, but they read the list and react: low miles, daily commute, not a cargo van. The LLM's enriched intent becomes "family SUV with low miles for a daily commute," and the budget tightens to $25,000 to $45,000.

### Step 3. The LLM calls `/v2/match-score` on the same VINs with the enriched intent.

The candidate pool is the shortlist, not the dealer's whole inventory. The LLM does not re-fetch and does not pay for a new search. It calls `/v2/match-score` with the VINs it already has and the now-richer intent.

<CodeGroup>
  ```bash cURL theme={null}
  curl -X POST "https://api.autosnap.com/v2/match-score" \
    -H "Content-Type: application/json" \
    -d '{
      "api_key": "'$AUTOSNAP_API_KEY'",
      "intent": "family SUV with low miles for a daily commute",
      "vins": [
        "W1Y4KBHY8ST201689",
        "W1Y4KBHY2ST196456",
        "W1W4NCVY6ST195403",
        "W1Y4NBHY7RT186541",
        "5GAERAKS3TJ346737"
      ],
      "dealership_id": 2,
      "price_min": 25000,
      "price_max": 45000
    }'
  ```
</CodeGroup>

```json Top result theme={null}
{
  "vin": "5GAERAKS3TJ346737",
  "match_score": 0.4215,
  "vehicle": {"year": 2026, "make": "Buick", "model": "Enclave", "price": 42204},
  "price_fit": "within_range",
  "in_stock": true
}
```

The Buick Enclave moves to the top of the response. The Sprinter vans, which led the first search on cargo space alone, fall to the back of the list because they fail the "SUV" and "daily commute" angle of the enriched intent. Same dealer, same five vehicles, sharper ranking. The LLM renders the new order to the shopper and the conversation continues.

### What Vault does. What the customer's LLM does.

Vault: encodes vehicles, stores vectors, serves the three retrievals, keeps the store in sync with the dealer's lot. That is the entire surface area.

The customer's LLM: decides when to call `/v2/search`, when to call `/v2/match-score`, holds the conversation, holds the shortlist between turns, renders responses, asks clarifying questions, and presents the dealership UI. None of that is in Vault.
