Skip to main content

Discovery Contract — jlr (us)

The vetting gate between discovery and coding. This file is the human-written description + 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; updated 2026-07-28 (per-product fetch, Jaguar coverage, brand derivation)
  • Gate status: 🟢 PASS — all hard gates pass; 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; root_config PRODUCT decomposition; 7 LR + Jag nameplates live
3Enumerator (dealer)dealers✅ PASSmulti-zip sweep per brand → LR + Jaguar ciCodes
4Multi-value filterinventory⬜ N/Aper-dealer NetDirector query, no combined filter
5Body shape / bot-blockinventory✅ PASSNetDirector JSON with static auth header; no dealer-page bot bypass
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✅ PASSNetDirector modelCode → configurator manufacturer_model_code + model_year; ~44% null model codes unresolved
13Cross-source identity keyfeatures→models✅ PASSshared programme_code, model_year_code, product_id key
14Real fixture (no synthetic)inventory✅ PASSjlr_netdirector_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={brand}&filter=dealer&radius=500&unitOfMeasure=Miles&country=usPublic; needs Origin/Referer per brandtests/data/jlr/jlr_retailerlocator_sample.jsonFetched per brand (Land Rover, Jaguar). Key = ciCode. Jaguar codes 0→J transformed.
modelsGET https://rules.config.landrover.com/rc/{brand_path}/en_us/{nameplate}_{my}/{ver}/.jsonp (root_config)Public JSONPtests/data/jlr/jlr_configurator_sample.jsonRoot config only. PRODUCT decomposition → model entities.
featuresGET https://rules.config.landrover.com{product_query_href} (per-PRODUCT body_style_config)Public JSONPtests/data/jlr/jlr_configurator_sample.jsonOne request per PRODUCT. Non-structural categories extracted (excludes BODYSTYLE, MODEL, ENGINE, PRODUCT, CHARGES, CURATEDCHOICES).
inventoryPOST https://production-api-oregon.search-api.netdirector.auto/api/vehicle-searchStatic authorization header + brand-specific uuid paramjlr_netdirector_sample.jsonBoth brands. Per-dealer query; Jaguar dealer codes 0→J transformed.

Cross-source identity / FK alignment (HARD)

FKReferencing entity.fieldTarget entity.fieldExample valueVerified
inventory→dealersinventory.dealer_code (location.manufacturerDealerNumber)dealers.dealer_code (ciCode, Jaguar 0→J)R0627 / J5806
inventory→modelsinventory.manufacturer_model_code + model_yearmodels.manufacturer_model_code + model_yearAT663 + 2026
features→modelsprogramme_code, model_year_code, product_idsameL663, k26, a-xdyn-hse-p400-110

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): NetDirector is queried per dealer with currentPage=1 and pageSize=5000; the current fetcher does not page beyond the first per-dealer response.
  • Enumerator (model): base nameplate /rc/lr/en_us/l663_k26/.jsonp → 302 → /4cvli.jsonp; root_config PRODUCT decomposition enumerates all products per nameplate. Both /lr/ and /jag/ brand paths. All nameplates resolve live.
  • Enumerator (dealer): multi-zip locator sweep per brand (Land Rover + Jaguar), dedupe by ciCode. Jaguar dealer codes transformed 0→J for NetDirector compatibility.
  • Body shape (inventory): NetDirector GraphQL returns JSON with the static authorization header and uuid parameter; no dealer-page Cloudflare/Akamai scrape is required for the current inventory source.
  • Body shape (configurator): JSONP rcjson(...), HTTP 200, 112KB, strips to JSON. No bot block.
  • Data quality: dealers real NYC coords (not 0.0); inventory valid unique VINs, real prices; models PRODUCT @ $63,500; features 124 priced leaves. ~44% of new-inventory records have null modelCode (stub allocations).

Overrides

None currently documented.