Skip to main content

Porsche US (PCNA) Public API Sources

Porsche Cars North America (PCNA) exposes vehicle and dealer data through four separate services. All are unauthenticated but the Finder endpoints require a realistic browser User-Agent (HTTP 429 is returned without one).

Postman: Porsche public APIs — US

Endpoint Overview

#EndpointMethodURLPrimary data
1MPI Models APIGEThttps://mpi.pccompare.aws.porsche-preview.cloud/markets/{marketCode}/models/Per-market model catalog (82 entries for PCNA); GET /markets/ lists all 113 market codes + locales
2Finder Inventory SearchGEThttps://finder.porsche.com/us/en-US/searchPaginated vehicle listings (RSC format); filterable by dealership, condition, model
3Finder Hitcounts APIGEThttps://finder.porsche.com/api/us/en-US/hitcountsLive facet counts: model series, condition, dealers with inventory
4Finder Vehicle Detail / FeaturesGEThttps://finder.porsche.com/us/en-US/details/{listingUrlSlug}Per-listing equipment codes and options
5Dealer Microsite InventoryGEThttps://{dealer-subdomain}.porsche.com/us/en-US/search/{condition}Per-dealer inventory; no page cap
6Dealer SearchGEThttps://www.porsche.com/us/en-US/dealersearch/All 217 PCNA dealers (Astro SSR HTML)
7Leasing / Finance DataGEThttps://finder.porsche.com/api/us/en-US/leasing-finance-dataRate estimates for all models
8Car Configurator CatalogGEThttps://configurator.porsche.com/en-US/mode/model/{modelCode}.dataPer-model option/feature catalog (~160 options incl. standard equipment)

1. MPI Models API

GET https://mpi.pccompare.aws.porsche-preview.cloud/markets/{marketCode}/models/

Pure JSON API, open CORS. No authentication or special headers required. The MPI service is global, keyed by its own market codes (PCNA = USA). Returns the market's full catalog unconditionally (82 active models for PCNA) — query parameters (e.g. modelRange=911) are silently ignored. No pagination; always one page.

The modelType field is the stable model identifier used as the FK from inventory.

The MPI host exposes three nested levels — a market list, a per-market endpoint index, and the model catalog (the one the pipeline ingests):

GET https://mpi.pccompare.aws.porsche-preview.cloud/markets/                 # all markets
GET https://mpi.pccompare.aws.porsche-preview.cloud/markets/{marketCode}/ # one market's endpoint index
GET https://mpi.pccompare.aws.porsche-preview.cloud/markets/{marketCode}/models/ # model catalog (ingested)

/markets/ — a JSON array of all Porsche markets (113 at discovery, 2026-07-17), each with its MPI market code, country description, languages + languageCodes (locales, e.g. en-US), and region — e.g. { "market": "PCNA", "description": ["USA", "US"], "languageCodes": { "en": ["en-US"] }, "region": "North America" }. This is where marketCode values come from.

/markets/{marketCode}/ — the per-market node one level above models/. Its links object enumerates every Porsche service URL for the market — finder, dealerSearch, porscheCodeSearch (the configurator), compare, icc, contactForm, modelOverview — and it carries the model hierarchy (ranges, preSales, outOfProduction). It is the canonical source for the finder/dealersearch/configurator base URLs this pipeline otherwise builds by hand (for PCNA: finder → https://finder.porsche.com/us/en-US, dealerSearch → https://www.porsche.com/us/en-US/dealersearch, porscheCodeSearch → https://configurator.porsche.com/porsche-code/en-US). The model data lives one level down, at models/.

Request

No required headers or parameters. Optional:

ParameterEffect
modelRangeSilently ignored — always returns all 82 models

Response shape

Top-level object { "models": [...] }. Each entry:

FieldTypeNotes
modelTypestringPrimary model identifier (e.g. 9921B2); FK target from inventory.modelCode
modelSeriesIdstringSlug (e.g. carrera-models)
modelRangeIdstringRange slug (e.g. 911)
modelNamestringDisplay name (e.g. 911 Carrera)
modelYearstring4-digit year string
modelRangestringRange display name
modelSeriesstringSeries display name
ecoGroupstringMarketing group
priceobject{ currencyCode, formattedValue, value } — base MSRP
wheelDrivestringe.g. Rear-Wheel Drive
gearTypestringe.g. AUTOMATIC
engineTypestringe.g. FUEL, ELECTRIC
bodyTypestringe.g. Coupe, SUV
fuelTypestringe.g. FUEL, BATTERY_ELECTRIC
seatsstringe.g. 2+2
numberOfDoorsinteger
technicalDetailobjectPower (HP/kW), acceleration, top speed, range, dimensions, weight
colorGroupsarrayAvailable exterior color options
interiorDesignOptionsarrayAvailable interior options
optionsarrayAvailable model options
imagesobjectsideShot and technicalTopShot image URLs
Discontinued models

6 modelCode values seen in live inventory (e.g. 991450) are absent from the MPI catalog — these are historical/discontinued models. Expect a partial join between inventory and models.

The verbatim response is captured at projects/ai_porsche/tests/data/porsche_mpi_models_sample.json.


GET https://finder.porsche.com/us/en-US/search?condition=<c>&dealership=<id>&page=<n>

Next.js SSR endpoint. Returns paginated vehicle listings. A realistic Chrome User-Agent header is required (HTTP 429 without one). The preferred protocol is RSC format (_rsc=<random> query parameter + RSC: 1 header) which returns text/x-component with clean unescaped inline JSON — simpler to parse than the SSR HTML variant, which double-escapes all JSON.

Working query-param filters (verified 2026-07-12)

The bare /search route honors query-param filters:

ParameterValuesEffect
dealershipA dealer's ppnOrgId (e.g. 6161)Scopes results to exactly that dealer's stock; the returned listings' meta.seller.sellerId equals the requested id
conditionnew, used, porsche_approved, classicFilters to that condition only — one condition per request; span conditions by calling once per value and merging on vin (stable cross-condition identity)
modelModel-range slug (e.g. macan)Optional; omitted = all model ranges
page1-based integerpages.totalPages in the response reports the page count for the filtered result set

A dealership-scoped query returns the dealer's full multi-range inventory in a handful of pages, so per-dealer retrieval never approaches the 100-page cap below.

Hard server-side page cap

Any single query is capped at 100 pages, regardless of request format or sorting. Page 101+ returns activePage=101, totalPages=0, items=[]. Broad queries (nationwide: ~1,843 pages; per {series} path: macan ~846, cayenne ~574, 911 ~185, panamera ~108, taycan ~105) are only partially accessible — at 15 items/page, page 100 yields up to 1,500 listings per query. Narrow queries (e.g. one dealership) stay far under the cap.

There is also a legacy /search/{series} path-segment variant (series slug in the URL path). On that variant the 2026-06 probes found modelCode=, condition=, modelSeries=, seller=, modelYear=, sortBy= silently ignored — note seller is not a working alias for dealership.

Request

Parameter / HeaderRequiredNotes
User-AgentYesRealistic Chrome UA required; 429 without
_rsc query paramRecommendedAny random string triggers RSC format (text/x-component)
RSC: 1 headerRecommendedPair with _rsc for RSC format
dealership / condition / modelOptionalSee working filters above
pageOptional1-based; defaults to 1; silently clamped to 100

Response shape (RSC format)

Lines in the text/x-component stream containing "pages":{"activePage":N,"totalPages":N},"items":[...] are plain inline JSON.

Per-item fields:

FieldTypeNotes
idstringPrimary listing identifier (short alphanumeric, e.g. 5KGQNM)
listingUrlSlugstringURL slug for the detail endpoint (e.g. porsche-cayenne-gts-new-5KGQNM)
meta.titlestringDisplay name (e.g. Cayenne GTS)
meta.imageUrlstringLead image URL
meta.detailsUrlstringFull detail page URL
meta.conditionstringnew, used, or porsche_approved
meta.priceCurrencystringUSD
meta.priceValuenumberListing price
meta.vinstring17-digit VIN
meta.modelYearnumber
meta.modelstringDisplay model name
meta.colorstringExterior color display name
meta.interiorColorstringInterior color display name
meta.transmissionstringTransmission type
meta.engineTypestringcombustion or electric
meta.mileageobject{ value, unit }
meta.sellerobjectSeller name, address, sellerId, porschePartnerNumber
dataLayerListingMeta.car.listingIdstringSame as id
dataLayerListingMeta.car.modelCodestringFK to mpi_models.modelType (e.g. 9YABS1)
dataLayerListingMeta.car.modelRangeNamestringSeries slug (e.g. cayenne)
dataLayerListingMeta.car.modelModelYearnumber
dataLayerListingMeta.car.isPorscheApprovedboolean
dataLayerListingMeta.partner.ppnOrgIdstringFK to dealers.ppnOrgId
dataLayerListingMeta.partner.companyIdstringFK to dealers.porschePartnerNo (7-digit)
dataLayerListingMeta.partner.zipCodestring

The verbatim response is the raw RSC flight stream (text/x-component), captured as projects/ai_porsche/tests/data/porsche_finder_inventory_raw.txt; the fields above are the pages/items payload parsed out of that stream.


3. Finder Hitcounts API

GET https://finder.porsche.com/api/us/en-US/hitcounts

Pure JSON API. Realistic Chrome User-Agent header required (HTTP 429 without). Returns live facet counts for the Finder: model series, condition values, and sellers with active inventory. The condition[].key values are the accepted condition= filter values on the search route, and sellers[].key values are ppnOrgIds accepted by the dealership= filter — but since the search route can be queried per dealer directly, the counts themselves are not needed to retrieve inventory.

Response shape

FieldTypeNotes
hitcounts.modelSeriesarray[{ key, value }] — 12 series; key is the URL path segment
hitcounts.conditionarray[{ key, value }]new, used, porsche_approved, classic
hitcounts.bodyTypearray[{ key, value }]suv, coupe, etc.
hitcounts.sellersarray[{ key, value }] — 207 entries; key is ppnOrgId

4. Finder Vehicle Detail / Features

GET https://finder.porsche.com/us/en-US/details/{listingUrlSlug}

Next.js RSC endpoint returning per-listing equipment (option codes and descriptions). Realistic Chrome User-Agent required. Use RSC format (_rsc=<random> + RSC: 1) for clean JSON output.

The {listingUrlSlug} comes from inventory.listingUrlSlug (e.g. porsche-cayenne-gts-new-5KGQNM). The listing ID (inventory.id) is the suffix after the last -.

Response shape

FieldTypeNotes
listingIdstringFK to inventory.id
vinstring17-digit VIN
modelCodestringFK to mpi_models.modelType
modelNamestringDisplay name
modelYearnumber
equipment.importantEquipmentOptionsarray[{ value, label }] — key highlight options
equipment.specialEquipmentarrayEquipment categories, each with { name, items: [{ code, name, description, images }] }

The code field in specialEquipment[*].items[*] is the Porsche option code (e.g. PU5 = Premium Package Plus, 3FU = Panoramic Roof, 6FU = Exterior Mirror Base). The correct identity grain is (listingId, equipmentCode) — option codes are per-listing, not per-model. For the per-model option catalog (all orderable features), see the Car Configurator (§8).

The verbatim RSC detail stream is captured at projects/ai_porsche/tests/data/porsche_finder_inventory_detail_raw.txt.


5. Dealer Microsite Inventory

GET https://{dealer-subdomain}.porsche.com/us/en-US/search/{condition}

97 Porsche dealers operate *.porsche.com microsites that serve the same Next.js Finder but scoped to their own inventory. Unlike the national Finder, these sites have no observed page cap (a dealer with 200 vehicles can be fully retrieved).

The dealer subdomain is not exposed in the main dealersearch response — it requires a separate lookup (the Finder seller={ppnOrgId} filter or the dealer's known homepage URL). This endpoint is documented for completeness; the pipeline uses the national Finder for inventory ingestion.

ParameterNotes
{dealer-subdomain}e.g. porscheminneapolis
{condition}new, used, or omit for all
page1-based; no observed cap on dealer microsites

GET https://www.porsche.com/us/en-US/dealersearch/

Astro SSR HTML page. No authentication or special headers required. Dealer data is embedded as HTML-encoded JSON (&quot; = double-quote) inside the Astro component props attribute. Each dealer appears twice in the source — 434 total occurrences, 217 unique dealers.

Parse by extracting the encoded JSON string from the props attribute and decoding HTML entities.

Response shape (after parsing)

FieldTypeNotes
idstringUUID
namestringDealership display name
porschePartnerNostring7-digit partner number; FK target from inventory.companyId
ppnOrgIdstringNumeric org ID; FK target from inventory.ppnOrgId and hitcounts.sellers[].key; the value the Finder search dealership= filter accepts
addressobject{ street, postalCode, city, state, countryCode }
facilityTypestringe.g. PORSCHE_CENTER
contactDetailsobject{ phoneNumber, emailAddress, homepage }
coordinatesobject{ latitude, longitude }
Private seller

Seller ppnOrgId=2795 appears in hitcounts (1 vehicle) but has no record in the dealersearch page — this is a private seller, not a dealer.

The verbatim SSR page HTML is captured at projects/ai_porsche/tests/data/porsche_dealersearch_dealers_sample.html.


8. Car Configurator Catalog

GET https://configurator.porsche.com/{locale}/mode/model/{modelCode}.data?_routes=customer-configurator

React Router single-fetch endpoint (.data suffix) returning the full per-model option catalog as a turbo-stream payload (text/x-script, ~470 KB). No authentication, no User-Agent enforcement (CloudFront-served — not behind the Finder's Vercel WAF). Unknown model codes return 404 (text/x-script body).

The configurator app is global: the single {locale} path segment (en-US, de-CH, …) selects both market and language. {modelCode} is the same code space as mpi_models.modelType (e.g. 992892 = 911 GT3 S/C). The optional _routes=customer-configurator query param narrows the payload to that route's loader data (drops root/translation payloads, ~12% smaller).

Full-catalog sweep (2026-07-17, all 74 live MPI codes × en-US + de-CH): every 200 decodes with the same shape (67–250 options per model, catalog.orderType always echoes the requested code, bundles always empty), and repeated requests return identical decoded payloads. 11/74 codes 404 on en-US, 15/74 on de-CH — all end-of-production models (every gas 718), market absences (gas Macans in CH), or sold-out limited editions (911 GT3 90 F.A. Porsche, 911 Spirit 70). A 404 therefore means "in the MPI catalog but no longer configurable", not an error.

The wire format is a flat JSON slot array with cross-references (the turbo-stream format React Router embeds in SSR HTML via window.__reactRouterContext.streamController.enqueue). Decoded, the customer-configurator route's data carries:

FieldTypeNotes
catalog.orderTypestringThe model code — FK to mpi_models.modelType
catalog.modelName / modelYear / modelFamily / engineTypescalarModel metadata
market.currencystringISO currency for all prices (USD for en-US)
views.search.optionsobjectFlat map of ~160 options keyed by option id
views.search.ptsOptionsobject~150 paint-to-sample colors (composite ids, e.g. 0UB.89.24931-24931_TD)

Each views.search.options entry:

FieldTypeNotes
idstringPorsche option code (e.g. F37, 24940, 2C6)
titlestringDisplay name
descriptionstringHTML fragment
optionTypestringSingle-letter type (I, Z, F, M, Q, L, C, P)
familystringOption family (e.g. AUSSEN_FARBE, RAD)
sectionId / categoryId / categoryTitle / groupId / groupTitlestringCatalog grouping
isStandardEquipment / isBasicOptionboolStandard-equipment flags
priceNumericnumberPrice in market.currency (0 for no-cost options)

The verbatim turbo-stream body is captured at projects/ai_porsche/tests/data/porsche_configurator_features_raw.txt.


Cross-source identity keys

Value-matched FKs proven by live API sampling (2026-06-10):

FKSource fieldTarget fieldExampleCoverage
inventory → dealersdataLayerListingMeta.partner.ppnOrgIddealers.ppnOrgId1500007384100% (3-page sample)
inventory → dealers (alt)dataLayerListingMeta.partner.companyIddealers.porschePartnerNo4500679100% (3-page sample)
inventory → modelsdataLayerListingMeta.car.modelCodempi_models.modelType95BAU127/33 codes seen; 6 historical absent from live MPI
hitcounts → dealershitcounts.sellers[].keydealers.ppnOrgId13846206/207 match; 1 private seller
search dealership= param → dealersquery param valuedealers.ppnOrgId6161Returned listings' meta.seller.sellerId equals the requested id (verified 2026-07-12)
detail → inventorylistingId (from URL slug suffix)inventory.idV3XXVKURL slug always encodes listing ID
configurator → modelscatalog.orderTypempi_models.modelType992892Same code space; MPI codes drive the configurator fan-out (verified 2026-07-17)

Availability and WAF notes

EndpointUA requiredWithout UANotes
MPI Models APINo200Open CORS; pure JSON
Finder Inventory (SSR or RSC)Yes429Realistic Chrome UA required
Finder HitcountsYes429Realistic Chrome UA required
Finder Vehicle DetailYes429Realistic Chrome UA required
Dealer Microsite InventoryYes429Same Finder WAF rules
Dealer SearchNo200Astro SSR; no UA enforcement
Car ConfiguratorNo200CloudFront; no UA enforcement; 404 on unknown model code