Running catalogue and inventory, reserving unique piecesAll articles

Running catalogue and inventory, reserving unique pieces

In used parts trading almost every item is a unique piece. This case shows why item, stocked piece and offer need separate identities.

Published: 2026-09-12Reading time: 4 mintapinomahub API & workflows
API & processesAPIMarketplacesPricing & valuationParts trade

A used parts dealer lists the same headlight on three channels. But owns only one. If the part sells on channel one, two offers have to disappear immediately — not in the nightly sync, but now. Modelling that with one item number and a quantity eventually sells it twice.

Running catalogue and inventory, reserving unique piecesInput: items and stocked pieces maintained separately per channel so far 1. Write the item (PUT /commerce/v1/catalog/items/{catalogItemId}): merchantSku, condition, identifiers and compatibility in one canonical version 2. Post the inventory (POST /commerce/v1/inventory/batches): physicalQuantity and safetyStockQuantity in one batch; accepted and rejected reported as counts 3. Reserve a piece (POST /commerce/v1/inventory/reservations): Quantity of a stocked piece bound to an order line (salesOrderId, orderLineId) 4. Set the offer (PUT /commerce/v1/offers/{offerId}): price, connectionId and publicationState — the offer is channel-bound, the item is not Output: an available quantity per stocked piece, derived from physical quantity, safety stock and active reservations Item, stocked piece and offer are separate identities. The contract does not promise that the separation rules out a double sale.Running catalogue and inventory, reserving unique piecesInput: items and stocked pieces maintained separately per channel so far01Write the itemPUT /commerce/v1/catalog/items/{catalogItemId}merchantSku, condition, identifiers and compatibility in one canonical version02Post the inventoryPOST /commerce/v1/inventory/batchesphysicalQuantity and safetyStockQuantity in one batch; accepted and rejected reported ascounts03Reserve a piecePOST /commerce/v1/inventory/reservationsQuantity of a stocked piece bound to an order line (salesOrderId, orderLineId)04Set the offerPUT /commerce/v1/offers/{offerId}price, connectionId and publicationState — the offer is channel-bound, the item is notOutput: an available quantity per stocked piece, derived from physical quantity, safety stock andactive reservationsItem, stocked piece and offer are separate identities. The contract does not promise that the separation rulesout a double sale.
Four calls, four identities. The reservation binds a quantity to an order line; atomic reservation is not yet activated in the contract.

The contract therefore separates four things that everyday practice likes to collapse: the catalogue item as a description, the stocked piece as a concrete specimen, the reservation as a temporary binding and the offer as a channel-bound publication with a price.

SurfaceRoles
CommerceParts trading, Vehicle recyclers, Platform and marketplace

What this case requires

  • Your own item number. The catalogue item carries your merchantSku; it is the anchor where your system and the contract meet.
  • A distinction between description and specimen. A catalogue item describes, a stocked piece exists. If you only keep items you cannot reserve unique pieces.
  • One connection per channel. The offer references connections; without them a publication has no object.
  • A revision on every write. The expected-revision fields stop two simultaneous changes from overwriting each other.

The sequence

The table names the responsible call per stage and what exists afterwards. The reasoning for why a stage cannot be skipped follows below it.

The call chain of this use case
StageCallWhat exists afterwards
Write the itemPUT /commerce/v1/catalog/items/{catalogItemId}merchantSku, condition, identifiers and compatibility in one canonical version
Post the inventoryPOST /commerce/v1/inventory/batchesphysicalQuantity and safetyStockQuantity in one batch; accepted and rejected reported as counts
Reserve a piecePOST /commerce/v1/inventory/reservationsQuantity of a stocked piece bound to an order line (salesOrderId, orderLineId)
Set the offerPUT /commerce/v1/offers/{offerId}price, connectionId and publicationState — the offer is channel-bound, the item is not

Why each stage is needed

  1. Write the item. PUT /commerce/v1/catalog/items/{catalogItemId} stores the canonical version: merchantSku, condition, identifiers, compatibility, media and attributes. Canonical means this version is independent of any channel, and switching channels forces no renaming.
  2. Post the inventory. POST /commerce/v1/inventory/batches takes physicalQuantity and safetyStockQuantity in one batch. The response reports the counts accepted and rejected and can list errors in errors.
  3. Reserve the unique piece. POST /commerce/v1/inventory/reservations binds a quantity of a concrete stocked piece (stockItemId, quantity) to an order line; salesOrderId and orderLineId are required fields. Active reservations feed into the available quantity (availableQuantity); atomic reservation is not yet activated in the contract. Releasing and consuming are separate calls.
  4. Set the offer. PUT /commerce/v1/offers/{offerId} ties together stockItemId, connectionId, price and publicationState. The offer is channel-bound, the item is not: the same item can stand at different prices on two channels without being described twice.
Write inventory changes in one batch
curl -X POST \
  -H 'X-Api-Key: <API_KEY>' \
  -H 'Content-Type: application/json' \
  -H 'Idempotency-Key: bestand-2026-09-12-a' \
  -d '{"entries":[{"stockItemId":"<stockItemId>","physicalQuantity":1,"safetyStockQuantity":0,"expectedRevision":"<revision>"}]}' \
  'https://commerce-preview.invalid/commerce/v1/inventory/batches'

What you end up with

What remains is inventory whose available quantity derives from physical quantity, safety stock and active reservations, and a unique piece whose reservation is bound to an order line and feeds into the available quantity. Description, specimen and price are separately maintainable — a price change does not touch the item description.

Where to find this in the documentation

The binding field lists, error codes and sample responses live in this surface’s OpenAPI contract at docs.tapinomahub.com (tapinoma-commerce). All use cases arranged by surface and role: overview of the use cases.

Frequently asked

Why not simply items with a quantity?

Because a used part is a specimen, not a quantity. A stocked piece can be reserved and assigned to an order; a quantity can only be decremented — and that too late.

Can the same item cost different amounts on two channels?

Yes. The price sits on the offer, not on the item. One item description therefore serves any number of channel-bound offers.

What happens to a rejected line in the batch?

The response counts rejected entries under rejected and accepted ones under accepted and can list errors in errors. The contract neither maps errors to individual lines nor promises that the remaining lines are taken over.