Skip to main content

BMW Global Public API Sources

BMW's global pipeline covers 29 markets across six source systems.

Postman collection — BMW public APIs

Endpoint Overview

#SourceEntityMarketsAuthStatus
1Stolo (stolo-data-service.prod.stolo.eu-central-1.aws.bmw.cloud)Inventory28 (all except za)User-Agent + X-Api-KeyConfirmed — headers fixed
2UCP (prod.ucp.bmw.cloud)Models + features + pricingAll 29Hardcoded SPA keyConfirmed
3c2b-services (c2b-services.bmw.com)Dealers28 (all except kr)PublicConfirmed — DE=652, ZA=67, AU=56
4BMW Korea (bmw-dealer-locator.co.kr)Dealerskr onlyPublic (geo-blocked)Geo-fenced outside Korean IPs
5RIS (ris.api.bmw.com/m2m/sales/masterdata)Model featuresin, rs, th, tr (datafox markets)OAuth2 machine2machine + apikey403 pending credential provision
6BMW SA BFF (buy.bmw.co.za)Inventoryza onlyAnonymous JWTConfirmed — 84 vehicles

1. Stolo — Inventory

BMW's stock-locator service. Two endpoints: a facets aggregate for enumerating model ranges, and a paginated inventory search filtered per model range.

Base URL: https://stolo-data-service.prod.stolo.eu-central-1.aws.bmw.cloud

Authentication

The Stolo WAF requires a browser-shaped User-Agent and a static X-Api-Key header. Requests without the key return 403.

HeaderValue
User-AgentMozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/144.0.0.0 Safari/537.36
X-Api-Key7f665f5b3cb8fe8e83293052367c575f666078b87570d5557f02f248ec98
Content-Typeapplication/json
Cache-Controlno-cache, no-store, must-revalidate

1a. Inventory Facets Aggregate

POST /vehiclesearch/aggregate/{locale}/{stock_resource}

Returns a MARKETING_SERIES → MARKETING_MODEL_RANGE facet tree used to enumerate model ranges before the inventory fan-out.

Path params:

  • {locale} — IETF locale tag, e.g. de-de, ko-kr, en-in
  • {stock_resource}stocklocator for most markets; odmah_dostupna_vozila for Serbia (sr-rs)

Query params: brand=BMW

Request body:

{
"searchContext": [{}],
"resultsContext": {"sort": [{"by": "MODEL_DESCRIPTION", "order": "ASC"}]}
}

Response: {aggregateGeneric: [{name: "MARKETING_SERIES", values: [...]}]}

Walk aggregateGeneric → filter name == "MARKETING_SERIES" → explode values → filter inner name == "MARKETING_MODEL_RANGE" → collect values[].name.

Observed counts: de-de = 52 model ranges, ko-kr = 21, en-in = 13.

ZA note: en-za returns 404 — ZA is not a Stolo market. ZA inventory is served by the BMW SA BFF (buy.bmw.co.za).

1b. Inventory Search (Paginated)

POST /vehiclesearch/search/{locale}/{stock_resource}

Paginated vehicle inventory filtered to one model range (and optionally a drive type).

Query params:

ParamValue
maxResults12 (page size)
startIndex0, 12, 24, … up to 1200
brandBMW

Request body — single model range:

{
"searchContext": [{"model": {"marketingModelRange": {"value": ["BMW 1 Series"]}}}],
"resultsContext": {"sort": [{"by": "MODEL_DESCRIPTION", "order": "ASC"}]}
}

Request body — model range + drive type filter (oversize ranges):

{
"searchContext": [
{
"model": {"marketingModelRange": {"value": ["BMW 5 Series"]}},
"marketingDriveType": {"value": ["Plug-in Hybrid"]}
}
],
"resultsContext": {"sort": [{"by": "MODEL_DESCRIPTION", "order": "ASC"}]}
}

Pagination: metadata.totalCount gives the total. Page size = 12, startIndex increments by 12. Hard cap: startIndex <= 1200. Ranges with totalCount > 1200 are split by MARKETING_DRIVE_TYPE from a secondary aggregate call before pagination.

Rate limiting: Stolo's WAF enforces roughly 0.9 req/s sustained. A shared throttle at ~0.8 req/s (1.25s interval) keeps requests under the refill rate. 429 responses include a Retry-After header.


2. UCP — Models, Features, and Pricing

BMW's Universal Configurator Platform. Three endpoint families: model matrix, per-model feature/option data, and per-model pricing.

Base URL: https://prod.ucp.bmw.cloud

Authentication

Hardcoded SPA API key in x-api-key header. Browser-shaped User-Agent required for the model matrix (Akamai-protected for some market/brand pairs).

HeaderValue
x-api-keyOmFpaEFpV0VUaUlrWTJ2Tnp0ZGdiUTd1NDhxR3JOcHRacXg1UWQK
User-Agent(same browser UA as Stolo)

Market variants

Country setvehicle-treesourceapplication
Standard (all except in, rs, th, tr)connext-bmwpcasoconnext
Datafox (in, rs, th, tr)connext-bmw-datafoxdatafoxconnext-datafox

Two brand calls per locale: bmwCar and bmwi.

2a. Model Matrix

GET /model-matrices/vehicle-trees/{vehicle_tree}/sources/{source}/brands/{brand}/countries/{country}/effect-dates/{date}/order-dates/{date}

Query params: future-models=true&closest-fallback=true

Response: A JSON object keyed by series name. Each series has a modelRanges dict; each model range has a models dict keyed by model code. Top-level also includes closestEffectDate and closestOrderDate string keys (non-series data to skip). The model codes from this response drive the model_details and pricing fan-outs.

2b. Model Details (Per-model Features/Options)

GET /localisations/overridden-vehicle-data/sources/{source}/brands/{brand}/countries/{country}/effect-dates/{date}/order-dates/{date}/applications/{application}/models/{model_id}/options/languages/{language}

Response: {option_code: {option: str, std: bool, ...}}. All keys = available options; keys where std=true = selected options.

404 behavior: Returns 404 when no overridden data exists for that model — this is suppressed (treated as empty, not a failure), matching the upstream product-data-pipeline reference.

2c. Pricing (Per-model Calculation)

POST /pricing/calculation/public-calculation/price-lists/{source},con/brands/{brand}/countries/{country}

Request body:

{
"settings": {
"priceTree": "DEFAULT",
"ignoreInvalidOptionCodes": true,
"ignoreOptionsWithUndefinedPrices": true,
"roundingScale": 1
},
"validityDates": {"taxDate": "2026-06-25", "effectDate": "2026-06-25"},
"configuration": {
"model": "{model_id}",
"availableOptions": ["P0300", "S0301"],
"selectedOptions": ["P0300"]
}
}

Country-specific additional params (in additionalParams body field):

CountriesRequired param
AT, ES, FI, GR, IE, NL, NO, PTemission.wltp.co2Value
IE, PTemission.particle.noxValue, emission.particle.particleMass, emission.particle.particleMassChargeSustaining
PT, TRotd2.C_HUBRAUM.targetValue

Models with no available options are skipped. 404 is suppressed.


3. C2B Dealers

BMW's global dealer locator service. Public, no auth required.

URL: GET https://c2b-services.bmw.com/c2b-localsearch/services/api/v4/clients/BMWSTAGE2_DLO/-/pois

Query params:

ParamValue
brandBMW_BMWM
categoryBM
languagemarket language, e.g. de, en
countryISO-2 uppercase, e.g. DE, ZA
lat0
lng0
maxResults700
showAlltrue
unitkm
cachedoff

lat=0&lng=0 with showAll=true returns all dealers regardless of location. maxResults=700 covers the largest market (DE = 652 dealers).

Response envelope: {status, translation, metadata, data: {pois: [...]}, count}

POI fields: key, name, countryCode, country, state, city, postalCode, street, additionalStreet, lat, lng, dist, oh, category, attributes (includes distributionPartnerId, outletId, agDealerCode, homepage, phone, fax, mail, portfolioCode, nickname, businessPartnerId).

Market coverage: 28 of 29 markets — all except kr (Korea), which has its own geo-fenced endpoint (see Section 4).

Sample response — DE (652 dealers, trimmed to 3)
bmw_c2b_dealers_de_sample.json
{
"status": {
"key": null,
"type": "OK",
"detail": null,
"subsystem": null,
"messages": null,
"logKey": null
},
"translation": {},
"metadata": {
"serviceVersion": "4.0",
"lists": null,
"colNames": []
},
"data": {
"pois": [
{
"key": "00131_2",
"name": "Autohaus Karl + Co. GmbH & Co. KG",
"countryCode": "DE",
"country": "Deutschland",
"state": null,
"city": "Wiesbaden",
"postalCode": "65203",
"street": "Carl-Bosch-Str. 6",
"additionalStreet": "",
"settlement": null,
"lat": 50.042728424072266,
"lng": 8.22134017944336,
"dist": -1.0,
"oh": "[]",
"category": "MINI",
"attributes": {
"distributionPartnerId": "00131",
"distributionCode": "EH",
"outletId": "2",
"ownerId": "01822",
"tradeRegisterName": "Mainz",
"tradeRegisterNumber": "HRA 1983",
"dealerLogoURL": null,
"homepage": "https://www.autohaus-krah-enders.de/",
"phone": "+49-611-278090",
"fax": "+49-611-2780939",
"mail": "info@bmw-karl-co.de",
"facebookPlace": "",
"agDealerCode": "03910",
"domesticDealerNumber": "",
"telephoneAreaCode": "+49-611-278090",
"faxAreaCode": "+49-611-2780939",
"portfolioCode": "MINI",
"nickname": "Karl",
"nicknameLocal": "Karl",
"additionalName": "GmbH & Co. KG",
"additionalNameLocal": "GmbH & Co. KG",
"businessPartnerId": "00000114",
"rfSupportedEmail": {
"RFO": "SVYqClDv8eSDtbimfagblVlv6xYvUKqaaMa5rG+eP/SYoEleH8J7GH+9vL6wubPKcZg2BhIxZfJxRoGM9JZDo6+WfA==",
"RFA": "SVYqe3RIrxAhI5m4fqZaG9MxqA7WMJi3KMZ5iAaS3JYKWhTsLecjRXMRfSzKaA7PU2CI",
"RFC": "SVYqlXECeI14WJTBSOVvoDucAty8LftHrP4hzoYE0jlK1+aKJuwAP6Yf4KTS0o5NZmvq",
"RFS": "SVYqED3XZ9uoL5GTiSs8AJsizJe7O7ilxoz+ANpUTKy0jAor/lfJ8nQCe6KuetQUmR6H"
},
"rfSupportedURL": {
"RFS": "SVYqHK/JIPhksNflyWtoMKW6PBTNfPIarO/lR1Bi5pqqiP4NpyxT1NoQ1VpqSunLnkxJm19kADNgJh7la/FqzjQkdo/QkrQ2wp6aISUcjVjc7XMHB5QTCBTLHUy8wR6z0bkh"
},
"naviPublished": true,
"businessTypeCodes": [
"BB",
"CA",
"CS",
"EC",
"ES",
"GV",
"NO",
"PR",
"PV",
"SP"
],
"distributionBranches": [
"G",
"F",
"T"
],
"outletTypes": [
"FU"
],
"requestServices": [
"RFA",
"RFC",
"RFI",
"RFO",
"RFS",
"SLG",
"STL",
"TDA"
],
"services": [],
"businessRelations": [
"BB_G",
"CA_F",
"CS_F",
"EC_G",
"ES_F",
"GV_G",
"NO_T",
"NO_F",
"PR_G",
"PV_F",
"SP_F"
],
"onlineSales": [
{
"salesType": "CAR_USED",
"contact": {
"phone": "+49-611-2780966",
"email": "wiesbaden@karlco.lead.carzilla.de"
}
}
]
}
},
{
"key": "00120_8",
"name": "AH Rhein Würzburg Zw.-Nl. der AH Heermann u. Rhein GmbH",
"countryCode": "DE",
"country": "Deutschland",
"state": null,
"city": "Würzburg",
"postalCode": "97076",
"street": "Louis-Pasteur-Str. 14",
"additionalStreet": "",
"settlement": null,
"lat": 49.79352951049805,
"lng": 9.998310089111328,
"dist": -1.0,
"oh": "[]",
"category": "MINI",
"attributes": {
"distributionPartnerId": "00120",
"distributionCode": "EH",
"outletId": "8",
"ownerId": "00120",
"tradeRegisterName": "Stuttgart",
"tradeRegisterNumber": "HRB 100287",
"dealerLogoURL": null,
"homepage": "https://www.rhein-bmw.de/",
"phone": "+49-931-278850",
"fax": "+49-931-2788585",
"mail": "info@rhein-wuerzburg.de",
"facebookPlace": "",
"agDealerCode": "02766",
"domesticDealerNumber": "",
"telephoneAreaCode": "+49-931-278850",
"faxAreaCode": "+49-931-2788585",
"portfolioCode": "MINI",
"nickname": "Rhein Würzburg",
"nicknameLocal": "Rhein Würzburg",
"additionalName": "AH Heermann u. Rhein GmbH",
"additionalNameLocal": "AH Heermann u. Rhein GmbH",
"businessPartnerId": "00002100",
"rfSupportedEmail": {
"RFO": "SVYqJxVmiKKiowLJ6qizqQ3O6UGSFQ+jwyzBanF3TWQI/PXCG1jVvZ8jo3t04CWBBS5c6yWViltlzA9SdGQ6llOu7Q==",
"RFA": "SVYqT0qVH3Kn9zRJosZy3enoh9Eg2moKYhS/hTziFiuEWwUmQWzCXcC+9LyX6DXDZHSO",
"RFC": "SVYqsVWO71yrTRsCujvXwSuyqrgmCnAixNoBNUzVKkyVv6rnxkhHWIJC2cP/nZpy8UgI",
"RFS": "SVYqn8qL+Ln1u+qzjiudnGPP4xGu8rSUL0QbpH3gYaJFNoEdBrbBJfjdbGR1RQHu45Fe"
},
"rfSupportedURL": {
"RFS": "SVYqt9/oqlueCFfL4kpGlu+B5HxZROFdpWGlpoQr2CBPlaoI5bTybsPbSFekhD0LdXKVjXJwx/lCujhHzQBYjgEktQxXZiTP9tDqurfKRvpLIT7/L1cimkvq3+enCrGmuNh/"
},
"naviPublished": true,
"businessTypeCodes": [
"BB",
"CA",
"CS",
"EC",
"ES",
"GV",
"MS",
"NO",
"PR",
"PV",
"SP"
],
"distributionBranches": [
"G",
"F",
"T"
],
"outletTypes": [
"FU"
],
"requestServices": [
"RFA",
"RFC",
"RFI",
"RFO",
"RFS",
"SLG",
"STL",
"TDA"
],
"services": [],
"businessRelations": [
"BB_G",
"CA_F",
"CS_F",
"EC_G",
"ES_F",
"GV_G",
"MS_T",
"NO_T",
"NO_F",
"PR_G",
"PV_F",
"SP_F"
],
"onlineSales": [
{
"salesType": "CAR_NEW",
"contact": {
"email": "markus.stumpf@rhein-wuerzburg.de"
}
},
{
"salesType": "CAR_USED",
"contact": {
"phone": "+49-931-87098122",
"email": "rhein-wuerzburg.verkauf@autocrm.de"
}
}
]
}
},
{
"key": "00116_1",
"name": "Auto-Leebmann GmbH",
"countryCode": "DE",
"country": "Deutschland",
"state": null,
"city": "Passau",
"postalCode": "94036",
"street": "Traminer Str. 1",
"additionalStreet": "",
"settlement": null,
"lat": 48.5546875,
"lng": 13.416739463806152,
"dist": -1.0,
"oh": "[]",
"category": "MINI",
"attributes": {
"distributionPartnerId": "00116",
"distributionCode": "EH",
"outletId": "1",
"ownerId": "00116",
"tradeRegisterName": "Passau",
"tradeRegisterNumber": "HRB 4377",
"dealerLogoURL": null,
"homepage": "https://www.leebmann.de/bmw",
"phone": "+49-851-700101",
"fax": "+49-851-700211",
"mail": "info@leebmann.de",
"facebookPlace": "",
"agDealerCode": "00116",
"domesticDealerNumber": "",
"telephoneAreaCode": "+49-851-700101",
"faxAreaCode": "+49-851-700211",
"portfolioCode": "MINI",
"nickname": "Leebmann",
"nicknameLocal": "Leebmann",
"additionalName": "",
"additionalNameLocal": "",
"businessPartnerId": "00000089",
"rfSupportedEmail": {
"RFO": "SVYqCSqT2K/++AX2TwqkZgETZwGeXtfzGxaS6feCldtzs3kymXrddd9v+cjuFp3a3tPd",
"RFA": "SVYqd9Z8Z5ZGyqHUl+uwvSQN30sN0ay9293+eT3KK5A9eWLeqQLKI+yg7sl3u/iVLsv/",
"RFC": "SVYqnOsdFWE6lxKDZS9um7t03mDvnlw1kYojRsFHJpiCGYcwQsFeM9xb5s5tjoAMNtE9",
"RFS": "SVYquhRGACnzpBA+VOY0ZCyd3cVGyQIbFeUxVbcSjioL8mooimBglAS/xrrdZp/dGZig"
},
"rfSupportedURL": {
"RFS": "SVYq+Wsu6HoVM6leAoCd5gsmchR4BMsvphmDyy3mj5W56AiRW6wcp8B+1DsyWXNMzgVryiwk54Kn6J3+gDHAuA1ICfwIx65IE5zbi5f683XitmwjGBtAy78paXneV9DN6zGY"
},
"naviPublished": true,
"businessTypeCodes": [
"BB",
"CA",
"CS",
"EC",
"ES",
"GA",
"GV",
"MS",
"NO",
"PR",
"PV",
"SP"
],
"distributionBranches": [
"G",
"F",
"T"
],
"outletTypes": [
"FU"
],
"requestServices": [
"RFA",
"RFC",
"RFI",
"RFO",
"RFS",
"SLG",
"STL",
"TDA"
],
"services": [],
"businessRelations": [
"BB_G",
"CA_F",
"CS_F",
"EC_G",
"ES_F",
"GA_F",
"GV_G",
"MS_T",
"NO_T",
"NO_F",
"PR_G",
"PV_F",
"SP_F"
],
"onlineSales": [
{
"salesType": "CAR_USED",
"contact": {
"phone": "+49-851-700101",
"email": "info@leebmann.de"
}
}
]
}
}
]
},
"count": 1344
}
Sample response — ZA (67 dealers, trimmed to 3)
bmw_c2b_dealers_za_sample.json
{
"status": {
"key": null,
"type": "OK",
"detail": null,
"subsystem": null,
"messages": null,
"logKey": null
},
"translation": {},
"metadata": {
"serviceVersion": "4.0",
"lists": null,
"colNames": []
},
"data": {
"pois": [
{
"key": "02487_1",
"name": "BMW Ermelo",
"countryCode": "ZA",
"country": "South Africa",
"state": "Mpumalanga",
"city": "Ermelo",
"postalCode": "2351",
"street": "114 Kerk Street",
"additionalStreet": "",
"settlement": "Ermelo",
"lat": -26.51883316040039,
"lng": 29.984800338745117,
"dist": -1.0,
"oh": "[]",
"category": "BMW",
"attributes": {
"distributionPartnerId": "02487",
"distributionCode": "EH",
"outletId": "1",
"ownerId": "02487",
"tradeRegisterName": null,
"tradeRegisterNumber": null,
"dealerLogoURL": null,
"homepage": "https://www.bmw.co.za/ermelo",
"phone": "+27-17-8112242",
"fax": "+27-17-8191313",
"mail": "info@autobmw.co.za",
"facebookPlace": "",
"agDealerCode": "02487",
"domesticDealerNumber": "",
"telephoneAreaCode": "+27-17-8112242",
"faxAreaCode": "+27-17-8191313",
"portfolioCode": "BMW",
"nickname": "BMW Ermelo",
"nicknameLocal": "BMW Ermelo",
"additionalName": "",
"additionalNameLocal": "",
"businessPartnerId": "00001819",
"rfSupportedEmail": {},
"rfSupportedURL": {},
"naviPublished": true,
"businessTypeCodes": [
"MC",
"NO",
"CR",
"HV",
"BA",
"RB"
],
"distributionBranches": [
"F",
"T"
],
"outletTypes": [
"FU"
],
"requestServices": [],
"services": [
"RB",
"CR",
"HV",
"BA"
],
"businessRelations": [
"MC_F",
"NO_T",
"NO_F",
"CR_T",
"HV_T",
"BA_T",
"RB_T"
],
"onlineSales": []
}
},
{
"key": "21819_2",
"name": "Service Fast Lane [Potchefstroom]",
"countryCode": "ZA",
"country": "South Africa",
"state": null,
"city": "Potchefstroom",
"postalCode": "2520",
"street": "66 Walter Sisulu lane",
"additionalStreet": "",
"settlement": null,
"lat": -26.708539962768555,
"lng": 27.097679138183594,
"dist": -1.0,
"oh": "[]",
"category": "MINI",
"attributes": {
"distributionPartnerId": "21819",
"distributionCode": "EH",
"outletId": "2",
"ownerId": "21819",
"tradeRegisterName": null,
"tradeRegisterNumber": null,
"dealerLogoURL": null,
"homepage": "https://www.bmw.co.za/klerksdorp",
"phone": "+27-18-0111888",
"fax": "+27-18-4622842",
"mail": "ggh.reception@teamdaly.co.za",
"facebookPlace": "",
"agDealerCode": "51797",
"domesticDealerNumber": "",
"telephoneAreaCode": "+27-18-0111888",
"faxAreaCode": "+27-18-4622842",
"portfolioCode": "MINI",
"nickname": "",
"nicknameLocal": "",
"additionalName": "",
"additionalNameLocal": "",
"businessPartnerId": "00764705",
"rfSupportedEmail": {},
"rfSupportedURL": {},
"naviPublished": true,
"businessTypeCodes": [
"NO"
],
"distributionBranches": [
"T"
],
"outletTypes": [
"FL"
],
"requestServices": [],
"services": [],
"businessRelations": [
"NO_T"
],
"onlineSales": []
}
},
{
"key": "33519_1",
"name": "BMW Century City",
"countryCode": "ZA",
"country": "South Africa",
"state": "Western Cape",
"city": "Cape Town",
"postalCode": "7441",
"street": "1 Century Way, Century City",
"additionalStreet": "",
"settlement": "Milnerton",
"lat": -33.8927001953125,
"lng": 18.504409790039062,
"dist": -1.0,
"oh": "[]",
"category": "MINI",
"attributes": {
"distributionPartnerId": "33519",
"distributionCode": "EH",
"outletId": "1",
"ownerId": "27191",
"tradeRegisterName": null,
"tradeRegisterNumber": null,
"dealerLogoURL": null,
"homepage": "https://www.bmw.co.za/en/retailers-pages/bmw_century_city.html",
"phone": "+27-21-5256000",
"fax": "+27-86-6877363",
"mail": "smgcpt@smg.co.za",
"facebookPlace": "",
"agDealerCode": "33519",
"domesticDealerNumber": "",
"telephoneAreaCode": "+27-21-5256000",
"faxAreaCode": "+27-86-6877363",
"portfolioCode": "MINI",
"nickname": "BMW Century City",
"nicknameLocal": "BMW Century City",
"additionalName": "",
"additionalNameLocal": "",
"businessPartnerId": "00198185",
"rfSupportedEmail": {},
"rfSupportedURL": {},
"naviPublished": true,
"businessTypeCodes": [
"NO"
],
"distributionBranches": [
"T"
],
"outletTypes": [
"SE"
],
"requestServices": [],
"services": [],
"businessRelations": [
"NO_T"
],
"onlineSales": []
}
}
]
},
"count": 144
}

4. BMW Korea Dealers (Geo-fenced)

URL: GET https://www.bmw-dealer-locator.co.kr/api/getList

No query parameters required. No auth required. Returns dealer list for Korea.

Availability: Geo-fenced — returns an empty body outside Korean IP space. Fixture capture requires a Korean IP or proxy.


5. RIS — Model Features (Datafox Markets Only)

BMW's Regional Information System. Covers datafox markets only: in, rs, th, tr. The API key provisioned for this integration has no permission for other countries.

Base URL: https://ris.api.bmw.com/m2m/sales/masterdata

Authentication — OAuth2 Client Credentials

Token URL: POST https://auth.bmwgroup.net/auth/oauth2/realms/root/realms/machine2machine/access_token

HeaderValue
AuthorizationBasic {base64(client_id:client_secret)}
Content-Typeapplication/x-www-form-urlencoded

Body (form-encoded string, NOT JSON):

grant_type=client_credentials&scope=machine2machine&client_id={client_id}

Scope must be machine2machine (not openid). Token is a Bearer JWT used in Authorization: Bearer {token} on all RIS requests.

Additional headers for RIS requests:

HeaderValue
apikey{BMW_RIS_API_KEY}
bmw-ris-conversation-idce470bc2-bd25-41f0-8952-821d7de46675
bmw-ris-system-id30850

These are fixed IDs from the BMW RIS web client.

Standard query params (shared across all RIS endpoints)

ParamValue
sourcedatafox
brandbmwCar or bmwi
countryISO-2 lowercase, e.g. in
orderDatetoday's date
effectDatetoday + 30 days

5a. Model IDs

GET /vehicle-configurations/v1/models

Response: {modelResponse: {key: {agModelCode: "...", ...}}}. Extract agModelCode values. Two brand calls per locale (bmwCar and bmwi).

5b. Model Feature Endpoints (per model)

Four endpoint families, one request per (brand, model_id):

EndpointURL
OptionsGET /vehicle-configurations/v1/models/{model_id}/options
PackagesGET /vehicle-configurations/v1/models/{model_id}/packages
PhrasesGET /vehicle-configurations/v1/models/{model_id}/options/phrases (+ Accept-Language: {language}-{COUNTRY} header)
PricesGET /pricings/v1/price-list (with modelCode={model_id}, priceListsIdentifiers=datafox, currency=EUR)

404 is suppressed on all four. Accept-Language format: en-IN (BCP47).

Availability note: Token acquisition confirmed successful in ECS (confirmed 2026-06-20). API returns 403 — credentials authenticate but are not authorized for this endpoint. Correct credentials are in GCP Secret Manager: ris-auth-credential, ris-api-key, ris-client-id. These must be provisioned in ECS container env before the endpoint becomes callable.


6. BMW SA BFF — South Africa Inventory

BMW South Africa uses an Angular SPA backed by a Rockar/Magento BFF at buy.bmw.co.za. The BFF proxies to a DSP GraphQL backend. No credentials required — auth uses an anonymous JWT acquired in Step 1.

Base URL: https://buy.bmw.co.za

Step 1 — Acquire Anonymous JWT

POST /api/load-page/bmw

Headers:

HeaderValue
User-Agent(browser UA)
Acceptapplication/json, text/plain, */*
Content-Typeapplication/json
Originhttps://buy.bmw.co.za
Refererhttps://buy.bmw.co.za/new-cars

Response: {token: "..."} — a JWT string.

Step 2 — Inventory Products

POST /api/product/products

Add clienttoken: {token} header from Step 1.

Request body:

{
"handle": "bto",
"storefrontCode": "bmw_vehicle",
"first": 500,
"after": 0,
"productCatalogFilters": [{"code": "", "values": []}],
"productCatalogSorting": {"method": "monthlyPrice", "order": "ASC"},
"productCatalogFinanceFilters": {
"financeType": ["select", "instalment"],
"minMonthlyBudget": 0,
"maxMonthlyBudget": 50000000
}
}

handle=bto selects the build-to-order (new-cars) category. first=500 returns all vehicles in one request (~84 vehicles as of 2026-06-20). after=0 is the cursor start.

Response fields: id, vin, model, title, price, bodyType, fuelType, driveTrain, modelYear, manufacturerCode, images.

Observed volume: 84 vehicles (totalCount=84). No pagination needed at current scale.