API Conventions

Common patterns used across all ConformaESG endpoints: identifiers, dates, pagination, uploads and error format.

Before diving into individual resources, it's useful to understand the patterns that are shared across the whole API.

Identifiers

  • All resource identifiers are UUID v4 strings (e.g. 3f2b9a1c-4d2e-4b6e-9c1a-6f5b8e2d7c10).
  • Clients never generate IDs — they are always assigned by the server on creation.
  • Path parameters like {id} and {stageId} always expect a UUID.

Field casing

All JSON request and response bodies use camelCase field names:

JSON
{
"orderNumber": "PO-2026-0001",
"supplierId": "…",
"reachCompliant": true,
"createdAt": "2026-04-21T10:00:00.000Z"
}

Dates & times

  • All timestamps use ISO 8601 format in UTC: 2026-04-21T10:00:00.000Z.
  • Fields ending in At (createdAt, updatedAt, verifiedAt, changedAt) are set by the server and are read-only.
  • Business dates (orderDate, expectedDelivery, actualDelivery, certificateExpiry) are client-supplied.

Monetary values

Monetary amounts (unitPrice, totalAmount, pricePerUnit) are returned as strings to preserve exact decimal precision:

JSON
{ "totalAmount": "1249.50", "currency": "EUR" }

Parse them with a decimal library on the client side — not Number / Float — whenever you need to perform arithmetic on them.

Enum fields

Enum fields are documented per endpoint. The API returns 400 Bad Request when you send a value that is not in the allowed set.

Commonly shared enums:

FieldAllowed values
unitOfMeasureKG, G, T, L, ML, M3, M, CM, MM, M2, PCS, ROLL, BOX, PALLET
Purchase statusDRAFT, CONFIRMED, IN_TRANSIT, DELIVERED, CANCELLED
Chemical zdhcLevelNOT_REGISTERED, LEVEL_1, LEVEL_2, LEVEL_3
Textile textileCategoryFIBER, YARN, FABRIC
Yarn yarnCountUnitNM, NE, TEX, DTEX, DEN
Stage transportModeTRUCK, SHIP, TRAIN, PLANE
Stage companyTypeSUPPLIER, COMPANY

Country codes

Fields named country, productOriginCountry, rawMaterialOriginCountry expect ISO 3166-1 alpha-2 codes (IT, DE, CN, IN, …).

List endpoints

Collection endpoints use one of three response shapes. The reference page for each resource states the exact shape.

Plain arrays are used by simple catalog endpoints:

JSON
[
{ "id": "…", "name": "…" },
{ "id": "…", "name": "…" }
]

Some newer endpoints return items plus paging fields:

JSON
{
"items": [{ "id": "..." }],
"total": 42,
"page": 1,
"pageSize": 20
}

Product materials and product traceability lists return data, meta and facets:

JSON
{
"data": [{ "id": "..." }],
"meta": {
"page": 1,
"limit": 20,
"total": 42,
"totalPages": 3,
"hasNextPage": true,
"hasPreviousPage": false
},
"facets": {}
}

Pagination parameters are 1-based where present (page=1). limit and pageSize maximums are documented per endpoint.

Partial updates

All update endpoints use PATCH with a partial body: include only the fields you want to change. Fields omitted from the request are left untouched.

Shell
curl -X PATCH {{BASE_URL}}/api/v1/suppliers/{id} \
-H "Content-Type: application/json" \
-d '{ "reachCompliant": true }'

Deletion

DELETE endpoints return 204 No Content on success. Delete operations are typically cascading: deleting a supplier removes its certifications; deleting a traceability journey removes its processing stages. Cascading behavior is noted per endpoint.

Custom metadata

Most core entities expose an optional metadata object — an arbitrary JSON map you can use to attach your own keys (ERP codes, external IDs, tags) without schema changes:

JSON
{
"metadata": {
"erpCode": "SUP-042",
"internalOwner": "procurement-team"
}
}

Keep metadata small (avoid storing large blobs), and do not store secrets or PII in it.

Document uploads

Document endpoints use two upload patterns:

PatternContent typeUse it when
Direct multipart uploadmultipart/form-dataThe endpoint accepts a file field and, sometimes, a category field
Presigned uploadapplication/json then direct storage uploadThe file should be uploaded directly to storage before calling complete

The presigned flow is always:

  1. POST .../presign with file metadata.
  2. PUT the bytes to the returned presignedUrl using the returned storage instructions.
  3. POST .../{documentId}/complete with checksumSha256.

Document status is PENDING_UPLOAD, READY or FAILED.

Idempotency

Raw-material purchase creation requires an idempotency-key header on:

  • POST /api/v1/product/materials/{kind}/{id}/purchases
  • POST /api/v1/product/materials/{kind}/{id}/purchases/with-documents

Reuse the same key only when retrying the same logical request. A conflicting replay can return 409 Conflict.

Error format

Every error response uses a consistent envelope:

JSON
{
"code": "VALIDATION_FAILED",
"message": "category is required",
"details": { "field": "category" },
"requestId": "req_01HXYZ…"
}
FieldMeaning
codeStable machine-readable error code — use in your error branching
messageHuman-readable explanation
detailsOptional structured context (varies per error)
requestIdCorrelation id — quote it when opening a support ticket

Common status codes

StatusMeaning
200 OKSuccessful GET / PATCH
201 CreatedSuccessful POST creating a resource
204 No ContentSuccessful DELETE
400 Bad RequestValidation failed — see details
401 UnauthorizedMissing or invalid credentials
403 ForbiddenTenant is not entitled to the resource/module
404 Not FoundResource does not exist or does not belong to your tenant
409 ConflictBusiness-rule violation (e.g. invalid purchase status transition)
429 Too Many RequestsRate limit hit — back off and retry
5xxServer error — retry with exponential backoff
Tip

Always log the requestId returned on failures — it's the fastest way for Conforma support to diagnose an issue.