Query stock

Step by step guide to querying your stock through the X-Sitter API – create a token, first request, understand the response, fetch all pages

This guide shows you how to get your stock levels from X-Sitter into your own system, for example to keep the stock in your online shop or ERP up to date. All you need is a token and a tool that can send HTTP requests (cURL, Postman, PHP, Python, JavaScript …).

For each article you get how many pieces are in which warehouse. The stock query does not show on which storage location the goods are.

Step 1: Check the requirements

  • Your user has the menu entry Settings > API access (German: Einstellungen > API Zugang) in X-Sitter and may open the stock or product overview.
  • Clients only: your logistician has made the stock visible to you. This is the same setting that lets you see your stock in X-Sitter itself. Without it, X-Sitter does not even offer you the permission Stock: read for a token. X-Sitter switches this setting ("Show stock", Lagerbestand zeigen) on at your logistician's request, so please talk to your logistician.

Step 2: Create a token

  1. In X-Sitter, click your name in the top right corner, then Settings.
  2. Choose API access on the left.
  3. In the API token section, enter a Name, e.g. "Stock sync shop".
  4. Optional: set a date under Valid until.
  5. Under Stock (Bestand), tick only read (lesen). The stock query needs no other permission.
  6. Click Create token.
  7. Use copy to take the token that is shown (it starts with xst_) right away and store it safely in your system. It is shown only this one time.

Step 3: Send your first request

In the examples, replace xst_YOUR_TOKEN with your token. The first request fetches the first five articles with their stock:

curl "https://app.x-sitter.com/api/v1/stock?per_page=5" \
  -H "Authorization: Bearer xst_YOUR_TOKEN"
<?php
$token = 'xst_YOUR_TOKEN';

$ch = curl_init('https://app.x-sitter.com/api/v1/stock?per_page=5');
curl_setopt_array($ch, [
    CURLOPT_RETURNTRANSFER => true,
    CURLOPT_HTTPHEADER => ['Authorization: Bearer ' . $token],
]);
$body = curl_exec($ch);
$status = curl_getinfo($ch, CURLINFO_HTTP_CODE);
curl_close($ch);

$result = json_decode($body, true);
print_r($status === 200 ? $result['data'] : $result['error']);
import requests

token = "xst_YOUR_TOKEN"

response = requests.get(
    "https://app.x-sitter.com/api/v1/stock",
    params={"per_page": 5},
    headers={"Authorization": f"Bearer {token}"},
    timeout=30,
)
result = response.json()
print(result["data"] if response.ok else result["error"])
const token = 'xst_YOUR_TOKEN';

const response = await fetch('https://app.x-sitter.com/api/v1/stock?per_page=5', {
    headers: { Authorization: `Bearer ${token}` },
});
const result = await response.json();
console.log(response.ok ? result.data : result.error);

If you get an error instead of data, the section If something does not work will help.

Step 4: Understand the response

A response looks like this:

{
  "data": [
    {
      "article_id": "01999a3c-7e41-7b2a-9d0e-3f6c2a1b4e57",
      "sku": "SKU-100",
      "owner_company_id": 27,
      "quantity": 120,
      "quality_assurance": 8,
      "warehouses": [
        {
          "id": "01999a3c-1111-7b2a-9d0e-3f6c2a1b4e57",
          "name": "Erfurt",
          "quantity": 120,
          "quality_assurance": 8
        }
      ]
    }
  ],
  "meta": { "page": 1, "per_page": 5, "total": 312, "total_pages": 63 }
}
Field Meaning
article_id Unique ID of the article in X-Sitter. Use it later to query a single article (step 6).
sku Your article number. Use it to match the stock to your articles in your shop or ERP.
owner_company_id Company number of the client that owns the article. null for articles of the logistician itself.
quantity Pieces across all warehouses, including the pieces in quality assurance.
quality_assurance Of these, the pieces blocked by quality assurance (e.g. damaged or under inspection).
warehouses The same figures per warehouse with ID and name. Empty if the article has no stock.
meta Page, entries per page, total number of articles and pages.

Good to know:

  • The list contains all your articles, including those without stock (then quantity: 0 and empty warehouses). With in_stock=true you only get articles with stock (step 5).
  • The stock is what lies on the storage locations in the warehouse. Goods for open orders keep counting until they have been booked off their location in the warehouse.
  • The articles are sorted by article number.

Step 5: Fetch all pages

The list comes page by page, at most 500 articles per page. For a complete sync, request page after page until you reach total_pages.

<?php
$token = 'xst_YOUR_TOKEN';
$stock = [];
$page = 1;

do {
    $url = 'https://app.x-sitter.com/api/v1/stock?' . http_build_query(['page' => $page, 'per_page' => 500]);
    $ch = curl_init($url);
    curl_setopt_array($ch, [
        CURLOPT_RETURNTRANSFER => true,
        CURLOPT_HTTPHEADER => ['Authorization: Bearer ' . $token],
    ]);
    $result = json_decode(curl_exec($ch), true);
    $status = curl_getinfo($ch, CURLINFO_HTTP_CODE);
    curl_close($ch);

    if ($status !== 200) {
        throw new RuntimeException('X-Sitter API: ' . $result['error']['code']);
    }

    foreach ($result['data'] as $article) {
        // Sellable stock = all pieces minus the ones blocked by quality assurance
        $stock[$article['sku']] = $article['quantity'] - $article['quality_assurance'];
    }

    $page++;
} while ($page <= $result['meta']['total_pages']);

print_r($stock);
import requests

token = "xst_YOUR_TOKEN"
stock = {}
page = 1

while True:
    response = requests.get(
        "https://app.x-sitter.com/api/v1/stock",
        params={"page": page, "per_page": 500},
        headers={"Authorization": f"Bearer {token}"},
        timeout=30,
    )
    result = response.json()
    if not response.ok:
        raise RuntimeError(f"X-Sitter API: {result['error']['code']}")

    for article in result["data"]:
        # Sellable stock = all pieces minus the ones blocked by quality assurance
        stock[article["sku"]] = article["quantity"] - article["quality_assurance"]

    if page >= result["meta"]["total_pages"]:
        break
    page += 1

print(stock)
const token = 'xst_YOUR_TOKEN';
const stock = {};
let page = 1;
let totalPages = 1;

do {
    const url = new URL('https://app.x-sitter.com/api/v1/stock');
    url.search = new URLSearchParams({ page, per_page: 500 });

    const response = await fetch(url, { headers: { Authorization: `Bearer ${token}` } });
    const result = await response.json();
    if (!response.ok) {
        throw new Error(`X-Sitter API: ${result.error.code}`);
    }

    for (const article of result.data) {
        // Sellable stock = all pieces minus the ones blocked by quality assurance
        stock[article.sku] = article.quantity - article.quality_assurance;
    }

    totalPages = result.meta.total_pages;
    page++;
} while (page <= totalPages);

console.log(stock);

Narrow down the list

You can combine these parameters as you like:

Parameter Example Effect
q q=SKU-1 Only articles whose article number contains the text. So SKU-1 also finds SKU-10 and SKU-100; if needed, check for the exact sku in your program.
in_stock in_stock=true Only articles with at least one piece.
warehouse warehouse=01999a3c-1111-… Counts only the stock of this warehouse. The ID is in every response under warehouses[].id. Combined with in_stock=true you only get articles stored in this warehouse.
page page=2 Which page.
per_page per_page=500 Articles per page, default 25, at most 500.
curl "https://app.x-sitter.com/api/v1/stock?in_stock=true&per_page=100" \
  -H "Authorization: Bearer xst_YOUR_TOKEN"

Step 6: Query a single article

If you know the article_id (from an earlier response), you get the stock of exactly this article:

curl "https://app.x-sitter.com/api/v1/stock/01999a3c-7e41-7b2a-9d0e-3f6c2a1b4e57" \
  -H "Authorization: Bearer xst_YOUR_TOKEN"

The response has the same structure as one entry of the list, just directly under data and without meta. If you only have the article number, use the list with q=<article number> and pick the entry with the matching sku.

Step 7: Sync regularly

  • A complete sync every 15 to 60 minutes is enough for most shops. Do not poll every second; the figures only change when something is booked in the warehouse.
  • Use per_page=500 to need as few requests as possible.
  • Whether your system really uses the token can be seen in X-Sitter under Settings > API access in the column Last used.
  • If you set an expiry date, create a new token in good time and swap it in your system.

For logisticians: query a client's stock

As a logistician, your token shows the stock of all articles you manage, including those of your clients (recognisable by owner_company_id). If you only want the articles of one particular client, send its company number in the header X-Company:

curl "https://app.x-sitter.com/api/v1/stock?in_stock=true" \
  -H "Authorization: Bearer xst_YOUR_TOKEN" \
  -H "X-Company: 27"

The "Show stock" setting plays no role here; it only applies to tokens the client creates itself.

If something does not work

Response Cause Solution
401 missing_token The header Authorization is missing or misspelled. Send it exactly like this: Authorization: Bearer xst_... (one space between Bearer and the token).
401 invalid_token The token does not exist (any more), is locked or has expired. Check its status under Settings > API access, enable it if needed or create a new token. Do not cut anything off when copying.
403 scope_missing The token does not have the permission Stock: read. Create a new token with this permission (permissions cannot be changed afterwards).
403 stock_not_visible You are a client and your logistician has not (or no longer) made the stock visible to you. Ask your logistician to enable it.
403 company_not_allowed The header X-Company names a company the token may not work for. Leave out X-Company (clients never need it) or enter the correct company number.
404 article_not_found The article_id does not exist or the article does not belong to your company. Take the ID from a current response of the list.
404 route_not_found The address is wrong. Check for typos: https://app.x-sitter.com/api/v1/stock.
400 invalid_parameter page or per_page is not a whole number. Only send numbers, e.g. per_page=100.

You will find all errors and permissions at a glance in the overview. If you are stuck, contact support via Create ticket in the footer of X-Sitter. Send the time, the address and the response, but never your token.