Skip to main content

BMW UCP Source

BmwModelEntity field mapping

Status (2026-07-20): 11 of 14 entity fields are now extracted from the UCP model matrix. Remaining 3 (model_year, base_price, m_performance_flag) are BQ-only — no UCP path identified. body_type_name has a UCP code (bodyStyle) mapped to body_type_code but no long-form name.

UCP source: prod.ucp.bmw.cloud/model-matrices

Legend: ✓ = direct mapping · — = not available · ❌ fmt = format differs · ⚠️ = uncertain/escalated

Note on UCP extraction: BmwModelEntity records are built directly in extract_models (ucp.py) — no Pydantic alias subclass. Fields set by keyword arg from nested UCP response {series_name: {modelRanges: {range_code: {models: {model_code: {...}}}}}}. Two brand calls (bmwCar, bmwi) per locale, merged. Language for phrases lookup is derived from the request locale.

UCP sample (DE fixture, brand bmwCar): series=1, range=F70, models=61GE, 11GF

BQ samples (all i7, MY2026): 267S = i7 M70, 267R = i7 eDrive50, 267Q = i7 xDrive60

Manual check procedure: Same as inventory mapping — 3 samples per source compared by eye. ✓ = concept and path confirmed by human reviewer.


Extracted fields

BQ columnEntity fieldUCP sourceUCP sample (61GE)UCP sample (11GF)BQ 1 (267S)manual checkcode note
codemodel_codetop-level key in models dict61GE11GF267S
is_bmwi (BOOL)brandrequest param brandbmwCarbmwCarfalseUCP: bmwCar/bmwi string; BQ: is_bmwi boolean
seriesseries_nametop-level series key11i7
model_rangemodel_range_codemodelRanges keyF70F70G70
series_codeseries_codemodel["series"]11i7
namemodel_namemodel["phrases"][lang]["longDescription"]BMW 123 xDriveBMW 118di7 M70locale language from request params; falls back to first available
bodystyle_codebody_type_codemodel["bodyStyle"]SHSH02UCP uses letter codes (SH); BQ uses numeric (02) — different coding
fuel_typefuel_typemodel["fuelType"]ODEsingle-letter code
drive_traindrive_typemodel["driveType"]ARVRxDrive all-wheel driveUCP uses 2-letter codes (AR, VR); BQ uses long-form strings
horsepowerhorsepowermodel["technicalData"]["enginePower"]150110650string→float coercion
sports_flag (BOOL)sports_flagmodel["sportsFlag"]NfalseNfalsefalseY/N → bool

Not available from UCP model matrix

BQ columnEntity fieldBQ 1 (267S)code note
yearmodel_year2026BQ only
body_stylebody_type_nameSedanBQ only (UCP has code bodyStyle, not long-form name)
pricebase_price168500BQ only
m_performance_flag (BOOL)m_performance_flagtrueBQ only

Notes

  • UCP bmwCar vs bmwi series_name / model_range_code conflict: The UCP catalog is queried once per brand per locale (bmwCar and bmwi). For EV variants, the same model_code appears in both catalogs with different values: bmwi appends an E suffix to model_range_code (e.g. G26E vs bmwCar's G26). Stripping the trailing E from a bmwi range code yields the bmwCar equivalent. series_name also diverges: bmwCar assigns M-performance models to their numeric or X series (e.g. "3", "X"), while bmwi classifies them as "M" or "i". A model can simultaneously be a numeric/X series and M-performance — the two catalogs are different perspectives on the same physical model. The tiebreak on model_range_code min, then series_name min, is arbitrary; it consistently picks the bmwCar row for EV variants (shorter range code sorts lower) and the non-M/i classification for M-performance models (digits and uppercase letters sort before M/i).
  • series vs series_code in BQ: identical for i-models (i7). For standard numeric series likely match too — to confirm with a broader sample.

BmwFeatureEntity field mapping (UCP)

Status (2026-07-03): extract_features_catalog (UCP details) and extract_features_pricing (UCP pricing) are live. family_type is on the entity but its model_to_visible_features extractor is pending.

UCP sources: prod.ucp.bmw.cloud model details endpoint · pricing endpoint

Note on extraction: BmwFeatureEntity records are built directly in extractor functions — there is no Pydantic alias subclass. extract_features_catalog handles UCP details; extract_features_pricing handles UCP pricing. Fields populated depend on the source — see the field matrix.

Composite primary key: feature_code + model_code

UCP model details samples (IE fixture):

feature_codenamefeature_typefamily_codeis_standarddescription
PIP6HPIP6HISPPNTfalseFashion Grey solid
P0C6RP0C6RPMETfalseBMW Individual Frozen Portimao Blue

UCP IE fixture: name field returns the option code itself (not a localised string) — locale artifact of the IE test environment.

Field × source matrix (UCP columns)

Entity fieldBQ columnUCP details pathUCP pricing pathmanual checkcode note
feature_codecoderesponse key (option code)priceTreeNode.subNodes[*].keycodes are 5-char alphanumeric (S05DM, P0C6R); format consistent across all sources
model_codeproduct_coderequest param model_idrequest param model_idBQ uses product_code column (not model_code)
brandrequest param brandrequest param brandnot in BQ raw_feature_metadata — must be set from request context
namename{code}.optionEU fixture (UCP IE): raw option code; BQ: English — locale differs, concept same
descriptionlong_description{code}.phrases.description or .longDescriptionBQ long_description empty for service-type options (S08S*)
feature_typetype{code}.typeall sources use same single-letter codes (S, F, I, P) — format consistent ✓
family_codefamily_code{code}.familyCodeBQ: empty string for service options; concept same
is_standardis_standard{code}.stdall sources: boolean — format matches ✓
price_grosslist_pricesubNodes[*].effectivePrice.grossListPriceUCP IE all 0.0 (staging)
price_netsubNodes[*].effectivePrice.netListPricenot in BQ — only available from GL Products and UCP pricing sources
currencymetadata.currencynot in BQ — EUR from UCP pricing metadata