Identifiers and data flow

This guide answers “where do I get this value?” and “where may I send it next?” for the identifiers exposed by the public OpenAPI 3.1 contract (version 1.71.0). Field paths below start at a successful JSON response body unless a callback or request location is stated explicitly.

Treat every identifier as opaque unless its schema gives a format or pattern. Preserve the original string, case and separators when the contract does not promise normalization. Never derive one identifier type from another.

VIN

Question Contract answer
Meaning vin is the vehicle identification number used by the VIN and vehicle-recall operations. extractVinFromImage returns only a visibly photographed, complete and unambiguous 17-character VIN; the browser-session request separately permits a partial 3–17-character input so that a user can complete it in the interface. A VIN identifies the vehicle input; it is not a compatibility result and is not interchangeable with tapiId.
Producers and exact response fields Extraction: extractRegistrationDocument — data.vehicle.vin in production and sandbox alike; its deprecated extractRegistrationDocumentLegacyPath alias returns the same field. extractInternationalRegistrationDocument and deprecated extractInternationalRegistrationDocumentLegacyPath — vehicle.vin; extractCalculationDocument and deprecated 11-field extractDocument — vehicle.vin; extractPurchaseContract — vehicle.vin; extractVehicleDocument and deprecated extractVehicleDocumentLegacyPath — vehicle.vin; extractVinFromImage — vin; intakeVehicle — registrationDocument.vehicle.vin and top-level vin. These fields may be null where their schemas permit it. VIN-operation echoes/results: getVehicleByVin — vin; getPartsByVin — immediate vin, accepted-job vin, successful async result.vin; getVinPartsJob — job vin and successful result.vin; checkVinCart — immediate vin, accepted-job vin, successful async result.vin; getVinCartCheckJob — job vin and successful result.vin; getVinEconomicEvaluation — immediate vin, accepted-job vin, successful async result.vin; getVinEconomicEvaluationJob — job vin and successful result.vin; matchVehicleRecalls — vin.
Consumers Request body vin in createVinRedirectSession — POST /vin/redirect-sessions; path vin in getVehicleByVin — GET /vin/{vin}/vehicle; path vin in getPartsByVin — GET /vin/{vin}/parts; request body vin in checkVinCart — POST /vin/cart-check; path vin in getVinEconomicEvaluation — GET /vin/{vin}/economic-evaluation; request body vin in createVinEconomicIntelligence — POST /vin/economic-intelligence; path vin in matchVehicleRecalls — GET /recalls/vehicles/{vin}; optional request field vehicle.vin in classifyEndOfLifeVehicle — POST /vision/vehicle/elv-classification; optional request body vin in identifyPart — POST /parts/identify.
Prerequisites The caller must be authorised to transmit and process the VIN. For getPartsByVin, use any optional numeric selection consistently; a conflicting value returns 409 vin_provider_mismatch. getVinEconomicEvaluation accepts only provider=1. createVinEconomicIntelligence additionally requires body marketCountry, currency and condition and returns evaluationId, not a VIN echo, in its final response. checkVinCart and createVinEconomicIntelligence require a 17-character vin matching ^[A-HJ-NPR-Z0-9]{17}$; createVinRedirectSession, identifyPart and classifyEndOfLifeVehicle accept 3–17 characters matching ^[A-HJ-NPR-Za-hj-npr-z0-9]{3,17}$; the path parameter vin of getVehicleByVin, getPartsByVin, getVinEconomicEvaluation and matchVehicleRecalls declares no length or pattern. Follow every operation's documented prerequisites.
Alternatives Obtain a VIN from a registration document with extractInternationalRegistrationDocument or extractRegistrationDocument, from a calculation with extractCalculationDocument, from a purchase contract with extractPurchaseContract, from a rich vehicle document with extractVehicleDocument, or through the combined intakeVehicle; obtain it from a photograph with extractVinFromImage. The four *LegacyPath/extractDocument paths are compatibility aliases, not alternatives for new integrations. If only tapiId is available, the public API can return Client-scoped technical vehicle data or compose listing text, but it has no operation that converts tapiId back to VIN.
Terminal/dead-end warnings A null scanner/intake VIN is not an identifier and must not be padded or guessed. The redirect callback carries no VIN: it only extends the returnUrl query by status, tapiId (on completion) and, if set, state; a partial 3–16-character session input stays partial and is rejected by the 17-character patterns of checkVinCart and createVinEconomicIntelligence, so obtain a full VIN independently before using it there. A cancelled callback has no tapiId. incomplete=true from getVehicleByVin means the VIN was not resolved to exactly one vehicle; remaining fields describe only the first candidate. matchVehicleRecalls returns 404 vin_not_resolvable when the VIN cannot be resolved to a vehicle series.

tapiId

Question Contract answer
Meaning tapiId is the stable public vehicle reference returned after a successful VIN flow or a successful vehicle-intake match. It refers to the matched technical vehicle type, not the individual physical vehicle; several VINs may share it. Access is Client-scoped. Store it separately from VIN.
Producers and exact response fields getVehicleByVin — tapiId; completed createVinRedirectSession flow — callback query parameter tapiId (not a session-creation JSON field); getPartsByVin — immediate tapiId or successful async result.tapiId (both nullable); getVinPartsJob — successful result.tapiId (nullable); getVinEconomicEvaluation — immediate tapiId or successful async result.tapiId; getVinEconomicEvaluationJob — successful result.tapiId; intakeVehicle — nullable top-level tapiId. getVehicleByTapiId and composeVehicleListing echo the consumed value as top-level tapiId.
Consumers Path tapiId in getVehicleByTapiId — GET /vehicles/{tapiId}; path tapiId in composeVehicleListing — POST /vehicles/{tapiId}/listing. No other public request field consumes it.
Prerequisites The reference must previously have been returned through a successful VIN flow or as a non-null intakeVehicle.tapiId for the same authenticated Client. A browser callback produces it only with status=completed; an async VIN job produces it only inside a successful result. For vehicle intake, use the returned tapiId only when it is non-null; do not infer one from other response fields.
Alternatives If tapiId is unavailable but VIN is available, run the applicable VIN vehicle flow: a successful getVehicleByVin lookup returns it; if getVehicleByVin answers 409 redirect_required instead, the lookup has to go through createVinRedirectSession. intakeVehicle can combine document extraction and VIN matching, but its tapiId remains nullable.
Terminal/dead-end warnings tapiId=null, a cancelled callback, or a failed job cannot feed a {tapiId} path. An unknown, foreign or unavailable value returns 404. GET /vehicles/{tapiId} returns no VIN or equipment, and there is no reverse-lookup endpoint. Do not treat shared tapiId equality as proof that two records are the same physical vehicle.

OE number

Question Contract answer
Meaning An OE number is the part-number string submitted through fields named oeNumber, oeNumbers or customerOeNumbers. A scanner reading is only a candidate until an OE operation confirms it. Preserve the business input separately from any normalized result.
Producers and exact response fields Vehicle-derived: getPartsByVin and getVinPartsJob — immediate or successful async parts[].number / result.parts[].number (nullable); getVinEconomicEvaluation and its job status — immediate or successful async parts[].number / result.parts[].number. Confirmed OE base: getOePart — part.number, grouped references[].numbers[], consolidated referenceNumbers.oe_oem_reference_numbers[], and directed replacementChain[].from / replacementChain[].to; its top-level oeNumber is the requested number with only outer whitespace removed. Normalization candidates: normalizeOeNumber — original input, normalizedOeNumber, equivalentOeNumbers[], and knownCandidates[].value. Image readings: extractLabelPartNumbers — partNumbers[]; extractLabelDetails — data.primaryPartNumber and data.otherPartNumbers[]. Production and sandbox use these same shapes. Part identification: identifyPart — nullable oeNumber and normalizedOeNumber, vinPart.number (vinPart is nullable) and candidates[].number. Intelligence clusters: resolvePartIntelligence, getPartClusterIntelligence and the final getPartIntelligenceJob response — cluster.identifiers[].value where scheme=oe. Operation echoes: getOeAftermarketReferences, getOePrice and getPartSeo — oeNumber; checkVinCart and its job status — successful results[].oe / result.results[].oe; matchPartRecalls — positions[].oeNumber; generatePartImagesFromOeNumber and its status — oeNumber and successful result.oeNumber.
Consumers Path oeNumber in getOePart — GET /parts/oe/{oeNumber}; getOeAftermarketReferences — GET /parts/oe/{oeNumber}/aftermarket-references; getOePrice — GET /parts/oe/{oeNumber}/price; getPartSeo — GET /parts/oe/{oeNumber}/seo. Query oeNumber in normalizeOeNumber — GET /parts/oe/normalize; query oeNumber in resolvePartIntelligence — GET /parts/intelligence. Body oeNumbers[] in checkVinCart — POST /vin/cart-check; body positions[].oeNumber in matchPartRecalls — POST /recalls/parts; body oeNumber in generatePartImagesFromOeNumber — POST /vision/part/generate; body customerOeNumbers[], labelReadings[].numbers[] and labelReadings[].extractAll in identifyPart — POST /parts/identify.
Prerequisites Validate a scanner reading with normalizeOeNumber or getOePart before treating it as a catalogue fact. Send the optional manufacturer only when it is known. Cart checking additionally requires a VIN and mode; recall matching accepts optional vehicle context; image generation takes body oeNumber matching ^[A-Za-z0-9][A-Za-z0-9 ._/-]{0,79}$ and the optional sourceMode (default references_required; also references_preferred or knowledge_only).
Alternatives If the number is only visible on a label, use a label extraction operation first. identifyPart combines customer numbers, label readings, designations and an optional VIN and answers status matched, candidates or unresolved. If the business goal is parts for a vehicle and only VIN is known, use getPartsByVin. tapiGenArt and VDI codes are separate output classifications and cannot replace an OE-number request input.
Terminal/dead-end warnings OCR strings, reference or comparison numbers from getOePart and aftermarket references from getOeAftermarketReferences do not guarantee technical interchangeability or fit. getOePart returns 404 (not_found, oe_part_not_found) when no part is known for the number and 422 ambiguous_oe_number when it cannot be resolved uniquely; every 200 contains a confirmed base match. A replacement edge is directed from from to to; do not invent the inverse or derive direction from references or referenceNumbers. In a cart response, fits=false is a reliable exclusion only when complete=true.

normalizedOeNumber

Question Contract answer
Meaning normalizedOeNumber is the confirmed normalized OE number returned by the API, not a local formatting transform. In normalization it is non-null only for status=matched; in the base OE response it is the confirmed normalized number to which the response applies.
Producers and exact response fields normalizeOeNumber — normalizedOeNumber; getOePart — normalizedOeNumber; matchPartRecalls — positions[].normalizedOeNumber; identifyPart — nullable top-level normalizedOeNumber.
Consumers No public request schema has a field named normalizedOeNumber. Pass a non-null value through an operation's oeNumber input when that is the intended next step.
Prerequisites For normalizeOeNumber, require status=matched before consuming the field. For matchPartRecalls, require a non-null position value; for identifyPart, require status=matched. A base OE 200 already represents a confirmed match.
Alternatives getOePart can return a confirmed normalized value together with the base part. When explicit status, reasons, equivalent numbers or candidates are required, use normalizeOeNumber instead.
Terminal/dead-end warnings The normalization response is null for unresolved, ambiguous and invalid. Do not implement uppercase/strip logic and label it normalizedOeNumber.

part.name

Question Contract answer
Meaning Nullable public part designation for the confirmed OE base response. The value is a string or null; the public contract makes no guarantee about its language or origin.
Producer and exact response field getOePart — part.name. When available, its value is a string or null.
Consumers Catalogue, ERP and display integrations may store or render the returned value. Translation can receive the non-null value as query text (at most 1000 characters, exactly one part designation) of translatePartName; that operation also requires query sourceLanguage, which part.name does not state.
Prerequisites Consume only after a successful getOePart base match and preserve the returned value exactly.
Alternatives When null, request human curation or leave the local label empty. Do not reconstruct it from another response field.
Terminal/dead-end warnings part.name describes a part but does not prove fitment, interchangeability or VIN-specific installation.

tapiGenArt

Question Contract answer
Meaning tapiGenArt is the stable public tapinomahub GenArt attached to a returned part, represented as a string matching ^TGA-[0-9]{6,}$ in getOePart, getPartsByVin and getVinPartsJob; identifyPart declares ^TGA-[0-9]{6}$ (exactly six digits). In getOePart the required field is null when no valid classification is available. It is opaque and distinct from OE numbers and VDI codes.
Producers and exact response fields getOePart — top-level required tapiGenArt containing a valid code or null; getPartsByVin — immediate parts[].tapiGenArt or accepted job's successful result.parts[].tapiGenArt; getVinPartsJob — successful result.parts[].tapiGenArt; identifyPart — required nullable top-level tapiGenArt, vinPart.tapiGenArt when vinPart is not null, and candidates[].tapiGenArt. Every successful getPartsByVin or getVinPartsJob position contains exactly one non-null value; the identifyPart fields can be null.
Consumers None. No public path, query parameter or request body field accepts tapiGenArt.
Prerequisites Obtain a non-null value from a successful confirmed OE base response, a returned VIN-parts position or an identifyPart response. Do not create it from a name, numeric suffix or another classification value, and do not treat null in a confirmed OE response as a failed base match.
Alternatives Use the OE number for OE operations and vdi[] for confirmed VDI mappings. These identifiers describe different contract concepts and are not substitutions for tapiGenArt.
Terminal/dead-end warnings It is output-only in the released API. There is no public “parts by tapiGenArt” or “vehicles by tapiGenArt” operation. Treat the entire string as opaque; do not convert its suffix to an integer. The independently returned vdi[] field is a separate classification and must not be derived from tapiGenArt.

VDI

Question Contract answer
Meaning A VDI 4081 code identifies a catalogue item. getVdiCatalog returns a base code matching ^VDI4081_[0-9]+$. A confirmed part mapping in getOePart.vdi[], getPartsByVin.parts[].vdi[] or getVinPartsJob.result.parts[].vdi[] may additionally have one numeric installation-location suffix and matches ^VDI4081_[0-9]+(?:_[0-9]+)?$.
Producers and exact response fields getVdiCatalog — entries[].code for base codes, plus stand, mainGroups[] and entry metadata; getOePart — required top-level vdi[] containing only valid confirmed full codes associated with the confirmed OE base record; getPartsByVin — required immediate parts[].vdi[] or a successful job's result.parts[].vdi[]; getVinPartsJob — required result.parts[].vdi[] on success.
Consumers None. No public path, query or body field accepts a VDI code.
Prerequisites Use getOePart after a confirmed OE base match when a mapping for one known OE number is required. Use the required vdi[] field of each returned VIN-parts position when the mapping belongs to that VIN result. Use getVdiCatalog with pagination when catalogue metadata is required.
Alternatives tapiGenArt is a separate tapinomahub part-category identity and OE number is a separate part identifier. Neither is a documented conversion of a VDI code.
Terminal/dead-end warnings vdi=[] means no valid mapping was available; it does not invalidate the part and does not leave a VIN-parts job incomplete. getVdiCatalog explicitly returns no OE assignments. A catalogue base code omits any installation-location mask; do not invent, append or strip a suffix to create an undocumented mapping.

vehicleTypeKey

Question Contract answer
Meaning vehicleTypeKey is the opaque string key of one type-level assignment in PartOeResponse.fitment[]. It is neither a VIN nor a tapiId. Keep every criteria[] value attached to the key that carries it.
Producers and exact response fields getOePart — fitment[].vehicleTypeKey. The same entry's criteria[] contains its documented restrictions; an empty list means no restriction is recorded for that assignment.
Consumers None in API 1.71.0. No public path, query parameter or request body accepts vehicleTypeKey.
Prerequisites Consume it only from a successful base OE response. fitment=[] means that no assignments were returned.
Alternatives For one known vehicle, use VIN plus POST /vin/cart-check. For Client-scoped technical vehicle data, obtain a tapiId through a documented VIN flow and call GET /vehicles/{tapiId}. Neither operation converts vehicleTypeKey.
Terminal/dead-end warnings The API does not resolve the key to make, model, VIN or tapiId, and it does not promise worldwide assignment completeness. Do not parse the key, join it to an undocumented table or treat it as installation approval.

clusterId

Question Contract answer
Meaning clusterId is the UUID identity of one versioned part cluster. clusterVersion identifies the returned composition of that cluster. Neither value is an OE number, aftermarket number, fitment result, kType, NatCode or GenArt.
Producers and exact response fields resolvePartIntelligence, getPartClusterIntelligence and the final getPartIntelligenceJob response — cluster.clusterId and cluster.clusterVersion; getPartClusterIntelligenceHistory — top-level clusterId and each points[].clusterVersion; createVinEconomicIntelligence and the final getVinEconomicIntelligenceJob response — candidates[].clusterId and candidates[].clusterVersion.
Consumers Path clusterId in getPartClusterIntelligence — GET /parts/clusters/{clusterId}/intelligence; path clusterId in getPartClusterIntelligenceHistory — GET /parts/clusters/{clusterId}/history. The current-snapshot operation can additionally consume the exact returned clusterVersion as a query parameter.
Prerequisites Obtain the UUID from an Intelligence result and keep clusterVersion, market scope, asOf and provenance.snapshotId with the result that produced it. A resolver request needs query oeNumber or aftermarketNumber; kType, natCode and genArt are only disambiguation context. resolvePartIntelligence, getPartClusterIntelligence and getPartClusterIntelligenceHistory require an Idempotency-Key header of 16–100 characters matching ^[A-Za-z0-9_-]+$.
Alternatives With only an OE or aftermarket number, call resolvePartIntelligence. With only a VIN, createVinEconomicIntelligence would return candidate clusters, but x-intelligence-release.vinEconomicIntelligence is disabled.
Terminal/dead-end warnings The six cluster-based Intelligence operations are a closed production pilot (x-intelligence-release.status is closed_production_pilot, commercialAccess is disabled); no real results are delivered without approved positive prices and atomic billing. A cluster UUID does not prove technical interchangeability or VIN fitment. A newer cluster version must not silently rewrite a stored snapshot. Evidence and results are scoped to the authenticated Client and returned market dimensions; matching UUID text does not make tenant-scoped evidence portable.

evaluationId

Question Contract answer
Meaning evaluationId is the UUID of one VIN Economic Intelligence evaluation. In the current pilot, the same UUID identifies the originating request and, during asynchronous processing, its job; the final response carries it as both requestId and evaluationId, equal to any previously returned jobId.
Producer and exact response field createVinEconomicIntelligence on immediate completion, or the final getVinEconomicIntelligenceJob response — top-level evaluationId. An accepted or still-running 202 exposes the same UUID as requestId and jobId, but does not yet contain an evaluationId field.
Consumers Pass the same UUID as path jobId to getVinEconomicIntelligenceJob; it answers 202 while processing runs and 200 with the final result afterwards. No separate lookup path consumes an evaluationId field in API 1.71.0.
Prerequisites Retain it only from a schema-valid final response and keep it with asOf, scope, pipeline, candidate set, confidence, provenance and warnings.
Alternatives Use the returned statusUrl while work is pending and retain the field roles even though requestId, jobId and the later evaluationId intentionally contain the same UUID in this pilot.
Terminal/dead-end warnings The equality is specific to the VIN Intelligence pilot contract. x-intelligence-release.vinEconomicIntelligence is disabled: the route is deployed but remains disabled fail-closed, so no evaluationId is currently issued. Never move the UUID to another job family or substitute it for clusterId, VIN or a local vehicle ID.

jobId

Question Contract answer
Meaning jobId is a UUID identifying one asynchronous job of one job family. It is not a general resource identifier and must be polled through the status operation paired with its producer.
Producers and exact response fields getPartsByVin 202 — jobId; checkVinCart 202 — jobId; getVinEconomicEvaluation 202 — jobId; generatePartImagesFromOeNumber 202 — jobId; resolvePartIntelligence or getPartClusterIntelligence 202 — jobId; createVinEconomicIntelligence 202 — jobId. For both Intelligence families, requestId and jobId are the same UUID. A pending Intelligence status response repeats that UUID; the final VIN result exposes it again as requestId and evaluationId.
Consumers getVinPartsJob — GET /vin/parts/jobs/{jobId}; getVinCartCheckJob — GET /vin/cart-check/jobs/{jobId}; getVinEconomicEvaluationJob — GET /vin/economic-evaluation/jobs/{jobId}; getPartImageGenerationJob — GET /vision/part/generation-jobs/{jobId}; getPartIntelligenceJob — GET /parts/intelligence/jobs/{jobId}; getVinEconomicIntelligenceJob — GET /vin/economic-intelligence/jobs/{jobId}.
Prerequisites Create the value only by receiving the corresponding 202. Store the required full statusUrl, job family and retry timing together; also capture Location for comparison. For getPartsByVin, checkVinCart and getVinEconomicEvaluation it is declared as uri-reference with one shared root-relative example; do not construct or origin-resolve a URL from it. Poll queued or running jobs after the returned Retry-After/retryAfterSeconds.
Alternatives Follow statusUrl rather than constructing a path. For VIN parts, cart checks, economic evaluations and Intelligence requests, an immediate 200 contains the result and creates no job to poll. Part-image generation is documented as asynchronous and starts with 202.
Terminal/dead-end warnings Use every jobId only with its returned statusUrl and paired status operation. Older job resources can return HTTP 200 while their domain state is still non-terminal; Intelligence status operations return 202 while pending and 200 only with the final business result. Never send a job ID to another family's path.

clientId

Question Contract answer
Meaning clientId is the integer that addresses a Client account. Every API key belongs to exactly one Client, and billing, credit, plans and rate limits attach to that Client. In ClientUser responses, the same Client identifier is spelled id, not clientId.
Producers and exact response fields listClientUsers — users[].id; createClientUser and updateClientUser — user.id; replaceClientUserRateLimits — rateLimits[].clientId; getClientUserUsage and getClientUsage — top-level clientId and balance.clientId; getClientCredits — clientId; listSponsorshipGrants and listReceivedSponsorshipGrants — sponsorshipGrants[].sponsor.clientId and .beneficiary.clientId; grant mutation/choice responses — sponsorshipGrant.sponsor.clientId and .beneficiary.clientId. listClientUsers, createClientUser and updateClientUser also return the parent Master client's ID as nullable users[].parentClientId or user.parentClientId. createPartnerWorkspace returns the created Client's ID as workspace.id (the contract gives the workspace the same structure as a sub-user from createClientUser and defines a workspace as a Client) and, when a grant was requested in the same call, sponsorshipGrant.beneficiaryClientId (ID of the beneficiary workspace).
Consumers Path clientId in updateClientUser — PATCH /client/users/{clientId}; createClientUserApiKey — POST /client/users/{clientId}/keys; replaceClientUserRateLimits — PUT /client/users/{clientId}/rate-limits; getClientUserUsage — GET /client/users/{clientId}/usage. The same identifier concept is consumed as body beneficiaryClientId by upsertSponsorshipGrant and optional body sponsorClientId by chooseSponsorshipBillingMode.
Prerequisites Managed Sub-user operations require the authenticated Master client and a managed Sub-user. Sponsorship operations apply sponsor/beneficiary roles as documented by the selected operation.
Alternatives externalReference is the integrator's stable key for createPartnerWorkspace; it prevents duplicate provisioning in that workflow but cannot replace a {clientId} path, and there is no public lookup by that value. Retrieve existing managed IDs with listClientUsers.
Terminal/dead-end warnings Do not confuse Client IDs (ClientUser.id, workspace.id, parentClientId and fields named clientId, beneficiaryClientId or sponsorClientId) with apiKey.id, plan IDs, rate-limit record IDs (rateLimits[].id) or sponsorship-grant IDs (sponsorshipGrant.id). Do not search only for a response field literally named clientId: Client creation returns user.id, partner provisioning workspace.id. A Client ID does not authorise cross-Client access by itself.

grantReference

Question Contract answer
Meaning grantReference is the sponsor-selected external reference used to address and idempotently replace a sponsorship grant. It is 1–100 characters matching ^[A-Za-z0-9._:-]+$ and is unique per sponsor. The response spelling is reference, not grantReference.
Producers and exact response fields The sponsor is the original producer because it chooses the path value. listSponsorshipGrants and listReceivedSponsorshipGrants return it as sponsorshipGrants[].reference; upsertSponsorshipGrant, revokeSponsorshipGrant and chooseSponsorshipBillingMode return it as sponsorshipGrant.reference. createPartnerWorkspace may also return sponsorshipGrant.reference. There is no JSON response field named grantReference.
Consumers Path grantReference in upsertSponsorshipGrant — PUT /client/sponsorship-grants/{grantReference}; revokeSponsorshipGrant — DELETE /client/sponsorship-grants/{grantReference}; chooseSponsorshipBillingMode — PUT /client/sponsorship-grants/received/{grantReference}/billing-mode.
Prerequisites Grant issue/replacement and revocation are sponsor operations. Billing-mode choice is a beneficiary operation. When several sponsors use the same text reference for one beneficiary, chooseSponsorshipBillingMode additionally requires body sponsorClientId.
Alternatives List issued or received grants to recover the response reference. The returned grant id is informational; public mutation paths do not address a grant by that ID. externalReference identifies partner provisioning and is not a general substitute.
Terminal/dead-end warnings Reusing a reference under the same sponsor replaces the grant; it does not create a second grant. The same text can be ambiguous from a beneficiary's perspective when used by several sponsors. Revocation stops new covered requests but does not delete existing results or entitlements. Active and historical grants remain listable; inspect active, dates and revocation state rather than treating presence as active coverage.

state

Question Contract answer
Meaning state is optional caller-owned context for the browser-guided VIN flow, for example a cart identifier. It is a string or null with a maximum of 512 characters and is returned unchanged to the callback URL. An empty value counts as unset.
Producers and exact response fields The caller is the only producer: send request body state to createVinRedirectSession. The session-creation JSON response has no state field. If set, the later browser redirect includes query parameter state on both completed and cancelled callbacks. This callback parameter is not a JSON response field.
Consumers Only the caller's returnUrl handler consumes it to recover its own context. No public tapinomahub operation accepts a path, query or body field named state after session creation.
Prerequisites Create the session server-side with body vin, an absolute HTTPS returnUrl without credentials or fragment, and optional state. Redirect the user's browser to the returned single-use redirectUrl; do not send the API key to the browser.
Alternatives Omit state and correlate the callback entirely in the caller's own application state. The public API defines no separate session identifier field in VinRedirectSessionResponse; it returns redirectUrl and expiresAt.
Terminal/dead-end warnings Empty or null state is omitted from the callback. state does not indicate completion: branch separately on callback status. A cancelled callback contains no tapiId; a completed callback contains no vehicle, equipment or access data beyond the documented query values. Do not expect state in the creation response or send it to another API endpoint.

Minimal hand-off rules

  1. Record the operation that produced each value and its exact response path.
  2. Record nullability and state gates such as status=matched, status=succeeded and status=completed with the value.
  3. Pass a value only to a consumer listed in its section; otherwise stop because the public contract does not define that use.
  4. Keep VIN, tapiId, vehicleTypeKey, OE number, normalizedOeNumber, tapiGenArt, VDI code, clusterId, clusterVersion, evaluationId, jobId, clientId, grantReference and state as distinct semantic fields in the integrating system. The current VIN Intelligence pilot intentionally places the same UUID in requestId, jobId and the later evaluationId; do not generalise that alias to another workflow.