Discovery Contract — audi (us)
The vetting gate between discovery and coding. This file is the human narrative + probe evidence; the authoritative gate state lives in the sidecar
discovery-contract.gate.json, validated bycheck_contract_gate.py. Keep this table in sync with the sidecar — every discovered endpoint/entity/FK inrequirementsmust have a matchingcategory:itemgate, and every HARD row should read✅ PASSor🟡 OVERRIDE: <reason>(user-approved) beforecheck_contract_gate.pypasses and coding may begin. A Postman row may instead read📦 MANUAL-IMPORT: <path>when the Postman MCP was unavailable and the collection was exported for hand-import — that state passes the gate but stays flagged. Probe markdown blocks are pasted in verbatim bypublic-api-contract-test.
- OEM / market:
audi/us - Discovered:
2026-07-09 - Gate status: ✅ all hard gates green (Postman rows recorded live in the "Public OEM APIs" collection, 2026-07-09)
Gate summary
| # | Gate | Entity / param | Status | Evidence |
|---|---|---|---|---|
| 1 | Pagination contract | inventory | ✅ PASS | pagination_probe (260/260, carline=s8l) |
| 2 | Enumerator (model) | models | ✅ PASS | live CarlineStructure flatten (36 codes / 75 catalog_ids) |
| 3 | Enumerator (year) | models | ✅ PASS | CarlineStructure modelId.year (2026/2027) |
| 4 | Enumerator (trim) | models | ✅ PASS | CarlineStructure carlines/trimlines (32/36) |
| 5 | Enumerator (dealer) | dealers | ✅ PASS | enumerator_probe (315 matPrimaryCode) |
| 6 | Multi-value filter | inventory | ⬜ N/A | pipeline sends criteria:[] — never combined |
| 7 | Body shape / bot-block | inventory | ✅ PASS | body_shape_probe (n=15, 0% block) |
| 8 | Body shape / bot-block | features (configurator) | ✅ PASS | body_shape_probe (CatalogForModel, n=15) |
| 9 | Data quality / plausibility | inventory | ✅ PASS | data_quality_probe (100 records) |
| 10 | Data quality / plausibility | dealers | ✅ PASS | data_quality_probe (315 records, real lat/long) |
| 11 | Data quality / plausibility | models | ✅ PASS | data_quality_probe (75 records) |
| 12 | Data quality / plausibility | features | ✅ PASS | data_quality_probe (207 records) |
| 13 | Cross-source identity key | inventory→dealers | ✅ PASS | matPrimaryCode 45/45 |
| 14 | Cross-source identity key | inventory→models | ✅ PASS | bare model_code (NOT composite) |
| 15 | Cross-source identity key | inventory→features | ✅ PASS | pr3_id shared namespace |
| 16 | Cross-source identity key | features→models | ✅ PASS | model_catalog_id |
| 17 | Real fixture (no synthetic) | inventory | ✅ PASS | tests/data/onegraph_stockcarsearch_sample.json |
| 18 | Real fixture (no synthetic) | dealers | ✅ PASS | tests/data/pss_dealers_sample.json |
| 19 | Real fixture (no synthetic) | models | ✅ PASS | tests/data/onegraph_carlines_sample.json |
| 20 | Real fixture (no synthetic) | features | ✅ PASS | tests/data/catalog_for_model_sample.json |
| 21 | Postman record | inventory | ✅ PASS | Postman "Public OEM APIs" → Audi folder, request StockCarSearch — inventory (ingested) (30657947-142fad49-6805-4e2b-bc50-4a7482860501) |
| 22 | Postman record | dealers | ✅ PASS | Postman "Public OEM APIs" → Audi folder, request dealersByMarket — dealers (ingested) (30657947-77f50d5e-ca1b-4d3b-bf46-45c3fd11d3d8) |
| 23 | Postman record | models | ✅ PASS | Postman "Public OEM APIs" → Audi folder, request CarlineStructure — models (ingested) (30657947-8cea62b4-20c7-4ff5-a264-26695ef0eb76) |
| 24 | Postman record | features | ✅ PASS | Postman "Public OEM APIs" → Audi folder, request CatalogForModel — features (ingested) (30657947-b2d48e26-9bad-4f3f-ae04-d366d7ba66f9) |
Per-entity endpoints
| Entity | Endpoint (method + URL) | Auth / protocol | Fixture | Notes |
|---|---|---|---|---|
| inventory | POST https://omnigraph.audi.com/graphql (StockCarSearch) | none; apollographql-client-name: fa-vlp-list-page | onegraph_stockcarsearch_sample.json | national, criteria:[], offset paging, resultNumber=52304, page-size ceiling 200 |
| dealers | POST https://graphql.pss.audi.com/ (dealersByMarket) | dynamic clientid header (market-context service) | pss_dealers_sample.json | one call per market A-<ISO alpha3>; 315 US dealers |
| models | POST https://omnigraph.audi.com/graphql (CarlineStructure) | none; apollographql-client-name: audi-data-platform | onegraph_carlines_sample.json | single nested tree; drives features fan-out |
| features | GET https://web-api.audi.com/vsapi/v1/us/en/CatalogForModel?model={id} | none | catalog_for_model_sample.json | one GET per model_catalog_id derived from models |
Cross-source identity / FK alignment (HARD)
Value-matched (not name-matched) join keys, verified against live data 2026-07-09.
| FK | Referencing entity.field | Target entity.field | Example value | Verified |
|---|---|---|---|---|
| inventory→dealers | inventory stockCar.dealer.id | dealers matPrimaryCode | USA01A23 | ✅ 45/45 (PSS dealerId fails — extra brand letter) |
| inventory→models | inventory stockCar.model.id.code | models modelId.code | GUBAAY | ✅ 14/21 (bare code; composite model_catalog_id = 0/32) |
| inventory→features | inventory feature prNumber.code | features id (PR3) | C5J | ✅ shared PR-code namespace |
| features→models | features model_catalog_id | models catalog_id | FJBABY0_2026 | ✅ by construction (per-model fetch) |
Probe evidence
1. Pagination contract — inventory
Pagination contract — ✅ PASS
- Endpoint:
POST https://omnigraph.audi.com/graphql - Contract:
offsetviasearchParameter.paging.offset+searchParameter.paging.limit, size 100 - Termination: short/empty page
- Completeness: fetched 260 unique records vs reported total 260 across 3 page(s).
- Method: narrowed to
criteria:[{"id":"carline","items":["s8l"]}](260 vehicles) so the full result set fits the page budget. Offset advances (page 2 ≠ page 1); natural termination on the short 3rd page. National unfilteredresultNumber= 52304. Page-size ceiling = 200 (limit >= 250returns aGRAPHQLsubgraph error); the pipeline sendslimit=100.
2–5. Enumerators (model / year / trim / dealer)
Enumerator (dealer) — ✅ PASS (enumerator_probe, live)
POST https://graphql.pss.audi.com/enumerates 315 distinctmatPrimaryCodevalues, e.g.['USA01A17','USA01A23','USA01A26','USA01A27','USA01A29','USA01A30','USA01A31','USA01A32']. Single nationaldealersByMarket(market:"A-USA")call returns the complete set; iterate live.
Enumerator (model / year / trim) — ✅ PASS (live CarlineStructure flatten)
enumerator_probecannot flatten Audi's 3-level-nestedCarlineStructuretree (carlineGroups → carlines → trimlines → models), so these were verified by a live flatten on 2026-07-09:CarlineStructure(POST omnigraph.audi.com/graphql, clientaudi-data-platform) returns 36 distinctmodelId.code, 75model_catalog_id, 32 distinct carline ids / 36 carlines, model years 2026 + 2027, across 16 groups.- This IS the features fan-out driver (node a → node b):
parse_model_entitiesconsumes it live — no hardcoded lineup.yearandtrimare attributes of the same single call, not independent fan-out params. Cross-checked vs inventoryStockCarSearchfacets:modelCode(48),carline(33),model-year(9, incl. older/used stock).
6. Multi-value filter — inventory
N/A — the pipeline sends searchParameter.criteria:[] (one unfiltered national pass). No
multi-value fan-out param is ever combined, so the contamination probe does not apply.
7–8. Body shape / bot-block
Body shape / bot-block (inventory) — ✅ PASS
- Endpoint:
POST https://omnigraph.audi.com/graphql— every 2xx (n=15) parsed as JSON, 0% block with and without a realistic UA. A realistic UA is not strictly required, but the source module sendsai_core.http.random_headers().
Body shape / bot-block (configurator / features) — ✅ PASS
- Endpoint:
GET https://web-api.audi.com/vsapi/v1/us/en/CatalogForModel?model=FJBABY0_2026— every 2xx (n=15) parsed as JSON, 0% block with/without UA.
9–12. Data quality / plausibility
Data quality (inventory) — ✅ PASS — 100 live records; vin, id, dealer.id,
model.id.code, carline.id all 0% implausible.
Data quality (dealers) — ✅ PASS — 315 live records; matPrimaryCode/name nonempty,
latitude/longitude in-range and non-zero across all 315 (NOT the Hyundai 0.0 signature).
Data quality (models) — ✅ PASS — 75 live records; model_code, catalog_id,
carline_id nonempty, model_year positive, 0% violations.
Data quality (features) — ✅ PASS — 207 live CatalogForModel equipment items
(FJBABY0_2026); id (PR3 code) and name nonempty, 0% violations (189 distinct pr3 ids).
13–16. Cross-source identity keys
- inventory→dealers:
stockCar.dealer.id== PSSmatPrimaryCode= 45/45 (100%). PSSdealerIdmatches 0/45 (carries an extra brand letter:USAA01A17vsUSA01A23). Stable key =matPrimaryCode→dealer_mat_primary_code. - inventory→models: bare
stockCar.model.id.code==modelId.code= 14/21 (the 7 unmatched are older-MY used/carryover stock absent from the current 2026/2027 catalog). The compositemodel_catalog_idvalue-matches 0/32 — inventory extensions/version differ from catalog — so the FK is baremodel_code, not the composite (value-match, not name-match). - inventory→features: feature
prNumber.code(PR3) and CatalogForModelidshare the same 3-char PR-code namespace; stable feature key =pr3_id. - features→models: features are fetched per
model_catalog_idderived from CarlineStructure, sofeature.model_catalog_id==models.catalog_idexactly. Stable FK =model_catalog_id.
17–20. Real fixtures
| Entity | Fixture | Live request |
|---|---|---|
| inventory | projects/ai_audi/tests/data/onegraph_stockcarsearch_sample.json | StockCarSearch (real VIN WAULSBF87RN010649) |
| dealers | projects/ai_audi/tests/data/pss_dealers_sample.json | dealersByMarket (matPrimaryCode USA01A17) |
| models | projects/ai_audi/tests/data/onegraph_carlines_sample.json | CarlineStructure |
| features | projects/ai_audi/tests/data/catalog_for_model_sample.json | CatalogForModel |
Freshness (models / features)
- models: live
CarlineStructure(2026-07-09) returns MY2026 (current) + 2027 and the full current Audi USA nameplate set (32 carlines: Q3/Q5/Q6 e-tron/Q7/Q8, A3/A5/A6/A8, e-tron GT, plus S/RS variants). Endpoint actively maintained — migratedonegraph→omnigraph2026-06-26. Fresh, not stale-but-valid. - features: live
CatalogForModelreturns current equipment data for the same MY2026model_catalog_ids (e.g.FJBABY0_2026Q3 → 207 items). Tracks the current model set.
21–24. Postman records
Reconciled 2026-07-09 directly against the live "Public OEM APIs" collection (Audi
folder, uid 30657947-4bc8f4a3-d3a9-4273-8fde-b1992a7b29bb) in the AutoIntel Workspace —
no exported JSON files; the collection itself is the record of record. The Postman MCP
still exposes no createCollectionFolder/deleteCollectionRequest/transfer tool in this
workspace, so a dedicated "Legacy / Unused" subfolder could not be created and the 11
non-ingested requests already in the folder could not be moved or deleted; each was
instead renamed with a [LEGACY / UNUSED] prefix and an explanatory description in
place. updateCollectionRequest itself needed the collection's bare UUID (no
{owner}- prefix) — passing the UID form (as the tool's own docstring implies) fails
with a changeParentError.
| Endpoint | Entity | Postman request (id) |
|---|---|---|
| OmniGraph StockCarSearch | inventory | StockCarSearch — inventory (ingested) (30657947-142fad49-6805-4e2b-bc50-4a7482860501) |
| PSS dealersByMarket | dealers | dealersByMarket — dealers (ingested) (30657947-77f50d5e-ca1b-4d3b-bf46-45c3fd11d3d8) |
| OmniGraph CarlineStructure | models | CarlineStructure — models (ingested) (30657947-8cea62b4-20c7-4ff5-a264-26695ef0eb76) |
| Web-API CatalogForModel | features | CatalogForModel — features (ingested) (30657947-b2d48e26-9bad-4f3f-ae04-d366d7ba66f9) |
11 other requests remain in the Audi folder (unmoved, due to the tool gap above) and are
now labeled [LEGACY / UNUSED]: two old scs.audi.de pre-migration captures ("Fetch
Inventory", "Vehicle Details"), the single-vehicle stockCar(...) query, the
stockCarsType: USED variant, a cdbCategories/configuredCar investigation pair
("OneGraph Config", "Configuration") already resolved as dead ends, an image-render
request, a duplicate single-VIN stockCarSearch capture, and two duplicate
dealersByGeoLocation requests (a different operation from the ingested
dealersByMarket). One stray empty-stub request ("Stock Search") was also flagged.
Overrides
No overrides. Every HARD gate is a green live probe or documented live verification.
| Gate | OVERRIDE reason | Approved by |
|---|---|---|
| — | — | — |