# Capability map

This page maps an integration goal to the public tapinomahub operation that implements it. It is derived only from the released [OpenAPI 3.1 contract](/specs/tapinoma-hub.en.json) (version 1.71.0). The OpenAPI contract remains authoritative for full schemas, status codes and examples.

Every operation below uses `apiKeyAuth`: send the API key in the server-side `X-Api-Key` header. A capability is not evidence that the authenticated Client is entitled to use it; handle the documented authentication, allowlist, billing and rate-limit responses for the selected operation.

## 1. Check API reachability

**Use when:** a server-side integration needs to confirm that the authenticated API endpoint is reachable.

**Do not use when:** the integration needs to verify a business-data source, a VIN, a part, credit sufficiency or entitlement. This operation performs no business-data query.

**Inputs:** no business input; only the authenticated request.

**Outputs:** `status` and `service` in `PingResponse`.

| operationId | Method and path | Selection note |
|---|---|---|
| `getSystemStatus` | `GET /ping` | Technical API availability only. |

**Next steps:** after `status="ok"`, call the operation required by the business workflow. No reusable identifier is produced.

## 2. Administer Sub-users, keys and isolated workspaces

**Use when:** a Master client must list or create Sub-users, change a managed Sub-user, issue a key, replace its rate limits, or provision a Client, key and endpoint allowlist from one external reference.

**Do not use when:** the goal is to process vehicle, part, document or image data. Do not use a single Sub-user as an undocumented substitute for multiple isolated customer accounts.

**Inputs:** `name` is required to create a Sub-user. Updates and key creation require the path `clientId`; key creation optionally accepts `label`. Rate-limit replacement requires `rateLimits`. Partner provisioning requires `name`, `externalReference` and `endpointKeys`, with optional `sponsorship`, `applicationLabel` and `rateLimits`. Where used, `defaultProviderId` must match its documented enum.

**Outputs:** list/create/update operations return `ClientUser` objects; the Client identifier is the response field `id`. Key-issuing responses contain `apiKey.key` in plaintext once. Partner provisioning returns `workspace.id`, `workspace.externalReference`, `apiKey`, `allowlist` and an optional `sponsorshipGrant`.

| operationId | Method and path | Selection note |
|---|---|---|
| `listClientUsers` | `GET /client/users` | List the authenticated Master client's managed Sub-users. |
| `createClientUser` | `POST /client/users` | Create one Sub-user and its initial key. |
| `updateClientUser` | `PATCH /client/users/{clientId}` | Change permitted fields or active status. |
| `createClientUserApiKey` | `POST /client/users/{clientId}/keys` | Issue another key for an existing managed Sub-user. |
| `replaceClientUserRateLimits` | `PUT /client/users/{clientId}/rate-limits` | Replace, rather than merge, the submitted rate-limit configuration. |
| `createPartnerWorkspace` | `POST /client/partner-workspaces` | Provision a Client, one key, an allowlist and optional sponsorship in one call. |

**Next steps:** store a newly returned `apiKey.key` immediately in a server-side secret store; it is not returned again. `user.id` is explicitly documented as the `clientId` used by later managed-Client operations. Do not use `workspace.id` in a `{clientId}` path unless the public contract explicitly establishes that relationship. After a timeout, enter operation-specific reconciliation instead of retrying blindly. Only `createClientUser` has partial public list-based reconciliation, and no public operation can recover a lost raw key.

## 3. Inspect usage, plans and sponsorship

**Use when:** a Client needs its balance or consumption, a Master client needs a managed Sub-user's consumption, or a sponsor and beneficiary need to inspect or control documented tapinomahub cost coverage.

**Do not use when:** the workflow needs a price quote for a part, a VIN economic evaluation or a general contract-pricing calculation. A sponsorship changes the documented billing route; it does not transfer the beneficiary's usage or VIN entitlement.

**Inputs:** own-credit, own-usage, plan and list operations need no business input. Managed usage needs `clientId`. Issuing or replacing a grant needs path `grantReference` plus `beneficiaryClientId` and `endpointKeys`; optional fields include `channels`, dates, terms permission and monthly cap. Revocation needs `grantReference`. A beneficiary's billing choice needs `grantReference`, `mode=own|partner`, and `sponsorClientId` when the reference is ambiguous.

**Outputs:** `CreditStatus` exposes `clientId`, balance values and `billingMode`; `UsageStatus` exposes `clientId`, `balance`, `period`, `plans` and `endpoints`. Plan responses expose visible standard and custom plans. Sponsorship responses expose `sponsorshipGrant` or `sponsorshipGrants[]`, including `reference`, parties, covered endpoint keys, dates, active state and terms fields.

| operationId | Method and path | Selection note |
|---|---|---|
| `getClientCredits` | `GET /client/credits` | Read the authenticated Client's balance and billing mode. |
| `getClientUsage` | `GET /client/usage` | Read the authenticated Client's balance, plan consumption and endpoint usage. |
| `getClientUserUsage` | `GET /client/users/{clientId}/usage` | Read usage for a managed Sub-user. |
| `listPlans` | `GET /client/plans` | List plans visible to the authenticated Master client. |
| `listSponsorshipGrants` | `GET /client/sponsorship-grants` | List active and historical grants issued by the caller. |
| `listReceivedSponsorshipGrants` | `GET /client/sponsorship-grants/received` | List grants received by the caller. |
| `upsertSponsorshipGrant` | `PUT /client/sponsorship-grants/{grantReference}` | Issue or replace the sponsor-selected reference. |
| `revokeSponsorshipGrant` | `DELETE /client/sponsorship-grants/{grantReference}` | Stop the grant for new requests; existing results and entitlements remain. |
| `chooseSponsorshipBillingMode` | `PUT /client/sponsorship-grants/received/{grantReference}/billing-mode` | Let the beneficiary choose `own` or an authorised `partner` mode. |

**Next steps:** use returned endpoint keys when configuring allowlists or grants. Branch on stable fields such as `billingMode`, `active` and the documented error code, not on human-readable messages. Keep the sponsor-selected `grantReference`; response objects expose it as `reference`.

## 4. Start a browser-guided VIN flow

**Use when:** the numeric data route required by the public contract must run through the tapinomahub browser interface, or the user must complete a partial VIN of 3–17 permitted characters.

**Do not use when:** the caller expects vehicle data in the session-creation response, wants to expose its API key in a browser, or needs a direct server-to-server response from another documented numeric route.

**Inputs:** JSON `vin` and an absolute HTTPS `returnUrl` without credentials or a fragment; optional `state` is at most 512 characters. The server creates the session with its API key.

**Outputs:** the creation response contains only `redirectUrl` and `expiresAt`. The later redirect to `returnUrl` carries `status=completed`, `tapiId` and optional unchanged `state`, or `status=cancelled` and optional unchanged `state`.

| operationId | Method and path | Selection note |
|---|---|---|
| `createVinRedirectSession` | `POST /vin/redirect-sessions` | Create a short-lived, single-use browser session. |

**Next steps:** redirect the user's browser to `redirectUrl`. On a completed callback, use `tapiId` with `GET /vehicles/{tapiId}` or `POST /vehicles/{tapiId}/listing`. The callback does not return the VIN completed in the browser: keep the caller's original input only as such, and enter any VIN-parts flow only when a full 17-character VIN has been confirmed independently. On cancellation, there is no `tapiId` to consume.

## 5. Retrieve vehicle data directly from a VIN

**Use when:** the caller has authority to process a VIN and needs the documented direct vehicle comparison, optional equipment, colours or technical details.

**Do not use when:** the selected numeric route requires the browser flow, or when `incomplete=true` would be incorrectly presented as an exact single-vehicle resolution.

**Inputs:** path `vin`; optional `country`, numeric `provider`, `includeEquipments`, `includeColors` and `includeTechnical` as documented by the selected operation.

**Outputs:** `VinVehicleResponse` includes `vin`, stable `tapiId`, numeric `provider`, `incomplete`, vehicle hierarchy and the requested optional data groups.

| operationId | Method and path | Selection note |
|---|---|---|
| `getVehicleByVin` | `GET /vin/{vin}/vehicle` | Direct lookup for the numeric routes the endpoint permits; the browser-only value returns `409 redirect_required`. |

**Next steps:** retain `tapiId` for `GET /vehicles/{tapiId}` or `POST /vehicles/{tapiId}/listing`. If a later `GET /vin/{vin}/parts` includes the optional numeric selection, use the documented value consistently; a conflict is rejected.

## 6. Retrieve VIN-related parts or check an OE cart

**Use when:** the caller needs the parts assigned to a VIN, or needs to compare 1–30 OE-number strings with that VIN at `type` or `vehicle` level.

**Do not use when:** an OE base record, OE normalization, a mapping for one already-known OE number, the general VDI catalogue or general aftermarket references are the actual goal. A cart result with `fits=false` is not a definitive exclusion when `complete=false`.

**Inputs:** parts lookup uses path `vin` plus optional `country` and numeric `provider` as documented for the operation. Cart checking uses JSON `vin`, `mode=type|vehicle`, optional `country` and `oeNumbers[]` with 1–30 strings. Status operations consume the `jobId` from the corresponding `202` only.

**Outputs:** an immediate parts response exposes `vin`, `tapiId`, numeric `provider`, `matchLevel`, category coverage and `parts[]`; every returned part has exactly one `tapiGenArt` and the required `vdi` array of confirmed full VDI 4081 codes. `vdi=[]` is the complete field value when no valid mapping is available for that position. A successful asynchronous job exposes the same part shape under `result.parts[]`. An immediate cart response exposes `vin`, `mode`, `complete` and ordered `results[]` with `oe` and `fits`. A `202` response exposes `jobId`, `status`, `statusUrl`, retry timing and later either `result` or `error`.

| operationId | Method and path | Selection note |
|---|---|---|
| `getPartsByVin` | `GET /vin/{vin}/parts` | Return the result immediately or accept the documented asynchronous route. |
| `getVinPartsJob` | `GET /vin/parts/jobs/{jobId}` | Poll only a VIN-parts job. |
| `checkVinCart` | `POST /vin/cart-check` | Compare the ordered OE cart at the requested level. |
| `getVinCartCheckJob` | `GET /vin/cart-check/jobs/{jobId}` | Poll only with the `jobId` and `statusUrl` returned by the cart-check operation. |

**Next steps:** on `202`, validate and follow the required full `statusUrl` after `Retry-After`; compare `Location` and quarantine a mismatch instead of constructing a URL from it. Do not resubmit the business request merely because it is asynchronous. On `succeeded`, consume `result`; on `failed`, consume `error`. Preserve every required `parts[].vdi` array as returned, including `[]`; an empty array is not a pending state. A returned `parts[].number` can be supplied to OE operations, but a nullable number and every technical or commercial conclusion still require the selected operation's documented validation.

## 7. Create a VIN economic evaluation

**Use when:** the caller needs the documented economic evaluation for a VIN, including parts-revenue potential, dismantling ranking and a vehicle purchase recommendation.

**Do not use when:** the goal is a binding purchase, sale or price guarantee, or when the required numeric selection is not accepted by this operation.

**Inputs:** a known full path `vin`; optional `country`; fixed numeric `provider=1`; `condition=used|new`; `vehicleType=car|motorcycle`; `maxPricedParts` from 1 to 100; `recoveryRate` from 0.05 to 1; and `costPerPart` from 0 to 1000.

**Outputs:** `VinEconomicEvaluationResponse` exposes `vin`, `tapiId`, numeric `provider`, `matchLevel`, `currency`, assumptions, coverage, revenue potential, purchase recommendation, ranked `parts[]`, warnings and live availability. A `202` exposes a type-specific job; its successful `result` has the same evaluation shape.

| operationId | Method and path | Selection note |
|---|---|---|
| `getVinEconomicEvaluation` | `GET /vin/{vin}/economic-evaluation` | Start or retrieve the evaluation. |
| `getVinEconomicEvaluationJob` | `GET /vin/economic-evaluation/jobs/{jobId}` | Poll only the economic-evaluation job. |

**Next steps:** on `202`, poll the validated full `statusUrl` after `Retry-After`. Keep the returned assumptions and coverage with any policy-permitted business use of the figures; do not detach the recommendation from its warnings or result character.

## 8. Validate an OE number and retrieve the confirmed base part

**Use when:** the caller needs an explicit normalization decision, or a confirmed OE base record with its tapinomahub GenArt, VDI mappings, documented type-level fitment, grouped comparison references and directed replacement chain.

**Do not use when:** a scanner reading alone is being treated as a catalogue match; tapinomahub GenArt or VDI is being used to create a base-part match independently; or a type-level assignment is being treated as a VIN-specific installation guarantee.

**Inputs:** `normalizeOeNumber` takes query `oeNumber` and optional `manufacturer`. `getOePart` takes path `oeNumber` and optional `manufacturer`.

**Outputs:** normalization returns `status=matched|unresolved|ambiguous|invalid`, `valid`, reasons, `lookupKey`, nullable `normalizedOeNumber`, equivalent numbers and known candidates. A successful base lookup returns exactly `oeNumber`, `normalizedOeNumber`, `tapiGenArt`, `vdi`, `part`, `fitment`, `replacementChain`, `references` and `referenceNumbers`; absence of a confirmed base match returns `404`. The required `part` object proves that the base record exists, while its public `manufacturer`, `name` and `listPrice` values can each be `null`. Preserve `part.name` as the returned string or `null`. The required `tapiGenArt` field contains a valid classification or `null`; the required `vdi` array contains only valid full codes and is `[]` when none is available. The two classifications are independent best-effort enrichments: absence of either one does not invalidate the confirmed base part or suppress the other. `fitment[]` contains the available `{vehicleTypeKey, criteria}` assignments and can be empty. `criteria` is unstructured display text, not an executable rule language. `references[]` groups confirmed reference and comparison numbers as `{manufacturer, numbers}`. `referenceNumbers` contains exactly `oe_oem_reference_numbers[]`, the consolidated confirmed numbers including the confirmed OE number. Keep both reference views separate from the directed `replacementChain`; do not derive one from another.

| operationId | Method and path | Selection note |
|---|---|---|
| `normalizeOeNumber` | `GET /parts/oe/normalize` | Obtain an explicit match state; read `normalizedOeNumber` only when `status=matched`. |
| `getOePart` | `GET /parts/oe/{oeNumber}` | Retrieve the closed confirmed base-part object. |

**Next steps:** preserve the submitted `oeNumber` and returned `normalizedOeNumber` separately. Use the confirmed number for further OE-number inputs. Preserve nullable `part.name` and `tapiGenArt` exactly as returned, and do not fill either from another field. In a validated `200`, treat empty `vdi` and `fitment` lists as absence of returned mappings, not as global negative proof. Keep `vehicleTypeKey` opaque. Follow `replacementChain` as directed edges rather than assuming bidirectional equivalence; use `POST /vin/cart-check` when one specific VIN must be checked.

## 9. Enrich or evaluate an OE number

**Use when:** the caller needs aftermarket references or an indicative price evaluation for an OE number. Marketplace and eBay article content has its own capability below.

**Do not use when:** the caller needs proof of installation on a vehicle, a confirmed base-part response, or a binding commercial price. Aftermarket references are not compatibility guarantees.

**Inputs:** both operations use path `oeNumber`. The aftermarket-reference lookup additionally accepts `limit` and `offset`. Price evaluation accepts `condition=new|used`, `currency` and `vehicleType=car|motorcycle`.

**Outputs:** references return `oeNumber`, `aftermarketReferences[]`, `count` and page data. Price evaluation returns condition-specific ranges, a recommendation with confidence, listing count, currency and vehicle type.

| operationId | Method and path | Selection note |
|---|---|---|
| `getOeAftermarketReferences` | `GET /parts/oe/{oeNumber}/aftermarket-references` | Paginated reference candidates; an empty list is a successful result. |
| `getOePrice` | `GET /parts/oe/{oeNumber}/price` | Indicative price evaluation with condition-specific ranges and recommendation. |

**Next steps:** independently verify references and price evaluations for the intended technical and commercial use. For article, listing or shop content, continue with the marketplace and eBay optimisation below.

## 10. Use part-cluster and VIN Economic Intelligence

**Use when:** the caller needs market evidence and uncertainty for a versioned part cluster rather than a value for one isolated OE number, wants to compare historical cluster snapshots, or wants to aggregate eligible cluster intelligence for one VIN.

**Do not use when:** a listing is to be treated as a verified sale, a score without its confidence and evidence scope would drive an automatic decision, or a binding purchase, sale, compatibility or price guarantee is required. These operations complement rather than replace the single-OE price evaluation and the existing VIN economic evaluation.

**Inputs:** cluster resolution requires at least `oeNumber` or `aftermarketNumber`; manufacturer, `kType`, `natCode` and `genArt` are optional disambiguation context. Current and historical reads require the returned UUID `clusterId`; the current read can also pin `clusterVersion`. Market, currency, condition and evidence dimensions follow the selected operation. Cluster resolution and current reads accept `freshnessPolicy`; history reads materialized points only, do not trigger refreshes and therefore do not accept that parameter. History additionally requires `from` and `to`. VIN Economic Intelligence accepts a full `vin` in its JSON body together with the documented market scope. Every initiating Intelligence operation declares a required `Idempotency-Key`, including its three GET operations; status polling consumes only its family-specific `jobId`. The commercial pilot remains closed until approved positive pricing and atomic billing are active; no real Intelligence result is delivered while either gate is missing.

**Current pilot boundary:** access to these six operations is allowlisted. Approved Observed Supply data and the authorised dealer panel are not yet available in production; adaptive refresh and VIN Economic Intelligence are disabled. Part operations can therefore read only eligible materialized data already present and return a documented error when a refresh would be required; VIN Intelligence returns `503` until enabled. Without sufficient evidence, scores remain `null` or `publishable=false`.

**Outputs:** a cluster result keeps `observedSupply`, `verifiedSales` and `internalUsage` as separate evidence blocks and returns prices, recommended ranges, expected standtime, trend, demand, liquidity, competition, price-confidence and opportunity scores. Preserve the top-level `confidence`, its `publishable` decision, caps and missing evidence with every score. History returns scoped `points[]` without rewriting their cluster versions. VIN Economic Intelligence returns `pipeline`, `portfolio`, cluster candidates, confidence, provenance and warnings; excluded or insufficient candidates remain explicit. A `202` returns `requestId`, `jobId`, `statusUrl`, reason and retry timing instead of a final result.

| operationId | Method and path | Selection note |
|---|---|---|
| `resolvePartIntelligence` | `GET /parts/intelligence` | Resolve OE or aftermarket input to one versioned cluster and return its scoped Intelligence result. |
| `getPartClusterIntelligence` | `GET /parts/clusters/{clusterId}/intelligence` | Read current or explicitly versioned Intelligence for a known cluster. |
| `getPartClusterIntelligenceHistory` | `GET /parts/clusters/{clusterId}/history` | Read the materialized history for one cluster and market scope. |
| `getPartIntelligenceJob` | `GET /parts/intelligence/jobs/{jobId}` | Poll only a refresh accepted by a part-cluster Intelligence operation. |
| `createVinEconomicIntelligence` | `POST /vin/economic-intelligence` | Aggregate eligible part-cluster evidence into a VIN-level economic portfolio. |
| `getVinEconomicIntelligenceJob` | `GET /vin/economic-intelligence/jobs/{jobId}` | Poll only the VIN Economic Intelligence job returned by the create operation. |

**Next steps:** after the corresponding pilot feature has been enabled, a `202` requires retaining the exact job family and polling its documented `statusUrl` after `Retry-After`; never move a `jobId` between the part and VIN paths. With a final result, retain `clusterId`, `clusterVersion`, scope, `asOf`, evidence separation, score version, confidence and warnings together. Do not substitute the older single-OE or VIN-evaluation response schemas for these cluster-based contracts.

## 11. Optimise a marketplace or eBay article listing

**Use when:** a confirmed OE number is to be published as an article, offer or listing — on eBay in particular, or in the caller's own shop — and the article needs a ready-to-use title, the matching marketplace category, structured item specifics, search keywords and on-page SEO text. This is the capability behind every "optimise my eBay listing", "which eBay category and item specifics belong to this part" or "write the article title for this OE number" goal. There is no separate eBay endpoint; the marketplace is selected with `marketplaceId`.

**Do not use when:** the caller needs a compatibility or installation statement, a confirmed base part, a price, or an unreviewed automatic publication. The enrichment produces publication content, not fitment evidence, and the result is to be checked for accuracy and permissibility before it goes live.

**Inputs:** path `oeNumber`, plus optional `marketplaceId`, `language` and `vehicleType`. `marketplaceId` selects the target marketplace; its documented enum values are the 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`, and the default is `EBAY_DE`. `language` is `de`, `en`, `fr`, `es`, `it`, `nl`, `pl` or `zh`; `vehicleType` is `car` or `motorcycle`. The operation is a `GET` and must not receive an `Idempotency-Key`.

**Outputs:** a successful response contains exactly `oeNumber`, `marketplaceId`, `language`, `vehicleType`, `categoryId`, `product`, `content`, `keywords` and `itemSpecifics`, plus `liveAvailability` when live enrichment is paused. Mapped to the fields of a marketplace article:

| Response field | Use in the listing |
|---|---|
| `content.ebayTitle` | The article title for the eBay listing headline, composed for the selected marketplace and language and kept inside the documented 80-character limit, which is the maximum length of an eBay listing title. |
| `categoryId` | The category identifier for the requested `marketplaceId`; for an `EBAY_*` marketplace, the eBay category the article belongs in. The field is required-present and is `null` when no category is returned. |
| `itemSpecifics[]` | The structured item specifics of the article as `{name, value[]}` entries; one name can carry several values. |
| `keywords[]` | Search terms for the listing and for shop search. |
| `product` | `manufacturer`, `name` and `nameAddition` for the article's product naming; `manufacturer` and `nameAddition` can be `null`. |
| `content.title`, `content.h1`, `content.metaTitle`, `content.metaDescription`, `content.slug`, `content.bulletPoints` | Shop and web SEO text: page title (at most 80 characters), heading (80), meta title (60), meta description (160), URL slug and up to five bullet points of at most 160 characters each. |
| `liveAvailability` | Present only while live enrichment is paused; carries `status`, `reason`, `availableAt` and `retryAfterSeconds`. |

Absence of an exact match is the documented `404` `seo_no_exact_match` response, which echoes `oeNumber`, `marketplaceId`, `language` and `vehicleType`. That is a documented no-match answer rather than a malfunction, and it follows the refund rule for a pre-charged call that ends at status 400 or above. `429 seo_live_requests_paused` states through `X-Tapinoma-Live-Available-At` and `Retry-After` when live enrichment can be requested again.

| operationId | Method and path | Selection note |
|---|---|---|
| `getPartSeo` | `GET /parts/oe/{oeNumber}/seo` | Marketplace and eBay article optimisation for one OE number: title, category, item specifics, keywords and shop SEO text. |

**Next steps:** publish through the shop or marketplace system, which remains the system of record for SKU, stock, condition, price and offer state. Review the generated copy before publication and keep `categoryId`, `itemSpecifics[]` and the returned title with the article record so that a later regeneration can be compared against it. Never present the enrichment as proof that the part fits a vehicle: that evidence comes from `GET /parts/oe/{oeNumber}` or `POST /vin/cart-check`.

## 12. Extract vehicle-registration, vehicle-order or general document data

**Use when:** the input is a registration-document image/PDF, a vehicle order, repair cost calculation, appraisal, invoice, vehicle configuration or another supported automotive document and structured fields are needed.

**Do not use when:** a label, a standalone VIN photograph, or a complete vehicle-intake workflow is the actual input. Do not assume every field is readable or non-null.

**Inputs:** national registration accepts `fileUrl` or deprecated `imageUrl`; international registration additionally accepts deprecated `imageURL`. New integrations use `fileUrl`. Calculation- and vehicle-document extraction require `fileUrl`. Vehicle-document extraction also accepts `includeSensitiveData`, which defaults to `false`. These personal-document operations accept only `quality=standard`.

**Outputs:** the international response has stable blocks `document`, `registration`, `holder`, `inspection`, `vehicle`, `fields[]` and `warnings[]`; `vehicle.vin` is nullable. The national registration operation has deliberately different production and sandbox shapes. Calculation extraction returns exactly the previous 11 top-level calculation fields plus required `equipment[]`. Its deprecated `/scanner/document/extract` alias deliberately retains the previous 11-field response without `equipment` for strict existing clients. Rich vehicle-document extraction instead returns the closed `schemaVersion=1.0` structure with `document`, a detailed `vehicle` block, `equipment[]`, `sensitiveData` and fixed `warnings[]` codes. Every equipment item keeps `equipmentKind` separate from `availability`, and every `codes[].value` is a string whose leading zeroes and printed formatting must be preserved.

| operationId | Method and path | Selection note |
|---|---|---|
| `extractRegistrationDocument` | `POST /scanner/document/registration` | National registration-document contract: production and sandbox both return `{status,data}` with lowerCamelCase fields. |
| `extractRegistrationDocumentLegacyPath` | `POST /scanner/registration-document` | Deprecated compatibility alias of `extractRegistrationDocument`; same request and response without an HTTP redirect. |
| `extractInternationalRegistrationDocument` | `POST /scanner/document/registration/international` | Normalized international structure with detected fields and warnings. |
| `extractInternationalRegistrationDocumentLegacyPath` | `POST /scanner/registration-document/v2` | Deprecated compatibility alias of `extractInternationalRegistrationDocument`; no HTTP redirect. |
| `extractCalculationDocument` | `POST /scanner/document/calculation` | Calculation-oriented 12-field extraction including `equipment[]`. |
| `extractDocument` | `POST /scanner/document/extract` | Deprecated compatibility path with the documented 11-field response and no `equipment`; no HTTP redirect. |
| `extractVehicleDocument` | `POST /scanner/document/vehicle` | Extract vehicle, identifier and equipment data from supported vehicle documents. |
| `extractVehicleDocumentLegacyPath` | `POST /scanner/vehicle-document/extract` | Deprecated compatibility alias of `extractVehicleDocument`; no HTTP redirect. |

**Next steps:** choose the canonical path for every new integration. The four deprecated paths are compatibility aliases, not `307`/`308` redirects, so callers retain the POST body and are never charged by a second hop. The national registration, international registration and rich vehicle pairs share idempotency across their canonical and legacy paths. Calculation is intentionally different: the canonical response has 12 fields while the legacy response has 11, so reusing one `Idempotency-Key` across those two paths returns HTTP `409`; use the canonical path for a new business action and reuse a key only on the same response contract. If a non-null VIN was extracted, it can start a VIN capability; if VIN is null, do not invent or pad it. Keep source values and warnings with normalized document fields. For rich vehicle-document extraction, treat `equipmentKind=standard|variant|special|null` and `availability` as independent axes; do not infer one from the other. Preserve both `codes[].value` and nullable `normalizedValue`, especially leading-zero codes. Every response is `Cache-Control: no-store`. Use an `Idempotency-Key` only while `includeSensitiveData` is omitted or `false`; the API rejects that header when sensitive data is explicitly enabled.

## 13. Read labels or a photographed VIN

**Use when:** the input is a part-label image, markings on a part, or an image expected to show one complete VIN.

**Do not use when:** OCR output is expected to establish an OE catalogue match, or a partial/uncertain VIN should be guessed. `hasPartNumber=false` does not prove that no number exists in the source image.

**Inputs:** a publicly accessible `imageUrl` and the supported `quality`; the part-number operation explicitly accepts absolute HTTP or HTTPS URLs, and operation-specific fetch restrictions apply. Label-details also accepts deprecated `imageURL` as documented.

**Outputs:** basic label detection returns `hasPartNumber` and `where`. Part-number extraction returns `partNumbers[]` in both environments. Detailed extraction always returns `{status,data}`; business fields such as `primaryPartNumber` and `otherPartNumbers` are omitted when not detected. VIN extraction returns nullable `vin` and never guesses an incomplete value.

| operationId | Method and path | Selection note |
|---|---|---|
| `extractLabelText` | `POST /scanner/label/basic` | Determine whether a plausible number is present and where. |
| `extractLabelPartNumbers` | `POST /scanner/label/extract-partnumbers` | Return normalized number readings. |
| `extractLabelDetails` | `POST /scanner/label/extract-all` | Return all sufficiently confident structured label findings. |
| `extractVinFromImage` | `POST /scanner/vin/extract` | Return a complete, unambiguous 17-character VIN or `null`. |

**Next steps:** send a candidate part number to `GET /parts/oe/normalize` or `GET /parts/oe/{oeNumber}` before treating it as an OE fact. Send a non-null VIN to the selected VIN flow. Preserve the production/sandbox response distinction in typed clients.

## 14. Translate one part designation

**Use when:** exactly one individual part designation must be rendered in English, French, Spanish and Italian.

**Do not use when:** the input is a title, heading, description, sentence, list, offer text or multiple designations.

**Inputs:** query `sourceLanguage` as a non-empty string within the documented 20-character limit and non-empty `text` within its documented length limit. The contract example uses `de`, but it does not enumerate or otherwise constrain supported language values.

**Outputs:** `TranslationResponse` contains the required string fields `en`, `fr`, `es` and `it`.

| operationId | Method and path | Selection note |
|---|---|---|
| `translatePartName` | `GET /translation/translations` | Translate one permitted designation only. |

**Next steps:** store or display the returned language field required by the caller. Do not concatenate prohibited content into one request.

## 15. Read the VDI 4081 catalogue

**Use when:** a caller needs the active catalogue version and entries.

**Do not use when:** the caller expects OE-to-VDI mappings from the catalogue endpoint.

**Inputs:** catalogue reading accepts `limit` and `offset`.

**Outputs:** catalogue reading returns `stand`, `count`, `mainGroups`, `entries` and `page`; each `entries[].code` is a base code.

| operationId | Method and path | Selection note |
|---|---|---|
| `getVdiCatalog` | `GET /vdi` | Read the active catalogue; no OE assignments are returned. |

**Next steps:** paginate with the returned page data when present. To obtain confirmed codes for an OE number, use `GET /parts/oe/{oeNumber}` and read `vdi[]`; do not join an OE number to catalogue entries through an invented endpoint.

## 16. Build and use a Client-scoped vehicle record

**Use when:** a Client already has a `tapiId`, needs a one-call vehicle intake from a registration document, or needs listing text based on documented vehicle facts.

**Do not use when:** `tapiId` belongs to another Client, when a response containing VIN or equipment is expected from the technical lookup, or when listing text must contain price, condition or value claims.

**Inputs:** technical lookup takes path `tapiId`. Intake requires document `fileUrl`, with optional `photoUrls`, `country` and `includeOwner`. Listing composition takes path `tapiId` plus optional `quality`, `language=de|en|fr` and `notes`.

**Outputs:** technical lookup returns `tapiId` and technical vehicle fields, but no VIN or equipment. Intake returns document data, nullable `vin`, numeric `provider`, nullable `tapiId`, nullable vehicle and condition data, component-delivery state and `complete`. Listing returns `tapiId`, language, title, description, highlights, documented-equipment count and truncation state.

| operationId | Method and path | Selection note |
|---|---|---|
| `getVehicleByTapiId` | `GET /vehicles/{tapiId}` | Technical lookup included in the previously ordered VIN workflow for this Client; it is not a new vehicle-match order. |
| `intakeVehicle` | `POST /vehicles/intake` | Compose document extraction, immediate VIN matching and optional condition reporting. |
| `composeVehicleListing` | `POST /vehicles/{tapiId}/listing` | Compose text from facts documented for the Client-scoped vehicle reference. |

**Next steps:** inspect `components` and `complete` rather than assuming every intake stage succeeded. Use a non-null intake `tapiId` for the two path-based vehicle operations; a null value is a terminal absence for those calls.

## 17. Match recall and safety measures

**Use when:** a caller needs a series-level match for one VIN already present through an earlier VIN retrieval, or needs to batch up to 100 OE positions with optional vehicle context.

**Do not use when:** the result would be represented as manufacturer confirmation that an individual vehicle or part is affected, repaired, safe for sale or compatible.

**Inputs:** vehicle matching takes path `vin`. Part matching takes `positions[]`; each position can carry `oeNumber`, caller `reference`, and optional `vehicle.make`, `vehicle.model`, `vehicle.productionFrom` and `vehicle.productionTo`.

**Outputs:** vehicle matching returns `vin`, `measures[]`, `measureCount`, register data versions and a fixed notice. Part matching preserves positions and returns each `oeNumber`, nullable `normalizedOeNumber`, caller `reference`, `status`, nullable unresolved reason, measures and count, plus aggregate counts, data versions and notice.

| operationId | Method and path | Selection note |
|---|---|---|
| `matchVehicleRecalls` | `GET /recalls/vehicles/{vin}` | Return the documented series-level recall match. |
| `matchPartRecalls` | `POST /recalls/parts` | Batch match 1–100 ordered positions. |

**Next steps:** retain each measure's confidence, evidence, data-version fields and notice. Treat `matched`, `no_measures` and `unresolved` as distinct states. Escalate individual applicability or completion confirmation to the responsible manufacturer process described by the contract.

## 18. Assess visible vehicle or part condition

**Use when:** images must be converted into a damage description, a part grade, a structured vehicle condition report, an end-of-life classification, or visible licence-plate readings.

**Do not use when:** the caller needs a functional test, expert appraisal, repair estimate, residual-value calculation, keeper lookup, registration validation or facts not visible in the submitted images.

**Inputs:** damage description accepts 1–5 `imageUrls`, `quality` and optional `textQuality`. Part grading accepts 1–3 images, optional `quality` and `partType`. Vehicle condition accepts up to 8 images. End-of-life classification accepts 1–10 images and optional vehicle facts. Licence-plate reading accepts up to 3 images.

**Outputs:** damage description returns the fixed-section `report`, `format` and `truncated`. Part and vehicle grading return `gradable`, nullable `grade`, reasons/findings, limitations and `visualOnly`. End-of-life output returns the documented classification, criteria, economic assessment, coverage, limitations and `visualOnly`. Licence-plate output returns image and plate counts plus `plates[]` with reading evidence.

| operationId | Method and path | Selection note |
|---|---|---|
| `describeDamageFromImages` | `POST /vision/damage/describe` | Fixed six-section description of visible damage only. |
| `gradePartQualityFromImages` | `POST /vision/part/quality` | Visual `A|B|C` grade or an explicit ungradable result. |
| `reportVehicleCondition` | `POST /vision/condition-report` | Fixed-zone walk-around report and visual grade. |
| `classifyEndOfLifeVehicle` | `POST /vision/vehicle/elv-classification` | Classification from the submitted images and optional vehicle facts. |
| `readLicensePlates` | `POST /vision/license-plate` | Read visible characters only; no register lookup. |

**Next steps:** persist limitations, coverage and `visualOnly` with the result. Route ungradable or incomplete evidence to a separate review process; no other public operation converts it into a verified technical fact.

## 19. Transform or generate publication images

**Use when:** a part or vehicle needs a transparent/white cut-out, a part needs evidence-constrained generated views, a photographed part must be composited into a background, visible damage must be transferred to supplied views, or instance identifiers must be redacted.

**Do not use when:** background removal is expected to redact number plates or faces; generated views are expected to prove dimensions or identity without evidence; or an unverified redaction result may be published.

**Inputs:** cut-outs require only `imageUrl`; `background=transparent|white` is optional and defaults to `transparent`, while quality and part type are optional where declared. Generation requires `oeNumber`, with optional angles, finish/colour settings, quality, base-model flag, reference URLs and `sourceMode=references_required|references_preferred|knowledge_only`; it has no `output` body field. Compositing requires part and background URLs, damage transfer requires `sources[]` and `targets[]`, and redaction requires 1–10 `imageUrls`; only those three request bodies expose `output` options. Each write operation's optional `Idempotency-Key` is a header, not an `output` property.

**Outputs:** cut-outs return `found`, nullable `imageUrl`/media/dimensions, coverage, `sourcePixelsPreserved` and limitations; they expose no generic asset or provenance object. Generation returns a `202` job. For a usable `succeeded` state, locally require the documented result with coverage, evidence basis, disclosure, part/dimension/material fields, generated views, identifier protection and limitations; for `failed`, locally require its error. Quarantine a state missing its corresponding result or error. Composite, transfer and redaction responses return their schema-specific verified assets and provenance; unsafe/unverified outcomes use the documented error response instead of returning an image.

| operationId | Method and path | Selection note |
|---|---|---|
| `removePartBackground` | `POST /vision/part/remove/bg` | Preserve submitted part pixels while replacing the background. |
| `removeVehicleBackground` | `POST /vision/vehicle/remove/bg` | Preserve submitted vehicle pixels; no plate or face redaction. |
| `generatePartImagesFromOeNumber` | `POST /vision/part/generate` | Start the asynchronous, evidence-labelled generation workflow. |
| `getPartImageGenerationJob` | `GET /vision/part/generation-jobs/{jobId}` | Poll only a part-image-generation job. |
| `compositePartIntoBackground` | `POST /vision/part/composite` | Place one photographed/cut-out part into one supplied background. |
| `transferVisibleDamageToPartViews` | `POST /vision/part/damage-transfer` | Transfer only reliably assignable visible findings to supplied target views. |
| `redactPartIdentifiers` | `POST /vision/identifiers/redact` | Apply and verify the documented public-asset identifier policy. |

**Next steps:** for generation, follow `statusUrl` after `Retry-After` until `succeeded` or `failed`. Retain returned disclosure, provenance, evidence basis, limitations and expiry fields when present. When `found=false`, a job fails, or verification rejects an output, do not fabricate an asset URL or silently publish the source image.

## 20. Identify a dismantled part from available evidence

**Use when:** a caller needs to determine the catalogue number of one dismantled part from submitted numbers, label readings, descriptions and vehicle-related inputs.

**Do not use when:** the caller expects a new VIN lookup, wants an inferred number, or would treat multiple candidates as one confirmed part.

**Inputs:** JSON may contain a 3–17 character `vin`, `manufacturer`, up to 20 `customerOeNumbers`, up to 20 `labelReadings` and up to 10 `descriptions` as documented by the request schema.

**Outputs:** `PartIdentifyResponse` reports `status=matched|candidates|unresolved`, nullable confirmed number fields, confidence and candidates. Only `matched` confirms exactly one catalogue number.

| operationId | Method and path | Selection note |
|---|---|---|
| `identifyPart` | `POST /parts/identify` | Compare the supplied evidence and return the documented result. |

**Next steps:** use `normalizedOeNumber` with the OE operations only when `status=matched`. Present `candidates` for review instead of selecting one automatically, and treat `unresolved` as a terminal no-match for the submitted evidence.

## Operation coverage

The capability groups above cover the operations under `paths` in the published OpenAPI contract. A feature that is absent from this map and from the released OpenAPI `paths` object is not documented as a public capability.
