Inventory
Stock: warehouses, the products kept in stock with their inventory and cost of goods sold accounts, adjustments, transfers between warehouses, stock counts, the stock postings with their journal entries, and the valuation at moving average tied to the inventory accounts.
| Operation | Summary | Scope | Idempotency-Key |
|---|---|---|---|
GET /v1/entities/{entity}/stock-valuation |
Value the stock on a day | read |
|
POST /v1/stock-adjustments |
Adjust stock | draft |
required |
GET /v1/stock-counts |
List stock counts | read |
|
POST /v1/stock-counts |
Open a stock count | draft |
required |
GET /v1/stock-counts/{count_id} |
Get a stock count | read |
|
POST /v1/stock-counts/{count_id}/cancel |
Cancel a stock count | draft |
|
PUT /v1/stock-counts/{count_id}/lines |
Enter counted quantities | draft |
|
POST /v1/stock-counts/{count_id}/post |
Post a stock count | draft |
required |
GET /v1/stock-items |
List stock items | read |
|
POST /v1/stock-items |
Keep a product in stock | draft |
required |
GET /v1/stock-items/{product_id} |
Get a stock item | read |
|
PATCH /v1/stock-items/{product_id} |
Change a stock item's accounts | draft |
|
GET /v1/stock-postings |
List stock postings | read |
|
GET /v1/stock-postings/{posting_id} |
Get a stock posting | read |
|
POST /v1/stock-transfers |
Move stock between warehouses | draft |
required |
GET /v1/warehouses |
List warehouses | read |
|
POST /v1/warehouses |
Create a warehouse | draft |
required |
PATCH /v1/warehouses/{warehouse_id} |
Change a warehouse | draft |
GET /v1/entities/{entity}/stock-valuation
Value the stock on a day
Each item's quantity and value at moving average on a day, the total, and the balance of the inventory accounts in the ledger it ties to.
| Required scope | read (admin implies every scope) |
| Operation id | stock_valuation_v1_entities__entity__stock_valuation_get |
Parameters
| In | Name | Type | Required | Description |
|---|---|---|---|---|
| path | entity |
string | yes | Entity code, e.g. CH01. |
| query | as_of |
string (date) or null | The day (end of day); default today. | |
| query | warehouse |
string or null | Only this warehouse's quantities. |
Example request
curl "$ERP_URL/v1/entities/CH01/stock-valuation" \
-H "Authorization: Bearer $ERP_KEY"
Responses
| Status | Meaning | Body |
|---|---|---|
| 200 | OK | ValuationOut |
| 401 | Missing or invalid API key (unauthorized). |
ErrorEnvelope |
| 403 | The caller lacks the required scope (missing_right, with scope), the key belongs to no person where a person is needed (forbidden), or the approval policy denies the action (policy_denied, with action and rule_id). |
ErrorEnvelope |
| 404 | The resource does not exist, or belongs to another organization (not_found). |
ErrorEnvelope |
| 422 | Validation failed: the error envelope (validation_failed). For a malformed body or parameter its message is in sentences ("Line 2: the quantity must be above zero") and fields lists each error with pydantic's loc, type and msg beside its sentence (message) and its parts, to word it in another language: items (name and number from 1: line 2), field (its name as sent) and the rule it breaks with its limit, count and choices (none for a validator's own sentence); FastAPI's own detail list stays beside the envelope. |
HTTPValidationError |
Example response (shape)
{
"entity": "string",
"as_of": "2026-09-21",
"currency": "string",
"warehouse": "string",
"lines": [
{
"product_id": "3fa85f64-5717-4562-b3fc-2c963f66afa6",
"item": "string",
"item_name": "string",
"unit": "string",
"inventory_account": "string",
"quantity": "string",
"value": "string",
"average_cost": "string"
}
],
"total": "string",
"ledger": "string",
"difference": "string"
}
POST /v1/stock-adjustments
Adjust stock
Book goods in or out without a document: damaged, lost or found goods, opening stock.
Goods going out leave at the moving average, goods coming in at the unit cost given (or the
average). The value is posted against the inventory adjustment account, or the account named.
An agent's adjustment waits for a person (status: pending_approval; the stock changes when
the entry is approved). 409 when a warehouse does not hold the quantity going out, on the day
or any later one. Needs an Idempotency-Key.
| Required scope | draft (admin implies every scope) |
| Idempotency-Key | required |
| Operation id | adjust_stock_v1_stock_adjustments_post |
Request body
application/json (required): AdjustmentInput
| Field | Type | Required | Description |
|---|---|---|---|
entity |
string | yes | Code (or id) of the entity. |
posting_date |
string (date) or null | The day the stock changes; omitted: today. Its period is open. | |
reason |
string | yes | Why: shown on the posting and its entry. (min length 3; max length 1000) |
offset_account |
string or null | The account the value is booked against (code or id); omitted: the inventory adjustment account (role inventory_adjustment). Opening stock names the opening balance clearing account. |
|
lines |
array of AdjustmentLine |
yes | The items. (min items 1; max items 500) |
Example request
curl -X POST "$ERP_URL/v1/stock-adjustments" \
-H "Authorization: Bearer $ERP_KEY" \
-H "Idempotency-Key: $(uuidgen)" \
-H "Content-Type: application/json" \
-d '{
"entity": "CH01",
"lines": [
{
"item": "SCANNER",
"quantity": "-2"
}
],
"posting_date": "2026-08-31",
"reason": "Two scanners damaged in the warehouse"
}'
Responses
| Status | Meaning | Body |
|---|---|---|
| 201 | Created | StockPostingOut |
| 401 | Missing or invalid API key (unauthorized). |
ErrorEnvelope |
| 403 | The caller lacks the required scope (missing_right, with scope), the key belongs to no person where a person is needed (forbidden), or the approval policy denies the action (policy_denied, with action and rule_id). |
ErrorEnvelope |
| 409 | The request conflicts with the data: an Idempotency-Key reused with a different request, a closed period, or an integrity rule of the database (conflict, integrity_violation). |
ErrorEnvelope |
| 422 | Validation failed: the error envelope (validation_failed). For a malformed body or parameter its message is in sentences ("Line 2: the quantity must be above zero") and fields lists each error with pydantic's loc, type and msg beside its sentence (message) and its parts, to word it in another language: items (name and number from 1: line 2), field (its name as sent) and the rule it breaks with its limit, count and choices (none for a validator's own sentence); FastAPI's own detail list stays beside the envelope. |
HTTPValidationError |
Example response (shape)
{
"id": "3fa85f64-5717-4562-b3fc-2c963f66afa6",
"entity": "string",
"number": "string",
"kind": "adjustment",
"posting_date": "2026-09-21",
"status": "pending_approval",
"currency": "string",
"value": "string",
"journal_entry_id": "3fa85f64-5717-4562-b3fc-2c963f66afa6",
"journal_entry_number": "string",
"note": "string",
"source_type": "string",
"source_id": "3fa85f64-5717-4562-b3fc-2c963f66afa6",
"source_number": "string",
"lines": [
{
"line_no": 1,
"item": "string",
"item_name": "string",
"unit": "string",
"warehouse": "string",
"quantity": "string",
"value": "string",
"unit_cost": "string",
"offset_account": "string"
}
],
"created_by": {},
"created_at": "2026-09-21T09:30:00Z"
}
GET /v1/stock-counts
List stock counts
Stock counts, newest first, with their lines.
| Required scope | read (admin implies every scope) |
| Operation id | list_stock_counts_v1_stock_counts_get |
Parameters
| In | Name | Type | Required | Description |
|---|---|---|---|---|
| query | entity |
string or null | Only this entity's (code or id). | |
| query | status |
"cancelled" | "open" | "posted" or null |
Only this status. | |
| query | limit |
integer | How many, newest first. (min 1; max 1000; default 200) |
Example request
curl "$ERP_URL/v1/stock-counts" \
-H "Authorization: Bearer $ERP_KEY"
Responses
| Status | Meaning | Body |
|---|---|---|
| 200 | OK | array of StockCountOut |
| 401 | Missing or invalid API key (unauthorized). |
ErrorEnvelope |
| 403 | The caller lacks the required scope (missing_right, with scope), the key belongs to no person where a person is needed (forbidden), or the approval policy denies the action (policy_denied, with action and rule_id). |
ErrorEnvelope |
| 422 | Validation failed: the error envelope (validation_failed). For a malformed body or parameter its message is in sentences ("Line 2: the quantity must be above zero") and fields lists each error with pydantic's loc, type and msg beside its sentence (message) and its parts, to word it in another language: items (name and number from 1: line 2), field (its name as sent) and the rule it breaks with its limit, count and choices (none for a validator's own sentence); FastAPI's own detail list stays beside the envelope. |
HTTPValidationError |
Example response (shape)
[
{
"id": "3fa85f64-5717-4562-b3fc-2c963f66afa6",
"entity": "string",
"number": "string",
"warehouse": "string",
"warehouse_name": "string",
"count_date": "2026-09-21",
"status": "cancelled",
"currency": "string",
"note": "string",
"counted": 1,
"lines": [
{
"item": "string",
"item_name": "string",
"unit": "string",
"book_quantity": "string",
"counted_quantity": null,
"difference": null,
"value_difference": null,
"counted_by": null
}
],
"posting_id": "3fa85f64-5717-4562-b3fc-2c963f66afa6",
"posting_number": "string",
"created_by": {},
"created_at": "2026-09-21T09:30:00Z",
"decided_by": {},
"decided_at": "2026-09-21T09:30:00Z"
}
]
POST /v1/stock-counts
Open a stock count
Open a count of a warehouse on a day (not in the future), with a line for each item to
count. One count of a warehouse is open at a time (409). Needs an Idempotency-Key.
| Required scope | draft (admin implies every scope) |
| Idempotency-Key | required |
| Operation id | open_stock_count_v1_stock_counts_post |
Request body
application/json (required): StockCountInput
| Field | Type | Required | Description |
|---|---|---|---|
entity |
string | yes | Code (or id) of the entity. |
warehouse |
string | yes | Warehouse counted (code or id). |
count_date |
string (date) or null | The day of the count; omitted: today. Not in the future. | |
note |
string or null | A note. (max length 1000) | |
items |
array of string or null | The items to count (product codes or ids); omitted: every active stock item of the entity. (max items 2000) |
Example request
curl -X POST "$ERP_URL/v1/stock-counts" \
-H "Authorization: Bearer $ERP_KEY" \
-H "Idempotency-Key: $(uuidgen)" \
-H "Content-Type: application/json" \
-d '{
"count_date": "2026-08-31",
"entity": "CH01",
"warehouse": "ZRH"
}'
Responses
| Status | Meaning | Body |
|---|---|---|
| 201 | Created | StockCountOut |
| 401 | Missing or invalid API key (unauthorized). |
ErrorEnvelope |
| 403 | The caller lacks the required scope (missing_right, with scope), the key belongs to no person where a person is needed (forbidden), or the approval policy denies the action (policy_denied, with action and rule_id). |
ErrorEnvelope |
| 409 | The request conflicts with the data: an Idempotency-Key reused with a different request, a closed period, or an integrity rule of the database (conflict, integrity_violation). |
ErrorEnvelope |
| 422 | Validation failed: the error envelope (validation_failed). For a malformed body or parameter its message is in sentences ("Line 2: the quantity must be above zero") and fields lists each error with pydantic's loc, type and msg beside its sentence (message) and its parts, to word it in another language: items (name and number from 1: line 2), field (its name as sent) and the rule it breaks with its limit, count and choices (none for a validator's own sentence); FastAPI's own detail list stays beside the envelope. |
HTTPValidationError |
Example response (shape)
{
"id": "3fa85f64-5717-4562-b3fc-2c963f66afa6",
"entity": "string",
"number": "string",
"warehouse": "string",
"warehouse_name": "string",
"count_date": "2026-09-21",
"status": "cancelled",
"currency": "string",
"note": "string",
"counted": 1,
"lines": [
{
"item": "string",
"item_name": "string",
"unit": "string",
"book_quantity": "string",
"counted_quantity": "string",
"difference": "string",
"value_difference": "string",
"counted_by": {}
}
],
"posting_id": "3fa85f64-5717-4562-b3fc-2c963f66afa6",
"posting_number": "string",
"created_by": {},
"created_at": "2026-09-21T09:30:00Z",
"decided_by": {},
"decided_at": "2026-09-21T09:30:00Z"
}
GET /v1/stock-counts/{count_id}
Get a stock count
One count: the book and counted quantity of each item, and the difference in value.
| Required scope | read (admin implies every scope) |
| Operation id | get_stock_count_v1_stock_counts__count_id__get |
Parameters
| In | Name | Type | Required | Description |
|---|---|---|---|---|
| path | count_id |
string (uuid) | yes | Id of the stock count. |
Example request
curl "$ERP_URL/v1/stock-counts/{count_id}" \
-H "Authorization: Bearer $ERP_KEY"
Responses
| Status | Meaning | Body |
|---|---|---|
| 200 | OK | StockCountOut |
| 401 | Missing or invalid API key (unauthorized). |
ErrorEnvelope |
| 403 | The caller lacks the required scope (missing_right, with scope), the key belongs to no person where a person is needed (forbidden), or the approval policy denies the action (policy_denied, with action and rule_id). |
ErrorEnvelope |
| 404 | The resource does not exist, or belongs to another organization (not_found). |
ErrorEnvelope |
| 422 | Validation failed: the error envelope (validation_failed). For a malformed body or parameter its message is in sentences ("Line 2: the quantity must be above zero") and fields lists each error with pydantic's loc, type and msg beside its sentence (message) and its parts, to word it in another language: items (name and number from 1: line 2), field (its name as sent) and the rule it breaks with its limit, count and choices (none for a validator's own sentence); FastAPI's own detail list stays beside the envelope. |
HTTPValidationError |
Example response (shape)
{
"id": "3fa85f64-5717-4562-b3fc-2c963f66afa6",
"entity": "string",
"number": "string",
"warehouse": "string",
"warehouse_name": "string",
"count_date": "2026-09-21",
"status": "cancelled",
"currency": "string",
"note": "string",
"counted": 1,
"lines": [
{
"item": "string",
"item_name": "string",
"unit": "string",
"book_quantity": "string",
"counted_quantity": "string",
"difference": "string",
"value_difference": "string",
"counted_by": {}
}
],
"posting_id": "3fa85f64-5717-4562-b3fc-2c963f66afa6",
"posting_number": "string",
"created_by": {},
"created_at": "2026-09-21T09:30:00Z",
"decided_by": {},
"decided_at": "2026-09-21T09:30:00Z"
}
POST /v1/stock-counts/{count_id}/cancel
Cancel a stock count
Cancel an open count; nothing is posted. 409 once posted, or while its differences wait for approval.
| Required scope | draft (admin implies every scope) |
| Idempotency-Key | not used |
| Operation id | cancel_stock_count_v1_stock_counts__count_id__cancel_post |
Parameters
| In | Name | Type | Required | Description |
|---|---|---|---|---|
| path | count_id |
string (uuid) | yes | Id of the stock count. |
Example request
curl -X POST "$ERP_URL/v1/stock-counts/{count_id}/cancel" \
-H "Authorization: Bearer $ERP_KEY"
Responses
| Status | Meaning | Body |
|---|---|---|
| 200 | OK | StockCountOut |
| 401 | Missing or invalid API key (unauthorized). |
ErrorEnvelope |
| 403 | The caller lacks the required scope (missing_right, with scope), the key belongs to no person where a person is needed (forbidden), or the approval policy denies the action (policy_denied, with action and rule_id). |
ErrorEnvelope |
| 404 | The resource does not exist, or belongs to another organization (not_found). |
ErrorEnvelope |
| 409 | The request conflicts with the data: an Idempotency-Key reused with a different request, a closed period, or an integrity rule of the database (conflict, integrity_violation). |
ErrorEnvelope |
| 422 | Validation failed: the error envelope (validation_failed). For a malformed body or parameter its message is in sentences ("Line 2: the quantity must be above zero") and fields lists each error with pydantic's loc, type and msg beside its sentence (message) and its parts, to word it in another language: items (name and number from 1: line 2), field (its name as sent) and the rule it breaks with its limit, count and choices (none for a validator's own sentence); FastAPI's own detail list stays beside the envelope. |
HTTPValidationError |
Example response (shape)
{
"id": "3fa85f64-5717-4562-b3fc-2c963f66afa6",
"entity": "string",
"number": "string",
"warehouse": "string",
"warehouse_name": "string",
"count_date": "2026-09-21",
"status": "cancelled",
"currency": "string",
"note": "string",
"counted": 1,
"lines": [
{
"item": "string",
"item_name": "string",
"unit": "string",
"book_quantity": "string",
"counted_quantity": "string",
"difference": "string",
"value_difference": "string",
"counted_by": {}
}
],
"posting_id": "3fa85f64-5717-4562-b3fc-2c963f66afa6",
"posting_number": "string",
"created_by": {},
"created_at": "2026-09-21T09:30:00Z",
"decided_by": {},
"decided_at": "2026-09-21T09:30:00Z"
}
PUT /v1/stock-counts/{count_id}/lines
Enter counted quantities
Record what was counted of the items named (null clears a line). 409 once the count is posted or cancelled, or while its differences wait for approval.
| Required scope | draft (admin implies every scope) |
| Idempotency-Key | not used |
| Operation id | enter_stock_count_v1_stock_counts__count_id__lines_put |
Parameters
| In | Name | Type | Required | Description |
|---|---|---|---|---|
| path | count_id |
string (uuid) | yes | Id of the stock count. |
Request body
application/json (required): CountLinesInput
| Field | Type | Required | Description |
|---|---|---|---|
lines |
array of CountLineInput |
yes | Counted quantities. (min items 1; max items 2000) |
Example request
curl -X PUT "$ERP_URL/v1/stock-counts/{count_id}/lines" \
-H "Authorization: Bearer $ERP_KEY" \
-H "Content-Type: application/json" \
-d '{
"lines": [
{
"counted_quantity": "37",
"item": "SCANNER"
}
]
}'
Responses
| Status | Meaning | Body |
|---|---|---|
| 200 | OK | StockCountOut |
| 401 | Missing or invalid API key (unauthorized). |
ErrorEnvelope |
| 403 | The caller lacks the required scope (missing_right, with scope), the key belongs to no person where a person is needed (forbidden), or the approval policy denies the action (policy_denied, with action and rule_id). |
ErrorEnvelope |
| 404 | The resource does not exist, or belongs to another organization (not_found). |
ErrorEnvelope |
| 409 | The request conflicts with the data: an Idempotency-Key reused with a different request, a closed period, or an integrity rule of the database (conflict, integrity_violation). |
ErrorEnvelope |
| 422 | Validation failed: the error envelope (validation_failed). For a malformed body or parameter its message is in sentences ("Line 2: the quantity must be above zero") and fields lists each error with pydantic's loc, type and msg beside its sentence (message) and its parts, to word it in another language: items (name and number from 1: line 2), field (its name as sent) and the rule it breaks with its limit, count and choices (none for a validator's own sentence); FastAPI's own detail list stays beside the envelope. |
HTTPValidationError |
Example response (shape)
{
"id": "3fa85f64-5717-4562-b3fc-2c963f66afa6",
"entity": "string",
"number": "string",
"warehouse": "string",
"warehouse_name": "string",
"count_date": "2026-09-21",
"status": "cancelled",
"currency": "string",
"note": "string",
"counted": 1,
"lines": [
{
"item": "string",
"item_name": "string",
"unit": "string",
"book_quantity": "string",
"counted_quantity": "string",
"difference": "string",
"value_difference": "string",
"counted_by": {}
}
],
"posting_id": "3fa85f64-5717-4562-b3fc-2c963f66afa6",
"posting_number": "string",
"created_by": {},
"created_at": "2026-09-21T09:30:00Z",
"decided_by": {},
"decided_at": "2026-09-21T09:30:00Z"
}
POST /v1/stock-counts/{count_id}/post
Post a stock count
Book the differences of a count whose every line is counted, at the moving average,
against the inventory adjustment account. An agent's differences wait for a person. 409 while
a line is not counted, or once goods moved in the warehouse after the count's day (cancel and
count again). Needs an Idempotency-Key.
| Required scope | draft (admin implies every scope) |
| Idempotency-Key | required |
| Operation id | post_stock_count_v1_stock_counts__count_id__post_post |
Parameters
| In | Name | Type | Required | Description |
|---|---|---|---|---|
| path | count_id |
string (uuid) | yes | Id of the stock count. |
Example request
curl -X POST "$ERP_URL/v1/stock-counts/{count_id}/post" \
-H "Authorization: Bearer $ERP_KEY" \
-H "Idempotency-Key: $(uuidgen)"
Responses
| Status | Meaning | Body |
|---|---|---|
| 200 | OK | StockCountOut |
| 401 | Missing or invalid API key (unauthorized). |
ErrorEnvelope |
| 403 | The caller lacks the required scope (missing_right, with scope), the key belongs to no person where a person is needed (forbidden), or the approval policy denies the action (policy_denied, with action and rule_id). |
ErrorEnvelope |
| 404 | The resource does not exist, or belongs to another organization (not_found). |
ErrorEnvelope |
| 409 | The request conflicts with the data: an Idempotency-Key reused with a different request, a closed period, or an integrity rule of the database (conflict, integrity_violation). |
ErrorEnvelope |
| 422 | Validation failed: the error envelope (validation_failed). For a malformed body or parameter its message is in sentences ("Line 2: the quantity must be above zero") and fields lists each error with pydantic's loc, type and msg beside its sentence (message) and its parts, to word it in another language: items (name and number from 1: line 2), field (its name as sent) and the rule it breaks with its limit, count and choices (none for a validator's own sentence); FastAPI's own detail list stays beside the envelope. |
HTTPValidationError |
Example response (shape)
{
"id": "3fa85f64-5717-4562-b3fc-2c963f66afa6",
"entity": "string",
"number": "string",
"warehouse": "string",
"warehouse_name": "string",
"count_date": "2026-09-21",
"status": "cancelled",
"currency": "string",
"note": "string",
"counted": 1,
"lines": [
{
"item": "string",
"item_name": "string",
"unit": "string",
"book_quantity": "string",
"counted_quantity": "string",
"difference": "string",
"value_difference": "string",
"counted_by": {}
}
],
"posting_id": "3fa85f64-5717-4562-b3fc-2c963f66afa6",
"posting_number": "string",
"created_by": {},
"created_at": "2026-09-21T09:30:00Z",
"decided_by": {},
"decided_at": "2026-09-21T09:30:00Z"
}
GET /v1/stock-items
List stock items
The products kept in stock, by code: the quantity in each warehouse, the value and the moving average cost.
| Required scope | read (admin implies every scope) |
| Operation id | list_stock_items_v1_stock_items_get |
Parameters
| In | Name | Type | Required | Description |
|---|---|---|---|---|
| query | entity |
string or null | Only this entity's (code or id). | |
| query | in_stock |
boolean or null | true: only those in stock; false: only those not. |
|
| query | limit |
integer | How many, by code. (min 1; max 5000; default 1000) |
Example request
curl "$ERP_URL/v1/stock-items" \
-H "Authorization: Bearer $ERP_KEY"
Responses
| Status | Meaning | Body |
|---|---|---|
| 200 | OK | array of StockItemOut |
| 401 | Missing or invalid API key (unauthorized). |
ErrorEnvelope |
| 403 | The caller lacks the required scope (missing_right, with scope), the key belongs to no person where a person is needed (forbidden), or the approval policy denies the action (policy_denied, with action and rule_id). |
ErrorEnvelope |
| 422 | Validation failed: the error envelope (validation_failed). For a malformed body or parameter its message is in sentences ("Line 2: the quantity must be above zero") and fields lists each error with pydantic's loc, type and msg beside its sentence (message) and its parts, to word it in another language: items (name and number from 1: line 2), field (its name as sent) and the rule it breaks with its limit, count and choices (none for a validator's own sentence); FastAPI's own detail list stays beside the envelope. |
HTTPValidationError |
Example response (shape)
[
{
"product_id": "3fa85f64-5717-4562-b3fc-2c963f66afa6",
"entity": "string",
"code": "string",
"name": "string",
"unit": "string",
"active": true,
"inventory_account": "string",
"cogs_account": "string",
"currency": "string",
"quantity": "string",
"value": "string",
"average_cost": "string",
"levels": [
{
"warehouse": "string",
"warehouse_name": "string",
"quantity": "string"
}
],
"created_by": {},
"created_at": "2026-09-21T09:30:00Z"
}
]
POST /v1/stock-items
Keep a product in stock
Start keeping a product in stock: goods sold per unit, with the accounts its stock and its
cost of goods sold are booked to. 409 when it is kept in stock already; 422 for a product
that is not goods sold per unit. Nothing is posted. Needs an Idempotency-Key.
| Required scope | draft (admin implies every scope) |
| Idempotency-Key | required |
| Operation id | create_stock_item_v1_stock_items_post |
Request body
application/json (required): StockItemInput
| Field | Type | Required | Description |
|---|---|---|---|
product |
string | yes | Code (or id) of the product to keep in stock: goods sold per unit. |
entity |
string or null | Code (or id) of the product's entity; needed with a code. | |
inventory_account |
string or null | Account (code or id) its stock is booked to: a control account on the inventories line; omitted: the entity's inventory account (role inventory). |
|
cogs_account |
string or null | Expense account (code or id) its cost of goods sold is booked to; omitted: the entity's account of the role cogs. |
Example request
curl -X POST "$ERP_URL/v1/stock-items" \
-H "Authorization: Bearer $ERP_KEY" \
-H "Idempotency-Key: $(uuidgen)" \
-H "Content-Type: application/json" \
-d '{
"product": "SCANNER"
}'
Responses
| Status | Meaning | Body |
|---|---|---|
| 201 | Created | StockItemOut |
| 401 | Missing or invalid API key (unauthorized). |
ErrorEnvelope |
| 403 | The caller lacks the required scope (missing_right, with scope), the key belongs to no person where a person is needed (forbidden), or the approval policy denies the action (policy_denied, with action and rule_id). |
ErrorEnvelope |
| 409 | The request conflicts with the data: an Idempotency-Key reused with a different request, a closed period, or an integrity rule of the database (conflict, integrity_violation). |
ErrorEnvelope |
| 422 | Validation failed: the error envelope (validation_failed). For a malformed body or parameter its message is in sentences ("Line 2: the quantity must be above zero") and fields lists each error with pydantic's loc, type and msg beside its sentence (message) and its parts, to word it in another language: items (name and number from 1: line 2), field (its name as sent) and the rule it breaks with its limit, count and choices (none for a validator's own sentence); FastAPI's own detail list stays beside the envelope. |
HTTPValidationError |
Example response (shape)
{
"product_id": "3fa85f64-5717-4562-b3fc-2c963f66afa6",
"entity": "string",
"code": "string",
"name": "string",
"unit": "string",
"active": true,
"inventory_account": "string",
"cogs_account": "string",
"currency": "string",
"quantity": "string",
"value": "string",
"average_cost": "string",
"levels": [
{
"warehouse": "string",
"warehouse_name": "string",
"quantity": "string"
}
],
"created_by": {},
"created_at": "2026-09-21T09:30:00Z"
}
GET /v1/stock-items/{product_id}
Get a stock item
One stock item with its quantity per warehouse, value and moving average cost.
| Required scope | read (admin implies every scope) |
| Operation id | get_stock_item_v1_stock_items__product_id__get |
Parameters
| In | Name | Type | Required | Description |
|---|---|---|---|---|
| path | product_id |
string (uuid) | yes | Id of the stock item's product (GET /v1/stock-items). |
Example request
curl "$ERP_URL/v1/stock-items/{product_id}" \
-H "Authorization: Bearer $ERP_KEY"
Responses
| Status | Meaning | Body |
|---|---|---|
| 200 | OK | StockItemOut |
| 401 | Missing or invalid API key (unauthorized). |
ErrorEnvelope |
| 403 | The caller lacks the required scope (missing_right, with scope), the key belongs to no person where a person is needed (forbidden), or the approval policy denies the action (policy_denied, with action and rule_id). |
ErrorEnvelope |
| 404 | The resource does not exist, or belongs to another organization (not_found). |
ErrorEnvelope |
| 422 | Validation failed: the error envelope (validation_failed). For a malformed body or parameter its message is in sentences ("Line 2: the quantity must be above zero") and fields lists each error with pydantic's loc, type and msg beside its sentence (message) and its parts, to word it in another language: items (name and number from 1: line 2), field (its name as sent) and the rule it breaks with its limit, count and choices (none for a validator's own sentence); FastAPI's own detail list stays beside the envelope. |
HTTPValidationError |
Example response (shape)
{
"product_id": "3fa85f64-5717-4562-b3fc-2c963f66afa6",
"entity": "string",
"code": "string",
"name": "string",
"unit": "string",
"active": true,
"inventory_account": "string",
"cogs_account": "string",
"currency": "string",
"quantity": "string",
"value": "string",
"average_cost": "string",
"levels": [
{
"warehouse": "string",
"warehouse_name": "string",
"quantity": "string"
}
],
"created_by": {},
"created_at": "2026-09-21T09:30:00Z"
}
PATCH /v1/stock-items/{product_id}
Change a stock item's accounts
Change its cost of goods sold account, or its inventory account while nothing is in stock (409 otherwise). Audited with the previous values.
| Required scope | draft (admin implies every scope) |
| Idempotency-Key | not used |
| Operation id | update_stock_item_v1_stock_items__product_id__patch |
Parameters
| In | Name | Type | Required | Description |
|---|---|---|---|---|
| path | product_id |
string (uuid) | yes | Id of the stock item's product (GET /v1/stock-items). |
Request body
application/json (required): StockItemUpdate
| Field | Type | Required | Description |
|---|---|---|---|
inventory_account |
string or null | New inventory account; only while nothing is in stock. | |
cogs_account |
string or null | New cost of goods sold account. |
Example request
curl -X PATCH "$ERP_URL/v1/stock-items/{product_id}" \
-H "Authorization: Bearer $ERP_KEY" \
-H "Content-Type: application/json" \
-d '{
"cogs_account": "4200"
}'
Responses
| Status | Meaning | Body |
|---|---|---|
| 200 | OK | StockItemOut |
| 401 | Missing or invalid API key (unauthorized). |
ErrorEnvelope |
| 403 | The caller lacks the required scope (missing_right, with scope), the key belongs to no person where a person is needed (forbidden), or the approval policy denies the action (policy_denied, with action and rule_id). |
ErrorEnvelope |
| 404 | The resource does not exist, or belongs to another organization (not_found). |
ErrorEnvelope |
| 409 | The request conflicts with the data: an Idempotency-Key reused with a different request, a closed period, or an integrity rule of the database (conflict, integrity_violation). |
ErrorEnvelope |
| 422 | Validation failed: the error envelope (validation_failed). For a malformed body or parameter its message is in sentences ("Line 2: the quantity must be above zero") and fields lists each error with pydantic's loc, type and msg beside its sentence (message) and its parts, to word it in another language: items (name and number from 1: line 2), field (its name as sent) and the rule it breaks with its limit, count and choices (none for a validator's own sentence); FastAPI's own detail list stays beside the envelope. |
HTTPValidationError |
Example response (shape)
{
"product_id": "3fa85f64-5717-4562-b3fc-2c963f66afa6",
"entity": "string",
"code": "string",
"name": "string",
"unit": "string",
"active": true,
"inventory_account": "string",
"cogs_account": "string",
"currency": "string",
"quantity": "string",
"value": "string",
"average_cost": "string",
"levels": [
{
"warehouse": "string",
"warehouse_name": "string",
"quantity": "string"
}
],
"created_by": {},
"created_at": "2026-09-21T09:30:00Z"
}
GET /v1/stock-postings
List stock postings
Every change of stock, newest first, with its movements and journal entry.
| Required scope | read (admin implies every scope) |
| Operation id | list_stock_postings_v1_stock_postings_get |
Parameters
| In | Name | Type | Required | Description |
|---|---|---|---|---|
| query | entity |
string or null | Only this entity's (code or id). | |
| query | kind |
"adjustment" | "count" | "delivery" | "receipt" | "return" | "revaluation" | "transfer" or null |
Only this kind. | |
| query | status |
"pending_approval" | "posted" | "rejected" or null |
Only this status. | |
| query | item |
string or null | Only those moving this product (code or id; a code needs entity). |
|
| query | warehouse |
string or null | Only those moving goods in this warehouse (code or id; a code needs entity). |
|
| query | start |
string (date) or null | Posting date from. | |
| query | end |
string (date) or null | Posting date to. | |
| query | limit |
integer | How many, newest first. (min 1; max 1000; default 200) |
Example request
curl "$ERP_URL/v1/stock-postings" \
-H "Authorization: Bearer $ERP_KEY"
Responses
| Status | Meaning | Body |
|---|---|---|
| 200 | OK | array of StockPostingOut |
| 401 | Missing or invalid API key (unauthorized). |
ErrorEnvelope |
| 403 | The caller lacks the required scope (missing_right, with scope), the key belongs to no person where a person is needed (forbidden), or the approval policy denies the action (policy_denied, with action and rule_id). |
ErrorEnvelope |
| 422 | Validation failed: the error envelope (validation_failed). For a malformed body or parameter its message is in sentences ("Line 2: the quantity must be above zero") and fields lists each error with pydantic's loc, type and msg beside its sentence (message) and its parts, to word it in another language: items (name and number from 1: line 2), field (its name as sent) and the rule it breaks with its limit, count and choices (none for a validator's own sentence); FastAPI's own detail list stays beside the envelope. |
HTTPValidationError |
Example response (shape)
[
{
"id": "3fa85f64-5717-4562-b3fc-2c963f66afa6",
"entity": "string",
"number": "string",
"kind": "adjustment",
"posting_date": "2026-09-21",
"status": "pending_approval",
"currency": "string",
"value": "string",
"journal_entry_id": "3fa85f64-5717-4562-b3fc-2c963f66afa6",
"journal_entry_number": "string",
"note": "string",
"source_type": "string",
"source_id": "3fa85f64-5717-4562-b3fc-2c963f66afa6",
"source_number": "string",
"lines": [
{
"line_no": 1,
"item": "string",
"item_name": "string",
"unit": "string",
"warehouse": null,
"quantity": "string",
"value": "string",
"unit_cost": null,
"offset_account": null
}
],
"created_by": {},
"created_at": "2026-09-21T09:30:00Z"
}
]
GET /v1/stock-postings/{posting_id}
Get a stock posting
One stock posting with its movements and journal entry.
| Required scope | read (admin implies every scope) |
| Operation id | get_stock_posting_v1_stock_postings__posting_id__get |
Parameters
| In | Name | Type | Required | Description |
|---|---|---|---|---|
| path | posting_id |
string (uuid) | yes | Id of the stock posting. |
Example request
curl "$ERP_URL/v1/stock-postings/{posting_id}" \
-H "Authorization: Bearer $ERP_KEY"
Responses
| Status | Meaning | Body |
|---|---|---|
| 200 | OK | StockPostingOut |
| 401 | Missing or invalid API key (unauthorized). |
ErrorEnvelope |
| 403 | The caller lacks the required scope (missing_right, with scope), the key belongs to no person where a person is needed (forbidden), or the approval policy denies the action (policy_denied, with action and rule_id). |
ErrorEnvelope |
| 404 | The resource does not exist, or belongs to another organization (not_found). |
ErrorEnvelope |
| 422 | Validation failed: the error envelope (validation_failed). For a malformed body or parameter its message is in sentences ("Line 2: the quantity must be above zero") and fields lists each error with pydantic's loc, type and msg beside its sentence (message) and its parts, to word it in another language: items (name and number from 1: line 2), field (its name as sent) and the rule it breaks with its limit, count and choices (none for a validator's own sentence); FastAPI's own detail list stays beside the envelope. |
HTTPValidationError |
Example response (shape)
{
"id": "3fa85f64-5717-4562-b3fc-2c963f66afa6",
"entity": "string",
"number": "string",
"kind": "adjustment",
"posting_date": "2026-09-21",
"status": "pending_approval",
"currency": "string",
"value": "string",
"journal_entry_id": "3fa85f64-5717-4562-b3fc-2c963f66afa6",
"journal_entry_number": "string",
"note": "string",
"source_type": "string",
"source_id": "3fa85f64-5717-4562-b3fc-2c963f66afa6",
"source_number": "string",
"lines": [
{
"line_no": 1,
"item": "string",
"item_name": "string",
"unit": "string",
"warehouse": "string",
"quantity": "string",
"value": "string",
"unit_cost": "string",
"offset_account": "string"
}
],
"created_by": {},
"created_at": "2026-09-21T09:30:00Z"
}
POST /v1/stock-transfers
Move stock between warehouses
Move goods from one warehouse of an entity to another. The value stays with the entity, so
nothing is posted to the ledger. 409 when the warehouse the goods leave does not hold them.
Needs an Idempotency-Key.
| Required scope | draft (admin implies every scope) |
| Idempotency-Key | required |
| Operation id | transfer_stock_v1_stock_transfers_post |
Request body
application/json (required): TransferInput
| Field | Type | Required | Description |
|---|---|---|---|
entity |
string | yes | Code (or id) of the entity. |
posting_date |
string (date) or null | The day; omitted: today. | |
from_warehouse |
string | yes | Warehouse the goods leave (code or id). |
to_warehouse |
string | yes | Warehouse they go to (code or id). |
note |
string or null | A note. (max length 1000) | |
lines |
array of TransferLine |
yes | The items. (min items 1; max items 500) |
Example request
curl -X POST "$ERP_URL/v1/stock-transfers" \
-H "Authorization: Bearer $ERP_KEY" \
-H "Idempotency-Key: $(uuidgen)" \
-H "Content-Type: application/json" \
-d '{
"entity": "CH01",
"from_warehouse": "ZRH",
"lines": [
{
"item": "SCANNER",
"quantity": "5"
}
],
"to_warehouse": "BSL"
}'
Responses
| Status | Meaning | Body |
|---|---|---|
| 201 | Created | StockPostingOut |
| 401 | Missing or invalid API key (unauthorized). |
ErrorEnvelope |
| 403 | The caller lacks the required scope (missing_right, with scope), the key belongs to no person where a person is needed (forbidden), or the approval policy denies the action (policy_denied, with action and rule_id). |
ErrorEnvelope |
| 409 | The request conflicts with the data: an Idempotency-Key reused with a different request, a closed period, or an integrity rule of the database (conflict, integrity_violation). |
ErrorEnvelope |
| 422 | Validation failed: the error envelope (validation_failed). For a malformed body or parameter its message is in sentences ("Line 2: the quantity must be above zero") and fields lists each error with pydantic's loc, type and msg beside its sentence (message) and its parts, to word it in another language: items (name and number from 1: line 2), field (its name as sent) and the rule it breaks with its limit, count and choices (none for a validator's own sentence); FastAPI's own detail list stays beside the envelope. |
HTTPValidationError |
Example response (shape)
{
"id": "3fa85f64-5717-4562-b3fc-2c963f66afa6",
"entity": "string",
"number": "string",
"kind": "adjustment",
"posting_date": "2026-09-21",
"status": "pending_approval",
"currency": "string",
"value": "string",
"journal_entry_id": "3fa85f64-5717-4562-b3fc-2c963f66afa6",
"journal_entry_number": "string",
"note": "string",
"source_type": "string",
"source_id": "3fa85f64-5717-4562-b3fc-2c963f66afa6",
"source_number": "string",
"lines": [
{
"line_no": 1,
"item": "string",
"item_name": "string",
"unit": "string",
"warehouse": "string",
"quantity": "string",
"value": "string",
"unit_cost": "string",
"offset_account": "string"
}
],
"created_by": {},
"created_at": "2026-09-21T09:30:00Z"
}
GET /v1/warehouses
List warehouses
Where the entities keep stock, by entity and code, with how many items each holds.
| Required scope | read (admin implies every scope) |
| Operation id | list_warehouses_v1_warehouses_get |
Parameters
| In | Name | Type | Required | Description |
|---|---|---|---|---|
| query | entity |
string or null | Only this entity's (code or id). | |
| query | active |
boolean or null | Only active (or inactive) ones. |
Example request
curl "$ERP_URL/v1/warehouses" \
-H "Authorization: Bearer $ERP_KEY"
Responses
| Status | Meaning | Body |
|---|---|---|
| 200 | OK | array of WarehouseOut |
| 401 | Missing or invalid API key (unauthorized). |
ErrorEnvelope |
| 403 | The caller lacks the required scope (missing_right, with scope), the key belongs to no person where a person is needed (forbidden), or the approval policy denies the action (policy_denied, with action and rule_id). |
ErrorEnvelope |
| 422 | Validation failed: the error envelope (validation_failed). For a malformed body or parameter its message is in sentences ("Line 2: the quantity must be above zero") and fields lists each error with pydantic's loc, type and msg beside its sentence (message) and its parts, to word it in another language: items (name and number from 1: line 2), field (its name as sent) and the rule it breaks with its limit, count and choices (none for a validator's own sentence); FastAPI's own detail list stays beside the envelope. |
HTTPValidationError |
Example response (shape)
[
{
"id": "3fa85f64-5717-4562-b3fc-2c963f66afa6",
"entity": "string",
"code": "string",
"name": "string",
"address": {},
"is_default": true,
"active": true,
"items": 1,
"created_by": {},
"created_at": "2026-09-21T09:30:00Z"
}
]
POST /v1/warehouses
Create a warehouse
A warehouse of an entity; its first one is its default. The entity's first warehouse also
adds the inventory accounts its chart names (inventory, cost of goods sold, inventory
adjustments, goods received not invoiced) when it lacks them, which needs the right to manage
accounts (403 otherwise). 409 when the entity has a warehouse with the code. Nothing is
posted. Needs an Idempotency-Key.
| Required scope | draft (admin implies every scope) |
| Idempotency-Key | required |
| Operation id | create_warehouse_v1_warehouses_post |
Request body
application/json (required): WarehouseInput
| Field | Type | Required | Description |
|---|---|---|---|
entity |
string | yes | Code (or id) of the entity that keeps stock there. |
code |
string or null | Unique in the entity and never changed; left out, it is made from the name (Lager Zürich gives LAGER-ZURICH). (pattern ^[A-Za-z0-9][A-Za-z0-9._-]{0,19}$) |
|
name |
string | yes | What it is called. (min length 1; max length 200) |
address |
WarehouseAddress or null |
Where it is; printed on delivery notes. | |
is_default |
boolean | Whether goods are taken from and put into it when nothing else is said; an entity's first warehouse is its default. (default false) |
Example request
curl -X POST "$ERP_URL/v1/warehouses" \
-H "Authorization: Bearer $ERP_KEY" \
-H "Idempotency-Key: $(uuidgen)" \
-H "Content-Type: application/json" \
-d '{
"address": {
"building_number": "201",
"country": "CH",
"postal_code": "8005",
"street": "Hardstrasse",
"town": "Zürich"
},
"code": "ZRH",
"entity": "CH01",
"name": "Lager Zürich"
}'
Responses
| Status | Meaning | Body |
|---|---|---|
| 201 | Created | WarehouseOut |
| 401 | Missing or invalid API key (unauthorized). |
ErrorEnvelope |
| 403 | The caller lacks the required scope (missing_right, with scope), the key belongs to no person where a person is needed (forbidden), or the approval policy denies the action (policy_denied, with action and rule_id). |
ErrorEnvelope |
| 409 | The request conflicts with the data: an Idempotency-Key reused with a different request, a closed period, or an integrity rule of the database (conflict, integrity_violation). |
ErrorEnvelope |
| 422 | Validation failed: the error envelope (validation_failed). For a malformed body or parameter its message is in sentences ("Line 2: the quantity must be above zero") and fields lists each error with pydantic's loc, type and msg beside its sentence (message) and its parts, to word it in another language: items (name and number from 1: line 2), field (its name as sent) and the rule it breaks with its limit, count and choices (none for a validator's own sentence); FastAPI's own detail list stays beside the envelope. |
HTTPValidationError |
Example response (shape)
{
"id": "3fa85f64-5717-4562-b3fc-2c963f66afa6",
"entity": "string",
"code": "string",
"name": "string",
"address": {},
"is_default": true,
"active": true,
"items": 1,
"created_by": {},
"created_at": "2026-09-21T09:30:00Z"
}
PATCH /v1/warehouses/{warehouse_id}
Change a warehouse
Rename it, change its address, make it the default or (in)activate it. 409 when deactivating the default warehouse or one that holds stock. Audited with the previous values.
| Required scope | draft (admin implies every scope) |
| Idempotency-Key | not used |
| Operation id | update_warehouse_v1_warehouses__warehouse_id__patch |
Parameters
| In | Name | Type | Required | Description |
|---|---|---|---|---|
| path | warehouse_id |
string (uuid) | yes | Id of the warehouse (GET /v1/warehouses). |
Request body
application/json (required): WarehouseUpdate
| Field | Type | Required | Description |
|---|---|---|---|
name |
string or null | New name. (min length 1; max length 200) | |
address |
WarehouseAddress or null |
New address. | |
is_default |
true or null |
true makes it the default (the previous one stops being it). |
|
active |
boolean or null | false: no goods move in or out; refused while it holds stock. |
Example request
curl -X PATCH "$ERP_URL/v1/warehouses/{warehouse_id}" \
-H "Authorization: Bearer $ERP_KEY" \
-H "Content-Type: application/json" \
-d '{
"is_default": true
}'
Responses
| Status | Meaning | Body |
|---|---|---|
| 200 | OK | WarehouseOut |
| 401 | Missing or invalid API key (unauthorized). |
ErrorEnvelope |
| 403 | The caller lacks the required scope (missing_right, with scope), the key belongs to no person where a person is needed (forbidden), or the approval policy denies the action (policy_denied, with action and rule_id). |
ErrorEnvelope |
| 404 | The resource does not exist, or belongs to another organization (not_found). |
ErrorEnvelope |
| 409 | The request conflicts with the data: an Idempotency-Key reused with a different request, a closed period, or an integrity rule of the database (conflict, integrity_violation). |
ErrorEnvelope |
| 422 | Validation failed: the error envelope (validation_failed). For a malformed body or parameter its message is in sentences ("Line 2: the quantity must be above zero") and fields lists each error with pydantic's loc, type and msg beside its sentence (message) and its parts, to word it in another language: items (name and number from 1: line 2), field (its name as sent) and the rule it breaks with its limit, count and choices (none for a validator's own sentence); FastAPI's own detail list stays beside the envelope. |
HTTPValidationError |
Example response (shape)
{
"id": "3fa85f64-5717-4562-b3fc-2c963f66afa6",
"entity": "string",
"code": "string",
"name": "string",
"address": {},
"is_default": true,
"active": true,
"items": 1,
"created_by": {},
"created_at": "2026-09-21T09:30:00Z"
}
Schemas
AdjustmentInput
| Field | Type | Required | Description |
|---|---|---|---|
entity |
string | yes | Code (or id) of the entity. |
posting_date |
string (date) or null | The day the stock changes; omitted: today. Its period is open. | |
reason |
string | yes | Why: shown on the posting and its entry. (min length 3; max length 1000) |
offset_account |
string or null | The account the value is booked against (code or id); omitted: the inventory adjustment account (role inventory_adjustment). Opening stock names the opening balance clearing account. |
|
lines |
array of AdjustmentLine |
yes | The items. (min items 1; max items 500) |
AdjustmentLine
| Field | Type | Required | Description |
|---|---|---|---|
item |
string | yes | Product code (or id) of the stock item. |
warehouse |
string or null | Warehouse code (or id); omitted: the default warehouse. | |
quantity |
decimal string | yes | What comes in (positive) or goes out (negative). A quantity in the item's unit, up to six decimals, e.g. 12 or 2.5. |
unit_cost |
decimal string or null | Of goods coming in: the cost of one unit in the functional currency; omitted: the moving average (needed when nothing is in stock). Goods going out always leave at the moving average. (min 0) |
CountLineInput
| Field | Type | Required | Description |
|---|---|---|---|
item |
string | yes | Product code (or id) of an item on the count. |
counted_quantity |
decimal string or null | yes | What was counted; null: not counted (yet). A quantity in the item's unit, up to six decimals, e.g. 12 or 2.5. (min 0) |
CountLinesInput
| Field | Type | Required | Description |
|---|---|---|---|
lines |
array of CountLineInput |
yes | Counted quantities. (min items 1; max items 2000) |
StockCountInput
| Field | Type | Required | Description |
|---|---|---|---|
entity |
string | yes | Code (or id) of the entity. |
warehouse |
string | yes | Warehouse counted (code or id). |
count_date |
string (date) or null | The day of the count; omitted: today. Not in the future. | |
note |
string or null | A note. (max length 1000) | |
items |
array of string or null | The items to count (product codes or ids); omitted: every active stock item of the entity. (max items 2000) |
StockCountLineOut
| Field | Type | Required | Description |
|---|---|---|---|
item |
string | yes | Product code. |
item_name |
string | yes | Product name. |
unit |
string | yes | Unit. |
book_quantity |
string | yes | What the books hold in the warehouse: today while the count is open, what it was posted against once posted. |
counted_quantity |
string or null | yes | What was counted; null: not counted. |
difference |
string or null | yes | Counted less book; null while not counted. |
value_difference |
string or null | yes | The difference at the moving average (once posted: what was booked). |
counted_by |
object or null | yes | Who entered the count. |
StockCountOut
| Field | Type | Required | Description |
|---|---|---|---|
id |
string (uuid) | yes | Count id. |
entity |
string | yes | Entity code. |
number |
string | yes | Number, e.g. CNT-2026-000003. |
warehouse |
string | yes | Warehouse code. |
warehouse_name |
string | yes | Warehouse name. |
count_date |
string (date) | yes | Day of the count. |
status |
"cancelled" | "open" | "posted" |
yes | open, posted or cancelled. |
currency |
string | yes | Functional currency of the values. |
note |
string or null | yes | Note. |
counted |
integer | yes | Lines counted so far. |
lines |
array of StockCountLineOut |
yes | The items, by code. |
posting_id |
string (uuid) or null | yes | The posting of its differences. |
posting_number |
string or null | yes | Number of that posting. |
created_by |
object | yes | Who opened it. |
created_at |
string (date-time) | yes | When (UTC). |
decided_by |
object or null | yes | Who posted or cancelled it. |
decided_at |
string (date-time) or null | yes | When (UTC). |
StockItemInput
| Field | Type | Required | Description |
|---|---|---|---|
product |
string | yes | Code (or id) of the product to keep in stock: goods sold per unit. |
entity |
string or null | Code (or id) of the product's entity; needed with a code. | |
inventory_account |
string or null | Account (code or id) its stock is booked to: a control account on the inventories line; omitted: the entity's inventory account (role inventory). |
|
cogs_account |
string or null | Expense account (code or id) its cost of goods sold is booked to; omitted: the entity's account of the role cogs. |
StockItemOut
| Field | Type | Required | Description |
|---|---|---|---|
product_id |
string (uuid) | yes | Id of the product (and of the stock item). |
entity |
string | yes | Entity code. |
code |
string | yes | Product code. |
name |
string | yes | Product name. |
unit |
string | yes | The unit its quantities are in. |
active |
boolean | yes | Whether the product is still sold. |
inventory_account |
string | yes | Code of its inventory account. |
cogs_account |
string | yes | Code of its cost of goods sold account. |
currency |
string | yes | The entity's functional currency: what values are in. |
quantity |
string | yes | Quantity in stock (all warehouses). |
value |
string | yes | Value of the stock, in the functional currency. |
average_cost |
string or null | yes | Moving average cost of one unit (value / quantity, six decimals); null when nothing is in stock. |
levels |
array of StockLevelOut |
yes | Quantity per warehouse that holds some. |
created_by |
object | yes | Who started keeping it in stock. |
created_at |
string (date-time) | yes | When (UTC). |
StockItemUpdate
| Field | Type | Required | Description |
|---|---|---|---|
inventory_account |
string or null | New inventory account; only while nothing is in stock. | |
cogs_account |
string or null | New cost of goods sold account. |
StockLevelOut
| Field | Type | Required | Description |
|---|---|---|---|
warehouse |
string | yes | Warehouse code. |
warehouse_name |
string | yes | Warehouse name. |
quantity |
string | yes | Quantity in the warehouse. |
StockMovementOut
| Field | Type | Required | Description |
|---|---|---|---|
line_no |
integer | yes | Line number. |
item |
string | yes | Product code. |
item_name |
string | yes | Product name. |
unit |
string | yes | Unit. |
warehouse |
string or null | yes | Warehouse code; null for a revaluation. |
quantity |
string | yes | In (positive) or out (negative). |
value |
string | yes | Value in the functional currency, with the same sign. |
unit_cost |
string or null | yes | Value / quantity (six decimals); null for a revaluation or no quantity. |
offset_account |
string or null | yes | Code of the account booked against. |
StockPostingOut
| Field | Type | Required | Description |
|---|---|---|---|
id |
string (uuid) | yes | Posting id. |
entity |
string | yes | Entity code. |
number |
string | yes | Number, e.g. STK-2026-000012. |
kind |
"adjustment" | "count" | "delivery" | "receipt" | "return" | "revaluation" | "transfer" |
yes | What happened. |
posting_date |
string (date) | yes | The day the stock changed. |
status |
"pending_approval" | "posted" | "rejected" |
yes | posted, or pending_approval (its entry waits for a person; the stock has not changed yet), or rejected. |
currency |
string | yes | The functional currency of the values. |
value |
string | yes | Total value of its lines (net, with signs). |
journal_entry_id |
string (uuid) or null | yes | Its entry; null for a transfer. |
journal_entry_number |
string or null | yes | Number of its entry, once posted. |
note |
string or null | yes | Why, or a note. |
source_type |
string or null | yes | What it is for (a count, a receipt, ...). |
source_id |
string (uuid) or null | yes | Id of that document. |
source_number |
string or null | yes | Number of that document. |
lines |
array of StockMovementOut |
yes | The movements. |
created_by |
object | yes | Who recorded it. |
created_at |
string (date-time) | yes | When (UTC). |
TransferInput
| Field | Type | Required | Description |
|---|---|---|---|
entity |
string | yes | Code (or id) of the entity. |
posting_date |
string (date) or null | The day; omitted: today. | |
from_warehouse |
string | yes | Warehouse the goods leave (code or id). |
to_warehouse |
string | yes | Warehouse they go to (code or id). |
note |
string or null | A note. (max length 1000) | |
lines |
array of TransferLine |
yes | The items. (min items 1; max items 500) |
TransferLine
| Field | Type | Required | Description |
|---|---|---|---|
item |
string | yes | Product code (or id) of the stock item. |
quantity |
decimal string | yes | What moves. A quantity in the item's unit, up to six decimals, e.g. 12 or 2.5. (greater than 0) |
ValuationLine
| Field | Type | Required | Description |
|---|---|---|---|
product_id |
string (uuid) | yes | Product id. |
item |
string | yes | Product code. |
item_name |
string | yes | Product name. |
unit |
string | yes | Unit. |
inventory_account |
string | yes | Code of its inventory account. |
quantity |
string | yes | Quantity on the day (all warehouses, or the one asked). |
value |
string | yes | Value on the day (company-wide; per item, not warehouse). |
average_cost |
string or null | yes | Value / quantity; null without quantity. |
ValuationOut
| Field | Type | Required | Description |
|---|---|---|---|
entity |
string | yes | Entity code. |
as_of |
string (date) | yes | The day, end of day. |
currency |
string | yes | Functional currency. |
warehouse |
string or null | yes | The warehouse asked for; quantities only. |
lines |
array of ValuationLine |
yes | Every item with a quantity or a value. |
total |
string | yes | Total value of the stock. |
ledger |
string | yes | Balance of the inventory accounts on the day from posted entries. |
difference |
string | yes | Total less ledger: zero, since only stock postings book the inventory accounts. |
WarehouseAddress
| Field | Type | Required | Description |
|---|---|---|---|
street |
string or null | Street. (max length 70) | |
building_number |
string or null | Number. (max length 16) | |
postal_code |
string or null | Postal code. (max length 16) | |
town |
string or null | Town. (max length 35) | |
country |
string or null | ISO 3166 country, e.g. CH. (pattern ^[A-Z]{2}$) |
WarehouseInput
| Field | Type | Required | Description |
|---|---|---|---|
entity |
string | yes | Code (or id) of the entity that keeps stock there. |
code |
string or null | Unique in the entity and never changed; left out, it is made from the name (Lager Zürich gives LAGER-ZURICH). (pattern ^[A-Za-z0-9][A-Za-z0-9._-]{0,19}$) |
|
name |
string | yes | What it is called. (min length 1; max length 200) |
address |
WarehouseAddress or null |
Where it is; printed on delivery notes. | |
is_default |
boolean | Whether goods are taken from and put into it when nothing else is said; an entity's first warehouse is its default. (default false) |
WarehouseOut
| Field | Type | Required | Description |
|---|---|---|---|
id |
string (uuid) | yes | Warehouse id. |
entity |
string | yes | Entity code. |
code |
string | yes | Code, unique in the entity. |
name |
string | yes | Name. |
address |
object or null | yes | Address, as recorded. |
is_default |
boolean | yes | Whether it is the entity's default warehouse. |
active |
boolean | yes | Whether goods move in and out of it. |
items |
integer | yes | How many items it holds a quantity of. |
created_by |
object | yes | Who created it. |
created_at |
string (date-time) | yes | When (UTC). |
WarehouseUpdate
| Field | Type | Required | Description |
|---|---|---|---|
name |
string or null | New name. (min length 1; max length 200) | |
address |
WarehouseAddress or null |
New address. | |
is_default |
true or null |
true makes it the default (the previous one stops being it). |
|
active |
boolean or null | false: no goods move in or out; refused while it holds stock. |