Warehouses
Warehouses and stock — the Warehouse object, stock levels with valuation, manual adjustments, goods receipts, movement history and returns of order products.
A warehouse keeps stock of materials and finished products. Stock changes through:
- manual adjustments, see Adjust Stock;
- receipts, which bring several items in at once, see Create Receipt;
- automations on order status changes, which write off materials or put finished products into stock (see Automations);
- returns, which roll back production for an order, see Return Order Products.
Every change is recorded in the warehouse's history. Stock can never go below zero; a movement that would do so is rejected as a whole.
A project always has exactly one default warehouse. Automations configured with "default warehouse" use it.
Field types follow the field notation.
Access
Every endpoint on this page requires both the projects and warehouses 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_warehouses |
Read warehouses, stock, receipts, history and return candidates |
can_edit_warehouses |
Everything else on this page |
can_view_purchase_price |
See stock valuation (value, total_value) |
Warehouse Object
Warehouse Structure
| Field | Type | Description |
|---|---|---|
| uuid | uuid | Warehouse ID |
| name | string | Name, 1–255 characters |
| is_default | boolean | Whether this is the project's default warehouse |
| address | string | Address |
| phone | string | Phone, up to 32 characters |
| note | string | Free text |
| created_at | ISO8601 datetime | When the warehouse was created |
| updated_at | ISO8601 datetime | When the warehouse was last changed |
Example Warehouse
{
"uuid": "0199a0b1-3c4d-7e5f-8a9b-0c1d2e3f4a5b",
"name": "Main warehouse",
"is_default": true,
"address": "12 Industrial Rd, Springfield",
"phone": "",
"note": "",
"created_at": "2026-07-20T09:00:00.000Z",
"updated_at": "2026-07-20T09:00:00.000Z"
}
List Warehouses
GET /api/v1/projects/{project.uuid}/warehouses
Returns the project's warehouses, the default first, then oldest first.
Requires can_view_warehouses.
Get Warehouse
GET /api/v1/projects/{project.uuid}/warehouses/{warehouse.uuid}
Requires can_view_warehouses.
Create Warehouse
POST /api/v1/projects/{project.uuid}/warehouses
The project's first warehouse always becomes the default.
Requires can_edit_warehouses.
JSON Params
| Field | Type | Description |
|---|---|---|
| name | string | 1–255 characters |
| is_default? | boolean | Make this the default warehouse. Default false |
| address? | string | Default "" |
| phone? | string | Up to 32 characters. Default "" |
| note? | string | Default "" |
Response
201 Created
{
"uuid": "0199a0b1-3c4d-7e5f-8a9b-0c1d2e3f4a5b"
}
Modify Warehouse
PATCH /api/v1/projects/{project.uuid}/warehouses/{warehouse.uuid}
Updates any of name, is_default, address, phone, note. At least one must be present. is_default: true
moves the default here. Sending is_default: false to the default warehouse is rejected; make another warehouse the
default instead.
Requires can_edit_warehouses.
Response
204 No Content
Replace Warehouse
PUT /api/v1/projects/{project.uuid}/warehouses/{warehouse.uuid}
Same as Modify Warehouse, but every field is required.
Delete Warehouse
DELETE /api/v1/projects/{project.uuid}/warehouses/{warehouse.uuid}
Deletes the warehouse with all its stock, receipts and history. Automations that referred to it are switched to the default warehouse. Deleting the default warehouse makes the oldest remaining one the default.
Requires can_edit_warehouses.
Response
204 No Content
Stock
Stock Item Structure
| Field | Type | Description |
|---|---|---|
| uuid | uuid | Stock row ID |
| item_type | string | material or product |
| item_uuid | uuid | The material or product |
| name | ?string | Its name; null if it was deleted |
| unit | ?string | Its unit |
| quantity | decimal | Quantity in stock, never negative |
| min_stock | decimal | Threshold for the low-stock report; 0 disables it |
| value? | decimal | quantity × purchase price. Present only with can_view_purchase_price. A product's purchase price is computed from its materials |
| updated_at | ISO8601 datetime | When the row last changed |
List Stock
GET /api/v1/projects/{project.uuid}/warehouses/{warehouse.uuid}/stocks
Returns a page of stock items: materials first, then products, each by quantity descending.
Requires can_view_warehouses.
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", "operator", "value"}; all combine with AND |
| field | operator | Matches |
|---|---|---|
name |
equal, include, starts_with, is_empty (case-sensitive) |
Item name |
item_type |
— | material or product |
quantity, min_stock |
equal, greater, less |
Numeric comparison |
Response
200 OK
{
"data": [
{
"uuid": "0199a0d0-0000-7000-8000-000000000001",
"item_type": "material",
"item_uuid": "0199a2c0-7a1b-7c2d-8e3f-a0b1c2d3e4f5",
"name": "Blackout 605",
"unit": "sm",
"quantity": 120.5,
"min_stock": 20,
"value": 506.1,
"updated_at": "2026-09-30T14:00:00.000Z"
}
],
"page": 1,
"limit": 50,
"total": 1,
"total_pages": 1,
"total_value": 506.1
}
total_value is the value of all stock matching the filters, not just this page; null without
can_view_purchase_price.
Adjust Stock
POST /api/v1/projects/{project.uuid}/warehouses/{warehouse.uuid}/stocks
Adds to or subtracts from one item's stock. Recorded in the history as a manual movement.
Requires can_edit_warehouses.
JSON Params
| Field | Type | Description |
|---|---|---|
| item_type | string | material or product |
| item_uuid | uuid | The material or product |
| amount | decimal | Positive to add, negative to subtract; not 0 |
Example Request
{
"item_type": "material",
"item_uuid": "0199a2c0-7a1b-7c2d-8e3f-a0b1c2d3e4f5",
"amount": -2.5
}
Response
204 No Content. Subtracting more than is in stock fails with 409 WAREHOUSE_INSUFFICIENT_STOCK.
Set Minimum Stock
PATCH /api/v1/projects/{project.uuid}/warehouses/{warehouse.uuid}/stocks
Sets the low-stock threshold for an item that already has a stock row.
Requires can_edit_warehouses.
| Field | Type | Description |
|---|---|---|
| item_type | string | material or product |
| item_uuid | uuid | The material or product |
| min_stock | decimal | ≥ 0 |
204 No Content, or 404 RES_NOT_FOUND if the item has never been in this warehouse.
Receipts
A receipt brings several items into a warehouse in one document, e.g. a supplier's delivery note. All its items are added in one transaction. Receipts cannot be edited or deleted; correct a mistake with Adjust Stock.
Receipt Structure
| Field | Type | Description |
|---|---|---|
| uuid | uuid | Receipt ID |
| number | ?string | Document number, up to 64 characters |
| contact_uuid | ?uuid | Supplier contact |
| contact_name | ?string | Supplier's name |
| file_uuid | ?uuid | Scanned document, a file |
| note | string | Free text |
| item_count | integer | Number of items. Only in List Receipts |
| items | array | {item_type, item_uuid, name, unit, amount}. Only in Get Receipt |
| created_at | ISO8601 datetime | When the receipt was created |
List Receipts
GET /api/v1/projects/{project.uuid}/warehouses/{warehouse.uuid}/receipts
Returns receipts newest first, 50 per page. Query param page? (integer, from 1). The response is a plain array.
Requires can_view_warehouses.
Get Receipt
GET /api/v1/projects/{project.uuid}/warehouses/{warehouse.uuid}/receipts/{receipt.uuid}
Returns a receipt with its items.
Requires can_view_warehouses.
Create Receipt
POST /api/v1/projects/{project.uuid}/warehouses/{warehouse.uuid}/receipts
Requires can_edit_warehouses.
JSON Params
| Field | Type | Description |
|---|---|---|
| items | array | 1–150 items: {item_type, item_uuid, amount}, amount > 0 |
| number? | ?string | Up to 64 characters |
| contact_uuid? | ?uuid | Supplier |
| file_uuid? | ?uuid | Attached file |
| note? | string | Default "" |
Example Request
{
"number": "DN-2026-0912",
"contact_uuid": "0199a6f2-2b3c-7d4e-8f50-617283940a1b",
"items": [
{
"item_type": "material",
"item_uuid": "0199a2c0-7a1b-7c2d-8e3f-a0b1c2d3e4f5",
"amount": 100
},
{
"item_type": "material",
"item_uuid": "0199a2c1-5d6e-7f70-8182-93a4b5c6d7e8",
"amount": 40
}
]
}
Response
201 Created
{
"uuid": "0199ac38-5f60-7172-8384-950617283940"
}
Get Warehouse History
GET /api/v1/projects/{project.uuid}/warehouses/{warehouse.uuid}/history
Returns stock movements, newest first, 50 per page.
Requires can_view_warehouses.
Query String Params
| Field | Type | Description |
|---|---|---|
| page? | integer | From 1. Default 1 |
| receipt? | uuid | Only the movements of this receipt |
Movement Structure
| Field | Type | Description |
|---|---|---|
| uuid | uuid | Movement ID |
| item_type | string | material or product |
| item_uuid | uuid | The material or product |
| item_name | ?string | Its name |
| amount | decimal | Positive for incoming, negative for outgoing |
| operation_type | string | See below |
| reference_uuid | ?uuid | The receipt or order the movement belongs to |
| receipt_number | ?string | Receipt number, for receipt |
| order_serial | ?string | Order number, for spend, income and return |
| created_at | ISO8601 datetime | When the movement happened |
| operation_type | Origin |
|---|---|
manual |
Adjust Stock |
receipt |
Create Receipt |
spend |
An automation wrote off materials for an order |
income |
An automation put finished products into stock for an order |
return |
Return Order Products |
Returns
A return rolls back production for some of an order's products: their materials go back into stock (by each product's bill of materials × the returned quantity), and the finished products still attributed to the order are taken out of stock. Each product can be returned to a given warehouse once per order.
Get Return Candidates
GET /api/v1/projects/{project.uuid}/warehouses/{warehouse.uuid}/returns?order={order.uuid}
Lists the order's products and whether each has already been returned to this warehouse.
Requires can_view_warehouses.
{
"order_uuid": "0199a4e2-7b1c-7c3e-9d2a-5f4e8b1c0a11",
"serial": "26274003",
"products": [
{
"product_uuid": "0199a3f1-5c2e-7d40-b1a2-3c4d5e6f7a8b",
"name": "Roller blind Blackout 605, 1200×1600 mm",
"unit": "pcs",
"quantity": 2,
"already_returned": false
}
]
}
Return Order Products
POST /api/v1/projects/{project.uuid}/warehouses/{warehouse.uuid}/returns
Returns the given quantities, in one transaction, and writes a warehouse_return entry to the order's journal.
The finished product is taken out of stock only up to what is still attributed to the order in this warehouse. If it was already shipped (written off by another automation), only the materials come back.
Requires can_edit_warehouses.
JSON Params
| Field | Type | Description |
|---|---|---|
| order_uuid | uuid | A non-deleted order of this project |
| items | array | 1–100 items: {product_uuid, quantity}, quantity > 0 and not more than on the order |
Response
200 OK with the movements made:
{
"movements": [
{
"item_type": "material",
"item_uuid": "0199a2c0-7a1b-7c2d-8e3f-a0b1c2d3e4f5",
"name": "Blackout 605",
"unit": "sm",
"amount": 4.536
},
{
"item_type": "product",
"item_uuid": "0199a3f1-5c2e-7d40-b1a2-3c4d5e6f7a8b",
"name": "Roller blind Blackout 605, 1200×1600 mm",
"unit": "pcs",
"amount": -2
}
]
}
Errors
| Status | Code | When |
|---|---|---|
| 400 | REQ_VALIDATION_FAILED |
The body does not match the schema; a return quantity exceeds the order; order query param missing |
| 400 | RES_NOT_FOUND |
Adjust Stock, Create Receipt: an item, contact_uuid or file_uuid does not belong to this project |
| 400 | REQ_NO_DATA_PROVIDED |
Modify Warehouse: the body has no fields |
| 400 | WAREHOUSE_DEFAULT_REQUIRED |
is_default: false sent to the default warehouse |
| 403 | AUTH_INSUFFICIENT_SCOPE |
The token lacks projects or warehouses |
| 403 | AUTH_NO_PROJECT_ACCESS |
The user's role lacks can_view_warehouses (read) or can_edit_warehouses (write) |
| 404 | RES_NOT_FOUND |
The project, warehouse, receipt, order or an order product does not exist |
| 409 | WAREHOUSE_INSUFFICIENT_STOCK |
A movement would take stock below zero |
| 409 | WAREHOUSE_RETURN_ALREADY_DONE |
One of the products was already returned to this warehouse for this order |