Skip to main content

Public Inventory Source

The inventory source fetches active dealer inventory from the Stellantis brand public web APIs (jeep.com, dodge.com, ramtrucks.com, chrysler.com). It is specific to the Stellantis project (projects/ai_stellantis).

Endpoint Pattern

https://www.<brand-domain>/hostd/inventory/getinventoryresults.json

Pagination uses pageNumber (1-based) and pageSize query params. Total record count is read from result.data.metadata.totalcount in the first page response.

Partitioning by dealer (100k offset cap)

The search returns only the first 100,000 results per query — pages past that offset return HTTP 500 (an HTML maintenance page, not JSON). A single high-volume modelYearCode (e.g. a Ram model year code reports ~100k nationwide) therefore cannot be retrieved by one nationwide query.

To capture everything, the fetch partitions by dealer: every vehicle belongs to exactly one dealer, so the asset queries small comma-joined dealerCodes chunks (DEALER_CHUNK_SIZE, default 10) per model year code and unions them. The result is complete and duplicate-free, with each query far below the cap. Comma is the only multi-value separator the endpoint honors. The dealer list comes from the brand's dealer_locator raw asset, so the inventory asset declares two upstreams (vehicle_data_<brand> for model year codes, dealer_locator_<brand> for dealer codes). With dealerCodes set, zip/radius are required-but-ignored placeholders.

Required Environment Variables

VariableDefaultDescription
STELLANTIS_INVENTORY_ZIPUS geographic centerPlaceholder center ZIP (ignored when dealerCodes is set)
STELLANTIS_INVENTORY_RADIUSUS nationwide radiusPlaceholder radius in miles (ignored when dealerCodes is set)
STELLANTIS_INVENTORY_DEALER_CHUNK10Dealers per comma-joined dealerCodes query
STELLANTIS_INVENTORY_MODEL_WORKERS20Concurrent request pool size across all (model, chunk, page) requests
STELLANTIS_INVENTORY_THROTTLE_INTERVAL0.20Min seconds between requests pool-wide (~5 req/s)
STELLANTIS_INVENTORY_TIMEOUT60.0Per-request timeout in seconds (covers connect + read)
STELLANTIS_INVENTORY_MAX_RETRIES3Retries per request on transient errors / bot-block pages
STELLANTIS_INVENTORY_RETRY_BACKOFF2.0Initial backoff in seconds; doubles each attempt
STELLANTIS_INVENTORY_MAX_PER_MODEL(unset)Cap total records per query (dev/testing)

Authentication

No credentials required — the endpoint is a public API used by the brand consumer websites. However, it bot-blocks datacenter IPs (e.g. the production ECS egress) with HTTP 403 while serving residential IPs normally. Requests therefore go through AkamaiSessionFactory (ai_http): a curl_cffi browser TLS impersonation that seeds ak_bmsc / bm_sv cookies from the brand homepage and rotates the session on a block before retrying.

Test fixtures

projects/ai_stellantis/tests/data/us/inventory_sample.json is a live Jeep search page for CUJ202610, trimmed to three vehicles spread across the dealers in the locator fixture. Refresh with uv run python tests/capture.py; capturing it needs a residential IP, since the same bot-block applies.

Known Data Quality Issues

Incorrect brand field on Jeep vehicles

The Jeep inventory API occasionally returns a small number of records (~7 per affected day) where the brand field contains a non-Stellantis value such as "Toyota", "Ford", or "Lexus". Inspection of the affected records confirms these are genuine Jeep vehicles — VINs start with 1C4 (Chrysler/Jeep WMI) and the Stellantis-internal extImage/intImage fields carry brand=J. The corrupted brand value originates in the Stellantis backend and is returned verbatim by the API.

COSY image URL generation requires a valid Stellantis brand. make_cosy_image_urls in ai_stellantis/cosy.py validates the brand against the set of values accepted by the COSY generator (StellantisBrand Literal type). Records with an unrecognized brand are written to the output with null image URLs and a warning is logged; the partition does not fail.

Co-occurring Customer-Preferred Package codes on Wranglers

A vehicle's options string sometimes lists two Customer-Preferred Package codes that cannot both be installed: on Wrangler trims (model_code starting JLJL or JLJS) the automatic-transmission CPP (22* / 24*) appears alongside the manual-transmission CPP of the same trim level (23*). Only one CPP is ever installed, so the manual code is spurious.

Impact: feature_refs is built from options, and the public source has priority 1 for feature_refs in consolidated inventory. Both codes therefore resolve to feature_ids, and every downstream consumer (take rates, vehicle attributes, ordering) sees a manual-transmission package on an automatic vehicle.

StellantisInventoryTransformedComponent (ai_stellantis/components/transformed.py) strips the superseded code from feature_refs in the transformed tier. Rules are (model_pattern, if_present, drop) triples declared once in the feature_co_occurrence_removals template var; add a rule there when a new pair is found. Rules match on the vehicle's own model_code, and every trigger is evaluated against the incoming list, so the rules apply simultaneously.

All three inventory feeds are configured, not just the public one. inventory_api_inventory builds feature_refs from options; inventory_from_dealerconnect_bq_active and ..._sold build it the same way from poc_option_codes. Consolidated merges the three by priority (public 1, dc_active 2, dc_sold 3), so a feed left unconfigured would reintroduce the pair for any VIN the higher-priority feeds do not carry. In-transit and in-production units never appear in the public scrape at all, and sold history rows outlive it.

Existing partitions are not corrected. The removal is built into the transformed Iceberg write, so partitions materialized before it shipped still carry both codes. Consolidated scans a trailing history_days window (default 365) of transformed partitions, so a vehicle whose last observation predates the fix keeps the spurious code until those partitions are rebuilt. Reaching the full window requires backfilling transformed → consolidated → enriched.

The record self-identifies the installed package. mackevisionData.ulp names the upper-level package, and llp the lower-level one. Across 700 live 2026 Jeep + Ram vehicles, ulp was populated on every record, always appeared in options, and always appeared in the COSY sa= list carried by extImage / intImage. The superseded partner, by contrast, appeared in sa= on none of the 108 vehicles that carried more than one package-formatted code.

Membership in that package set is what the raw record does not carry. Code format is not a substitute — 553 of the 700 vehicles carry two or more codes matching \d\d[A-Z] (52Z, 51G), and restricting to the trim letter still leaves non-package codes in scope. The set is named in the features taxonomy instead: equipment-categories options whose description reads Customer Preferred Package <code> (category 112, "Do Not Display"), covering both the 2T* lower-level and 2[234]* upper-level forms.