Products
Manage your product catalog — create, update, search, and track inventory. All product endpoints require authentication.
Price Format
All prices are stored as integers in cents. For example, 1499 represents $14.99. This avoids floating-point precision issues in financial calculations.
/api/v1/productsList all products for the current vendor
Query Parameters
| Parameter | Type | Description |
|---|---|---|
| page | number | Page number (default: 1) |
| limit | number | Items per page (default: 20, max: 100) |
| search | string | Search by name, SKU, or barcode |
| category_id | uuid | Filter by category |
| in_stock | boolean | Filter to only in-stock items |
| sort | string | Sort field: name, price, created_at, stock |
| order | string | Sort order: ASC or DESC |
Response
[
{
"id": "uuid",
"name": "Organic Coffee Beans",
"sku": "COF-001",
"barcode": "1234567890123",
"price": 1499,
"cost": 800,
"stock": 150,
"low_stock_threshold": 20,
"category_id": "uuid",
"category": { "id": "uuid", "name": "Beverages" },
"tax_rate": 0,
"unit": "bag",
"image": "/uploads/products/cof-001.jpg",
"is_active": true,
"created_at": "2025-01-15T10:00:00Z",
"updated_at": "2025-05-10T14:30:00Z"
}
]Prices are in cents (integer). Divide by 100 for display. Results are paginated.
/api/v1/products/:idGet a single product by ID
Response
{
"id": "uuid",
"name": "Organic Coffee Beans",
"sku": "COF-001",
"barcode": "1234567890123",
"price": 1499,
"cost": 800,
"stock": 150,
"low_stock_threshold": 20,
"category_id": "uuid",
"category": { "id": "uuid", "name": "Beverages" },
"variants": [
{ "id": "uuid", "name": "250g", "price": 1499, "sku": "COF-001-250" },
{ "id": "uuid", "name": "500g", "price": 2499, "sku": "COF-001-500" }
],
"modifiers": [],
"tax_rate": 0,
"unit": "bag",
"image": "/uploads/products/cof-001.jpg",
"is_active": true,
"created_at": "2025-01-15T10:00:00Z"
}Includes full variant and modifier details. Returns 404 if not found.
/api/v1/productsCreate a new product
Request Body
{
"name": "Organic Coffee Beans",
"sku": "COF-001",
"barcode": "1234567890123",
"price": 1499,
"cost": 800,
"stock": 150,
"low_stock_threshold": 20,
"category_id": "uuid",
"tax_rate": 0,
"unit": "bag",
"is_active": true
}Response
{
"id": "uuid",
"name": "Organic Coffee Beans",
"sku": "COF-001",
...
}Required fields: name, price. All other fields are optional. SKU must be unique within the vendor.
/api/v1/products/:idUpdate an existing product
Request Body
{
"name": "Updated Product Name",
"price": 1599,
"stock": 200
}Response
{
"id": "uuid",
"name": "Updated Product Name",
"price": 1599,
"stock": 200,
...
}Partial updates supported — only include the fields you want to change.
/api/v1/products/:idDelete a product
Response
{
"message": "Product deleted successfully"
}Soft-deletes the product. Products with existing sales history are deactivated rather than deleted.
/api/v1/products/:id/adjust-stockAdjust product stock level
Request Body
{
"quantity": 50,
"type": "add",
"reason": "New shipment received"
}Response
{
"id": "uuid",
"name": "Organic Coffee Beans",
"stock": 200,
"adjustment": {
"quantity": 50,
"type": "add",
"reason": "New shipment received",
"created_at": "2025-05-18T12:00:00Z"
}
}Type can be "add" or "subtract". Creates a stock adjustment record for auditing.
Product Model
| Field | Type | Description |
|---|---|---|
| id | uuid | Unique identifier |
| name | string | Product name |
| sku | string? | Stock keeping unit (unique per vendor) |
| barcode | string? | Barcode (EAN-13, UPC-A, etc.) |
| price | integer | Selling price in cents |
| cost | integer? | Cost price in cents |
| stock | integer | Current stock level |
| low_stock_threshold | integer | Alert when stock falls below this |
| category_id | uuid? | Category reference |
| tax_rate | decimal | Tax rate (0 to 1, e.g. 0.07 = 7%) |
| unit | string | Unit of measure (piece, kg, bag, etc.) |
| image | string? | Image URL |
| is_active | boolean | Whether product is available for sale |