Skip to main content

Products API

Auto-generated from the OpenAPI spec. Run node docs-site/scripts/fetch-openapi.js to regenerate.

POST /api/v1/products

Create Product

Create a new product. Manager-only.

Request body

FieldRequiredTypeDescription
nameYesstring
skuNostring
priceYesnumber
stock_quantityNointeger
is_activeNoboolean

Responses

  • 201 — Successful Response
  • 422 — Validation Error

GET /api/v1/products

List Products

List all products. Manager-only.

Parameters

NameInRequiredTypeDescription
active_onlyqueryNoboolean
pagequeryNointeger
page_sizequeryNointeger

Responses

  • 200 — Successful Response
  • 422 — Validation Error

GET /api/v1/products/{product_id}

Get Product

Get a product by ID. Manager-only.

Parameters

NameInRequiredTypeDescription
product_idpathYesinteger

Responses

  • 200 — Successful Response
  • 422 — Validation Error

PUT /api/v1/products/{product_id}

Update Product

Update a product. Manager-only.

stock_quantity is intentionally absent from ProductUpdate — the only code path allowed to move stock is POST /products/{id}/stock-adjustment.

Parameters

NameInRequiredTypeDescription
product_idpathYesinteger

Request body

FieldRequiredTypeDescription
nameNostring
skuNostring
priceNonumber
is_activeNoboolean

Responses

  • 200 — Successful Response
  • 422 — Validation Error

DELETE /api/v1/products/{product_id}

Deactivate Product

Deactivate a product (set is_active=False). Manager-only. Soft-delete — never a real row delete.

Parameters

NameInRequiredTypeDescription
product_idpathYesinteger

Responses

  • 200 — Successful Response
  • 422 — Validation Error

POST /api/v1/products/{product_id}/photo

Upload Product Photo

Upload (or replace) a product's photo. Manager-only — Products has no client-facing surface at all, so unlike Client/Instructor this has no dual-role authorization resolver to port.

Parameters

NameInRequiredTypeDescription
product_idpathYesinteger

Responses

  • 200 — Successful Response
  • 422 — Validation Error

POST /api/v1/products/{product_id}/stock-adjustment

Adjust Product Stock

Restock (or manually correct) a product's stock_quantity by a delta.

A single atomic UPDATE (stock_quantity += delta), safe under concurrent calls — this is why it takes a delta rather than an absolute "set to N", which would be a lost-update hazard between two concurrently-restocking managers. Rejects if the delta would drive stock below 0.

Parameters

NameInRequiredTypeDescription
product_idpathYesinteger

Request body

FieldRequiredTypeDescription
deltaYesinteger
reasonNostring

Responses

  • 200 — Successful Response
  • 422 — Validation Error

POST /api/v1/product-sales

Create Product Sale

Record a completed in-person sale of one or more products.

sold_by_user_id is always set server-side from the resolved manager user, never accepted from the request body. total_amount and every line's line_total are always computed server-side from unit_price_at_sale * quantity — never trusted from the request.

Request body

FieldRequiredTypeDescription
client_idNointeger
itemsYesarray
payment_methodYesstring
notesNostring

Responses

  • 201 — Successful Response
  • 422 — Validation Error

GET /api/v1/product-sales

List Product Sales

List product sales, newest first. Manager-only.

Parameters

NameInRequiredTypeDescription
client_idqueryNo
start_datequeryNo
end_datequeryNo

Responses

  • 200 — Successful Response
  • 422 — Validation Error

GET /api/v1/product-sales/{sale_id}

Get Product Sale

Get a product sale by ID, with nested line items. Manager-only.

Parameters

NameInRequiredTypeDescription
sale_idpathYesinteger

Responses

  • 200 — Successful Response
  • 422 — Validation Error