Hyundai Public API Sources
The ai_hyundai pipeline uses three public API endpoints — no authentication
credentials are required. The BSI API endpoints require Origin and Referer
headers; the dealer locator requires Referer only.
Endpoints
Ingested
| Source | Resource | Method | URL |
|---|---|---|---|
inventory_search | inventory | POST | https://papp-bsi-api.hyundaiusa.com/inventory/item/v2/search |
dealer_locator | dealers | GET | https://www.hyundaiusa.com/var/hyundai/services/dealer.allDealers.service |
vehicle_models | models | POST | https://papp-bsi-api.hyundaiusa.com/inventory/vehicle-models/v1/search |
Discovered, not currently ingested
| Endpoint | Method | URL | What it provides |
|---|---|---|---|
| BYO model index | GET | https://www.hyundaiusa.com/var/hyundai/services/byo.build.json | All BYO-eligible models with seriesModelGroupCode and starting price |
| BYO builder API | POST | https://papp-bsi-api.hyundaiusa.com/inventory/builder-api/v1/search | Per-model accessory catalog with individual prices; same color pricing as vehicle-models |
See BYO Configurator Endpoints for details.
BSI Inventory Search
POST https://papp-bsi-api.hyundaiusa.com/inventory/item/v2/search
Required headers
| Header | Value |
|---|---|
Origin | https://www.hyundaiusa.com |
Referer | https://www.hyundaiusa.com/ |
Accept | application/json, text/plain, */* |
Content-Type | application/json;charset=UTF-8 |
Request body
{
"zipCode": "10001",
"distance": 5000,
"page": 1,
"pageSize": 100,
"sort": {"attributeName": "distance", "order": "asc"},
"atDealershipOnly": false,
"availableOnline": false,
"filterTag": null,
"personalization": null
}
Response shape
The API returns an envelope with data.total (integer) and data.items[].
{
"data": {
"total": 33285,
"items": [
{
"vin": "KMHLM4DJ8TU208020",
"dealerCode": "NY144",
"dealerName": "Koeppel Hyundai",
"dealerAddress": "34-54 44th Street",
"dealerLatitude": 40.74,
"dealerLongitude": -73.92,
"model": "ELANTRA",
"modelDisplayName": "ELANTRA",
"modelYear": 2026,
"trim": "SEL SPORT PREMIUM",
"trimDisplayName": "SEL Sport Premium",
"trimId": "K",
"sapModelCode": "494K2F4S",
"bsiModelCode": "494K2F4S",
"inventoryStatusCode": "AA",
"msrp": 26985.0,
"dealerInternetPrice": 25985.0,
"exteriorColor": "AMAZON GRAY",
"exteriorColorCode": "A5G",
"exteriorGenericColor": "gray",
"interiorColor": "BLACK",
"interiorColorCode": "NNB",
"drivetrain": "FRONT WHEEL DRIVE",
"drivetrainCode": "F",
"drivetrainName": "FWD",
"engine": "2.0L 4-CYL",
"transmission": "AUTO",
"transmissionCode": "2",
"horsepower": 147,
"cityMpg": 30.0,
"highwayMpg": 40.0,
"createDate": "2026-05-28 00:00:00",
"plannedDeliveryDate": null,
"optionCodes": ["C1", "CF", "CN"],
"distanceFromOrigin": "4.1"
}
]
}
}
Field mapping
Inventory fields (each items[] element):
| API field | Canonical field | Notes |
|---|---|---|
vin | vin | Primary key |
dealerCode | dealer_id | FK to dealers |
modelYear | model_year | Integer in API; coerced to string |
model | model_code | Uppercase model name, e.g. ELANTRA |
trimId | trim_code | Single-letter or short code, e.g. K |
trim | trim_name | Display name, e.g. SEL SPORT PREMIUM |
exteriorColorCode | ext_color_code | |
exteriorColor | ext_color_name | |
interiorColorCode | int_color_code | |
interiorColor | int_color_name | |
drivetrainName | drive_train | e.g. FWD, AWD |
engine | engine_type | e.g. 2.0L 4-CYL |
transmission | transmission | e.g. AUTO |
msrp | msrp | Float |
inventoryStatusCode | inventory_status | See status codes below |
plannedDeliveryDate | estimated_arrival_date | Null for on-lot vehicles |
Dealer fields (extracted from the same items[] elements, deduplicated by dealerCode):
| API field | Canonical field |
|---|---|
dealerCode | dealer_id |
dealerName | name |
dealerAddress | address |
dealerLatitude | latitude |
dealerLongitude | longitude |
Model fields (extracted from unique (gerpModelCode, modelYear, trimId) tuples):
| API field | Canonical field | Notes |
|---|---|---|
gerpModelCode | model_code | Cross-source join key — matches powerTrain[].gerpModelCode in the vehicle-models endpoint |
modelYear | model_year | |
modelDisplayName | model_name | |
trimId | trim_code | |
trim | trim_name | |
drivetrainName | drive_train | |
engine | engine_type | |
transmission | transmission |
Inventory status codes
| Code | Meaning |
|---|---|
AA | Available — physically on lot |
DS | In transit to dealer |
IR | In route |
PA | Port arrival |
Pagination and coverage
The API uses offset-based page numbers (page, pageSize). data.total drives
the page count: ceil(total / pageSize) pages are fetched. With distance=5000
from zip 10001, the API returns results sorted by distance from New York and
covers the full US fleet — approximately 33,300 vehicles. Page size is 100;
paginated_post_raw_fetch_result runs up to 4 pages concurrently
(max_workers=4). Each raw row stores the items[] array from one page
(extracted from the response envelope by _extract_items_content).
Three extractors from one raw asset
All three entity types — inventory, dealers, and models — are extracted from
hyundai/us/raw/inventory_search_inventory via the registry:
(inventory_search, inventory, inventory)→extract_inventory(inventory_search, inventory, dealers)→extract_dealers_from_inventory(inventory_search, inventory, models)→extract_models_from_inventory
The dealer and model transforms deduplicate by dealerCode and
(model, modelYear, trimId) respectively as they scan across pages.
allDealers Locator
GET https://www.hyundaiusa.com/var/hyundai/services/dealer.allDealers.service
Required headers
| Header | Value |
|---|---|
Referer | https://www.hyundaiusa.com/us/en/dealer-locator |
Accept | application/json, text/plain, */* |
Query parameters
| Param | Value |
|---|---|
brand | hyundai |
model | all |
lang | en |
Response shape
{
"dealers": [
{
"dealerCd": "AK003",
"dealerNm": "LITHIA HYUNDAI OF ANCHORAGE",
"address1": "...",
"city": "ANCHORAGE",
"state": "AK",
"zipCd": "99503",
"latitude": 61.18,
"longitude": -149.87,
"phone": "...",
"dealerUrl": "...",
"isIoniqDealer": false,
"isLocatorActive": true
}
]
}
A single request returns all ~861 US Hyundai dealers with no geographic filtering.
The dealer_locator raw asset stores the entire dealers[] array in one row.
Field mapping
| API field | Canonical field |
|---|---|
dealerCd | dealer_id |
dealerNm | name |
address1 | address |
city | city |
state | state |
zipCd | zip_code |
latitude | latitude |
longitude | longitude |
phone | phone |
dealerUrl | url |
This source is used as the sole (priority 1) dealer source in consolidation — it provides richer metadata (phone, URL, type flags) than the inventory-embedded dealer records.
BSI Vehicle Models
POST https://papp-bsi-api.hyundaiusa.com/inventory/vehicle-models/v1/search
Required headers
Same as the inventory search: Origin, Referer, Accept, Content-Type.
Request body
{"zipCode": "10001", "distance": 5000, "filterTag": null}
Response shape
{
"data": [
{
"modelGroupCode": "J001",
"modelName": "PALISADE",
"yearGroups": [
{
"year": 2026,
"vehicleModel": {
"seriesModelGroupCode": "J001",
"modelYear": "2026",
"modelName": "PALISADE",
"minPrice": 39435.0,
"maxPrice": 56560.0,
"freights": [{"region": "all", "price": "1600"}],
"exteriorColors": [
{"colorCode": "A2B", "colorName": "Abyss Black", "price": null},
{"colorCode": "YBM", "colorName": "Earthy Brass Matte", "price": "1000"}
],
"compareSpecifications": [
{
"categoryName": "Safety/SmartSense",
"specSubCategory": [
{
"subCategoryName": "SmartSense",
"specifications": [
{
"name": "Forward Collision-Avoidance Assist",
"values": [
{"trimId": "1", "value": "Standard"},
{"trimId": "4", "value": "Standard"}
]
}
]
}
]
}
],
"trim": [
{
"trimID": "1",
"trimName": "SE",
"minPrice": 39435.0,
"maxPrice": 41435.0,
"powerTrain": [
{
"modelCode": "J2412A65",
"driveTrain": "AWD",
"transmissionName": "Automatic",
"horsePower": "287",
"price": 41435.0,
"packages": [{"packageID": "P1", "packageName": "NO PACKAGE"}]
}
]
}
]
}
}
]
}
]
}
A single request returns all 20 current-MY models. The raw asset stores the
data[] array in one row.
Two extractors from one raw asset
vehicle_models/models feeds two transformed assets:
extract_models — one row per unique (gerpModelCode, modelYear, trimID)
powertrain variant, flattened from
data[].yearGroups[].vehicleModel.trim[].powerTrain[].
model_code is the powertrain-level gerpModelCode (e.g. PL1AAJ9AW8A5) —
this matches the gerpModelCode field on BSI inventory items, enabling the
cross-source FK join from consolidated inventory to consolidated models. The
per-model freight destination charge (freights[0].price) is stored as
freight_price.
| Source path | Canonical field | Notes |
|---|---|---|
powerTrain[].gerpModelCode | model_code | Cross-source join key — matches gerpModelCode on inventory items |
yearGroups[].year | model_year | |
modelName | model_name | |
trim[].trimID | trim_code | Coerced to string |
trim[].trimName | trim_name | |
powerTrain[].driveTrain | drive_train | |
powerTrain[].transmissionName | transmission | |
powerTrain[].price | base_msrp | |
freights[0].price | freight_price |
extract_features_and_colors — produces three row types stored together in
hyundai/us/transformed/vehicle_models_features:
Spec rows — one row per (model_code, trimId, spec_name), sourced from
compareSpecifications. model_code is the FWD powertrain's modelCode for the
trim (falls back to the first powertrain when no FWD entry exists), so the FK join
to the models consolidated entity resolves correctly.
| Field | Source / Value |
|---|---|
spec_category | compareSpecifications[].categoryName (e.g. Safety/SmartSense, Powertrain & Handling) |
spec_subcategory | specSubCategory[].subCategoryName |
spec_name | specifications[].name |
spec_value | "Standard", "Available", "Not Available", or numeric string |
model_code | FWD powertrain gerpModelCode for the trim |
trim_code | trimId from compareSpecifications values |
bsiTrimFeatures rows — one row per (model_code, trimId, feature_name),
sourced from the bsiTrimFeatures dict on each trim object. This is a curated set
of marketing-facing features grouped into categories by Hyundai's BSI system.
spec_value is always "true" (presence indicates availability on that trim).
| Field | Source / Value |
|---|---|
spec_category | bsiTrimFeatures key (e.g. comfort, connectivity, drivingAssistance, infotainment, parkingConvenience) |
spec_subcategory | "bsiTrimFeatures" |
spec_name | feature name string from the category list |
spec_value | "true" (always — presence implies availability) |
model_code | FWD powertrain gerpModelCode for the trim |
trim_code | trimID from the trim object |
Exterior color rows — one row per (seriesModelGroupCode, model_year, colorCode).
| Field | Source / Value |
|---|---|
spec_category | "exterior_color" |
spec_subcategory | "pricing" |
spec_name | exteriorColors[].colorName |
spec_value | Premium price string ("500", "1000") or "0" for no charge |
model_code | seriesModelGroupCode (e.g. "8001") — no FK match to models |
Package pricing note
Hyundai does not sell priced option packages at the trim level. The packages
array on each powertrain object contains only seat configuration choices
(e.g. "Captain's Chair Option" vs "Bench Seat Option") with
totalPackagePrice=0. These are mutually exclusive seating selections, not
paid add-ons.
BYO Configurator Endpoints
These two endpoints power the Build Your Own configurator on the Hyundai website. They are not currently wired into the Dagster pipeline but are documented here for future ingestion or reference.
BYO Model Index
GET https://www.hyundaiusa.com/var/hyundai/services/byo.build.json
No authentication required. Returns a lightweight manifest of all BYO-eligible
models — one entry per (modelYear, seriesModelGroupCode) — with starting price,
body style, and the trim/powertrain/color shortIds used by the configurator UI.
The 17 current 2026 BYO-eligible models, with their seriesModelGroupCode:
| Model | Code | Starting price |
|---|---|---|
| VENUE | 3001 | $20,550 |
| KONA | Q001 | $25,500 |
| TUCSON | 8001 | $29,450 |
| TUCSON Hybrid | 8006 | $32,450 |
| TUCSON Plug-in Hybrid | 8005 | $40,325 |
| SANTA CRUZ | 9001 | $29,750 |
| IONIQ 5 | 5004 | $35,000 |
| SANTA FE | 6001 | $35,050 |
| SANTA FE Hybrid | 6006 | $36,400 |
| PALISADE | J001 | $39,435 |
| PALISADE Hybrid | J006 | $44,160 |
| IONIQ 9 | 7004 | $58,955 |
| ELANTRA | 4001 | $22,625 |
| ELANTRA Hybrid | 4006 | $25,450 |
| ELANTRA N | 4008 | $35,100 |
| SONATA | 2001 | $27,450 |
| SONATA Hybrid | 2006 | $29,200 |
BYO Builder API
POST https://papp-bsi-api.hyundaiusa.com/inventory/builder-api/v1/search
Required headers
Same as the inventory search: Origin, Referer, Accept, Content-Type.
Request body
{"seriesModelGroupCode": "J001", "modelYear": 2026, "zipCode": "10001", "radiusDistance": 100}
One request per model code. The zipCode / radiusDistance parameters control
which dealers are factored into availability but do not affect the accessory or
color catalog.
Response shape (relevant fields)
{
"vehicleModel": {
"seriesModelGroupCode": "J001",
"modelYear": "2026",
"modelName": "PALISADE",
"trim": [...],
"exteriorColors": [
{"colorCode": "A2B", "colorName": "Abyss Black", "price": null},
{"colorCode": "YBM", "colorName": "Earthy Brass Matte", "price": "1000"}
],
"accessories": [
{"accessoryCode": "UC", "accessoryName": "100W Charging Cable", "price": "50", "accessoryType": "internal"},
{"accessoryCode": "FL", "accessoryName": "All-season fitted liners", "price": "280", "accessoryType": "internal"},
{"accessoryCode": "CV", "accessoryName": "Cargo screen", "price": "205", "accessoryType": "internal"}
]
}
}
The accessories array contains ~29 items per model with individual MSRP
prices. accessoryType is either "internal" (OEM-sourced, in the Hyundai
catalog) or "external" (dealer-installed). This is the only source of
dealer-installable accessory pricing in the Hyundai public API.
The exteriorColors[].price field is identical to what vehicle-models/v1/search
returns — no new color pricing data from this endpoint.
Difference from vehicle-models/v1/search
| Data | vehicle-models | builder-api |
|---|---|---|
| Trim + powertrain pricing | ✅ | ✅ |
compareSpecifications (feature availability) | ✅ | ❌ |
bsiTrimFeatures (marketing features) | ✅ | ❌ |
| Exterior color pricing | ✅ | ✅ (identical) |
| Accessories with prices (~29 items) | ❌ (empty array) | ✅ |
| Freight charge | ✅ | ❌ |
To ingest accessory pricing, a new raw source sweeping all 17 model codes via
builder-api/v1/search would be needed. No additional infrastructure changes
are required — the same BSI auth headers apply.
Data Relationships
inventory ──dealer_id──────────→ dealers (consolidated)
inventory ──(model_code, model_year)──→ models (consolidated)
features ──(model_code, model_year)──→ models (consolidated) [spec rows only]
The consolidated tier resolves both inventory FKs: dealer_id → dealer_id and
(model_code, model_year) → model_id. Features color rows use
seriesModelGroupCode as model_code, which does not match the powertrain-level
model codes, so the FK join produces no match for color rows — this is expected.
Environment Variables
No Hyundai-specific environment variables are required beyond the standard
platform variables (ICEBERG_CATALOG_URI, ICEBERG_WAREHOUSE, RAW_STORAGE_URI).
Asset Keys
| Asset | Key |
|---|---|
| Inventory source | hyundai/us/sources/inventory_search_inventory |
| Inventory raw | hyundai/us/raw/inventory_search_inventory |
| Dealer source | hyundai/us/sources/dealer_locator_dealers |
| Dealer raw | hyundai/us/raw/dealer_locator_dealers |
| Vehicle models source | hyundai/us/sources/vehicle_models_models |
| Vehicle models raw | hyundai/us/raw/vehicle_models_models |
| Transformed inventory | hyundai/us/transformed/inventory_search_inventory |
| Transformed dealers | hyundai/us/transformed/dealer_locator_dealers |
| Transformed models | hyundai/us/transformed/vehicle_models_models |
| Transformed features | hyundai/us/transformed/vehicle_models_features |
| Consolidated dealers | hyundai/us/consolidated/dealers |
| Consolidated models | hyundai/us/consolidated/models |
| Consolidated features | hyundai/us/consolidated/features |
| Consolidated inventory | hyundai/us/consolidated/inventory |