Skip to main content

Configurator Source

The Stellantis brand "Build & Price" sites (jeep.com, dodge.com, ramtrucks.com, chrysler.com, fiatusa.com, alfaromeousa.com) expose four public configurator APIs, fetched per trim (ccode + llp). They are implemented in projects/ai_stellantis/src/ai_stellantis/sources/configurator.py.

EndpointPurpose
CVDAll trims/configurations + base pricing for a model-year code (archival).
Equipment CategoriesFull ~350-option catalog with descriptions, standard flag, category hierarchy.
Catalog Option DetailsPer-option pricing, extended descriptions, associations, media.
ConfigureThe standard configuration state of each selectable option — the choice-group half of is_configurable.

No credentials required; requests use browser-impersonating headers (random_headers()).

Test fixtures

projects/ai_stellantis/tests/data/us/{cvd,equipment_categories,catalog_option,configure}_sample.json are live captures of all four endpoints for one trim — Jeep Wrangler CUJ202610JLJL74F / 2TF, a vehicle that also appears in the inventory and vehicle-data fixtures. Refresh the whole set with uv run python tests/capture.py.

The state field — deciding is_configurable

The configure endpoint (/hostd/api/configure/EN/states/US/models/{ccode}/lowerLevelPackages/{llp}/configurations/standard) returns options grouped as options[categoryId][subCategoryId][optionKey]. Each option carries a state. Established by scanning ~33k options across all 6 brands (MY2023–2027):

statemeaningselectable?
Uunselected, freely-available add-onyes
Cunselected mutually-exclusive alternative (a priced swap for the standard sibling)yes
Runselected alternative constrained by a combinations rule (jeep/dodge/ram only)yes
Sstandard equipment, selected — the fixed/standard configno
Gpackage-forced selection: on the build only because another selected option pulls it in (always prices.included=true, stateSetBy populated)no

Other useful signals: prices.included=true is the exclusive signature of S/G; locked is unused (always false in current data — do not key on it); content items (option.content[]) carry no state of their own.

The rule

A single option's flags cannot decide configurability. The standard default of a real choice and always-on standard equipment are byte-identical (state="S", standard=true, selected=true, onlyOne=true) — they differ only by whether the group offers an alternative. For example, on the Wrangler the engine group holds ERC (3.6L, state="S") and EC1 (state="C"), so the standard ERC is configurable; on the Grand Cherokee L the engine group holds only EC7 (state="S"), so it is not.

A top-level option is is_configurable iff its (categoryId, subCategoryId) group contains a member with state ∈ {U, C, R}. A group whose members are all S/G is fixed equipment. Every member of a configurable group — including its standard S/G default — is configurable.

There is intentionally no special-case for powertrain: a trim with a single engine (state="S", no alternative) is not configurable.

Content items (constituents listed under a package, e.g. the standard Quick Order Package) have no own state, so they inherit from the parent option: content of a selectable parent (state ∈ {U, C, R}) is configurable; content that exists only under fixed-standard parents (the standard QOP) is standard equipment. A content code that is also a configurable top-level option stays configurable.

The group-state rule keeps the configure feed aligned with code_guides, which treats standard equipment as non-configurable.

The visibility half — and where the two are combined

A selectable state is necessary but not sufficient. The buyer configurator only renders subcategories that equipment categories assigns to a view; options in an unassigned subcategory (e.g. 50 "Other(s)", 113 "Upper Level Packages") are never offered even when a group member has state=U. Equipment categories owns that map — subcategory_view_class is non-null exactly when the subcategory belongs to a view.

The two halves stay with the feeds that own them and are combined once, at consolidated:

HalfFeedWhere
choice groupconfigureextract_features_from_configurestate ∈ {U, C, R} within the group
subcategory_is_visibleequipment categoriesconsolidated source-group adapter.fieldssubcategory_view_class IS NOT NULL
is_configurableconsolidated derived_fieldsis_configurable AND COALESCE(subcategory_is_visible, TRUE)

subcategory_is_visible is derived in the equipment-categories adapter, from that feed's own rows, so it never reads a subcategory_view_class another feed picked up through the upstream taxonomy backfill. COALESCE(..., TRUE) covers keys equipment categories has no row for, which nothing guards. The AND applies to whichever feed won is_configurable on merge — code_guides at priority 3 where it covers a key, configure at priority 5 otherwise.

Taxonomy backfill

code_guides (PDF/LLM) and feature_catalog (BigQuery) are the two feature feeds outside the configurator fan-out, so neither carries the category/subcategory taxonomy. code_guides carries no feature_prefix either. Both properties are stable per option code, so StellantisFeatureTaxonomyComponent backfills each feed from a pool of the others, emitting enriched/code_guides_features and enriched/feature_catalog_features. These are the assets consolidated actually reads, via tier: enriched on their source groups.

enriched is an optional tier between transformed and consolidated, for a feed that has been processed by other assets before the merge. A source group is keyed <oem>/<market>/transformed/<source> unless it sets tier: enriched.

Three tiers are tried in order: (model_code, option_code), (brand, option_code), then option_code alone, each drawing from the most recent model_year among resolved pool rows. Only nulls are filled. A handful of codes resolve nowhere at all and are pinned by name in the consolidated derived_fields.

Doing this per feed rather than on the merged frame keeps each source group arriving with the columns it is expected to contribute, so merge priority means what it says.

Where a manual override goes

derived_fields entries apply in order and may reuse a name, so the guard is followed by a second is_configurable entry holding every forced-True assertion — the codes on structurally single-select axes that must stay configurable, and the option mutually exclusive with TBK. Putting them after the guard is load-bearing: the AND would otherwise undo them.

Forced-False corrections stay with the feed that owns them (code_guides is_configurable_overrides at the transformed tier), since an AND cannot undo a False.

Scope of the single-select list

An option that goes configurable → standard keeps existing on the car but stops producing an attribute, because the attribute layer filters on is_configurable. For a structural single-select axis that is wrong: every car has a transmission and tires whether or not the buyer chose them, and the cohort silently loses the attribute. JLJL74/B manual reads NO_TRANSMISSION_TYPE, and WL*P/E reads NO_TIRE_TYPE on two thirds of candidates. This presents downstream as a candidate-carried demand gap.

The forced-True list is scoped to the MY2026 → MY2027 cohorts that have actually been diagnosed, not applied by subcategory. The general rule would be that every code in a structurally single-select subcategory (Tires, Transmissions, Wheels, Engine, Gear Ratios) stays configurable, since presence on the car never depends on it having been orderable. Applying it wholesale needs the is_configurable consumers in synthetic_candidates checked first: the generator reads the same flag to decide what is a choice, so flipping it broadly risks emitting candidates without tires from the other direction.

The variation_id field — compound pair codes and tiebreaking

Each option in the configure response is identified by a variation_id. For most options this is a plain three-character code (e.g. PW7 for White Exterior Paint). For options that are defined as built-in pairings — combinations that the ordering system treats as a single unit — the API returns a hyphenated compound form: PW7-QW7 (White Paint + Glass Roof), PW7-QX8 (White Paint

  • Black Roof), etc.

The three-character form is the operationally significant one for the ordering system. The compound form is a configure-API artifact: the same PW7 option appears as a standalone code on trims where the roof is not paired, and as half of a compound code on trims where it is. The choice between PW7-QW7 and PW7-QX8 is arbitrary from a pipeline perspective — both encode the same PW7 base option, and the pairing half (roof finish) varies by trim configuration.

Because multiple configure API calls for the same option key may return different compound forms depending on query order or trim variant, the same logical option can show up as conflicting variation_id values across raw rows. The pipeline resolves this by tiebreaking on variation_id with strategy: min (lexicographic ascending), which produces a stable, deterministic choice without privileging any particular pairing.

invoice and msrp values on configure rows are considered unreliable and are overridden at the consolidation tier from more authoritative sources.

Content items and missing data via href

Both top-level options and content items carry an href pointing to the catalog-option details endpoint:

# top-level option
"href": "https://www.jeep.com/hostd/api/catalog-option/EN/details/models/{ccode}/lowerLevelPackages/{llp}/options/{variation}"

# content item
"href": "https://www.jeep.com/hostd/api/catalog-option/EN/details/models/{ccode}/lowerLevelPackages/{llp}/options/{content_variation}"

Querying these hrefs would yield:

  • Full descriptions for content items not already captured by the equipment-categories source.
  • Prefixed codes — the catalog-option response includes a media.mackevision.image.code field that carries the prefixed form (e.g. *NL), making the prefix recoverable for content items without a parent lookup.
  • Prices for content items whose parent option does not propagate pricing.
  • Potentially other fields (associations, extended descriptions) not returned in the configure response itself.

The catalog-option source already fetches details for top-level options via a separate raw asset.