Products

The Product object — a concrete configuration of a configurator, or a standalone item — its bill of materials, de-duplication by hash, and the endpoints to list, create, update and delete products.

A product is one concrete thing that can be put on an order: a configurator with specific control values (a 1200×1600 roller blind in Blackout 605), or a standalone item. A product stores its bill of materials and cut-list, so its cost can be computed and warehouse automations know what to write off.

Products are de-duplicated. Each product has a hash of its configurator, configuration and materials; creating a product identical to an existing one returns the existing one instead.

Field types follow the field notation.

Access

Every endpoint on this page requires both the projects and products OAuth scopes. The user must be a member of the project, and the owner's subscription must be active. Otherwise the endpoint returns 404 RES_NOT_FOUND. The project owner bypasses permission checks.

Permission Grants
can_view_products Read products
can_edit_products Create, update and delete products

Product Object

Product Structure

Field Type Description
uuid uuid Product ID
configurator_uuid ?uuid Configurator the product was built with; null for a standalone item
name string Name, 1–1024 characters
configuration ?object Control values, keyed by control id, e.g. {"$width": 1200, "$cloth": "Blackout 605"}
materials array Bill of materials, see Product Material Structure
parts array Cut-list rows, as calculated_parts of Calculate Configurator
unit string Unit of the product
hash string SHA-1 of the configurator, configuration and materials, used for de-duplication
orders_count integer Number of order lines using this product. Only in Get Product
created_at ISO8601 datetime When the product was created
updated_at ISO8601 datetime When the product was last changed

Product Material Structure

Field Type Description
uuid uuid Material ID
name string Material name
unit string Material unit
quantity string/number Quantity of the material per one product, in its unit

This is the shape the app stores, taken from a configurator calculation. The API accepts any array, but the order cost (purchase_price of order lines) and warehouse write-offs read only uuid and quantity. Materials that are not linked to the product's configurator are ignored when computing cost.

Example Product

{
  "uuid": "0199a3f1-5c2e-7d40-b1a2-3c4d5e6f7a8b",
  "configurator_uuid": "0199ab16-3d4e-7f50-8162-738495061728",
  "name": "Roller blind Blackout 605, 1200×1600 mm",
  "configuration": {
    "$width": 1200,
    "$height": 1600,
    "$cloth": "Blackout 605"
  },
  "materials": [
    {
      "uuid": "0199a2c0-7a1b-7c2d-8e3f-a0b1c2d3e4f5",
      "name": "Blackout 605",
      "unit": "sm",
      "quantity": "2.268"
    }
  ],
  "parts": [
    {
      "name": "Blackout 605",
      "quantity": 1,
      "unit": "pcs",
      "size": "1157×1600",
      "size_unit": "mm"
    }
  ],
  "unit": "pcs",
  "hash": "3f1c9a5e0b7d2c4e6f8a1b3d5e7f9a0c2e4b6d8f",
  "orders_count": 4,
  "created_at": "2026-10-01T09:20:00.000Z",
  "updated_at": "2026-10-01T09:20:00.000Z"
}

List Products

GET /api/v1/projects/{project.uuid}/products

Returns a page of products, newest first, without orders_count.

Requires can_view_products.

Query String Params

Field Type Description
page? integer Page number, from 1. Default 1
limit? integer Page size, 1–100. Default 50
filters? string A URL-encoded JSON array of {"field", "value"} objects. Invalid JSON is ignored

Filters with the same field combine with OR; different fields combine with AND.

field value Matches
name string Name contains the value, case-insensitive
unit string Exact unit
configurator / configurator_uuid uuid Products of this configurator

Response

200 OK — {data, page, limit, total, total_pages}, as in List Materials.

Get Product

GET /api/v1/projects/{project.uuid}/products/{product.uuid}

Returns a single product with orders_count.

Requires can_view_products.

Create Product

POST /api/v1/projects/{project.uuid}/products

Creates a product, or returns the existing identical one.

Requires can_edit_products.

JSON Params

Field Type Description
name string 1–1024 characters
configurator_uuid? ?uuid Configurator in this project
configuration? object Control values; each value a string, number, boolean or null
materials? array Bill of materials. Default []
parts? array Cut-list. Default []
unit? string Up to 16 characters; an invalid value becomes pcs. Ignored when configurator_uuid is set: the configurator's product_unit is used

name and parts do not take part in the hash. Two requests with the same configurator, configuration and materials but different names return the same product, with the first name.

Example Request

The usual flow is to run Calculate Configurator and save its result:

{
  "name": "Roller blind Blackout 605, 1200×1600 mm",
  "configurator_uuid": "0199ab16-3d4e-7f50-8162-738495061728",
  "configuration": {
    "$width": 1200,
    "$height": 1600,
    "$cloth": "Blackout 605"
  },
  "materials": [
    {
      "uuid": "0199a2c0-7a1b-7c2d-8e3f-a0b1c2d3e4f5",
      "name": "Blackout 605",
      "unit": "sm",
      "quantity": "2.268"
    }
  ],
  "parts": []
}

Response

201 Created for a new product:

{
  "uuid": "0199a3f1-5c2e-7d40-b1a2-3c4d5e6f7a8b",
  "hash": "3f1c9a5e0b7d2c4e6f8a1b3d5e7f9a0c2e4b6d8f"
}

200 OK if an identical product already exists:

{
  "uuid": "0199a3f1-5c2e-7d40-b1a2-3c4d5e6f7a8b",
  "unit": "pcs",
  "hash": "3f1c9a5e0b7d2c4e6f8a1b3d5e7f9a0c2e4b6d8f"
}

Modify Product

PATCH /api/v1/projects/{project.uuid}/products/{product.uuid}

Updates only the fields you send, with the same rules as Create Product. At least one field must be present. The hash is recomputed.

If the change makes the product identical to another existing product, the two are merged: order lines and warehouse stock move to the other product, this product is deleted, and the response is 200 OK with:

{
  "merged_into": "0199a3f1-77d0-7a11-8c9b-0a1b2c4d5e6f"
}

Otherwise the response is 204 No Content.

Requires can_edit_products.

Replace Product

PUT /api/v1/projects/{project.uuid}/products/{product.uuid}

Same as Modify Product, but every field of Create Product is required.

Delete Product

DELETE /api/v1/projects/{project.uuid}/products/{product.uuid}

Deletes the product and its stock in every warehouse. Order lines that used it keep their prices and quantities but lose the link (product_uuid: null). Warehouse automations can then no longer write off its materials for those orders.

Requires can_edit_products.

Response

204 No Content

Errors

Status Code When
400 REQ_VALIDATION_FAILED The body does not match the schema
400 REQ_NO_DATA_PROVIDED Modify only: the body has no fields
403 AUTH_INSUFFICIENT_SCOPE The token lacks projects or products
403 AUTH_NO_PROJECT_ACCESS The user's role lacks can_view_products (read) or can_edit_products (write)
404 RES_NOT_FOUND The project, product, or (on create) configurator_uuid does not exist