Domain model and terminology

This page defines the public tapinomahub terms and API relationships that integrations need. Exact request and response shapes remain normative in the OpenAPI reference.

The machine-readable definitions are available as domain-dictionary.json.

Canonical account terms

Client

An account addressed by clientId. Every API key belongs to exactly one Client. Billing, credit, plans and rate limits attach to that Client, not to its parent.

Master client

A Client with no parent and with administrative rights. Only a Master client can create and manage Sub-users and issue sponsorships. A directly contracted customer is a Master client.

Sub-user

A Client below one Master client. It has its own API keys, credit, plans and limits but cannot create another hierarchy level. Deactivating the Master client also deactivates its Sub-users.

Use Sub-user in English and Unter-Nutzer in German.

Workspace

Not an object of its own: the contract uses "workspace" as the everyday word for a Client together with its keys, credit and plans, so wherever it says workspace, it means a Client. The only response field of that name is PartnerWorkspaceResponse.workspace, returned with HTTP 201 by POST /client/partner-workspaces; it describes the created workspace in the same structure as a Sub-user returned by POST /client/users, extended with externalReference. The beneficiary of a sponsorship can be any active Client, Master client or Sub-user alike. A workspace does not introduce a separate tenant resource.

Tenant

Not a tapinomahub object. It is the end customer inside the integrating system. The public API has no tenant or tenantId field; never invent one. Map each Tenant that needs isolation to its own Client, normally a Sub-user with its own API key. POST /client/partner-workspaces creates such a Client with an API key and an endpoint allowlist in one call and requires an integrator-defined externalReference for the end customer: pattern ^[A-Za-z0-9._:-]{1,80}$, unique within the Master client, and a repeat returns 409 workspace_reference_exists. It is the only request field the contract defines as a stable end-customer reference; keep the integrating system's own tenant key in that system.

Public contract concepts

VIN

vin is the vehicle identification number accepted by VIN operations and returned by several scanner and vehicle operations. The VIN is the starting input for vehicle lookup, vehicle-related parts, OE-cart checking, recall matching and economic evaluation. It is not a compatibility result and must not be used as a substitute for tapiId.

For exact producers and consumers, see VIN data flow.

tapiId

tapiId is the stable public vehicle reference, a uuid-formatted string, returned by a successful vehicle lookup (GET /vin/{vin}/vehicle); VinPartsResponse, VehicleIntakeResponse and VinEconomicEvaluationResponse also define a tapiId field, the first two as nullable. The consuming operations GET /vehicles/{tapiId} and POST /vehicles/{tapiId}/listing take a reference from a VIN flow previously completed successfully for the same client; the listing operation documents that foreign and unknown references return 404. API 1.71.0 does not define whether one tapiId stands for an individual vehicle or for a vehicle type, so do not assume a one-to-one relation between VIN and tapiId. Store the VIN and tapiId in separate fields.

Use tapiId for subsequent technical vehicle data and listing-text calls where the operation explicitly requires it. Do not derive, parse or create it locally.

OE number

oeNumber is the submitted original-equipment part-number string used by OE operations. Different operations make different normalization promises. Preserve the original business input and also store normalizedOeNumber only when the selected operation returns a confirmed value.

An OE number may identify or reference a part, but by itself it does not prove that the part fits a particular vehicle.

Normalized OE number

normalizedOeNumber is a contract result, not a string transformation that clients should guess. In OeNormalizationResponse (GET /parts/oe/normalize), it is a required nullable string next to the required status (matched, unresolved, ambiguous or invalid); API 1.71.0 does not state for which status values it is null, so accept null with every status and branch on status before using a value. In PartOeResponse, it is a required non-empty string: the confirmed normalized OE number to which the response applies.

Do not replace the API's normalization result with locally guessed formatting rules. Use GET /parts/oe/normalize when the workflow needs an explicit normalization decision, and treat the returned value as authoritative for that response.

OE part name

PartOeResponse.part.name is a required, nullable part designation: PartOePart always contains number, manufacturer, name and listPrice, and name is a non-empty string when a designation is available, otherwise null. Clients should preserve the returned value and must not reconstruct a missing name from another field.

tapinomahub GenArt

tapiGenArt is the tapinomahub GenArt classification of a part: a string matching ^TGA-[0-9]{6,}$, that is TGA- followed by at least six digits, in PartOeResponse and in VIN-parts positions. Every successful base OE response contains the field, but its value is null when no valid classification is available. A successful VIN-parts position contains one non-null value.

Treat a returned code as opaque. Store it as a string, do not convert it to an integer, and do not infer equality with any external taxonomy. A null OE value does not invalidate the confirmed base part.

VDI 4081 code

The required vdi field of a successful base OE response and of every successful VIN-parts position contains only confirmed full codes matching ^VDI4081_[0-9]+(?:_[0-9]+)?$, that is VDI4081_<number> optionally followed by _<number>. GET /vdi lists catalogue entries only under the base code VDI4081_<number>. In the asynchronous VIN flow, the same field appears under result.parts[].vdi. [] means no valid mapping was available and is a complete terminal value, not a pending state. It does not mean the part is invalid and does not prove installation on a vehicle.

VDI 4081 is a classification system named by the public contract.

Asynchronous job and jobId

Some order operations may return HTTP 202 instead of a result. jobId identifies the accepted processing job. Every documented 202 body requires jobId, status and an absolute statusUrl (format: uri); poll that address or the Location header unchanged. For VIN parts, cart check and economic evaluation, Location is typed uri-reference and can be root-relative, and its documented example is a VIN-parts status path on all three operations, so never derive a cart-check or economic-evaluation status path from that example. A job-status request returning HTTP 200 can still report the domain state failed. Branch on status; for the part-image family, locally require and validate the corresponding result or error because the released schema does not make those fields state-dependent.

Different workflows use different job resources. Never send a VIN-parts jobId to the cart-check or economic-evaluation status path.

OE replacement chain

replacementChain contains confirmed direct, directed edges in a base OE response: in each edge, from is replaced by to, the OE number of the direct successor part. An empty list means that no directed replacement is documented. It is not a list of interchangeable inventory items and not a vehicle-fit guarantee. Preserve edge direction and validate the business use before substituting a part number.

OE fitment

PartOeResponse.fitment[] contains the available type-level vehicle assignments for a confirmed OE base part. The list can be empty; an empty list means that no assignments were returned and is not proof that the part fits no vehicle.

Every fitment entry contains a non-empty string vehicleTypeKey and a criteria[] list of distinct non-empty strings; no two entries share a vehicleTypeKey. API 1.71.0 defines neither the format of the key nor the meaning of the criteria: it states no AND/OR relationship, polarity, vocabulary or executable rule, and no meaning for an empty criteria[]. Treat the key as opaque, preserve the criteria with their key, do not derive compatibility logic from the text, and never read an assignment, with or without criteria, as an unconditional installation guarantee.

Do not use the key as a VIN or as a tapiId. Keep it as a string and compare it only with other vehicleTypeKey values. API 1.71.0 does not expose a public operation that resolves vehicleTypeKey to make, model or tapiId.

OE reference numbers

PartOeResponse.references[] groups confirmed reference and comparison numbers by manufacturer, which can be an empty string when a group is recorded without one; each group contains a non-empty numbers[] list of distinct numbers, and an empty references[] means that no such group is available. PartOeResponse.referenceNumbers is a closed object with exactly oe_oem_reference_numbers[], the consolidated confirmed numbers including the confirmed OE number.

These reference views do not state that every number is bidirectionally interchangeable and do not prove vehicle fitment. Read replacement direction only from replacementChain, and do not derive references from that chain or a chain from the references.

Vehicle data describes the matched vehicle or technical vehicle type. Vehicle-related parts describes part assignments or candidates returned in a VIN workflow. These are different results and different operations. A vehicle lookup can produce tapiId; a parts lookup can produce parts[] and matchLevel.

matchLevel, when present, is one value for the whole VIN-parts result, vehicle_specific_best_available, vehicle_type_candidates or vehicle_specific_unverified; according to GET /vin/{vin}/parts it describes the scope of the result, and API 1.71.0 gives no per-value definition. It must be stored and interpreted with the result. Do not collapse every value into “fits”.

Vehicle–part compatibility

Two public evidence scopes for vehicle–part compatibility must remain separate:

Neither result is an installation approval. Do not infer VIN-specific fitment from a type-level assignment, an OE family member, VDI or a replacement edge.

Marketplace article optimisation

Marketplace article optimisation is the publication-side counterpart to the part data: for one OE number it produces the content an article needs in a marketplace or shop — the listing title, the marketplace category, the item specifics, search keywords and the on-page SEO text. GET /parts/oe/{oeNumber}/seo implements it, and marketplaceId selects the target marketplace. The documented marketplaceId values are the 16 eBay marketplaces EBAY_AT, EBAY_AU, EBAY_BE, EBAY_CA, EBAY_CH, EBAY_DE, EBAY_ES, EBAY_FR, EBAY_GB, EBAY_HK, EBAY_IE, EBAY_IT, EBAY_NL, EBAY_PL, EBAY_SG and EBAY_US, with EBAY_DE as the default. The optional language (de, en, fr, es, it, nl, pl or zh) is the ISO 639-1 code for the generated content, and the optional vehicleType is car (the default) or motorcycle. "eBay article optimisation", "eBay listing title", "eBay category" and "eBay item specifics" therefore all resolve to this one operation and its required response fields content.ebayTitle (at most 80 characters), categoryId (a string or null) and itemSpecifics[]; the response also carries keywords[], product and the shop SEO text in content.

The result is publication content, not compatibility evidence. It says how an article should be titled, categorised and described; it never states that the part fits a particular vehicle. Keep it separate from fitment[] and from a cart check, and review it before publishing.

Market intelligence

Market intelligence is the evaluating counterpart to the descriptive part data. A part cluster is a versioned group of part identifiers (cluster.identifiers[] with the schemes oe, aftermarket, mpn and gtin) for which a market picture is drawn; a VIN economic intelligence run aggregates vehicle-specific part candidates across part clusters for one vehicle. GET /parts/intelligence resolves a cluster from oeNumber or aftermarketNumber (at least one is required), GET /parts/clusters/{clusterId}/intelligence and GET /parts/clusters/{clusterId}/history read its current and recorded picture, and POST /vin/economic-intelligence starts the vehicle-level run. GET /parts/intelligence and GET /parts/clusters/{clusterId}/intelligence answer 202 when a targeted refresh of a known cluster has been accepted; that job is read through GET /parts/intelligence/jobs/{jobId}. POST /vin/economic-intelligence answers 202 while the run is processed asynchronously and is read through GET /vin/economic-intelligence/jobs/{jobId}. GET /parts/clusters/{clusterId}/history has no 202 response.

The family has its own availability state. In API 1.71.0, x-intelligence-release declares it a closed production pilot with billing set to disabled_pending_approved_positive_prices and vinEconomicIntelligence set to disabled. While its billing is not enabled, every one of these operations answers 503 market_intelligence_billing_unavailable before authentication. That is a documented availability answer, not a malformed request, and it is unrelated to the caller's balance.

Key relationships

VIN
  -> vehicle lookup
  -> tapiId
  -> technical vehicle data or listing text

VIN
  -> vehicle-related parts lookup
  -> parts[] + matchLevel + parts[].tapiGenArt + parts[].vdi[]

OE number
  -> optional normalization decision
  -> confirmed normalizedOeNumber
  -> base OE lookup
  -> part + tapiGenArt + vdi[] + fitment[] + replacementChain[] + references[] + referenceNumbers

OE number
  -> marketplace article optimisation (marketplaceId + language + vehicleType)
  -> content.ebayTitle + categoryId + itemSpecifics[] + keywords[] + product + shop SEO text in content

VIN + OE-number positions
  -> OE-cart check
  -> results[] (oe + fits, in request order) + complete

registration-document file URL
  -> POST /scanner/document/registration/international
  -> normalized document fields, including vehicle.vin when detected
  -> vehicle lookup with that VIN

registration-document photo URL (fileUrl)
  -> POST /vehicles/intake
  -> registrationDocument + vin + tapiId + vehicle + conditionReport + components + complete

calculation document file URL
  -> POST /scanner/document/calculation
  -> fixed calculation fields + source-backed equipment[]

rich vehicle document file URL
  -> POST /scanner/document/vehicle
  -> detailed vehicle + equipment[] + warnings

The graph is a routing model, not a claim that each arrow always succeeds. Exact success, null and error behaviour comes from the selected operation's OpenAPI responses.