Skip to main content

Discovery Contract — jlr (us)

The vetting gate between discovery and coding. This file is the human narrative + probe evidence; the authoritative gate state lives in the sidecar discovery-contract.gate.json, which public-api-implement checks via check_contract_gate.py. Keep this table in sync with the sidecar.

  • OEM / market: jlr / us (Land Rover + Jaguar)
  • Discovered: 2026-06-12
  • Gate status: 🟢 PASS — all hard gates green; identity_key inventory→models OVERRIDE user-approved (2026-06-12)

Gate summary

#GateEntity / paramStatusEvidence
1Pagination contractinventory✅ PASStotal=289, perPage=20, page2∩page1=0 VINs
2Enumerator (model/nameplate)models✅ PASSbase URL 302→version; no-view lists bodystyles; 7 nameplates live
3Enumerator (dealer)dealers✅ PASS20-zip sweep → 181 unique ciCodes
4Multi-value filterinventory⬜ N/Aper-dealer scrape, no combined filter
5Body shape / bot-blockinventory✅ PASScurl_cffi chrome clears Cloudflare; search API 200 JSON
6Body shape / bot-blockfeatures (configurator)✅ PASSJSONP rcjson(...), 200, strips cleanly
7Data quality / plausibilityinventory✅ PASSvalid unique VINs, real prices $52-53k, mmc populated
8Data quality / plausibilitydealers✅ PASSreal NYC coords (not 0.0), ciCode+name 100%
9Data quality / plausibilitymodels✅ PASSPRODUCT A-S-P300-110 @ $63,500 w/ 5000Code
10Data quality / plausibilityfeatures✅ PASS124 priced/described leaf features
11Cross-source identity keyinventory→dealers✅ PASSccid→ciCode; dealer.location name match
12Cross-source identity keyinventory→models🟢 OVERRIDE (approved 2026-06-12)no shared code; fuzzy (model,trim,year), 95.1% FK
13Cross-source identity keyfeatures→models✅ PASSshared SCS response, FK programme_code L663
14Real fixture (no synthetic)inventory✅ PASSjlr_carscommerce_search_sample.json
15Real fixture (no synthetic)dealers✅ PASSjlr_retailerlocator_sample.json
16Real fixture (no synthetic)models✅ PASSjlr_scs_sample.json (LIVE)
17Real fixture (no synthetic)features✅ PASSjlr_scs_sample.json (LIVE)
18Postman recordinventory✅ PASSCollection uid 53897914-9cdbecc6-...a5e1
19Postman recorddealers✅ PASSsame collection
20Postman recordmodels✅ PASSsame collection
21Postman recordfeatures✅ PASSsame collection

Per-entity endpoints

EntityEndpoint (method + URL)Auth / protocolFixtureNotes
dealersGET https://retailerlocator.jaguarlandrover.com/dealers?postCode=&requestMarketLocale=en_us&brand=Land Rover&filter=dealer&radius=500&unitOfMeasure=Miles&country=usPublic; needs Origin/Referer = Land Rover UStests/data/jlr_retailerlocator_sample.jsonReal capture — Land Rover Manhattan etc. Key = ciCode.
modelsGET https://rules.config.landrover.com/rc/lr/en_us/{nameplate}_{my}/{ver}/{bodystyle}/.jsonp?view=summaryPublic JSONPtests/data/jlr_scs_sample.jsonReal LIVE capture l663_k26. PRODUCT features = models.
features(same SCS configurator response)Public JSONPtests/data/jlr_scs_sample.jsonNon-PRODUCT feature-list categories = features.
inventoryPOST https://websites-search.api.carscommerce.inc/api/v1/listings/{ccid}/searchx-api-key + Origin/Referer; Cloudflare on dealer page (curl_cffi chrome clears)jlr_carscommerce_search_sample.jsonCURRENT endpoint. ccid+x-api-key scraped from dealer page. Old admin-ajax.php is OBSOLETE (400).

Cross-source identity / FK alignment (HARD)

FKReferencing entity.fieldTarget entity.fieldExample valueVerified
inventory→dealersinventory.dealer_id (= dealer ciCode passed through)dealers.dealer_id (ciCode)R0627
inventory→modelsinventory (model, trim, year) (fuzzy)models (model_name, trim, model_year)Discovery Sport / Landmark / 2026🟢 (no shared code — OVERRIDE approved, 95.1% FK)
features→modelsprogramme_codeprogramme_codeL663

Probe evidence

1. Pagination contract — inventory

paste pagination_probe block

2–3. Enumerators (model / dealer)

paste enumerator_probe blocks

4. Multi-value filter — inventory

N/A — inventory is scraped per dealer; no combined multi-value filter endpoint.

5–6. Body shape / bot-block

paste body_shape_probe blocks

7–10. Data quality / plausibility

paste data_quality_probe blocks per entity

11–13. Cross-source identity keys

paste value-match evidence for every FK listed in the sidecar requirements

14–17. Real fixtures

list every fixture path and the live request it came from

18–21. Postman records

list the Postman request/folder URL for every discovered endpoint

Probe results (verified 2026-06-12)

  • Pagination (inventory): POST websites-search.api.carscommerce.inc/api/v1/listings/6035416/search → HTTP 200, data.total_vehicle_count=289, 20 rows/page; page 2 VIN set has 0 overlap with page 1. Minimal body returns 400 — the full sort+facets arrays are required.
  • Enumerator (model): base nameplate /rc/lr/en_us/l663_k26/.jsonp → 302 → /4cvli.jsonp; version-level no-view response lists BODYSTYLE [A-SV-110, A-90, A-110, A-130]. All 7 nameplates resolve live.
  • Enumerator (dealer): 20-metro locator sweep, radius 250mi, dedupe by ciCode → 181 unique US dealers (151 with newVehicleInventoryLink).
  • Body shape (inventory): plain curl → 403 Cloudflare; curl_cffi impersonate=chrome → 200 (493KB page, nonce/ccid/api-key extractable), search API → 200 JSON. ~42% of dealers are behind Akamai "Access Denied" that blocks even real Chrome (chrome-devtools also got 403).
  • Body shape (configurator): JSONP rcjson(...), HTTP 200, 112KB, strips to JSON. No bot block.
  • Data quality: dealers real NYC coords (not 0.0); inventory 4 valid unique VINs, prices $52,756-$53,706; models PRODUCT @ $63,500; features 124 priced leaves.

Overrides

GateOVERRIDE reasonApproved by
identity_key:inventory→modelsCars Commerce inventory exposes manufacturer_model_code (e.g. HQ550/353BT) which shares no token with the SCS catalog's 5000Code / DerivativePackCode / programme_code. The only available join is fuzzy normalized (model_name, trim, model_year). This is a genuine API limitation (two independent feeds), not a discovery miss.User-approved 2026-06-12 (measured 95.1% FK resolution)