Materials
The project's materials catalog — the Material object with its three price tiers, waste allowance and free-form properties, and the endpoints to list, create, update and delete materials.
A material is anything a product is made of or priced by: fabric, profile, hardware, labour, packaging. Materials are linked to configurators, and configurator formulas turn customer input into quantities of them. Materials are also what warehouses keep stock of.
Every material has three independent prices: purchase (your cost), dealer and sale. Which of them a user can see depends on their role.
Field types follow the field notation.
Access
Every endpoint on this page requires both the projects and materials 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_materials |
Read materials |
can_edit_materials |
Create, update and delete materials |
can_view_purchase_price |
See purchase_price; otherwise null |
can_view_dealer_price |
See dealer_price; otherwise null |
can_view_sale_price |
See sale_price; otherwise null |
Material Object
Material Structure
| Field | Type | Description |
|---|---|---|
| uuid | uuid | Material ID |
| name | string | Name, 1–512 characters. Configurator conditions match materials by name, so renaming can break them |
| group | string | Group, up to 255 characters; empty for none. A group holds interchangeable alternatives, e.g. all fabrics |
| vendorcode | string | Vendor code / SKU, up to 255 characters |
| unit | string | Unit the prices are quoted in, see Units |
| description | string | Free text |
| properties | object | Free-form attributes, e.g. {"color": "white", "sockets": ["AM5", "LGA1700"]}. Configurator selects can read them |
| purchase_price | ?decimal | Cost per unit; null if the user may not see it |
| dealer_price | ?decimal | Dealer price per unit; null if the user may not see it |
| sale_price | ?decimal | Retail price per unit; null if the user may not see it |
| percent_waste | decimal | Waste allowance in percent. A quantity of 10 with percent_waste: 5 is billed as 10.5 |
| image_uuid | ?uuid | A file used as the material's picture |
| created_at | ISO8601 datetime | When the material was created |
| updated_at | ISO8601 datetime | When the material was last changed |
Units
unit is a label of up to 16 characters and is never converted: a configurator formula must produce the quantity in
this unit. The app offers these values:
| Unit | Meaning |
|---|---|
mm, cm, m |
Length |
lm |
Running (linear) metre |
sm |
Square metre |
m3 |
Cubic metre |
kg, g, mg |
Weight |
l, ml |
Volume |
pcs, set, box, roll |
Count |
hour, day, month, year |
Time |
Example Material
{
"uuid": "0199a2c0-7a1b-7c2d-8e3f-a0b1c2d3e4f5",
"name": "Blackout 605",
"group": "Fabric",
"vendorcode": "BO-605-W",
"unit": "sm",
"description": "",
"properties": {
"color": "white",
"opacity": "blackout"
},
"purchase_price": 4.2,
"dealer_price": 7.5,
"sale_price": 9.9,
"percent_waste": 5,
"image_uuid": null,
"created_at": "2026-07-10T12:00:00.000Z",
"updated_at": "2026-09-01T08:30:00.000Z"
}
List Materials
GET /api/v1/projects/{project.uuid}/materials
Returns a page of materials, sorted by group (ungrouped last), then by name.
Requires can_view_materials.
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. Empty values are skipped.
| field | value | Matches |
|---|---|---|
name |
string | Name contains the value, case-insensitive |
vendorcode |
string | Vendor code contains the value, case-insensitive |
group |
string | Exact group |
unit |
string | Exact unit |
configurator / configurator_uuid |
uuid | Materials linked to this configurator |
unassigned |
any non-empty | Materials linked to no configurator |
Response
200 OK
| Field | Type | Description |
|---|---|---|
| data | array of material objects | The page |
| page | integer | Current page |
| limit | integer | Page size |
| total | integer | Number of matching materials |
| total_pages | integer | Number of pages, at least 1 |
{
"data": [
{
"uuid": "0199a2c0-7a1b-7c2d-8e3f-a0b1c2d3e4f5",
"name": "Blackout 605",
"...": "..."
}
],
"page": 1,
"limit": 50,
"total": 1,
"total_pages": 1
}
Errors
| Status | Code | When |
|---|---|---|
| 403 | AUTH_INSUFFICIENT_SCOPE |
The token lacks projects or materials |
| 403 | AUTH_NO_PROJECT_ACCESS |
The user's role lacks can_view_materials |
| 404 | RES_NOT_FOUND |
The project does not exist or is not accessible |
Get Material
GET /api/v1/projects/{project.uuid}/materials/{material.uuid}
Returns a single material.
Requires can_view_materials.
Create Material
POST /api/v1/projects/{project.uuid}/materials
Requires can_edit_materials.
JSON Params
| Field | Type | Description |
|---|---|---|
| name | string | 1–512 characters |
| group? | string | Up to 255 characters. Default "" |
| vendorcode? | string | Up to 255 characters. Default "" |
| unit? | string | Up to 16 characters. Default pcs |
| description? | string | Default "" |
| properties? | object | Default {} |
| purchase_price? | decimal | ≥ 0. Default 0 |
| dealer_price? | decimal | ≥ 0. Default 0 |
| sale_price? | decimal | ≥ 0. Default 0 |
| percent_waste? | decimal | ≥ 0. Default 0. Applied only between 0 and 100 |
| image_uuid? | ?uuid | Picture file |
A price tier left at 0 contributes nothing to that tier's total. To model internal cost such as labour, create a
material with only purchase_price.
Example Request
{
"name": "Blackout 605",
"group": "Fabric",
"unit": "sm",
"properties": {
"color": "white"
},
"purchase_price": 4.2,
"sale_price": 9.9,
"percent_waste": 5
}
Response
201 Created
{
"uuid": "0199a2c0-7a1b-7c2d-8e3f-a0b1c2d3e4f5"
}
Modify Material
PATCH /api/v1/projects/{project.uuid}/materials/{material.uuid}
Updates only the fields you send, with the same rules as Create Material. At least one field must
be present. properties, if sent, replaces the whole object.
Requires can_edit_materials.
Response
204 No Content
Replace Material
PUT /api/v1/projects/{project.uuid}/materials/{material.uuid}
Same as Modify Material, but every field of Create Material is required.
Delete Material
DELETE /api/v1/projects/{project.uuid}/materials/{material.uuid}
Deletes the material, unlinks it from every configurator, and removes its stock from every warehouse. Configurator calculations that refer to it stop producing a line.
Requires can_edit_materials.
Response
204 No Content
Errors
| Status | Code | When |
|---|---|---|
| 400 | REQ_VALIDATION_FAILED |
The body does not match the schema |
| 400 | RES_NOT_FOUND |
image_uuid is not a file of this project or of the user |
| 400 | REQ_NO_DATA_PROVIDED |
Modify only: the body has no fields |
| 403 | AUTH_INSUFFICIENT_SCOPE |
The token lacks projects or materials |
| 403 | AUTH_NO_PROJECT_ACCESS |
The user's role lacks can_view_materials (read) or can_edit_materials (write) |
| 404 | RES_NOT_FOUND |
The project or material does not exist |