Skip to main content
Version: Next

Products API

The Products API manages products — the goods, materials, and items that move through the supply chain. The Reference Implementation stores product records as tenant-scoped master data that can be referenced by UNTP credentials.

Interactive API documentation

The Reference Implementation includes a Swagger UI at /api-docs with full request/response schemas you can try directly from the browser. The endpoint descriptions below focus on behaviour and internal logic — refer to Swagger for exact payload shapes. All endpoints require authentication — see Authentication for how to obtain a Bearer token.

Concepts

Product Levels

Every product has a level that represents its position in the product hierarchy. The level is set at creation and is immutable — it cannot be changed after the product is created.

LevelDescriptionParent Requirement
MODELA product definition or SKU — the abstract design of a productMust not have a parent
BATCHA specific production run of a model — a group of items manufactured togetherMust have a MODEL parent
ITEMAn individual serialised unit from a batch or standaloneMay optionally have a BATCH parent

This three-tier hierarchy mirrors how products are identified in supply chains: a model defines what a product is, a batch identifies when and where a group was produced, and an item identifies a specific unit.

Product Hierarchy

Products form a tree structure through parentId references:

MODEL (e.g., "Organic Coffee Beans 1kg")
├── BATCH (e.g., "Batch 2024-Q1-001")
│ ├── ITEM (e.g., "Serial #A001")
│ └── ITEM (e.g., "Serial #A002")
└── BATCH (e.g., "Batch 2024-Q2-001")
└── ITEM (e.g., "Serial #B001")

Hierarchy rules:

  • A MODEL cannot have a parent
  • A BATCH must reference a MODEL as its parent
  • An ITEM may optionally reference a BATCH as its parent (standalone items are permitted)
  • Hierarchy depth is limited to three levels — nesting beyond MODEL → BATCH → ITEM is not permitted

These constraints are enforced during creation and update.

Each product can optionally be linked to:

  • Producing organisation (producedByOrganisationId) — the organisation that brands or produces the product
  • Manufacturing facility (manufacturingFacilityId) — the facility where the product is manufactured

These links connect the product to other master data entities and are used during extraction to link credentials back to the relevant organisation and facility records.

Identifiers

Products support the same identifier model as organisations and facilities:

  • Primary identifier — a single main identifier for the product. Set via primaryIdentifierId.
  • Secondary identifiers — additional identifiers. Set via secondaryIdentifierIds.

Identifiers are managed through the Identifiers API and linked to products by their database IDs. The primary identifier cannot also appear in the secondary identifiers list.

Deletion Behaviour

Deleting a product has cascading effects that depend on the product's level and its children:

ScenarioBehaviour
MODEL with BATCH childrenBlocked — the batches must be deleted first
BATCH with ITEM childrenPermitted — item children are detached (their parentId is set to null)
Product with no childrenPermitted

Tenant Scoping

Products are scoped to the authenticated tenant. Each tenant manages its own product catalogue independently.

Endpoints

Create products

POST /api/v1/products

Creates one or more products in bulk. The request body is an array of product objects — each must include a name and a level. Optional fields include description, parentId, producedByOrganisationId, manufacturingFacilityId, primaryIdentifierId, and secondaryIdentifierIds.

The hierarchy rules are enforced for each item. If any item violates the rules, the entire request is rejected.


List products

GET /api/v1/products

Returns products for the authenticated tenant with optional filtering. Results are paginated.

ParameterTypeDefaultDescription
searchstringSearch by product name or identifier value
levelstringFilter by product level (MODEL, BATCH, or ITEM)
parentIdstringFilter by parent product ID
organisationIdstringFilter by producing organisation ID
facilityIdstringFilter by manufacturing facility ID
limitinteger20Maximum results per page (clamped to 100)
offsetinteger0Number of results to skip

Get a product

GET /api/v1/products/{id}

Retrieves a specific product by its database ID. The response includes the full primary identifier (with scheme and registrar details), secondary identifiers, the producing organisation, the manufacturing facility, and the parent product (if any).


Update a product

PATCH /api/v1/products/{id}

Updates one or more fields of an existing product. The product level is immutable — if provided in the request body, it is silently stripped. At least one updatable field must be provided.

Updatable FieldDescription
nameProduct name (must be non-empty if provided)
descriptionFree-text description
parentIdParent product ID (subject to hierarchy rules)
producedByOrganisationIdID of the producing organisation (set to null to clear)
manufacturingFacilityIdID of the manufacturing facility (set to null to clear)
primaryIdentifierIdID of the primary identifier (set to null to clear)
secondaryIdentifierIdsArray of secondary identifier IDs (replaces existing)

Delete a product

DELETE /api/v1/products/{id}

Deletes a product from the database. See deletion behaviour for how children are handled.