Inventory & Products | Products | Stock | Get Products Stock

Getting Product Stock Data

This document outlines the procedure for making API calls to retrieve product stock data from https://easycms.fi/public_api/get_products_stock/.

Important Note

The pid (Product ID) parameter is MANDATORY for this endpoint. You must provide at least one valid product ID to retrieve stock data.

Multi-Value Parameters

All filter parameters (pid, location_id, shelf_id) accept three input formats for flexibility:

Format Example Description
Single value pid=5 Returns data for one product
Array pid[]=5&pid[]=10&pid[]=15 Returns data for multiple products
JSON array pid=[5,10,15] Same as array, sent as JSON string

This allows you to query stock for multiple products, locations, or shelves in a single API call — reducing round trips and simplifying integration code.

Combining Multi-Value Filters

When multiple filters use arrays, they are combined with AND logic. For example:

  • pid=[1,2]&location_id=[5,8] → stock for products 1 and 2 at locations 5 and 8
  • pid=123&location_id=5&shelf_id=[1,3,7] → stock for product 123 at location 5 on shelves 1, 3, and 7

Product Stock Data Retrieval

Fetch product stock data for all locations/shelves or filter by specific locations and shelves.

Endpoint and Method

  • Endpoint: https://easycms.fi/public_api/get_products_stock/
  • Method: GET or POST

Parameters | Payload

  • TOKEN (api_key): Your unique API key for authentication. How to Create API Credentials.
  • username: Your login username.
  • password: Your login password.
  • account: Your specific account ID.

Required Parameter

  • pid: Product ID (MANDATORY) — The ID(s) of the product(s) to retrieve stock for. Accepts single integer, array, or JSON array (see Multi-Value Parameters above).

Optional Filter Parameters

  • location_id: Filter results by location ID(s). Accepts single integer, array, or JSON array. When provided, returns stock only for the specified location(s).
  • shelf_id: Filter results by shelf ID(s). Accepts single integer, array, or JSON array. Note: Requires location_id to be provided as well.

Pagination Parameters

  • start - Specify the starting point of the row from which to begin fetching stock data (default: 0).
  • limit - Control the number of stock records returned in a single request (default: 50, max: 50).



Call Examples in Different Languages


# Get all stock for a single product
curl -X POST 'https://easycms.fi/public_api/get_products_stock' \
-H 'Authorization1: TOKEN' \
-d 'username=USERNAME&password=PASSWORD&account=ACCOUNT_ID&pid=12345'

# Get stock for a specific location
curl -X POST 'https://easycms.fi/public_api/get_products_stock' \
-H 'Authorization1: TOKEN' \
-d 'username=USERNAME&password=PASSWORD&account=ACCOUNT_ID&pid=12345&location_id=1'

# Get stock for a specific location and shelf
curl -X POST 'https://easycms.fi/public_api/get_products_stock' \
-H 'Authorization1: TOKEN' \
-d 'username=USERNAME&password=PASSWORD&account=ACCOUNT_ID&pid=12345&location_id=1&shelf_id=5'

# Get stock for MULTIPLE products (array format)
curl -X POST 'https://easycms.fi/public_api/get_products_stock' \
-H 'Authorization1: TOKEN' \
-d 'username=USERNAME&password=PASSWORD&account=ACCOUNT_ID&pid[]=12345&pid[]=67890&pid[]=11111'

# Get stock for MULTIPLE products (JSON format)
curl -X POST 'https://easycms.fi/public_api/get_products_stock' \
-H 'Authorization1: TOKEN' \
-d 'username=USERNAME&password=PASSWORD&account=ACCOUNT_ID&pid=[12345,67890,11111]'

# Get stock for MULTIPLE locations (all shelves in each)
curl -X POST 'https://easycms.fi/public_api/get_products_stock' \
-H 'Authorization1: TOKEN' \
-d 'username=USERNAME&password=PASSWORD&account=ACCOUNT_ID&pid=12345&location_id=[1,2,5]'

# Get stock for multiple products at multiple locations
curl -X POST 'https://easycms.fi/public_api/get_products_stock' \
-H 'Authorization1: TOKEN' \
-d 'username=USERNAME&password=PASSWORD&account=ACCOUNT_ID&pid=[12345,67890]&location_id=[1,2]'

# Get stock for specific shelves across locations
curl -X POST 'https://easycms.fi/public_api/get_products_stock' \
-H 'Authorization1: TOKEN' \
-d 'username=USERNAME&password=PASSWORD&account=ACCOUNT_ID&pid=12345&location_id=[1,2]&shelf_id=[3,5]'

$curl = curl_init();
curl_setopt_array($curl, array(
  CURLOPT_URL => "https://easycms.fi/public_api/get_products_stock",
  CURLOPT_RETURNTRANSFER => true,
  CURLOPT_POST => true,
  CURLOPT_POSTFIELDS => http_build_query([
    'username' => 'USERNAME', 
    'password' => 'PASSWORD', 
    'account' => 'ACCOUNT_ID',
    'pid' => [12345, 67890],         // multiple products
    'location_id' => [1, 2],         // multiple locations (optional)
    'shelf_id' => [3, 5]             // multiple shelves (optional)
  ]),
  CURLOPT_HTTPHEADER => array("Authorization1: TOKEN"),
));
$response = curl_exec($curl);
curl_close($curl);
echo $response;

import requests
url = "https://easycms.fi/public_api/get_products_stock"
headers = {"Authorization1": "TOKEN"}
payload = {
    'username': 'USERNAME', 
    'password': 'PASSWORD', 
    'account': 'ACCOUNT_ID',
    'pid[]': [12345, 67890],           # multiple products (array format)
    'location_id[]': [1, 2],           # multiple locations (optional)
    'shelf_id[]': [3, 5]               # multiple shelves (optional)
}
response = requests.post(url, headers=headers, data=payload)
print(response.text)

HttpClient client = HttpClient.newHttpClient();
// Multiple products and locations using array format
String formData = "username=USERNAME&password=PASSWORD&account=ACCOUNT_ID"
    + "&pid[]=12345&pid[]=67890"
    + "&location_id[]=1&location_id[]=2";
HttpRequest request = HttpRequest.newBuilder()
    .uri(URI.create("https://easycms.fi/public_api/get_products_stock"))
    .headers("Authorization1", "TOKEN")
    .POST(HttpRequest.BodyPublishers.ofString(formData))
    .build();
HttpResponse response = client.send(request, HttpResponse.BodyHandlers.ofString());
System.out.println(response.body());

const https = require('https');
const params = new URLSearchParams({
  username: 'USERNAME', 
  password: 'PASSWORD', 
  account: 'ACCOUNT_ID',
  // Multiple products as JSON array
  pid: JSON.stringify([12345, 67890]),
  // Multiple locations as JSON array
  location_id: JSON.stringify([1, 2])
});
const options = {
  hostname: 'easycms.fi',
  path: '/public_api/get_products_stock',
  method: 'POST',
  headers: {
    'Authorization1': 'TOKEN',
    'Content-Type': 'application/x-www-form-urlencoded',
    'Content-Length': Buffer.byteLength(params.toString())
  }
};
const req = https.request(options, (res) => {
  let data = '';
  res.on('data', (chunk) => { data += chunk; });
  res.on('end', () => { console.log(data); });
});
req.on('error', (e) => { console.error(e); });
req.write(params.toString());
req.end();

import React, { useEffect, useState } from 'react';
function App() {
  const [stockData, setStockData] = useState('');
  useEffect(() => {
    const fetchData = async () => {
      try {
        const response = await fetch('https://easycms.fi/public_api/get_products_stock', {
          method: 'POST',
          headers: {'Authorization1': 'TOKEN', 'Content-Type': 'application/x-www-form-urlencoded'},
          body: new URLSearchParams({
            username: 'USERNAME', 
            password: 'PASSWORD', 
            account: 'ACCOUNT_ID',
            pid: JSON.stringify([12345, 67890]),
            location_id: JSON.stringify([1, 2])
          }).toString()
        });
        const data = await response.text();
        setStockData(data);
      } catch (error) {
        console.error(error);
      }
    };
    fetchData();
  }, []);
  return (<div>{stockData}</div>);
}
export default App;

import okhttp3.OkHttpClient
import okhttp3.FormBody
import okhttp3.Request

fun main() {
    val client = OkHttpClient()

    // Multiple products using array format
    val formBody = FormBody.Builder()
        .add("username", "USERNAME")
        .add("password", "PASSWORD")
        .add("account", "ACCOUNT_ID")
        .add("pid[]", "12345")
        .add("pid[]", "67890")
        .add("location_id[]", "1")
        .add("location_id[]", "2")
        .build()

    val request = Request.Builder()
        .url("https://easycms.fi/public_api/get_products_stock")
        .post(formBody)
        .addHeader("Authorization1", "TOKEN")
        .build()

    client.newCall(request).execute().use { response ->
        if (!response.isSuccessful) throw IOException("Unexpected code $response")
        println(response.body?.string())
    }
}

using System;
using System.Net.Http;
using System.Threading.Tasks;
class Program
{
    static async Task Main()
    {
        var token = "TOKEN";
        // Multiple products and locations
        var content = new FormUrlEncodedContent(new[]
        {
            new KeyValuePair("username", "USERNAME"),
            new KeyValuePair("password", "PASSWORD"),
            new KeyValuePair("account", "ACCOUNT_ID"),
            new KeyValuePair("pid[]", "12345"),
            new KeyValuePair("pid[]", "67890"),
            new KeyValuePair("location_id[]", "1"),
            new KeyValuePair("location_id[]", "2")
        });
        using (var httpClient = new HttpClient())
        {
            httpClient.DefaultRequestHeaders.Add("Authorization1", token);
            var response = await httpClient.PostAsync("https://easycms.fi/public_api/get_products_stock", content);
            if (response.IsSuccessStatusCode)
            {
                var responseData = await response.Content.ReadAsStringAsync();
                Console.WriteLine(responseData);
            }
            else
            {
                Console.WriteLine($"Error: {response.StatusCode}");
            }
        }
    }
}




Handling Endpoint Results

When you make a request to the endpoint, you receive a JSON response containing various keys and values. Here's an explanation of the response keys and their meanings:


- `start`: This represents the starting index for the data. In this case, it's set to 0, indicating that the data starts from the first item.

- `limit`: The maximum number of items returned in the response. In this example, the limit is set to 50, meaning that the response will include up to 50 items.

- `count`: The number of items included in the current response. In this case, there are 4 items in the response.

- `total_count`: The total count of items available in the dataset. In this response, there is a total of 4 items available.

- `WHERE`: The filter conditions applied to the query. Shows which pids, location_ids, and shelf_ids were used.

    

- `pid`: The product ID for this stock entry.
- `location_id`: The unique identifier for the location/warehouse.
- `location_name`: The name of the location/warehouse.
- `shelf_id`: The unique identifier for the shelf within the location.
- `shelf_name`: The name of the shelf.
- `stock`: The current stock quantity at this location/shelf combination.
- `best_before_date`: The best before date for the stock at this location (YYYY-MM-DD format, null if not set).
- `default_location`: Flag indicating if this is the default location for the product (1 = yes, 0 = no).
- `location_shelf_combo_id`: A combined identifier in format "location_id-shelf_id" for easy reference.

These key-value pairs provide comprehensive information about the product stock across all locations and can be used for inventory management in your application.
    

{
  "INFO": {
    "start": 0,
    "limit": 50,
    "count": 4,
    "total_count": 4,
    "WHERE": "pid IN (12345, 67890) AND location_id IN (1, 2)"
  },
  "OUTPUT": [
    {
      "pid": 12345,
      "location_id": 1,
      "location_name": "Main Warehouse",
      "shelf_id": 5,
      "shelf_name": "Shelf A1",
      "stock": 150.5,
      "best_before_date": "2025-12-31",
      "default_location": 1,
      "location_shelf_combo_id": "1-5"
    },
    {
      "pid": 12345,
      "location_id": 2,
      "location_name": "Secondary Warehouse",
      "shelf_id": 3,
      "shelf_name": "Shelf B2",
      "stock": 50.0,
      "best_before_date": "2025-06-30",
      "default_location": 0,
      "location_shelf_combo_id": "2-3"
    },
    {
      "pid": 67890,
      "location_id": 1,
      "location_name": "Main Warehouse",
      "shelf_id": 2,
      "shelf_name": "Shelf A2",
      "stock": 200.0,
      "best_before_date": null,
      "default_location": 1,
      "location_shelf_combo_id": "1-2"
    },
    {
      "pid": 67890,
      "location_id": 2,
      "location_name": "Secondary Warehouse",
      "shelf_id": 1,
      "shelf_name": "Shelf B1",
      "stock": 75.0,
      "best_before_date": "2026-03-15",
      "default_location": 0,
      "location_shelf_combo_id": "2-1"
    }
  ]
}
      

Error Handling

Here are the possible error messages and their meanings:

Error Code HTTP Status Description
pid_parameter_is_required 400 The pid parameter is required
pid_must_be_a_valid_positive_integer_or_array 400 The pid must be a valid integer or array of integers
product_not_found_pid_{N} 404 The product with the specified pid does not exist
location_id_must_be_a_valid_positive_integer_or_array 400 location_id must be valid integer(s)
location_not_found_id_{N} 404 The specified location does not exist
shelf_id_must_be_a_valid_positive_integer_or_array 400 shelf_id must be valid integer(s)
location_id_is_required_when_shelf_id_is_provided 400 shelf_id cannot be used without location_id
shelf_not_found_id_{N} 404 The specified shelf does not exist
UN-AUTHORIZED 401 Incorrect username or password
this_account_does_not_exist_or_your_credentials_do_not_match_this_account 401 The account doesn't exist or mismatched credentials
Maximum query size is 50 rows per query 400 Exceeded maximum limit of 50 rows per query

Error Response Example

{
  "status": "error",
  "error_code": "MISSING_PID",
  "message": "The pid parameter is required"
}

Empty Stock Response

When products exist but have no stock data:

{
  "INFO": {
    "start": 0,
    "limit": 50,
    "count": 0,
    "total_count": 0,
    "WHERE": "pid IN (12345, 67890)"
  },
  "OUTPUT": []
}

Use Cases

Get Stock for Multiple Products at Multiple Locations

Query stock for several products across multiple warehouses in a single call:

POST /get_products_stock?pid=[12345,67890]&location_id=[1,2]

Get Total Stock Across All Locations

To calculate the total stock for a product across all locations, omit location_id and sum the stock values:

const response = await getProductsStock({pid: 12345});
const totalStock = response.OUTPUT.reduce((sum, item) => sum + item.stock, 0);
console.log(`Total stock: ${totalStock}`);

Get Stock for Multiple Products Across All Locations

POST /get_products_stock?pid[]=12345&pid[]=67890&pid[]=11111

Check Stock at Specific Locations

Use location_id as an array to check stock at multiple warehouses:

POST /get_products_stock?pid=12345&location_id[]=1&location_id[]=2&location_id[]=5

Check Stock at Specific Shelves

Use both location_id and shelf_id with arrays to check specific shelves:

POST /get_products_stock?pid=12345&location_id=[1,2]&shelf_id=[3,5]

Find Default Location

Look for the item where default_location is 1 to find the primary stocking location for a product.

Pagination for Large Results

When querying many products/locations, results are limited to 50 rows. Use pagination:

POST /get_products_stock?pid=[1,2,3,4,5]&start=0&limit=50
POST /get_products_stock?pid=[1,2,3,4,5]&start=50&limit=50

Parameter Format Reference

Parameter Single Array JSON
pid pid=5 pid[]=5&pid[]=10 pid=[5,10]
location_id location_id=1 location_id[]=1&location_id[]=2 location_id=[1,2]
shelf_id shelf_id=3 shelf_id[]=3&shelf_id[]=5 shelf_id=[3,5]