Artikel lesen und pflegen

Schritt-für-Schritt-Anleitung zum Auflisten, Anlegen, Ändern und Löschen von Artikeln über die X-Sitter API – Felder, Kategorien, Varianten, Abgleich mit deinem eigenen System

Mit den Artikel-Adressen der API hältst du deine Artikelstammdaten in X-Sitter aktuell, ohne sie von Hand zu pflegen: neue Artikel aus deinem Shop oder ERP anlegen, Namen, EANs oder Gewichte ändern, Artikel deaktivieren. Den Bestand liest du über eine eigene Adresse, siehe Bestand abfragen.

Was Methode und Adresse Recht des Tokens
Artikel auflisten und suchen GET /api/v1/articles Artikel: lesen
Ein Artikel mit allen Feldern GET /api/v1/articles/{id} Artikel: lesen
Artikel anlegen POST /api/v1/articles Artikel: anlegen
Artikel ändern PATCH /api/v1/articles/{id} Artikel: ändern
Artikel löschen DELETE /api/v1/articles/{id} Artikel: löschen (nur Logistiker)

Schritt 1: Token mit den richtigen Rechten anlegen

Wie du einen Token anlegst, steht in der Übersicht. Hake für Artikel unter Artikel nur an, was dein System wirklich tut:

  • Nur lesen (z. B. die Artikelliste in dein ERP holen): lesen
  • Artikel aus deinem Shop übertragen: lesen, anlegen und ändern

X-Sitter bietet diese Rechte nur an, wenn dein Benutzer die Artikelübersicht öffnen (für lesen) bzw. Artikel bearbeiten darf (für anlegen und ändern). Löschen steht Mandanten nicht zur Verfügung: Es bleibt beim Logistiker, der deine Artikel verwaltet.

Schritt 2: Die Felder kennenlernen

Ein Artikel in X-Sitter besteht aus ein paar festen Angaben und beliebig vielen Feldern (Attributen) wie Name, EAN, Gewicht oder Zolltarifnummer. Welche Felder es gibt, legt dein Logistiker fest. Jedes Feld hat einen technischen Namen, den Slug (z. B. name, ean, weight). Mit diesem Slug liest und schreibst du den Wert.

Am einfachsten siehst du alle Felder, wenn du einen beliebigen einzelnen Artikel abfragst. Die ID bekommst du aus der Liste (Schritt 3):

curl "https://app.x-sitter.com/api/v1/articles/01999a3c-7e41-7b2a-9d0e-3f6c2a1b4e57" \
  -H "Authorization: Bearer xst_YOUR_TOKEN"
{
  "data": {
    "id": "01999a3c-7e41-7b2a-9d0e-3f6c2a1b4e57",
    "sku": "SKU-100",
    "active": true,
    "company_id": 12,
    "managing_company_id": null,
    "owner_company_id": 27,
    "attributes": [
      { "slug": "name", "label": "Name", "type": "text", "value": "Orange juice 1 l" },
      { "slug": "ean", "label": "EAN", "type": "text", "value": "4260000000017" },
      { "slug": "weight", "label": "Gewicht", "type": "number", "value": "1.05" },
      { "slug": "color", "label": "Farbe", "type": "select", "value": null }
    ],
    "categories": [
      { "id": "01999a3c-2222-7b2a-9d0e-3f6c2a1b4e57", "name": "Juices", "path": "Beverages > Juices", "is_main": true }
    ],
    "groups": ["Beverages"],
    "added_at": "2026-09-30 10:12:44",
    "updated_at": "2026-10-06 08:01:13"
  }
}
Feld Bedeutung
id Eindeutige ID des Artikels in X-Sitter. Speichere sie in deinem System, damit du den Artikel später direkt ändern kannst.
sku Die Artikelnummer.
active Ob der Artikel aktiv ist.
company_id Firmennummer des Logistikers, der den Artikel verwaltet.
owner_company_id Firmennummer des Mandanten, dem der Artikel gehört. null bei Artikeln des Logistikers selbst.
managing_company_id Technische Angabe, für eine Anbindung nicht nötig.
attributes Alle Felder des Logistikers mit Slug, Bezeichnung, Typ und dem Wert dieses Artikels (null = kein Wert). Die Bezeichnung ist die, die dein Logistiker dem Feld gegeben hat.
categories Die Kategorien des Artikels mit ID und Pfad. is_main kennzeichnet die Hauptkategorie.
groups Die Namen der Artikelgruppen, zu denen der Artikel gehört.
added_at, updated_at Wann der Artikel angelegt und zuletzt geändert wurde.

Notiere dir die Slugs der Felder, die dein System füllen soll. Fehlt dir ein Feld, bitte deinen Logistiker, es anzulegen. Felder lassen sich nicht über die API anlegen.

Schritt 3: Artikel auflisten und suchen

curl "https://app.x-sitter.com/api/v1/articles?per_page=100&fields=name,ean" \
  -H "Authorization: Bearer xst_YOUR_TOKEN"

In der Liste kommen die Felder kompakt als "slug": "value":

{
  "data": [
    {
      "id": "01999a3c-7e41-7b2a-9d0e-3f6c2a1b4e57",
      "sku": "SKU-100",
      "active": true,
      "company_id": 12,
      "managing_company_id": null,
      "owner_company_id": 27,
      "attributes": { "name": "Orange juice 1 l", "ean": "4260000000017" },
      "added_at": "2026-09-30 10:12:44",
      "updated_at": "2026-10-06 08:01:13"
    }
  ],
  "meta": { "page": 1, "per_page": 100, "total": 312, "total_pages": 4 }
}

Als Mandant siehst du nur deine eigenen Artikel, als Logistiker alle Artikel, die du verwaltest. Die Liste kommt seitenweise; wie du alle Seiten abrufst, zeigt Bestand abfragen, Schritt 5. Tausch einfach die Adresse aus.

Parameter Beispiel Wirkung
fields fields=name,ean,weight Welche Felder jeder Eintrag mitbringt (Slugs durch Kommas getrennt). Ohne den Parameter bekommst du die Standardfelder, die dein Logistiker eingestellt hat.
q q=Orange Sucht den Text in der Artikelnummer und in allen Feldwerten (Teiltreffer).
attribute[slug] attribute[ean]=4260000000017 Nur Artikel, bei denen das Feld genau diesen Wert hat. Mehrere Filter werden kombiniert.
active active=true Nur aktive (true) oder nur inaktive (false) Artikel.
category category=01999a3c-2222-… Nur Artikel dieser Kategorie und ihrer Unterkategorien.
sort sort=added Sortierung: sku (Standard), added (Anlagedatum) oder der Slug eines Felds.
direction direction=desc asc (Standard) oder desc.
page, per_page per_page=500 Seite und Einträge je Seite (Standard 25, höchstens 500).

Einen Artikel über seine EAN finden:

curl -G "https://app.x-sitter.com/api/v1/articles" \
  -H "Authorization: Bearer xst_YOUR_TOKEN" \
  --data-urlencode "attribute[ean]=4260000000017"

Schritt 4: Artikel anlegen

Schick die Angaben als JSON. Pflicht ist nur die Artikelnummer sku, alles andere ist optional.

curl -X POST "https://app.x-sitter.com/api/v1/articles" \
  -H "Authorization: Bearer xst_YOUR_TOKEN" \
  -H "Content-Type: application/json" \
  -d '{
    "sku": "SKU-200",
    "active": true,
    "attributes": {
      "name": "Apple juice 1 l",
      "ean": "4260000000024",
      "weight": "1.05"
    },
    "categories": ["01999a3c-2222-7b2a-9d0e-3f6c2a1b4e57"]
  }'
<?php
$token = 'xst_YOUR_TOKEN';
$article = [
    'sku' => 'SKU-200',
    'active' => true,
    'attributes' => [
        'name' => 'Apple juice 1 l',
        'ean' => '4260000000024',
        'weight' => '1.05',
    ],
];

$ch = curl_init('https://app.x-sitter.com/api/v1/articles');
curl_setopt_array($ch, [
    CURLOPT_RETURNTRANSFER => true,
    CURLOPT_POST => true,
    CURLOPT_HTTPHEADER => ['Authorization: Bearer ' . $token, 'Content-Type: application/json'],
    CURLOPT_POSTFIELDS => json_encode($article),
]);
$result = json_decode(curl_exec($ch), true);
$status = curl_getinfo($ch, CURLINFO_HTTP_CODE);
curl_close($ch);

echo $status === 201 ? 'Created: ' . $result['data']['id'] : 'Error: ' . $result['error']['code'];
import requests

token = "xst_YOUR_TOKEN"
article = {
    "sku": "SKU-200",
    "active": True,
    "attributes": {"name": "Apple juice 1 l", "ean": "4260000000024", "weight": "1.05"},
}

response = requests.post(
    "https://app.x-sitter.com/api/v1/articles",
    json=article,
    headers={"Authorization": f"Bearer {token}"},
    timeout=30,
)
result = response.json()
print(result["data"]["id"] if response.status_code == 201 else result["error"])

Die Antwort hat den Status 201 und enthält den neuen Artikel in derselben Form wie in Schritt 2, einschließlich seiner id. Speichere die ID in deinem System.

Angabe Pflicht Bedeutung
sku ja Artikelnummer, höchstens 255 Zeichen.
active nein true (Standard) oder false.
attributes nein Felder als "slug": "value". Nur Slugs, die beim Logistiker existieren, werden angenommen.
categories nein Liste von Kategorie-IDs. Die erste ist die Hauptkategorie. Die IDs siehst du in Schritt 2 unter categories[].id.
parent_id nein Für Varianten: die Nummer des Elternartikels, so wie dein System sie nennt (höchstens 52 Zeichen).
owner_company_id nein Nur Logistiker: Firmennummer des Mandanten, dem der Artikel gehört. Leer oder null = Artikel des Logistikers. Als Mandant lässt du das Feld weg; deine Artikel gehören automatisch dir.

So werden Feldwerte gespeichert:

  • Text: wie geschickt, führende und nachfolgende Leerzeichen werden entfernt.
  • Zahl: Komma und Punkt sind beide als Dezimaltrennzeichen erlaubt ("1,05" und 1.05). Alles, was keine Zahl ist, wird mit 422 invalid_article_value abgelehnt.
  • Ja/Nein: true oder false werden zu 1 und 0.
  • Mehrfachauswahl: als Liste, z. B. ["red", "blue"]; gespeichert als red;blue.
  • Auswahlfeld: Schick den gespeicherten Wert der Option, nicht ihren Anzeigetext.

Schritt 5: Artikel ändern

Mit PATCH änderst du nur, was du schickst. Alles andere bleibt, wie es ist.

curl -X PATCH "https://app.x-sitter.com/api/v1/articles/01999a3c-7e41-7b2a-9d0e-3f6c2a1b4e57" \
  -H "Authorization: Bearer xst_YOUR_TOKEN" \
  -H "Content-Type: application/json" \
  -d '{
    "attributes": {
      "ean": "4260000000031",
      "color": null
    }
  }'

Das Beispiel setzt eine neue EAN und entfernt den Wert des Felds color. Die Antwort enthält den Artikel nach der Änderung.

  • Ein Feld mit null (oder einem leeren Text) verliert seinen Wert.
  • categories ersetzt die komplette Liste. Willst du eine Kategorie hinzufügen, schick die vorhandenen mit.
  • Einen Artikel deaktivierst du mit {"active": false}. Er behält alle seine Daten und kann jederzeit wieder aktiviert werden.
  • Auch die Artikelnummer lässt sich ändern ({"sku": "SKU-200-NEW"}), solange die neue noch nicht vergeben ist.

Schritt 6: Dein System mit X-Sitter abgleichen

Für einen regelmäßigen Abgleich aus deinem Shop oder ERP hat sich dieses Vorgehen bewährt:

  1. Für jeden Artikel aus deinem System: Kennst du schon seine X-Sitter-id? Dann schick ein PATCH mit den geänderten Feldern.
  2. Kennst du sie nicht, schick ein POST.
  3. Bekommst du 409 article_number_taken, existiert der Artikel schon. Nimm die ID aus details.existing_id, speichere sie und schick ein PATCH.
import requests

BASE = "https://app.x-sitter.com/api/v1/articles"
HEADERS = {"Authorization": "Bearer xst_YOUR_TOKEN"}


def upsert(article: dict, known_id: str | None) -> str:
    """Create or change one article, return its X-Sitter id."""
    if known_id is None:
        response = requests.post(BASE, json=article, headers=HEADERS, timeout=30)
        if response.status_code == 201:
            return response.json()["data"]["id"]
        error = response.json()["error"]
        if error["code"] != "article_number_taken":
            raise RuntimeError(f"{error['code']}: {error['message']}")
        known_id = error["details"]["existing_id"]

    changes = {key: value for key, value in article.items() if key != "sku"}
    response = requests.patch(f"{BASE}/{known_id}", json=changes, headers=HEADERS, timeout=30)
    if not response.ok:
        error = response.json()["error"]
        raise RuntimeError(f"{error['code']}: {error['message']}")
    return known_id

Schick nur Artikel, die sich seit dem letzten Abgleich geändert haben, nicht jedes Mal den kompletten Katalog.

Schritt 7: Artikel löschen (nur Logistiker)

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

Die Antwort hat den Status 204 ohne Inhalt.

Für Logistiker: Artikel für einen Mandanten pflegen

Schick die Firmennummer des Mandanten im Header X-Company. Dann siehst du nur die Artikel dieses Mandanten, und neue Artikel gehören automatisch ihm:

curl -X POST "https://app.x-sitter.com/api/v1/articles" \
  -H "Authorization: Bearer xst_YOUR_TOKEN" \
  -H "X-Company: 27" \
  -H "Content-Type: application/json" \
  -d '{"sku": "SKU-300", "attributes": {"name": "Grape juice 1 l"}}'

Ohne X-Company kannst du den Eigentümer auch mit owner_company_id angeben. Dieselbe Artikelnummer darf es einmal beim Logistiker und einmal bei jedem Mandanten geben.

Wenn etwas nicht funktioniert

Antwort Ursache Lösung
403 scope_missing Dem Token fehlt das Recht (lesen, anlegen, ändern oder löschen). Lege einen neuen Token mit dem nötigen Recht an.
400 invalid_json Der Body ist kein gültiges JSON-Objekt. Prüfe das JSON (Anführungszeichen, Kommas) und schick Content-Type: application/json.
400 invalid_parameter Ein Listen-Parameter hat das falsche Format, z. B. active=maybe. Siehe die Tabelle in Schritt 3.
404 article_not_found Die ID existiert nicht oder der Artikel gehört nicht zu deiner Firma. Nimm die ID aus einer aktuellen Antwort.
409 article_number_taken Die Artikelnummer existiert schon. Ändere den vorhandenen Artikel aus details.existing_id (Schritt 6).
409 article_in_use Der Artikel hat noch Bestand und kann nicht gelöscht werden. Deaktiviere ihn, statt ihn zu löschen.
422 invalid_article_value Ein Wert passt nicht, z. B. ein Feld, das es nicht gibt, keine Zahl in einem Zahlenfeld, eine unbekannte Kategorie oder eine fehlende sku. Die message nennt das Feld. Vergleiche die Slugs mit Schritt 2.

Alle Fehler und Rechte auf einen Blick findest du in der Übersicht.