Inventory API¶
Module Only - API Coming Soon
The Inventory module is implemented for internal use with product stock tracking. The public REST API endpoints described below are planned for release in v0.2. Basic inventory operations are available through the product API.
The Inventory API provides comprehensive stock management including inventory levels, stock reservations, movements, and low stock alerts. It supports multi-location inventory tracking and automated stock reservation for orders.
Base URL¶
Authentication¶
All inventory endpoints require authentication via API key or JWT token.
Inventory Object¶
{
"product_id": "550e8400-e29b-41d4-a716-446655440000",
"total_available": 150,
"total_reserved": 25,
"total_incoming": 50,
"low_stock_threshold": 20,
"locations": [
{
"location_id": "550e8400-e29b-41d4-a716-446655440020",
"location_name": "Warehouse A",
"available": 100,
"reserved": 15,
"incoming": 30
},
{
"location_id": "550e8400-e29b-41d4-a716-446655440021",
"location_name": "Warehouse B",
"available": 50,
"reserved": 10,
"incoming": 20
}
]
}
Inventory Fields¶
| Field | Type | Description |
|---|---|---|
product_id |
UUID | Product unique identifier |
total_available |
integer | Total available quantity across all locations |
total_reserved |
integer | Total reserved quantity for pending orders |
total_incoming |
integer | Total incoming stock (in transit) |
low_stock_threshold |
integer | Alert threshold for low stock |
locations |
array | Inventory breakdown by location |
Location Inventory Fields¶
| Field | Type | Description |
|---|---|---|
location_id |
UUID | Location unique identifier |
location_name |
string | Human-readable location name |
available |
integer | Available quantity at location |
reserved |
integer | Reserved quantity at location |
incoming |
integer | Incoming quantity at location |
Endpoints¶
List Inventory Levels¶
Retrieve a paginated list of inventory levels across all products.
Query Parameters¶
| Parameter | Type | Description |
|---|---|---|
page |
integer | Page number (default: 1) |
per_page |
integer | Items per page (default: 20, max: 100) |
product_id |
UUID | Filter by specific product |
location_id |
UUID | Filter by specific location |
stock_status |
string | Filter by in_stock, low_stock, out_of_stock |
low_stock_only |
boolean | Show only low stock items |
include_incoming |
boolean | Include incoming stock in calculations |
sort |
string | product_id, available, updated_at |
order |
string | asc or desc (default: desc) |
Example Request¶
Example Response¶
{
"data": [
{
"product_id": "550e8400-e29b-41d4-a716-446655440000",
"product_name": "Premium Cotton T-Shirt",
"total_available": 150,
"total_reserved": 25,
"total_incoming": 50,
"low_stock_threshold": 20,
"stock_status": "in_stock",
"locations": [
{
"location_id": "550e8400-e29b-41d4-a716-446655440020",
"location_name": "Warehouse A",
"available": 100,
"reserved": 15,
"incoming": 30
}
],
"updated_at": "2024-01-20T14:30:00Z"
}
],
"meta": {
"pagination": {
"total": 156,
"per_page": 50,
"current_page": 1,
"total_pages": 4,
"has_next": true,
"has_prev": false
},
"request_id": "req_abc123"
}
}
Get Product Inventory¶
Retrieve detailed inventory information for a specific product.
Parameters¶
| Parameter | Type | Description |
|---|---|---|
product_id |
UUID | Product unique identifier |
Query Parameters¶
| Parameter | Type | Description |
|---|---|---|
include_history |
boolean | Include recent stock movements |
include_reservations |
boolean | Include active reservations |
Example Request¶
GET /api/v1/inventory/550e8400-e29b-41d4-a716-446655440000?include_history=true
Authorization: Bearer sk_live_xxx
Example Response¶
{
"data": {
"product_id": "550e8400-e29b-41d4-a716-446655440000",
"product_name": "Premium Cotton T-Shirt",
"total_available": 150,
"total_reserved": 25,
"total_incoming": 50,
"low_stock_threshold": 20,
"stock_status": "in_stock",
"locations": [
{
"location_id": "550e8400-e29b-41d4-a716-446655440020",
"location_name": "Warehouse A",
"available": 100,
"reserved": 15,
"incoming": 30
},
{
"location_id": "550e8400-e29b-41d4-a716-446655440021",
"location_name": "Warehouse B",
"available": 50,
"reserved": 10,
"incoming": 20
}
],
"recent_movements": [
{
"id": "550e8400-e29b-41d4-a716-446655440030",
"movement_type": "in",
"quantity": 50,
"location_name": "Warehouse A",
"reference": "PO-2024-001",
"created_at": "2024-01-19T10:00:00Z"
},
{
"id": "550e8400-e29b-41d4-a716-446655440031",
"movement_type": "out",
"quantity": -10,
"location_name": "Warehouse A",
"reference": "Order #1001",
"created_at": "2024-01-18T15:30:00Z"
}
],
"active_reservations": [
{
"id": "550e8400-e29b-41d4-a716-446655440040",
"order_id": "550e8400-e29b-41d4-a716-446655440100",
"quantity": 5,
"location_name": "Warehouse A",
"expires_at": "2024-01-20T15:00:00Z"
}
],
"updated_at": "2024-01-20T14:30:00Z"
}
}
Adjust Inventory¶
Manually adjust inventory levels with audit trail.
Request Body¶
{
"product_id": "550e8400-e29b-41d4-a716-446655440000",
"variant_id": "550e8400-e29b-41d4-a716-446655440001",
"location_id": "550e8400-e29b-41d4-a716-446655440020",
"adjustment": -5,
"reason": "damaged",
"notes": "Water damage during storage",
"reference": "ADJ-2024-001"
}
Adjustment Reasons¶
| Reason | Description |
|---|---|
damaged |
Product damaged or defective |
lost |
Inventory lost or missing |
found |
Additional inventory found |
count |
Stock count correction |
return |
Customer return |
other |
Other reason (specify in notes) |
Required Fields¶
product_id- Product to adjustlocation_id- Location to adjustadjustment- Quantity to add (positive) or remove (negative)reason- Reason for adjustment
Example Response¶
{
"data": {
"movement_id": "550e8400-e29b-41d4-a716-446655440050",
"product_id": "550e8400-e29b-41d4-a716-446655440000",
"location_id": "550e8400-e29b-41d4-a716-446655440020",
"adjustment": -5,
"quantity_before": 100,
"quantity_after": 95,
"reason": "damaged",
"notes": "Water damage during storage",
"reference": "ADJ-2024-001",
"adjusted_by": "550e8400-e29b-41d4-a716-446655440200",
"created_at": "2024-01-20T14:30:00Z"
}
}
Set Inventory¶
Set absolute inventory quantity (useful for stock counts).
Request Body¶
{
"product_id": "550e8400-e29b-41d4-a716-446655440000",
"variant_id": "550e8400-e29b-41d4-a716-446655440001",
"location_id": "550e8400-e29b-41d4-a716-446655440020",
"quantity": 95,
"reason": "count",
"notes": "Monthly stock count",
"reference": "COUNT-2024-01"
}
Example Response¶
{
"data": {
"movement_id": "550e8400-e29b-41d4-a716-446655440051",
"product_id": "550e8400-e29b-41d4-a716-446655440000",
"location_id": "550e8400-e29b-41d4-a716-446655440020",
"quantity_before": 100,
"quantity_after": 95,
"adjustment": -5,
"reason": "count",
"notes": "Monthly stock count",
"reference": "COUNT-2024-01",
"adjusted_by": "550e8400-e29b-41d4-a716-446655440200",
"created_at": "2024-01-20T14:30:00Z"
}
}
Receive Stock¶
Receive incoming stock (inbound inventory).
Request Body¶
{
"product_id": "550e8400-e29b-41d4-a716-446655440000",
"variant_id": "550e8400-e29b-41d4-a716-446655440001",
"location_id": "550e8400-e29b-41d4-a716-446655440020",
"quantity": 50,
"cost_per_unit": "12.50",
"reference": "PO-2024-001",
"notes": "Received from supplier"
}
Example Response¶
{
"data": {
"movement_id": "550e8400-e29b-41d4-a716-446655440052",
"product_id": "550e8400-e29b-41d4-a716-446655440000",
"location_id": "550e8400-e29b-41d4-a716-446655440020",
"movement_type": "in",
"quantity": 50,
"quantity_before": 100,
"quantity_after": 150,
"cost_per_unit": "12.50",
"reference": "PO-2024-001",
"notes": "Received from supplier",
"created_at": "2024-01-20T14:30:00Z"
}
}
Reserve Stock¶
Reserve stock for an order. Reservations expire automatically after the configured timeout (default: 30 minutes).
Request Body¶
{
"product_id": "550e8400-e29b-41d4-a716-446655440000",
"variant_id": "550e8400-e29b-41d4-a716-446655440001",
"location_id": "550e8400-e29b-41d4-a716-446655440020",
"order_id": "550e8400-e29b-41d4-a716-446655440100",
"quantity": 5
}
Required Fields¶
product_id- Product to reservelocation_id- Location to reserve fromorder_id- Order to reserve forquantity- Quantity to reserve
Example Response¶
{
"data": {
"reservation_id": "550e8400-e29b-41d4-a716-446655440060",
"product_id": "550e8400-e29b-41d4-a716-446655440000",
"variant_id": "550e8400-e29b-41d4-a716-446655440001",
"location_id": "550e8400-e29b-41d4-a716-446655440020",
"order_id": "550e8400-e29b-41d4-a716-446655440100",
"quantity": 5,
"status": "active",
"expires_at": "2024-01-20T15:00:00Z",
"created_at": "2024-01-20T14:30:00Z"
}
}
Release Reservation¶
Release a stock reservation (e.g., when order is cancelled).
Request Body¶
Release Reasons¶
| Reason | Description |
|---|---|
order_cancelled |
Order was cancelled |
order_expired |
Reservation expired |
manual_release |
Manually released by admin |
order_completed |
Order completed (reservation converted) |
Example Response¶
{
"data": {
"reservation_id": "550e8400-e29b-41d4-a716-446655440060",
"status": "released",
"released_at": "2024-01-20T14:35:00Z",
"reason": "order_cancelled"
}
}
Transfer Inventory¶
Transfer stock between locations.
Request Body¶
{
"product_id": "550e8400-e29b-41d4-a716-446655440000",
"variant_id": "550e8400-e29b-41d4-a716-446655440001",
"from_location_id": "550e8400-e29b-41d4-a716-446655440020",
"to_location_id": "550e8400-e29b-41d4-a716-446655440021",
"quantity": 10,
"reference": "TF-2024-001",
"notes": "Restock retail location"
}
Example Response¶
{
"data": {
"transfer_id": "550e8400-e29b-41d4-a716-446655440070",
"product_id": "550e8400-e29b-41d4-a716-446655440000",
"from_location_id": "550e8400-e29b-41d4-a716-446655440020",
"to_location_id": "550e8400-e29b-41d4-a716-446655440021",
"quantity": 10,
"status": "completed",
"reference": "TF-2024-001",
"notes": "Restock retail location",
"created_at": "2024-01-20T14:30:00Z",
"completed_at": "2024-01-20T14:30:00Z"
}
}
Stock Movements¶
List Stock Movements¶
Retrieve a paginated list of stock movements.
Query Parameters¶
| Parameter | Type | Description |
|---|---|---|
page |
integer | Page number (default: 1) |
per_page |
integer | Items per page (default: 20, max: 100) |
product_id |
UUID | Filter by product |
location_id |
UUID | Filter by location |
movement_type |
string | Filter by in, out, return, lost, found, transfer |
start_date |
datetime | Movements after date |
end_date |
datetime | Movements before date |
reference |
string | Filter by reference number |
sort |
string | created_at (default) |
order |
string | asc or desc (default: desc) |
Example Request¶
GET /api/v1/inventory/movements?product_id=550e8400-e29b-41d4-a716-446655440000&movement_type=in
Authorization: Bearer sk_live_xxx
Example Response¶
{
"data": [
{
"id": "550e8400-e29b-41d4-a716-446655440030",
"product_id": "550e8400-e29b-41d4-a716-446655440000",
"product_name": "Premium Cotton T-Shirt",
"variant_id": null,
"location_id": "550e8400-e29b-41d4-a716-446655440020",
"location_name": "Warehouse A",
"quantity": 50,
"movement_type": "in",
"cost_per_unit": "12.50",
"reference": "PO-2024-001",
"notes": "Received from supplier",
"created_at": "2024-01-19T10:00:00Z"
},
{
"id": "550e8400-e29b-41d4-a716-446655440031",
"product_id": "550e8400-e29b-41d4-a716-446655440000",
"product_name": "Premium Cotton T-Shirt",
"variant_id": null,
"location_id": "550e8400-e29b-41d4-a716-446655440020",
"location_name": "Warehouse A",
"quantity": -10,
"movement_type": "out",
"cost_per_unit": null,
"reference": "Order #1001",
"notes": "Customer order fulfillment",
"created_at": "2024-01-18T15:30:00Z"
}
],
"meta": {
"pagination": {
"total": 45,
"per_page": 20,
"current_page": 1,
"total_pages": 3,
"has_next": true,
"has_prev": false
}
}
}
Movement Types¶
| Type | Description |
|---|---|
in |
Stock received |
out |
Stock sold or removed |
return |
Customer return |
lost |
Stock lost or damaged |
found |
Additional stock found |
transfer |
Stock transferred between locations |
Low Stock Alerts¶
List Low Stock Alerts¶
Retrieve low stock alerts for products below their threshold.
Query Parameters¶
| Parameter | Type | Description |
|---|---|---|
page |
integer | Page number (default: 1) |
per_page |
integer | Items per page (default: 20, max: 100) |
alert_level |
string | Filter by low or critical |
product_id |
UUID | Filter by specific product |
location_id |
UUID | Filter by specific location |
acknowledged |
boolean | Filter by acknowledgment status |
sort |
string | created_at, alert_level |
order |
string | asc or desc (default: desc) |
Example Request¶
Example Response¶
{
"data": [
{
"alert_id": "550e8400-e29b-41d4-a716-446655440080",
"product_id": "550e8400-e29b-41d4-a716-446655440000",
"product_name": "Premium Cotton T-Shirt",
"current_stock": 5,
"threshold": 20,
"alert_level": "critical",
"recommended_reorder_quantity": 95,
"locations_affected": [
{
"location_id": "550e8400-e29b-41d4-a716-446655440020",
"location_name": "Warehouse A",
"current_stock": 3,
"alert_level": "critical"
},
{
"location_id": "550e8400-e29b-41d4-a716-446655440021",
"location_name": "Warehouse B",
"current_stock": 2,
"alert_level": "critical"
}
],
"acknowledged": false,
"created_at": "2024-01-20T14:30:00Z"
}
],
"meta": {
"pagination": {
"total": 12,
"per_page": 20,
"current_page": 1,
"total_pages": 1,
"has_next": false,
"has_prev": false
}
}
}
Acknowledge Alert¶
Acknowledge a low stock alert.
Request Body¶
Example Response¶
{
"data": {
"alert_id": "550e8400-e29b-41d4-a716-446655440080",
"acknowledged": true,
"acknowledged_by": "550e8400-e29b-41d4-a716-446655440200",
"acknowledged_at": "2024-01-20T15:00:00Z",
"notes": "Reorder placed with supplier"
}
}
Alert Levels¶
| Level | Description |
|---|---|
low |
Stock below threshold but above critical level (50% of threshold) |
critical |
Stock below critical level (50% of threshold) |
Inventory Locations¶
List Locations¶
Retrieve all inventory locations.
Query Parameters¶
| Parameter | Type | Description |
|---|---|---|
page |
integer | Page number (default: 1) |
per_page |
integer | Items per page (default: 20, max: 100) |
is_active |
boolean | Filter by active status |
Example Response¶
{
"data": [
{
"id": "550e8400-e29b-41d4-a716-446655440020",
"name": "Warehouse A",
"code": "WH-A",
"address": "123 Industrial Blvd, Warehouse District",
"is_active": true,
"created_at": "2024-01-01T00:00:00Z"
},
{
"id": "550e8400-e29b-41d4-a716-446655440021",
"name": "Warehouse B",
"code": "WH-B",
"address": "456 Commerce St, Business Park",
"is_active": true,
"created_at": "2024-01-01T00:00:00Z"
}
],
"meta": {
"pagination": {
"total": 2,
"per_page": 20,
"current_page": 1,
"total_pages": 1,
"has_next": false,
"has_prev": false
}
}
}
Get Location¶
Retrieve details for a specific location.
Query Parameters¶
| Parameter | Type | Description |
|---|---|---|
include_inventory |
boolean | Include inventory summary |
Example Response¶
{
"data": {
"id": "550e8400-e29b-41d4-a716-446655440020",
"name": "Warehouse A",
"code": "WH-A",
"address": "123 Industrial Blvd, Warehouse District",
"is_active": true,
"inventory_summary": {
"total_products": 156,
"total_value": "45000.00",
"low_stock_count": 12,
"out_of_stock_count": 3
},
"created_at": "2024-01-01T00:00:00Z"
}
}
Error Codes¶
| Code | HTTP Status | Description |
|---|---|---|
PRODUCT_NOT_FOUND |
404 | Product does not exist |
LOCATION_NOT_FOUND |
404 | Inventory location does not exist |
INSUFFICIENT_STOCK |
400 | Not enough stock available for operation |
INVALID_ADJUSTMENT |
400 | Adjustment would result in negative inventory |
RESERVATION_NOT_FOUND |
404 | Stock reservation does not exist |
RESERVATION_EXPIRED |
409 | Reservation has already expired |
INVALID_MOVEMENT_TYPE |
400 | Invalid movement type specified |
INVALID_TRANSFER |
400 | Cannot transfer to same location |
ALERT_NOT_FOUND |
404 | Low stock alert does not exist |
ALERT_ALREADY_ACKNOWLEDGED |
409 | Alert already acknowledged |
Webhooks¶
The Inventory API emits the following webhook events:
| Event | Description |
|---|---|
inventory.adjusted |
Inventory manually adjusted |
inventory.received |
Stock received |
inventory.transferred |
Stock transferred between locations |
inventory.reserved |
Stock reserved for order |
inventory.reservation_released |
Reservation released |
inventory.reservation_expired |
Reservation expired |
inventory.low_stock |
Stock below threshold |
inventory.critical_stock |
Stock below critical level |
inventory.out_of_stock |
Stock reached zero |
inventory.movement.created |
Stock movement recorded |
Configuration¶
Inventory Settings¶
Configure inventory behavior in your application settings:
[inventory]
low_stock_threshold = 20 # Default low stock threshold (%)
enable_restock_alerts = true # Enable automatic restock alerts
enable_reservations = true # Enable stock reservations
reservation_timeout_minutes = 30 # Reservation timeout
Reservation Behavior¶
- Reservations are created with
activestatus - Reservations automatically expire after the configured timeout
- Expired reservations can be cleaned up via the API or automatically
- When an order is completed, reservations are converted to actual stock reduction
- When an order is cancelled, reservations should be released