Plan Search Reference
Every integration path uses the same search call. This page covers it in full: how to identify a vehicle, what you can put in a request, what comes back, and how to make it faster.
If you have not picked a path yet, start with Choose Your Integration.
Which endpoint to call
There are more search endpoints than you need. In practice:
| Endpoint | Use it when |
|---|---|
POST /api/v2/Partners/PlansSearch |
Default choice. Accepts any vehicle identifier and works out which one you sent. One integration handles all three. |
POST /api/v2/Partners/PlansSearch/Vin |
You only ever search by VIN and want the request validated strictly against that. |
POST /api/v2/Partners/PlansSearch/MakeModelYear |
You only ever search by make, model, and year. |
POST /api/v2/Partners/PlansSearch/LicensePlate |
You only ever search by plate and state. |
POST /api/v2/Partners/PlansSearchWithUserInfo/Vin |
You have the customer's details and want a pre-filled checkout. VIN only. See Search and Hand Off. |
POST /api/v2/Partners/PlansSearchAsync/* |
You need non-blocking searches or instant cached results, and Chaiz has enabled it for you. See make searches faster. |
The generic and the specific endpoints return the same shape. The specific ones just reject a request that carries the wrong identifier, which can be useful as a guardrail.
The synchronous route is /PlansSearch/Vin and the asynchronous one is /PlansSearchAsync/VIN. Note
the different capitalization. It is inconsistent, and we are keeping it that way rather than breaking
existing integrations.
Identify the vehicle
Three ways, in descending order of accuracy.
Prefer VIN wherever you can get one. It prices the exact trim, and it removes a step from checkout later. Make/model/year works, but the customer will be asked for a VIN before the sale completes, and that is where you lose people.
Always required, whichever you use: the customer's stateShortName (two-letter US code) and the
current mileage. Pricing depends on both, so neither is optional in practice.
If you send more than one identifier, precedence is VIN, then license plate plus state, then make/model/year. Send exactly one to avoid surprises.
Resolving loose make and model text
make and model must match our catalog. Free text a customer typed usually will not. Resolve it
first:
curl "https://chaiz-api-uat.azurewebsites.net/api/v2/Partners/Vehicles/Lookup?make=merc&model=f150&year=2019" \
-H "Authorization: Bearer YOUR_API_KEY"
Returns up to five matches ordered by confidence, plus suggestions when the input is ambiguous.
Responses are cached and come back in under 50 ms.
| Confidence | Meaning | Example |
|---|---|---|
HIGH |
Exact match, ignoring case | ford resolves to FORD |
MEDIUM |
Matched after normalizing punctuation | f150 resolves to F-150 |
LOW |
Partial or contains match | merc could be MERCURY or MERCEDES-BENZ |
Treat LOW as "ask the customer to confirm" rather than as an answer. Check yearsAvailable on the
match before searching a year we do not carry.
To build your own dropdowns instead, GET /api/v2/Partners/Vehicles/Makes and
GET /api/v2/Partners/Vehicles/Makes/{makeId}/Models return the full catalog.
Request anatomy
{
"searchCriteria": { "vin": "5XXG14J25MG015777", "stateShortName": "NY", "mileage": 42000 },
"filters": { "duration": { "from": 24, "to": 60 }, "returnResults": 10 },
"tracking": { "queryParams": "utm_source=partner&utm_campaign=your-campaign" },
"responseDetailLevel": "Full",
"resultOrder": "Recommended",
"showProviderInfo": true
}
filters, tracking, responseDetailLevel, resultOrder, and showProviderInfo are root-level
fields, siblings of searchCriteria, not properties inside it. Nesting them inside searchCriteria is
the single most common request mistake, and it fails silently: the fields are ignored and you get an
unfiltered search.
| Field | Required | Notes |
|---|---|---|
searchCriteria |
Yes | The vehicle, state, and mileage |
filters |
No | Narrow the results. See below. |
tracking |
No | queryParams and referrer, for attribution. See Search and Hand Off. |
responseDetailLevel |
No | Full (default) or Essential. See response shapes. |
resultOrder |
No | Recommended (default), Rating, or None |
showProviderInfo |
No | Include provider detail in the results |
partner |
No | Leave it out. Resolved from your token, and a mismatch is rejected. |
searchId, userId |
No | For continuing an existing search session. Omit unless you have been told to use them. |
Filters
All optional, all under filters.
| Filter | Type | Notes |
|---|---|---|
providers |
array of strings | Only these providers, by name: "NAAC", "Omega", "CAPS", "ServiceContract" |
excludeProviders |
array of strings | Everything except these |
numberOfProviders |
integer | Cap on distinct providers in the results |
coverageTypes |
array of strings | See the vocabulary note below |
coverageType |
enum | Single value. Different vocabulary from coverageTypes. See below. |
categoryTypes |
array of strings | Only plans covering these components: Engine, TurboSuper, TransferCase, Steering, Transmission, DriveAxle, Suspension, AirCon, Brakes, Electricals, Cooling, Fuel, Hybrid, Body, Consumables, Exhaust, General, Interior, Services, Assist |
planChaizRating |
range | Chaiz quality rating, 0 to 10. { "from": 7, "to": 10 } |
duration |
range, months | { "from": 24, "to": 60 } |
miles |
range, thousands | { "from": 50, "to": 150 } is 50,000 to 150,000 miles. 999 means unlimited. |
monthlyPrice |
range, USD | { "from": 50, "to": 150 } |
totalPrice |
range, USD | { "from": 1000, "to": 5000 } |
returnResults |
integer | Maximum results. Default depends on your account. |
Provider names are real catalog values, and which of them you can see depends on your account. Filtering to a provider you are not configured for returns nothing rather than an error.
The two coverage filters do not speak the same language
coverageTypes (the array) accepts either the friendly aliases "basic", "basicplus", "best" or
the canonical names "Powertrain", "PowertrainPlus", "MostComprehensive".
coverageType (the singular) accepts only the canonical names. The aliases do not work there.
An unrecognized value in coverageTypes is silently dropped, not rejected, so a typo looks like a
filter that had no effect. Prefer the canonical names everywhere and you avoid the whole problem.
| Alias | Canonical name | Meaning |
|---|---|---|
basic |
Powertrain |
Core powertrain components |
basicplus |
PowertrainPlus |
Powertrain plus additional systems |
best |
MostComprehensive |
Exclusionary, the broadest coverage |
Results report coverage using the canonical names, so using those consistently means your request and response vocabularies match.
Response shapes
responseDetailLevel controls how much comes back.
Full (default) |
Essential |
|
|---|---|---|
| Coverage breakdown, component scores, add-ons, provider detail, highlights | Yes | No |
planContractUrl |
Yes | No |
| Maintenance program | Full detail, as maintenanceProgram |
Yes/no only, as hasMaintenanceProgram |
| Core fields: price, duration, deductible, rating, handoff URLs | Yes | Yes |
| Payload size | Large | Small |
Use Full when you are rendering a comparison UI where customers want the detail. Use Essential when
you only need price, name, rating, and a link, which keeps responses small and fast to parse.
Fields you will use most
| Field | Notes |
|---|---|
searchResultPlanId |
This plan at this price. Needed to create an order, embedded in the handoff URLs, valid 30 days. |
planId |
Essential only. Shared across the duration and mileage variants of the same plan, so it is what you dedupe on. Not returned on the default Full shape; see below. |
totalPrice, downpayment, monthlyPrice |
Already reflect vehicle, mileage, state, and your account. Do not recompute. |
duration, miles, deductible |
Contract terms |
planChaizRating, planRatingVerdict |
Chaiz quality score out of 10, and its label |
displayProviderName, planName |
What to show the customer |
resultLabels |
Badges such as BEST_VALUE and LOWEST_PRICE |
maintenanceProgram |
Full only. The bundled maintenance program, or null when the plan has none. See below. |
hasMaintenanceProgram |
Essential only. Whether the plan bundles a maintenance program. |
planSummaryUrl, planCheckoutUrl |
Handoff destinations. See Search and Hand Off. |
The same plan legitimately appears several times at different durations and mileage tiers. That is not duplication in the results; it is the same product on different terms.
Maintenance programs
Some plans bundle a prepaid maintenance program at no extra cost, covering routine servicing such as oil changes, brake pads, battery replacement and cooling system service. The two response shapes answer this differently, so check the right field for the shape you requested:
-
On
Full, readmaintenanceProgram. It isnullwhen the plan does not include one; when it does, it carries adescription, anitemsarray of{ label, info }describing each covered service and its reimbursement limit, and adocumentUrl. There is no boolean on this shape. -
On
Essential, read thehasMaintenanceProgramboolean. The program's contents are not included; requestFullfor those.
"maintenanceProgram": {
"description": "Covers essential repairs to keep your car running smoothly",
"items": [
{ "label": "3 oil changes", "info": "$40 towards a standard oil change." },
{ "label": "1 battery or light replacement", "info": null }
],
"documentUrl": "https://assets.chaiz.com/files/maintenance-program.pdf"
}
documentUrl is null when the administrator has not published a program document. That does not
mean the plan lacks a maintenance program: the program's presence is signalled by
maintenanceProgram being non-null, never by documentUrl. Likewise, info is null on items
that have no limit or condition to state.
Deduping variants: planId groups those variants, but it is returned only on the Essential
shape. If you need to collapse variants down to one row per plan, request
responseDetailLevel: "Essential". On the default Full shape, group on
displayProviderName plus planName plus coverageType instead.
Make searches faster
A cold search takes 2 to 8 seconds because Chaiz is collecting live rates from multiple warranty administrators. That is unavoidable on the synchronous path.
If you know which vehicles a customer might ask about before they ask (a listing page, a saved vehicle, an inventory feed), you can move that wait off the customer's request entirely.
Cached and asynchronous search is opt-in per account. If it is not enabled for you, these endpoints return an error regardless of a valid request. Email dev-support@chaiz.com to have it turned on, and do not build against it until it is.
Pre-registering a vehicle
POST /api/v2/Partners/VehicleRegistration with a VIN and mileage starts the quoting work in the
background so a later search returns immediately.
| Status | Meaning |
|---|---|
200 |
Registration accepted, quoting started |
201 |
Already cached and ready to search |
202 |
Already in progress, nothing more to do |
400 |
The request did not validate |
The cache is keyed on VIN plus mileage, so a meaningful mileage change means the entry no longer
matches; re-register when the odometer moves by roughly 5,000 miles. Entries last 30 days.
POST /api/v2/Partners/VehicleRegistration/CleanVehicleCache clears one explicitly if you know the
underlying data changed.
Searching asynchronously
POST /api/v2/Partners/PlansSearchAsync/VIN (or /MakeModelYear, /LicensePlate, or the bare route)
never blocks for the full quoting round trip.
| Status | Meaning | What to do |
|---|---|---|
200 |
Done. The body holds your plans. | Use the results. This is the terminal success state. |
202 |
Still quoting | Poll the same endpoint with the same body every 1 to 2 seconds |
400 |
Validation failed, or quoting errored | Read the errors; do not poll |
Asynchronous search completes with 200, not 201. Only VehicleRegistration returns 201, and
it means something different there (already cached). If you are polling for a 201 from a search
endpoint you will poll forever.
There is no Retry-After header on a 202. Use your own 1 to 2 second interval, and set a sane
overall ceiling so a stuck search does not hang your request.
Responses carry an X-Cache header of HIT or MISS, which is useful for confirming your
pre-registration strategy is actually working.
Just the starting price
POST /api/v2/Partners/PlansSearchAsync/GetStartPrice returns only the lowest down payment for a
vehicle, for a "protection from $X/mo" teaser without pulling a full result set. It follows the same
200 / 202 / 400 contract.
When no price is available this returns an empty string rather than a number or null, despite
being typed as a number. Handle the empty case explicitly.
Next steps
- Search and Hand Off for what to do with the results.
- Errors & Rate Limits for validation codes and retry behavior.
- API Reference for complete schemas.