Master Inventory Management with API
Master multi-location inventory management with the NoPOS Inventory API. This comprehensive tutorial covers everything from basic tracking to advanced automation.
Prerequisites
- NoPOS API credentials
- Node.js 18+ installed
- Basic understanding of REST APIs
- Multiple locations configured in your account
Inventory Data Model
Understanding the inventory structure:
const inventoryItem = {
product_id: "prod_123",
variant_id: "var_456",
locations: [
{
location_id: "loc_001",
quantity: 150,
reserved: 10,
available: 140,
reorder_point: 20,
reorder_quantity: 100
},
{
location_id: "loc_002",
quantity: 75,
reserved: 5,
available: 70,
reorder_point: 15,
reorder_quantity: 50
}
],
total_quantity: 225,
total_available: 210
};Basic Inventory Operations
Get Current Inventory
Retrieve inventory for a product:
async function getInventory(productId) {
const response = await fetch(
`https://api.nopos.dev/v1/inventory/products/${productId}`,
{
headers: {
'Authorization': 'Bearer YOUR_API_KEY'
}
}
);
return await response.json();
}Update Inventory
Adjust stock levels:
async function updateInventory(productId, locationId, adjustment) {
const response = await fetch(
`https://api.nopos.dev/v1/inventory/adjust`,
{
method: 'POST',
headers: {
'Authorization': 'Bearer YOUR_API_KEY',
'Content-Type': 'application/json'
},
body: JSON.stringify({
product_id: productId,
location_id: locationId,
adjustment: adjustment,
reason: 'stock_receipt',
notes: 'Weekly delivery'
})
}
);
return await response.json();
}Stock Transfers
Transfer Between Locations
Move inventory from one location to another:
async function transferStock(productId, fromLocation, toLocation, quantity) {
const response = await fetch(
'https://api.nopos.dev/v1/inventory/transfer',
{
method: 'POST',
headers: {
'Authorization': 'Bearer YOUR_API_KEY',
'Content-Type': 'application/json'
},
body: JSON.stringify({
product_id: productId,
from_location_id: fromLocation,
to_location_id: toLocation,
quantity: quantity,
notes: 'Rebalancing stock'
})
}
);
return await response.json();
}Stock Alerts
Configure Alert Thresholds
Set up automated low stock alerts:
async function configureAlerts(productId, locationId, threshold) {
const response = await fetch(
'https://api.nopos.dev/v1/inventory/alerts',
{
method: 'POST',
headers: {
'Authorization': 'Bearer YOUR_API_KEY',
'Content-Type': 'application/json'
},
body: JSON.stringify({
product_id: productId,
location_id: locationId,
reorder_point: threshold,
reorder_quantity: threshold * 5,
alert_emails: ['inventory@example.com']
})
}
);
return await response.json();
}Listen for Low Stock Webhooks
Handle low stock notifications:
app.post('/webhooks/low-stock', async (req, res) => {
const { product_id, location_id, current_quantity, reorder_point } = req.body;
console.log(`Low stock alert: Product ${product_id} at ${location_id}`);
console.log(`Current: ${current_quantity}, Reorder point: ${reorder_point}`);
// Trigger automatic reorder
await createPurchaseOrder(product_id, location_id);
res.status(200).send('OK');
});Automated Reordering
Create Purchase Orders
Automatically generate purchase orders:
async function createPurchaseOrder(productId, locationId) {
// Get product details and supplier
const product = await getProduct(productId);
const inventory = await getInventory(productId);
const location = inventory.locations.find(l => l.location_id === locationId);
const po = await fetch(
'https://api.nopos.dev/v1/purchase-orders',
{
method: 'POST',
headers: {
'Authorization': 'Bearer YOUR_API_KEY',
'Content-Type': 'application/json'
},
body: JSON.stringify({
supplier_id: product.supplier_id,
location_id: locationId,
items: [
{
product_id: productId,
quantity: location.reorder_quantity,
unit_cost: product.cost_price
}
],
notes: 'Auto-generated from low stock alert'
})
}
);
return await po.json();
}Inventory Valuation
Calculate Total Inventory Value
Track inventory value across locations:
async function calculateInventoryValue() {
const inventory = await fetch(
'https://api.nopos.dev/v1/inventory/valuation',
{
headers: {
'Authorization': 'Bearer YOUR_API_KEY'
}
}
);
const data = await inventory.json();
return {
total_units: data.total_units,
total_value: data.total_value,
by_location: data.locations.map(loc => ({
location_name: loc.name,
units: loc.units,
value: loc.value
}))
};
}Stock Movements Report
Track All Inventory Changes
Generate comprehensive movement reports:
async function getStockMovements(startDate, endDate) {
const response = await fetch(
`https://api.nopos.dev/v1/inventory/movements?start=${startDate}&end=${endDate}`,
{
headers: {
'Authorization': 'Bearer YOUR_API_KEY'
}
}
);
const movements = await response.json();
return movements.map(m => ({
date: m.created_at,
product: m.product_name,
location: m.location_name,
type: m.movement_type, // sale, adjustment, transfer, receipt
quantity: m.quantity,
user: m.user_name
}));
}Barcode Management
Generate Barcodes
Create barcodes for products:
async function generateBarcode(productId, type = 'EAN13') {
const response = await fetch(
'https://api.nopos.dev/v1/products/barcode',
{
method: 'POST',
headers: {
'Authorization': 'Bearer YOUR_API_KEY',
'Content-Type': 'application/json'
},
body: JSON.stringify({
product_id: productId,
barcode_type: type
})
}
);
return await response.json();
}Best Practices
1. Implement Audit Trails
Always track who made inventory changes:
const adjustment = {
product_id: productId,
quantity: adjustmentQty,
user_id: currentUser.id,
reason: 'inventory_count',
notes: 'Physical count reconciliation',
timestamp: new Date().toISOString()
};2. Use Transactions
Group related inventory changes:
// When selling multiple items, update all inventory atomicallytry {
for (const item of orderItems) {
await updateInventory(item.product_id, locationId, -item.quantity);
}
await commitTransaction(transaction);
} catch (error) {
await rollbackTransaction(transaction);
throw error;
}
`
3. Regular Cycle Counts
Implement periodic inventory verification:
async function scheduleCycleCount(locationId, frequency = 'weekly') {
// Schedule regular physical counts
const products = await getHighValueProducts(locationId);
for (const product of products) {
await createCountTask({
product_id: product.id,
location_id: locationId,
scheduled_date: getNextCountDate(frequency),
assigned_to: 'inventory_team'
});
}
}Troubleshooting
Inventory Discrepancies
When physical counts don't match system:
- Check recent movements for the product
- Verify all transactions completed successfully
- Look for failed webhook deliveries
- Review audit logs for manual adjustments
- Perform full reconciliation
Performance Optimization
For large inventories:
- Use pagination for inventory lists
- Implement caching for frequently accessed data
- Batch updates when possible
- Use webhooks instead of polling
Next Steps
- Set up [real-time webhooks](/blog/webhook-event-system)
- Integrate with [accounting software](https://developer.nopos.dev/integrations/accounting)
- Implement [demand forecasting](https://developer.nopos.dev/analytics/forecasting)
Visit the Developer Portal for complete inventory API documentation.
Ready to dive deeper?
Explore our comprehensive API documentation and code examples.