Audi Public API Sources
Audi exposes its data through three public APIs used by the ai_audi pipeline.
No API keys or partner credentials are required; all endpoints are the same backends
the www.audiusa.com website (and the other market sites) calls from the browser.
Postman collection — Audi public APIs. All four ingested endpoints are recorded as
runnable requests in the live "Public OEM APIs" collection, Audi folder, in the
AutoIntel Workspace
(reconciled 2026-07-09) — the collection itself is the record of record, not an exported
file. The Postman MCP still exposes no folder-creation/delete/transfer tool in this
workspace, so the Audi folder mixes the 4 ingested requests with pre-existing
non-ingested items (now labeled [LEGACY / UNUSED] in place rather than moved to a
subfolder):
StockCarSearch — inventory (ingested)CarlineStructure — models (ingested)dealersByMarket — dealers (ingested)CatalogForModel — features (ingested)
Market coverage
All three APIs are market-parameterized and were probed against the full ISO 3166-1
alpha-2 country list on 2026-07-07 (neither GraphQL endpoint allows introspection, so
there is no authoritative market list — coverage below reflects what actually returned
data). Each market lives in its own defs/<market>/raw/defs.yaml; a market only gets
the components its APIs actually serve:
| Tier | Assets | Markets |
|---|---|---|
| Full | dealers, carlines, catalog features, inventory | ar, au, az, bh, br, ca, ch, de, es, fr, gb, gr, ie, it, jo, jp, kr, kw, lu, mx, nl, no, om, pl, sa, se, tw, us |
| No inventory | dealers, carlines, catalog features | be, dk, fi, in, th, tr |
| Dealers only | dealers | at, bg, cz, hu, my, pt, ro, rs, si, sk |
"No inventory" markets return a carline structure but no stockCarSearch results;
"dealers only" markets return an empty carlineStructure.carlineGroups (they are not
on the OneGraph stack at all). PSS dealersByMarket responds for nearly every country
on earth — many with 1–2 import-dealer rows — so dealer counts alone do not indicate a
real market. Several more countries (e.g. nz, hk, eg, sg, qa, lb, and most
of Central America / the Caribbean) do return carline structures and could be onboarded
the same way if ever needed.
The partial tiers are not a language artifact: sweeping the full ISO 639-1 list
(the API rejects region variants like de-AT) confirms the dealers-only markets return
no OneGraph data in any language, and the no-inventory markets return carlines only in
the configured language(s) with no language yielding stock (stockCarsType: USED is
equally unknown for them). Every language that has ever returned data is in the
country's CLDR territory-language set (or en) — when re-verifying a market, probing
those candidates (plus en) is sufficient.
For multi-language markets one site language is ingested: ca→en, be→nl,
ch→de, lu→fr (both languages return identical inventory counts; only display
text differs).
API Domains
| Domain | Used for |
|---|---|
omnigraph.audi.com | Inventory (StockCarSearch) and model structure (CarlineStructure) |
graphql.pss.audi.com | Dealer locator |
web-api.audi.com | Feature / option catalog per model |
Raw dependency graph
| Node | Raw asset | Upstream | Source |
|---|---|---|---|
| a | audi/us/raw/onegraph_models | — | OmniGraph CarlineStructure |
| b | audi/us/raw/catalog_features | a | Web-API CatalogForModel per model_id |
| c | audi/us/raw/onegraph_inventory | — | OmniGraph StockCarSearch |
| d | audi/us/raw/pss_dealers | — | PSS dealersByMarket |
OmniGraph GraphQL API
POST https://omnigraph.audi.com/graphql
The original endpoint https://onegraph.audi.com/graphql began returning 403 on
2026-06-26. The replacement is https://omnigraph.audi.com/graphql. The GraphQL schema
and all response shapes are identical; only the hostname changed. See Dagster run
f72f5698-d36b-420c-a93a-cee7bb182bba for the first failed production run.
Required headers (copied from live www.audiusa.com browser traffic):
| Header | Inventory | CarlineStructure |
|---|---|---|
apollographql-client-name | fa-vlp-list-page | audi-data-platform |
apollographql-client-version | 5.16.0 | 1.0.0 |
content-type | application/json | application/json |
origin | https://www.audiusa.com | https://www.audiusa.com |
referer | https://www.audiusa.com/ | https://www.audiusa.com/ |
CarlineStructure (node a)
Fetches the full Audi USA model hierarchy — carline groups → carlines → trimlines →
models. Drives the catalog_features fan-out (node b).
A single live call (verified 2026-07-09) returns the complete current lineup in one
nested tree: 16 carline groups, 32 distinct carline ids / 36 carlines, 36
distinct modelId.code, and 75 model_catalog_id values, spanning model years
2026 (current) and 2027. There is no per-model/-year/-trim fan-out endpoint — the
tree carries every model, year, and trim as attributes of this one response. The full
current nameplate set is present (Q3/Q5/Q6 e-tron/Q7/Q8, A3/A5/A6/A8, e-tron GT, plus
the S/RS variants).
query CarlineStructure($country: String!, $language: String!) {
carlineStructure(identifier: { country: $country, language: $language }) {
carlineGroups { id name carlines { id name vehicleClass trimlines { id name
models { name hidden driveName engineName
modelId { code version extensions year }
prices { financingParameters { modelPrice } }
technicalDataV2 { modelAttributes {
bodyType drive driveTrain engineType engineTechnology fuelType gear gearType
} }
}
} } }
}
}
Variables: {"country": "us", "language": "en"}
Single request; response is a tree of carline groups stored as one raw row.
StockCarSearch (node c)
Fetches all new vehicles nationwide. Paginated with offset; total available from
resultNumber on the first page.
query StockCarSearch(
$stockIdentifier: StockIdentifierInput!,
$searchParameter: StockCarSearchParameterInput,
$groupIds: [String!],
$imageIds: [String!]
) {
stockCarSearch(stockIdentifier: $stockIdentifier, searchParameter: $searchParameter) {
resultNumber
results {
sort { id direction }
paging { limit offset }
cars { stockCar {
avpCode businessModelCode commissionNumber doors driveText gearText id
subtitleText titleText vin weblink
carPrices { label price { value } type }
carline { id name }
code { id }
colorInfo {
interiorColor { colorInfo { code text } baseColorInfo { code text } label }
exteriorColor { colorInfo { code text } baseColorInfo { code text } label }
}
dealer { id hid name zip city region position { latitude longitude } }
dynamicAttributes { id value }
engineInfo { fuel { code text } maxPowerKW { unitText value { number formatted } } maxPowerPS { unitText value { number formatted } } }
features { text featureType prNumber { family code class } }
images(groupIds: $groupIds, imageIds: $imageIds) { url type mimeType id { group image } }
model { name salesModelyear id { year code version extensions } }
salesInfo { isBuyOnline saleOrderTypeText orderStatusText physicalOrderStatus availableFromDateInfo { value type } offerDateInfo { value type } }
} }
}
}
}
Variables:
{
"stockIdentifier": {
"marketIdentifier": {"brand": "A", "country": "us", "language": "en"},
"stockCarsType": "NEW"
},
"searchParameter": {
"paging": {"limit": 100, "offset": 0},
"sort": {"id": "DATE_PREDATEEND", "direction": "ASC"},
"criteria": []
},
"groupIds": ["renderImagesPNG"],
"imageIds": []
}
Pagination: offset via searchParameter.paging.offset + .limit. resultNumber
from the first response gives the total; termination is a short/empty page. Verified
2026-07-09: paging advances (page 2 ≠ page 1) and terminates naturally on the short
final page. Pages are dispatched concurrently (10 workers) via
paginated_post_raw_fetch_result, streaming to an IPC-backed LazyFrame. The pipeline
sends limit=100.
Page-size ceiling = 200. A limit of 250 or more returns a GRAPHQL subgraph
error; limit=100 is safely under the cap.
Coverage: No geo or criteria filters — criteria: [] returns the full US
national inventory in one paginated pass. The unfiltered national resultNumber was
52,304 on 2026-07-09.
features.featureType — standard vs. optional equipment
Since OmniGraph disallows introspection, featureType semantics and the fields below
were reverse-engineered from the TypeScript source of Audi's Tier-3 dealer VDP apps
(fa-vdp-feature-and-specs, fa-vdp-pricing-bar, fa-vdp-pricing-breakdown), which
consume this same schema client-side.
featureType distinguishes SERIES = standard equipment from SPECIAL =
optional; the dealer frontend renders its standard/optional tabs directly from
this flag. It is fetched and retained verbatim in the raw tier, but is
not surfaced on the transformed feature_refs entries — those carry only
the join keys (pr3_id, parent_package_code), and the consolidation join does
not use featureType. Its intended home is a per-(model, feature)
standard-vs-optional signal on the consolidated feature entity (planned
follow-up), which is where the SERIES/SPECIAL distinction is actually queryable.
Kept as a raw string — the full vocabulary is unconfirmed.
manufacturerSpecificItems.cdbCategories — investigated, not ingested
cdbCategories (under manufacturerSpecificItems { ... on StockCarManufacturerAudi })
groups features into a category → subcategory → feature tree with per-feature
marketing copy (textInfos { name details benefits }, imageResources). It was
evaluated (July 2026) as a signal for detecting "optional but default" trim packages
and rejected. Findings from live probes (~3,900 US vehicles):
- cdb features are a strict subset of
stockCar.features(zero violations observed), but membership reflects marketing display content (CDB = content database), not ordering configuration. - Trim packages (e.g.
WPS) are omitted fromcdbCategoriesuniversally — for every model, regardless of whether the package is the trim default or a paid second tier. TheconfiguredCarquery's feature lists omit them the same way. So cdb absence carries no default-vs-optional signal; only inventorystockCar.featuresincludes package codes at all. - ~45% of
SERIESfeatures are also absent from cdb — it is a curated display list, not a complete standard-equipment list. - US-only: CA and DE return
manufacturerSpecificItemswith zero cdb feature codes.
Contrast with AccessAudi (private/ordering side), which omits a package code only when the package is the trim default — that asymmetry is the signal that still needs an independent discriminator to reconcile.
carPrices — full price breakdown
The pipeline now persists the full carPrices list (type, label,
price.value) instead of only the msrp and final price scalars. The price
object also exposes valueAsText/formattedValue (display strings) — schema-valid
but not collected. Price-type vocabulary confirmed from the frontend's priority-order
constants (not exhaustive — Audi can add types without a schema change):
- US, new:
list,OEMDiscount,dealerMarkup,dealerDocFees,destinationAndHandlingFees,dealerDiscount,dealerPrice,nonConditionalBonus,sale - Canada, new: adds levies —
freightPDI,acLevy,tireLevy,motoCouncil,adminFee,luxuryTax - Used: adds
final
Live US sampling (July 2026) observed list, dealerPrice, sale, final,
dealerDiscount (negative values), dealerMarkup, and dealerDocFees; label was
null on every entry.
Additional fields observed but not currently ingested
Schema-valid on OmniGraph, confirmed either in live www.audiusa.com traffic or in
the feature-hub app source; deliberately not collected:
| Field | Description |
|---|---|
stockCar.techDataGroups { id label techDataList { id text label } } | Full per-car technical specs (displacement, max output/torque, transmission, suspension, brakes, steering, top speed, acceleration, fuel consumption, weights, cargo). Group/item ids differ by market: US uses engine/drivetrain/suspension/brakes/fuelconsumption; international markets use power/driveline/chassis/brake-system/fuel-consumption/performance-data/volumes. Skipped because these are model-level attributes, not per-vehicle. |
stockIdentifier.stockCarsType: "USED" | Same endpoint serves used stock with mileage, qualityLabel, preUse { code text }. Not ingested — see stockCar.preUse/qualityLabel below for the individual fields. |
stockCar.metaData { statImport } | Provenance tag (AGC_USA_JDP / AGC_CAN_JDP = JD Power feed). Not ingested. |
stockCar.modelInfo.genericModel { code text } | Generic model code alongside model |
stockCar.modelInfo.modelyear | Model year, redundant with model.salesModelyear |
stockCar.qualityLabel { label } | Quality label (e.g. Certified Pre-Owned) |
stockCar.cartypeText | Car type text |
stockCar.preUse { code text } | Pre-use classification |
stockCar.descriptionByDealer | Free-text dealer description |
stockCar.colorInfo.*.imageUrl | Swatch image URLs per color |
stockCar.carPrices.disclaimers { id legalEntityKey text } | Legal disclaimer text per price line — only observed on the single-vehicle stockCar(...) query, not stockCarSearch |
cars.geoDistance { unitText value { formatted number } } | Distance from a geo anchor (only populated when geo is passed in searchParameter) |
search.criteria[].possibleItems/selectedItems | Facet counts per filter dimension |
Single-vehicle query. stockCar(stockCarIdentifier: StockCarIdentifierInput!)
also exists and returns the same fragment as stockCarSearch; unnecessary for
ingestion since the search query accepts the full fragment for all results in one
pass.
Search criteria ids. Confirmed in the wild: stat-import, t_vin (VIN
filter — useful for targeted spot-check probes). The pipeline always sends
criteria: [].
Frontend brand codes. us=50710 / ca=50720 feed the mediaservice render API
(https://mediaservice.audi.com/renderapi/v1/urlsvin) for VIN imagery. Our
pipeline already receives image URLs via images(groupIds:["renderImagesPNG"]), so
this is unused.
Known data quality issues
dealer_mat_primary_code — same VIN listed under two dealers simultaneously during vehicle transit
Observed: 2026-06-30, e.g. VIN WAUF2BF21RN008391 at USA02F21 (Audi Ann Arbor) and USA03C10 (Audi North Shore).
The StockCarSearch API returns two records for the same VIN when a vehicle is in transit between dealers. One record represents the vehicle as allocated and priced at the receiving dealer (vehicle_order_status: "Dealer Stock", non-null msrp); the other is an open allocation at the originating dealer (sale_order_type: "SHIP - Deliverable Inventory Order", null pricing). Both records are genuine concurrent line items in Audi's order management system — neither is stale or erroneous.
The true current dealer location can be determined by following the weblink field — the URL resolves to the dealer's own inventory page for that VIN, which reflects where the vehicle actually is. No scalar field in the API response reliably identifies the authoritative record without resolving the URL.
The pipeline currently uses dealer_mat_primary_code: min as a secondary tiebreak (after date_offer: max) to produce stable output when date_offer does not discriminate. This tiebreak is deterministic but not semantically meaningful — it picks the alphabetically lowest dealer code, not necessarily the dealer currently holding the vehicle.
PSS GraphQL API — Dealer Locator (node d)
POST https://graphql.pss.audi.com/
Authentication — dynamic client ID
The PSS API requires a clientid header. The value is not static — it is fetched
at runtime from the Audi Market Context Service before every dealer request:
GET https://oneaudi-falcon-market-context-service.prod.renderer.one.audi/api/market-context
?path=/content/dam/country/us/configurations/config---market-context
&aemEnvironmentId=p119811-e1162341
&aemEnvironmentService=publish
Response: {"clientId": "<value>", ...}. The clientId field is passed as the
clientid request header to the PSS endpoint.
Dealers query
query dealersByMarket($market: Market!) {
dealersByMarket(market: $market) {
dealers { ...FragmentDealerFields }
}
}
Key fields returned: dealerId, matPrimaryCode, kvpsId, name, address,
houseNumber, street, city, region, zipCode, latitude, longitude,
phone, fax, services, additionalData (display name, location
image, additional URL), openingHours (per-department day schedules).
A single A-USA call returns all 315 US dealers (verified 2026-07-09), each with a
real, in-range non-zero latitude/longitude. Two dealer identifiers are returned:
matPrimaryCode (e.g. USA01A23) and dealerId (e.g. USAA01A17, carrying an extra
brand letter). The value that matches the dealer code carried on inventory records
(stockCar.dealer.id) is matPrimaryCode, not dealerId.
Market coverage: The market variable is A-<ISO alpha-3> — A is the Audi
brand and <ISO alpha-3> the market's 3-letter country code (e.g. A-USA). Our
market identifiers are ISO alpha-2 (e.g. us), upconverted with a static map
(ai_audi.sources.iso_country). One request per market returns all of that market's
dealers in a single call. Each ingested market is a separate defs/<market>/ tree —
see Market coverage.
Audi Web-API — Feature Catalog (node b)
GET https://web-api.audi.com/vsapi/v1/us/en/CatalogForModel?model={model_id}
No authentication. One request per model ID (e.g. A31SB_2024). Model IDs are
derived from the upstream onegraph_models asset (CarlineStructure).
Response shape: featuresData containing named category lists —
accessories, bodyColors, extColors, groups, interiorTiles, roofColors,
specialGroups, stealthItems — each holding equipment families and individual
equipmentList items with id (PR3 code), name, price, type,
mbvId (PR7), renderCode, benefits, media, attributes, and optional
content (package sub-items).
Retry: 5 attempts with a 15-second pause between rounds. Fetches are sequential per model; failures up to 20 models are logged and skipped rather than hard-failing the run.