Inventory
Inventory API
Access and manage inventory data for the authenticated store. The list endpoint returns product-level stock aggregates, while the single-product endpoint includes variant (SKU) details. Write endpoints allow setting or adjusting stock quantities.
List Inventory
Retrieve a paginated list of products with aggregated stock data.
GET /api/apps/v1/inventory
Authentication
Required. Must include valid app credentials.
Scope
read:inventory
Query Parameters
| Parameter | Type | Default | Description |
|---|---|---|---|
page | integer | 1 | Page number |
limit | integer | 50 | Items per page (max 250) |
sort | string | updated_at:desc | Sort results. Format: column:asc or column:desc. Allowed: updated_at, name, total_quantity |
status | string | -- | Filter by stock status: in_stock or out_of_stock |
search | string | -- | Search by product name |
Example Request
curl -X GET "https://api.selorax.io/api/apps/v1/inventory?page=1&limit=50" \
-H "Authorization: Bearer <token>"Filter out-of-stock products:
curl -X GET "https://api.selorax.io/api/apps/v1/inventory?status=out_of_stock&sort=name:asc" \
-H "Authorization: Bearer <token>"Or using client credentials:
curl -X GET "https://api.selorax.io/api/apps/v1/inventory?page=1&limit=50" \
-H "X-Client-Id: sx_app_..." \
-H "X-Client-Secret: sx_secret_..." \
-H "X-Store-Id: 22"Response
{
"data": [
{
"product_id": 150,
"name": "Premium Rose Bouquet",
"is_active": 1,
"updated_at": "2025-06-12T14:30:00.000Z",
"total_quantity": 37,
"variant_count": 3,
"has_stock": 1
},
{
"product_id": 149,
"name": "Seasonal Flower Basket",
"is_active": 1,
"updated_at": "2025-05-20T09:15:00.000Z",
"total_quantity": 0,
"variant_count": 2,
"has_stock": 0
}
],
"pagination": {
"page": 1,
"limit": 50,
"total": 2
},
"status": 200
}Response Fields
| Field | Type | Description |
|---|---|---|
product_id | integer | Product ID |
name | string | Product title |
is_active | integer (0 or 1) | Whether the product is active |
updated_at | string (ISO 8601) | When the product was last updated |
total_quantity | integer | Sum of stock across all variants |
variant_count | integer | Number of variant SKUs |
has_stock | integer (0 or 1) | Whether any stock is available |
Node.js Example
const response = await fetch(
"https://api.selorax.io/api/apps/v1/inventory?status=out_of_stock",
{ headers: { Authorization: "Bearer sx_at_..." } }
);
const { data } = await response.json();
const outOfStock = data.filter(p => p.has_stock === 0);
console.log(`${outOfStock.length} products are out of stock`);Python Example
import requests
response = requests.get(
"https://api.selorax.io/api/apps/v1/inventory",
headers={"Authorization": "Bearer sx_at_..."},
params={"sort": "total_quantity:asc", "limit": 100},
)
data = response.json()
for item in data["data"]:
status = "In Stock" if item["has_stock"] else "Out of Stock"
print(f"{item['name']}: {item['total_quantity']} units ({status})")Get Product Inventory
Retrieve inventory for a specific product, including all of its variant SKUs with stock data.
GET /api/apps/v1/inventory/:product_id
Authentication
Required. Must include valid app credentials.
Scope
read:inventory
Path Parameters
| Parameter | Type | Description |
|---|---|---|
product_id | integer | The product ID to retrieve inventory for |
Example Request
curl -X GET "https://api.selorax.io/api/apps/v1/inventory/150" \
-H "Authorization: Bearer <token>"Response
{
"data": {
"product_id": 150,
"name": "Premium Rose Bouquet",
"is_active": 1,
"updated_at": "2025-06-12T14:30:00.000Z",
"variants": [
{
"sku_id": 450,
"sku_code": "PRB-SM-RED",
"variant_name": "Small / Red",
"price": 500,
"quantity": 25,
"available": 1,
"is_default": 0
},
{
"sku_id": 451,
"sku_code": "PRB-LG-RED",
"variant_name": "Large / Red",
"price": 750,
"quantity": 12,
"available": 1,
"is_default": 1
},
{
"sku_id": 452,
"sku_code": "PRB-LG-WHT",
"variant_name": "Large / White",
"price": 750,
"quantity": 0,
"available": 0,
"is_default": 0
}
]
},
"status": 200
}Variant Fields
| Field | Type | Description |
|---|---|---|
sku_id | integer | SKU identifier |
sku_code | string | Human-readable SKU code |
variant_name | string | Variant option combination (e.g. "Large / Red") |
price | number | Current selling price |
quantity | integer | Stock quantity on hand |
available | integer (0 or 1) | Whether the variant is available for purchase |
is_default | integer (0 or 1) | Whether this is the product's default variant |
Error Responses
| Code | Status | Meaning |
|---|---|---|
invalid_token | 401 | Token is expired or invalid |
insufficient_scope | 403 | App does not have read:inventory scope |
If the product_id does not exist or does not belong to the authenticated store:
{
"message": "Product not found.",
"status": 404
}Update Stock
Set absolute stock levels for one or more variants of a product.
PUT /api/apps/v1/inventory/:product_id
Authentication
Required. Must include valid app credentials.
Scope
write:inventory
Path Parameters
| Parameter | Type | Description |
|---|---|---|
product_id | integer | The product ID to update stock for |
Request Body
| Field | Type | Required | Description |
|---|---|---|---|
variants | array | Yes | Array of variant stock updates |
variants[].sku_id | integer | Yes | The SKU ID to update |
variants[].quantity | integer | Yes | New absolute stock quantity (minimum 0) |
Example Request
curl -X PUT "https://api.selorax.io/api/apps/v1/inventory/150" \
-H "Authorization: Bearer <token>" \
-H "Content-Type: application/json" \
-d '{
"variants": [
{ "sku_id": 450, "quantity": 50 },
{ "sku_id": 451, "quantity": 20 },
{ "sku_id": 452, "quantity": 0 }
]
}'Response
{
"data": {
"product_id": 150,
"variants": [
{
"sku_id": 450,
"sku_code": "PRB-SM-RED",
"variant_name": "Small / Red",
"price": 500,
"quantity": 50,
"available": 1,
"is_default": 0
},
{
"sku_id": 451,
"sku_code": "PRB-LG-RED",
"variant_name": "Large / Red",
"price": 750,
"quantity": 20,
"available": 1,
"is_default": 1
},
{
"sku_id": 452,
"sku_code": "PRB-LG-WHT",
"variant_name": "Large / White",
"price": 750,
"quantity": 0,
"available": 0,
"is_default": 0
}
]
},
"message": "Inventory updated.",
"status": 200
}Webhook
This endpoint triggers an inventory.updated webhook event with the product ID and updated quantities.
Error Responses
| Code | Status | Meaning |
|---|---|---|
invalid_token | 401 | Token is expired or invalid |
insufficient_scope | 403 | App does not have write:inventory scope |
| -- | 400 | Validation error (missing variants array, invalid quantity) |
| -- | 404 | Product not found |
Adjust Stock
Apply a relative stock adjustment (add or subtract) to a single variant. Uses an atomic database update to prevent race conditions.
POST /api/apps/v1/inventory/:product_id/adjust
Authentication
Required. Must include valid app credentials.
Scope
write:inventory
Path Parameters
| Parameter | Type | Description |
|---|---|---|
product_id | integer | The product ID containing the variant |
Request Body
| Field | Type | Required | Description |
|---|---|---|---|
sku_id | integer | Yes | The SKU ID to adjust |
adjustment | integer | Yes | Signed integer: positive to add stock, negative to subtract (cannot be 0) |
reason | string | No | Optional reason for the adjustment (max 255 characters) |
Example Request
Add 10 units:
curl -X POST "https://api.selorax.io/api/apps/v1/inventory/150/adjust" \
-H "Authorization: Bearer <token>" \
-H "Content-Type: application/json" \
-d '{
"sku_id": 452,
"adjustment": 10,
"reason": "Restock from supplier"
}'Subtract 3 units:
curl -X POST "https://api.selorax.io/api/apps/v1/inventory/150/adjust" \
-H "Authorization: Bearer <token>" \
-H "Content-Type: application/json" \
-d '{
"sku_id": 450,
"adjustment": -3,
"reason": "Damaged items removed"
}'Response
{
"data": {
"sku_id": 452,
"product_id": 150,
"previous_quantity": 0,
"quantity": 10,
"adjustment": 10,
"available": 1
},
"message": "Stock adjusted.",
"status": 200
}Response Fields
| Field | Type | Description |
|---|---|---|
sku_id | integer | The adjusted SKU |
product_id | integer | Parent product ID |
previous_quantity | integer | Stock before adjustment |
quantity | integer | Stock after adjustment |
adjustment | integer | The adjustment applied |
available | integer (0 or 1) | Updated availability flag |
Webhook
This endpoint triggers an inventory.updated webhook event with the SKU, previous quantity, new quantity, adjustment amount, and reason.
Negative Stock Prevention
If the adjustment would result in a negative quantity, the API returns a 400 error with code negative_quantity and does not modify the stock.
Error Responses
| Code | Status | Meaning |
|---|---|---|
invalid_token | 401 | Token is expired or invalid |
insufficient_scope | 403 | App does not have write:inventory scope |
negative_quantity | 400 | Adjustment would result in negative stock |
| -- | 400 | Validation error (missing sku_id, zero adjustment) |
| -- | 404 | Product or variant not found |
Negative quantity error:
{
"message": "Adjustment would result in negative quantity. Current: 5, adjustment: -8",
"code": "negative_quantity",
"status": 400
}