Developer dashboard

Inventory#

Inventory is tracked per Product and active physical branch. The authoritative balance fields are
onHand, reserved, and available, where available = max(0, onHand - reserved). This page
covers the Inventory API, invoice and POS stock behavior, and recovery procedures.

Overview#

  • Balances show On Hand, Reserved, Available, and stock condition by active physical branch.
  • Movements record manual Quantity In and Quantity Out for tracked Products.
  • Stocktakes apply physical counts to branch balances.
  • Suppliers can be attached to incoming movements.
  • Activity records manual changes, counts, and automated sales.

Authentication#

All /api/v1/inventory endpoints are admin REST endpoints. Send the headers described in
Invoices. Read endpoints require invoices.view; write and
recovery endpoints require invoices.manage. The merchant scope comes from the authenticated
request. A locationId used for an inventory operation must be an active physical branch UUID
owned by that merchant. Quantities support up to three decimal places.

The matching requests are in Admin API / Invoicing / Inventory in the Postman collection.

Common errors#

Status Cause
400 Invalid input, unavailable Product, inactive branch, or insufficient Available stock.
401 Missing or invalid authentication.
403 Permission or merchant scope denied.
404 Record is not found in the merchant scope.
409 Another inventory operation currently holds the branch; retry later.

Inventory endpoints#

List inventory balances#

Endpoint#

GET/api/v1/inventory/balances
List inventory balancesbash
curl -X GET "https://uat.auxcore.net/api/v1/inventory/balances?productId=PRODUCT_ID" \
  -H "Authorization: Bearer YOUR_TOKEN" \
  -H "X-Tenant-ID: your-tenant-id"

Query parameters#

Field Description
productId Optional Product filter. Product-scoped results include zero-balance active branches.
locationId Optional physical branch filter.
includeHistorical Set true to include persisted inactive-branch balances (read-only).

Response#

200 OK: data[] contains productId, locationId, onHand, reserved, available, and
stockCondition. Product-scoped responses include aggregate meta.totals.

Responsejson
{
  "success": true,
  "data": [{
    "productId": "PRODUCT_ID", "locationId": "LOCATION_ID", "onHand": 20,
    "reserved": 3, "available": 17, "stockCondition": "in_stock"
  }],
  "meta": { "total": 1, "totals": { "onHand": 20, "reserved": 3, "available": 17 } }
}

Errors#

Status Cause
400 Invalid merchant scope.
403 Missing invoices.view or merchant access denied.

Create a stock movement#

Endpoint#

POST/api/v1/inventory/movements
Create a stock movementbash
curl -X POST "https://uat.auxcore.net/api/v1/inventory/movements" \
  -H "Authorization: Bearer YOUR_TOKEN" \
  -H "X-Tenant-ID: your-tenant-id" \
  -H "Content-Type: application/json" \
  -d '{"type":"quantity_in","locationId":"LOCATION_ID","date":"2026-10-28","reason":"Supplier delivery","lines":[{"productId":"PRODUCT_ID","quantity":12.5}]}'

Request#

Field Required Description
type Yes quantity_in or quantity_out.
locationId, date, reason Yes Active physical branch UUID, ISO date, nonblank reason.
lines Yes Nonempty unique { productId, quantity } entries for tracked Products.
supplierId, reference, note No Movement metadata.
idempotencyKey No 1–128 letters, digits, ., _, :, or -; retry returns original movement.
Requestjson
{
  "type": "quantity_in",
  "locationId": "2d8b4e17-ec2e-41f2-b6e9-6a32c5fd1780",
  "date": "2026-10-28",
  "reason": "Supplier delivery",
  "supplierId": "supplier-uuid",
  "idempotencyKey": "delivery:po-1042",
  "lines": [{ "productId": "product-uuid", "quantity": 12.5 }]
}

Response#

201 Created: data contains the saved movement and lines.

Responsejson
{
  "success": true,
  "data": {
    "movement": { "id": "MOVEMENT_ID", "type": "quantity_in", "locationId": "LOCATION_ID", "reason": "Supplier delivery" },
    "lines": [{ "productId": "PRODUCT_ID", "quantity": 12.5, "before": 0, "after": 12.5 }]
  }
}

Errors#

Status Cause
400 Invalid movement fields, tracked Product, branch, supplier, or idempotency key.
403 Missing invoices.manage or merchant access denied.
400 Quantity Out exceeds Available or request validation fails.
409 Branch lease is held by another inventory operation.

List stock movements#

Endpoint#

GET/api/v1/inventory/movements
List stock movementsbash
curl -X GET "https://uat.auxcore.net/api/v1/inventory/movements?productId=PRODUCT_ID&page=1&limit=10" \
  -H "Authorization: Bearer YOUR_TOKEN" \
  -H "X-Tenant-ID: your-tenant-id"

Query parameters#

Field Description
productId, locationId, supplierId Optional filters.
type quantity_in or quantity_out.
page, limit Defaults 1 / 10; maximum limit 200.

Response#

200 OK: data is the movement list; meta contains page, limit, and total.

Responsejson
{ "success": true, "data": [], "meta": { "page": 1, "limit": 10, "total": 0 } }

Get a stock movement#

Endpoint#

GET/api/v1/inventory/movements/:id
Get a stock movementbash
curl -X GET "https://uat.auxcore.net/api/v1/inventory/movements/MOVEMENT_ID" \
  -H "Authorization: Bearer YOUR_TOKEN" \
  -H "X-Tenant-ID: your-tenant-id"

Response#

200 OK: data contains the movement and its lines.

Responsejson
{ "success": true, "data": { "movement": { "id": "MOVEMENT_ID" }, "lines": [] } }

Errors#

Status Cause
404 Movement is not found in the merchant scope.

Count stock#

Endpoint#

POST/api/v1/inventory/stocktakes
Count stockbash
curl -X POST "https://uat.auxcore.net/api/v1/inventory/stocktakes" \
  -H "Authorization: Bearer YOUR_TOKEN" \
  -H "X-Tenant-ID: your-tenant-id" \
  -H "Content-Type: application/json" \
  -d '{"locationId":"LOCATION_ID","name":"Monthly count","date":"2026-10-28","lines":[{"productId":"PRODUCT_ID","counted":25}]}'

Request#

Field Required Description
locationId, name, date Yes Active physical branch, stocktake name, ISO date.
lines Yes Nonempty unique { productId, counted } entries for tracked Products.
note No Stocktake note.

Creation applies the count immediately; counted cannot be below Reserved.

Response#

201 Created: data contains the completed stocktake and lines.

Responsejson
{
  "success": true,
  "data": {
    "stocktake": { "id": "STOCKTAKE_ID", "status": "completed", "locationId": "LOCATION_ID" },
    "lines": [{ "productId": "PRODUCT_ID", "expected": 20, "counted": 25, "difference": 5 }]
  }
}

Errors#

Status Cause
400 Invalid input or count below Reserved.
403 Missing invoices.manage or merchant access denied.

List stocktakes#

Endpoint#

GET/api/v1/inventory/stocktakes
List stocktakesbash
curl -X GET "https://uat.auxcore.net/api/v1/inventory/stocktakes?locationId=LOCATION_ID&page=1&limit=10" \
  -H "Authorization: Bearer YOUR_TOKEN" \
  -H "X-Tenant-ID: your-tenant-id"

Query parameters#

Field Description
locationId Optional physical branch filter.
status draft or completed.
page, limit Defaults 1 / 10; maximum limit 200.

Response#

200 OK: data is the stocktake list; meta contains page, limit, and total.

Responsejson
{ "success": true, "data": [], "meta": { "page": 1, "limit": 10, "total": 0 } }

Get a stocktake#

Endpoint#

GET/api/v1/inventory/stocktakes/:id
Get a stocktakebash
curl -X GET "https://uat.auxcore.net/api/v1/inventory/stocktakes/STOCKTAKE_ID" \
  -H "Authorization: Bearer YOUR_TOKEN" \
  -H "X-Tenant-ID: your-tenant-id"

Response#

200 OK: data contains the stocktake and its lines.

Responsejson
{ "success": true, "data": { "stocktake": { "id": "STOCKTAKE_ID" }, "lines": [] } }

Errors#

Status Cause
404 Stocktake is not found in the merchant scope.

Complete a stocktake#

Endpoint#

POST/api/v1/inventory/stocktakes/:id/complete
Complete a stocktakebash
curl -X POST "https://uat.auxcore.net/api/v1/inventory/stocktakes/STOCKTAKE_ID/complete" \
  -H "Authorization: Bearer YOUR_TOKEN" \
  -H "X-Tenant-ID: your-tenant-id" \
  -H "Content-Type: application/json" \
  -d '{"lines":[{"productId":"PRODUCT_ID","counted":25}]}'

Request#

Field Required Description
lines Yes Existing stocktake lines as { productId, counted }.

Response#

200 OK: data contains the completed stocktake and lines.

Responsejson
{ "success": true, "data": { "stocktake": { "id": "STOCKTAKE_ID", "status": "completed" }, "lines": [] } }

Errors#

Status Cause
400 Already completed, stale balance, invalid line, or count below Reserved.
404 Stocktake is not found in the merchant scope.

Suppliers#

Create a supplier#

Endpoint#

POST/api/v1/inventory/suppliers
Create a supplierbash
curl -X POST "https://uat.auxcore.net/api/v1/inventory/suppliers" \
  -H "Authorization: Bearer YOUR_TOKEN" \
  -H "X-Tenant-ID: your-tenant-id" \
  -H "Content-Type: application/json" \
  -d '{"name":"Example Supply Co","email":"orders@example.com","phone":"5550100"}'

Request#

Field Required Description
name Yes Supplier name.
contact, email, phone, address, notes No Supplier details.

Response#

201 Created: data is the created supplier.

Responsejson
{ "success": true, "data": { "id": "SUPPLIER_ID", "name": "Example Supply Co", "email": "orders@example.com", "phone": "5550100" } }

Errors#

Status Cause
400 Supplier name is empty.
403 Missing invoices.manage or merchant access denied.

List suppliers#

Endpoint#

GET/api/v1/inventory/suppliers
List suppliersbash
curl -X GET "https://uat.auxcore.net/api/v1/inventory/suppliers?search=Example&page=1&limit=10" \
  -H "Authorization: Bearer YOUR_TOKEN" \
  -H "X-Tenant-ID: your-tenant-id"

Query parameters#

Field Description
search Matches name, contact, or email.
page, limit Defaults 1 / 10; maximum limit 200.

Response#

200 OK: data is the supplier list; meta contains page, limit, and total.

Responsejson
{ "success": true, "data": [], "meta": { "page": 1, "limit": 10, "total": 0 } }

Get a supplier#

Endpoint#

GET/api/v1/inventory/suppliers/:id
Get a supplierbash
curl -X GET "https://uat.auxcore.net/api/v1/inventory/suppliers/SUPPLIER_ID" \
  -H "Authorization: Bearer YOUR_TOKEN" \
  -H "X-Tenant-ID: your-tenant-id"

Response#

200 OK: data is the scoped supplier.

Responsejson
{ "success": true, "data": { "id": "SUPPLIER_ID", "name": "Example Supply Co", "email": "orders@example.com" } }

Errors#

Status Cause
404 Supplier is not found in the merchant scope.

Update a supplier#

Endpoint#

PUT/api/v1/inventory/suppliers/:id
Update a supplierbash
curl -X PUT "https://uat.auxcore.net/api/v1/inventory/suppliers/SUPPLIER_ID" \
  -H "Authorization: Bearer YOUR_TOKEN" \
  -H "X-Tenant-ID: your-tenant-id" \
  -H "Content-Type: application/json" \
  -d '{"phone":"5550101"}'

Request#

Field Required Description
name, contact, email, phone, address, notes No Supplied fields are updated; omitted fields are unchanged.

Response#

200 OK: data is the updated supplier.

Responsejson
{ "success": true, "data": { "id": "SUPPLIER_ID", "name": "Example Supply Co", "phone": "5550101" } }

Errors#

Status Cause
400 Supplier name is empty.
404 Supplier is not found in the merchant scope.

Delete a supplier#

Endpoint#

DELETE/api/v1/inventory/suppliers/:id
Delete a supplierbash
curl -X DELETE "https://uat.auxcore.net/api/v1/inventory/suppliers/SUPPLIER_ID" \
  -H "Authorization: Bearer YOUR_TOKEN" \
  -H "X-Tenant-ID: your-tenant-id"

Response#

200 OK: { "success": true, "data": { "id": "supplier-uuid" } }.

Errors#

Status Cause
404 Supplier is not found in the merchant scope.

Read inventory activity#

Endpoint#

GET/api/v1/inventory/activity
Read inventory activitybash
curl -X GET "https://uat.auxcore.net/api/v1/inventory/activity?productId=PRODUCT_ID&locationId=LOCATION_ID&page=1&limit=10" \
  -H "Authorization: Bearer YOUR_TOKEN" \
  -H "X-Tenant-ID: your-tenant-id"

Query parameters#

Field Description
productId, locationId Optional Product and physical branch filters.
type quantity_in, quantity_out, invoice_sale, pos_sale, item_count, tracking_disabled, tracking_enabled, or stock_update_pending.
startDate, endDate Optional date range.
page, limit Defaults 1 / 10; maximum limit 200.

Response#

200 OK: data is the activity list; meta contains page, limit, and total.

Responsejson
{ "success": true, "data": [], "meta": { "page": 1, "limit": 10, "total": 0 } }