Product materials provide a unified API over the textile material kinds FIBER, YARN and FABRIC. Path parameter {kind} accepts only FIBER, YARN or FABRIC.
Endpoints
Materials
| Method | Path | Description |
|---|---|---|
GET | /api/v1/product/materials | List product materials with pagination and facets |
POST | /api/v1/product/materials | Create a product material |
GET | /api/v1/product/materials/{kind}/{id} | Get a material by kind and id |
DELETE | /api/v1/product/materials/{kind}/{id} | Delete a material |
GET | /api/v1/product/materials/{kind}/{id}/detail | Get detail overview, metrics and latest document |
GET | /api/v1/product/materials/{kind}/{id}/activities | List material activity timeline events |
Material documents
| Method | Path | Description |
|---|---|---|
GET | /api/v1/product/materials/{kind}/{id}/documents | List documents attached to a material |
POST | /api/v1/product/materials/{kind}/{id}/documents | Upload one or more material documents |
POST | /api/v1/product/materials/{kind}/{id}/documents/presign | Create presigned upload URLs |
POST | /api/v1/product/materials/{kind}/{id}/documents/{documentId}/complete | Complete a presigned upload |
DELETE | /api/v1/product/materials/{kind}/{id}/documents/{documentId} | Soft-delete a material document |
Purchases and purchase documents
| Method | Path | Description |
|---|---|---|
GET | /api/v1/product/materials/{kind}/{id}/purchases | List purchase lines for a material |
POST | /api/v1/product/materials/{kind}/{id}/purchases | Create a material purchase |
POST | /api/v1/product/materials/{kind}/{id}/purchases/estimate | Estimate transport emissions |
POST | /api/v1/product/materials/{kind}/{id}/purchases/with-documents | Create a purchase with documents |
PATCH | /api/v1/product/materials/{kind}/{id}/purchases/{purchaseId} | Update a material purchase |
GET | /api/v1/product/materials/{kind}/{id}/purchases/{purchaseId}/documents | List documents for a material purchase |
POST | /api/v1/product/materials/{kind}/{id}/purchases/{purchaseId}/documents | Upload documents for a material purchase |
DELETE | /api/v1/product/materials/{kind}/{id}/purchases/{purchaseId}/documents/{documentId} | Remove a material purchase document |
GET /api/v1/product/materials
| Query parameter | Type | Required | Notes |
|---|---|---|---|
page | number | no | 1-based, default 1 |
limit | number | no | Default 8, max 100 |
search | string | no | Case-insensitive search on name, code, supplier and composition |
kind | enum | no | ALL, FIBER, YARN, FABRIC |
supplierId | uuid | no | Filter by supplier |
certification | string | no | Filter by certification |
available | boolean | no | Filter availability |
unitOfMeasure | enum | no | See API conventions |
sortBy | enum | no | name, category, supplier, stock, createdAt, updatedAt |
sortDirection | enum | no | asc or desc |
200 OK returns ProductMaterialListResponseDto with data, meta and facets.
POST /api/v1/product/materials
Request body (CreateProductMaterialDto)
| Field | Type | Required | Description |
|---|---|---|---|
kind | enum | yes | FIBER, YARN or FABRIC |
name | string | yes | Material display name |
supplierId | uuid | yes | Linked supplier |
code | string | no | Internal or supplier code |
description | string | no | Description |
technicalSpecs | string | no | Technical specifications |
composition | string | no | Material composition |
gotsCertified | boolean | no | Defaults to false |
grsCertified | boolean | no | Defaults to false |
oekoTexCertified | boolean | no | Defaults to false |
cradleToCradle | boolean | no | Defaults to false |
betterCotton | boolean | no | Defaults to false |
otherCertifications | string | no | Additional certification labels |
recycledContentPct | number | no | 0 to 100 |
organicContentPct | number | no | 0 to 100 |
sustainabilityNotes | string | no | Sustainability notes |
unitOfMeasure | enum | no | Defaults to KG |
metadata.categoryLabel | string | no | Custom category label |
201 Created returns ProductMaterialDto. 400 indicates validation errors; 404 indicates a linked supplier was not found.
Material detail and activity
GET /api/v1/product/materials/{kind}/{id} returns ProductMaterialDto.
GET /api/v1/product/materials/{kind}/{id}/detail returns MaterialDetailDto, including overview metrics and the latest document.
GET /api/v1/product/materials/{kind}/{id}/activities?page=1&pageSize=20 returns MaterialActivityListResponseDto.
Material documents
GET /api/v1/product/materials/{kind}/{id}/documents accepts page, pageSize, includeDeleted and category. It returns ProductMaterialDocumentListResponseDto.
Direct document upload accepts one or more files as multipart form data and returns UploadProductMaterialDocumentsResponseDto.
Presigned material documents
POST /api/v1/product/materials/{kind}/{id}/documents/presign accepts PresignProductMaterialDocumentsRequestDto:
| Field | Type | Required | Description |
|---|---|---|---|
category | enum | no | TECHNICAL_SHEET or OTHER, default TECHNICAL_SHEET |
files | object[] | yes | 1 to 10 files |
files[].fileName | string | yes | Original filename |
files[].contentType | string | yes | MIME type |
files[].sizeBytes | integer | yes | File size in bytes |
The response contains one documentId, presignedUrl, objectKey and expiresAt per file. Upload each file to its URL, then call POST /api/v1/product/materials/{kind}/{id}/documents/{documentId}/complete with checksumSha256.
Purchases
GET /api/v1/product/materials/{kind}/{id}/purchases?page=1&pageSize=20 returns MaterialPurchaseListResponseDto.
POST /api/v1/product/materials/{kind}/{id}/purchases creates a purchase and requires the idempotency-key header.
Request body (CreateMaterialPurchaseDto)
| Field | Type | Required | Description |
|---|---|---|---|
lotNumber | string | yes | Lot or batch number |
purchaseDate | date-time | yes | Purchase date |
quantity | string decimal | yes | Quantity as a decimal string |
unitOfMeasure | enum | yes | Unit of measure |
value | string decimal | no | Purchase value |
currency | string | no | Defaults to EUR |
originCountry | string | no | Origin country |
originProvince | string | no | Origin province |
transportMode | enum | no | TRUCK, SHIP, TRAIN, PLANE |
distanceKm | number | no | Positive distance in km |
estimatedScope3Tco2e | string | no | Scope 3 estimate |
ddtNumber | string | yes | Transport document number |
invoiceNumber | string | yes | Invoice number |
transactionCertificateNumber | string | no | Transaction certificate number |
testReportNumber | string | no | Test report number |
notes | string | no | Notes |
attachments | object[] | no | Attachment metadata for with-documents |
curl -X POST {{BASE_URL}}/api/v1/product/materials/FABRIC/{id}/purchases \-H "Authorization: Bearer $CONFORMA_PAT" \-H "Content-Type: application/json" \-H "idempotency-key: po-2026-0001-line-1" \-d '{"lotNumber": "LOT-2026-0001","purchaseDate": "2026-06-16T00:00:00.000Z","quantity": "120","unitOfMeasure": "M","ddtNumber": "DDT-2026-0001","invoiceNumber": "INV-2026-0001"}'
PATCH /api/v1/product/materials/{kind}/{id}/purchases/{purchaseId} updates an existing material purchase.
Purchase estimate
POST /api/v1/product/materials/{kind}/{id}/purchases/estimate accepts EstimateMaterialPurchaseTransportDto and returns EstimateMaterialPurchaseTransportResponseDto.
Purchase with documents
POST /api/v1/product/materials/{kind}/{id}/purchases/with-documents creates a material purchase with documents in a single multipart request. It requires the idempotency-key header and returns MaterialPurchaseCreatedResponseDto.
The multipart implementation expects:
| Field | Type | Required | Description |
|---|---|---|---|
payload | string | yes | JSON string matching CreateMaterialPurchaseDto |
attachments | string | no | JSON array of attachment manifest entries |
<clientId> | binary | for each manifest entry | File field named with the manifest clientId |
Each attachment manifest entry contains clientId, fileName, contentType, sizeBytes and category. Supported categories are DDT, INVOICE, TRANSACTION_CERTIFICATE, TEST_REPORT and OTHER.
Purchase documents
GET /api/v1/product/materials/{kind}/{id}/purchases/{purchaseId}/documents lists documents for an existing material purchase.
POST /api/v1/product/materials/{kind}/{id}/purchases/{purchaseId}/documents uploads documents for that purchase and returns 201 Created.
DELETE /api/v1/product/materials/{kind}/{id}/purchases/{purchaseId}/documents/{documentId} removes a document and returns 204 No Content.