Checking Inventory

Checking Inventory Guide

This guide explains how to query real-time inventory levels using the Spreetail Channel Integration API.

Overview

The inventory endpoint allows you to check stock availability, quantities, and product information in real-time. This is essential for:

  • Validating orders before creation
  • Displaying accurate stock levels to customers
  • Managing product availability
  • Planning restocking

Endpoint

GET /inventory

Full URL: https://api.spreetaileu.com/api/api/v1/inventory

Authentication

Requires Bearer token authentication. See the Authentication Guide for details.

Query Parameters

ParameterTypeRequiredDescription
pageintegerNoPage number to retrieve (default: 1, minimum: 1)
page_sizeintegerNoItems per page (default: 25, minimum: 1, maximum: 200)
ℹ️

Note: The inventory returned is automatically filtered based on your authenticated client. Your JWT token determines which inventory you can see. Each client has specific warehouse locations and SKU prefixes configured.

Examples

Get All Inventory (First Page)

GET https://api.spreetaileu.com/api/api/v1/inventory
Authorization: Bearer <your-token>

Paginated Results

GET https://api.spreetaileu.com/api/api/v1/inventory?page=1&page_size=50
Authorization: Bearer <your-token>

Response Format

Success Response (200)

{
  "success": true,
  "data": {
    "client_name": "BBG",
    "total_inventory": 500,
    "total_count_of_skus": 50,
    "location_count": 2,
    "locations": [
      {
        "location_name": "BBG Integration PS",
        "location_filter": "3050db4c-2422-4457-b8f5-d2e8fcd3af5a",
        "keyword": "BBG",
        "total_inventory": 250,
        "total_count_of_skus": 25,
        "sku_count_in_page": 25,
        "has_more": false,
        "sku": [
          {
            "sku": "PROD-12345",
            "Height": 10.5,
            "Width": 20,
            "Depth": 15,
            "Weight": 1.5,
            "StockLevel": 100,
            "InOrderBook": 20,
            "Available": 80,
            "LastUpdateDate": "2025-10-29T10:00:00Z",
            "LastUpdateOperation": "Stock adjustment"
          },
          {
            "sku": "PROD-67890",
            "Height": 5,
            "Width": 10,
            "Depth": 8,
            "Weight": 0.5,
            "StockLevel": 0,
            "InOrderBook": 0,
            "Available": 0,
            "LastUpdateDate": "2025-10-29T09:15:00Z",
            "LastUpdateOperation": "Stock adjustment"
          }
        ]
      }
    ]
  },
  "pagination": {
    "current_page": 1,
    "page_size": 25,
    "has_more": true,
    "next_page": 2
  }
}

Response Fields

FieldTypeDescription
client_namestringAuthenticated client name
total_inventoryintegerGrand total inventory count across all locations and SKUs
total_count_of_skusintegerTotal number of unique SKUs across all locations
location_countintegerNumber of warehouse locations for this client
locationsarrayInventory breakdown by warehouse location
locations[].location_namestringHuman-readable location name
locations[].location_filterstringLinnworks location UUID filter
locations[].keywordstringSKU search keyword for this location
locations[].total_inventoryintegerTotal inventory for this specific location
locations[].total_count_of_skusintegerTotal number of unique SKUs for this location on this page
locations[].sku_count_in_pageintegerNumber of SKUs returned in this page for this location
locations[].has_morebooleanWhether this location has more pages available
locations[].sku[]arrayDetailed per-SKU inventory information
locations[].sku[].skustringSKU/Part Number
locations[].sku[].HeightnumberProduct height
locations[].sku[].WidthnumberProduct width
locations[].sku[].DepthnumberProduct depth
locations[].sku[].WeightnumberProduct weight
locations[].sku[].StockLevelintegerCurrent stock level at this location
locations[].sku[].InOrderBookintegerQuantity allocated to orders
locations[].sku[].AvailableintegerAvailable quantity (StockLevel - InOrderBook)
locations[].sku[].LastUpdateDatestring (ISO 8601)Last inventory update timestamp
locations[].sku[].LastUpdateOperationstringLast inventory operation

Code Examples

Python

import requests

def get_inventory(access_token, page=1, page_size=25):
    """Get inventory information"""
    url = "https://api.spreetaileu.com/api/api/v1/inventory"
    headers = {
        "Authorization": f"Bearer {access_token}"
    }
    params = {
        "page": page,
        "page_size": page_size
    }
    
    response = requests.get(url, headers=headers, params=params)
    response.raise_for_status()
    return response.json()

# Get first page of inventory
inventory = get_inventory(access_token, page=1, page_size=50)
print(f"Total inventory: {inventory['data']['total_inventory']}")
print(f"Total SKUs: {inventory['data']['total_count_of_skus']}")

# Iterate through locations
for location in inventory['data']['locations']:
    print(f"\nLocation: {location['location_name']}")
    print(f"SKUs in this location: {location['total_count_of_skus']}")
    for sku_item in location['sku']:
        print(f"  {sku_item['sku']}: {sku_item['Available']} available (Total: {sku_item['StockLevel']})")

JavaScript/Node.js

async function getInventory(accessToken, page = 1, pageSize = 25) {
  const url = new URL('https://api.spreetaileu.com/api/api/v1/inventory');
  url.searchParams.append('page', page);
  url.searchParams.append('page_size', pageSize);
  
  const response = await fetch(url, {
    headers: {
      'Authorization': `Bearer ${accessToken}`
    }
  });
  
  if (!response.ok) {
    const error = await response.json();
    throw new Error(`Inventory check failed: ${error.error || response.statusText}`);
  }
  
  return await response.json();
}

// Get first page of inventory
const inventory = await getInventory(accessToken, 1, 50);
console.log(`Total inventory: ${inventory.data.total_inventory}`);
console.log(`Total SKUs: ${inventory.data.total_count_of_skus}`);

// Iterate through locations
inventory.data.locations.forEach(location => {
  console.log(`\nLocation: ${location.location_name}`);
  console.log(`SKUs in this location: ${location.total_count_of_skus}`);
  location.sku.forEach(skuItem => {
    console.log(`  ${skuItem.sku}: ${skuItem.Available} available (Total: ${skuItem.StockLevel})`);
  });
});

Use Cases

1. Validate Order Before Creation

def validate_order_items(access_token, order_items):
    """Check if all order items are in stock"""
    unavailable_items = []
    page = 1
    all_skus = {}
    
    # Collect all SKU data from all pages
    while True:
        inventory = get_inventory(access_token, page=page, page_size=200)
        
        # Build a map of all SKUs across all locations
        for location in inventory['data']['locations']:
            for sku_item in location['sku']:
                sku = sku_item['sku']
                if sku not in all_skus:
                    all_skus[sku] = {
                        'available': 0,
                        'stock_level': 0
                    }
                all_skus[sku]['available'] += sku_item['Available']
                all_skus[sku]['stock_level'] += sku_item['StockLevel']
        
        # Check if there are more pages
        if not inventory['pagination']['has_more']:
            break
        page = inventory['pagination']['next_page']
    
    # Validate order items
    for item in order_items:
        sku = item['SKU']
        required_qty = item['Qty']
        
        if sku not in all_skus:
            unavailable_items.append({
                'sku': sku,
                'reason': 'SKU not found'
            })
        elif all_skus[sku]['available'] < required_qty:
            unavailable_items.append({
                'sku': sku,
                'reason': f"Insufficient stock. Available: {all_skus[sku]['available']}, Required: {required_qty}"
            })
    
    return unavailable_items

# Before creating order
order_items = [
    {'SKU': 'PROD-12345', 'Qty': 2},
    {'SKU': 'PROD-67890', 'Qty': 1}
]

issues = validate_order_items(access_token, order_items)
if issues:
    print("Cannot create order - stock issues:")
    for issue in issues:
        print(f"  {issue['sku']}: {issue['reason']}")
else:
    print("All items in stock - proceeding with order creation")

2. Monitor Low Stock

def check_low_stock(access_token, threshold=10):
    """Find items with low stock levels across all locations"""
    low_stock_items = []
    page = 1
    
    while True:
        inventory = get_inventory(access_token, page=page, page_size=200)
        
        for location in inventory['data']['locations']:
            for sku_item in location['sku']:
                if sku_item['Available'] <= threshold:
                    low_stock_items.append({
                        'sku': sku_item['sku'],
                        'location': location['location_name'],
                        'available': sku_item['Available'],
                        'stock_level': sku_item['StockLevel']
                    })
        
        if not inventory['pagination']['has_more']:
            break
        page = inventory['pagination']['next_page']
    
    return low_stock_items

low_stock = check_low_stock(access_token, threshold=10)
if low_stock:
    print(f"Warning: {len(low_stock)} items below threshold")
    for item in low_stock:
        print(f"  {item['sku']} ({item['location']}): {item['available']} available")

3. Get All Inventory Across All Pages

def get_all_inventory(access_token):
    """Retrieve all inventory items across all pages"""
    all_skus = []
    page = 1
    
    while True:
        inventory = get_inventory(access_token, page=page, page_size=200)
        
        # Collect SKUs from all locations
        for location in inventory['data']['locations']:
            all_skus.extend(location['sku'])
            print(f"Page {page}, Location {location['location_name']}: {len(location['sku'])} SKUs")
        
        # Check if there are more pages
        if not inventory['pagination']['has_more']:
            break
        
        page = inventory['pagination']['next_page']
    
    return all_skus

# Get complete inventory
complete_inventory = get_all_inventory(access_token)
print(f"Total SKUs retrieved: {len(complete_inventory)}")

Pagination

The inventory endpoint supports efficient pagination:

  • Default: page=1, page_size=25
  • Maximum: page_size=200
  • Performance: Typical response time is 2-5 seconds per request
  • Recommended: Start with page_size=25-50 for best performance

Each location in the response includes a has_more field indicating if more data is available for that location. The top-level pagination object indicates if any location has more pages.

Error Handling

def safe_get_inventory(access_token, page=1, page_size=25):
    """Get inventory with error handling"""
    try:
        return get_inventory(access_token, page=page, page_size=page_size)
    except requests.exceptions.HTTPError as e:
        if e.response.status_code == 401:
            raise Exception("Authentication failed. Token may be expired.")
        elif e.response.status_code == 400:
            error_data = e.response.json()
            raise Exception(f"Inventory check failed: {error_data.get('error', 'Bad request')}")
        else:
            raise Exception(f"Inventory check failed: {e}")

Best Practices

  1. Use Pagination: For large inventories, use pagination with page_size=25-50 for optimal performance
  2. Check Before Orders: Always validate stock before creating orders
  3. Cache Results: Inventory data can be cached for a few minutes to reduce API calls
  4. Monitor Updates: Check LastUpdateDate timestamp to ensure data freshness
  5. Respect Rate Limits: Don't poll inventory too frequently
  6. Handle Multiple Locations: Remember that inventory is organized by warehouse locations

Performance Notes

  • Typical response time: 2-5 seconds per request
  • Pagination: Handled efficiently by Linnworks API
  • Recommended page_size: 25-50 for best balance of performance and data volume
  • Multiple locations: Each client may have multiple warehouse locations, each with its own SKU set

Related Endpoints

  • POST /outbound - Create orders (check inventory first)
  • POST /inbound - Register inbound deliveries (affects inventory)