API Dokumentation

v1

Vollstaendige Referenz der Priceivy REST API. Verwalte Produkte, Preise, Kategorien und mehr programmatisch.

Basis

Base URL

https://app.priceivy.com/api/v1

Format

Alle Requests und Responses verwenden application/json

Pagination

Alle Listen-Endpoints unterstuetzen offset-basierte und cursor-basierte Pagination:

FeldTypStatusBeschreibung
limitintegerOptionalAnzahl Ergebnisse pro Seite. Min: 1, Max: 1.000, Default: 50
offsetintegerOptionalAnzahl zu ueberspringender Ergebnisse. Min: 0, Max: 1.000.000, Default: 0
afterstringOptionalCursor-Pagination: next_cursor Wert der vorherigen Response (product external_id). Schneller als offset bei grossen Datenmengen. Wenn gesetzt, wird offset ignoriert.

Werte ausserhalb des gueltigen Bereichs werden automatisch auf den naechsten gueltigen Wert begrenzt (z.B. limit=2000 wird zu limit=500).

Die Response enthaelt immer ein pagination Objekt mit limit, offset, total und next_cursor. Bei Cursor-Pagination (after) kann total den Wert null haben, da der Count aus Performance-Gruenden uebersprungen wird. Nutze next_cursor als after Parameter im naechsten Request fuer effiziente Cursor-Pagination. Ergebnisse werden standardmaessig nach Erstelldatum sortiert (neueste zuerst).

Authentifizierung

Die API verwendet Bearer-Token-Authentifizierung. API-Keys koennen im Dashboard unter Einstellungen → API-Keys erstellt werden.

Format

Alle API-Keys beginnen mit dem Prefix rp_ (Legacy-Prefix, wird in zukuenftigen Versionen aktualisiert)

Header

Authorization: Bearer rp_dein_api_key
Sicherheitshinweis: API-Keys werden als SHA256-Hash gespeichert. Der vollstaendige Key wird nur bei der Erstellung einmalig angezeigt. Bewahre ihn sicher auf.

Auth-Fehlercodes

CodeBeschreibung
401Kein API-Key im Header oder Key ungueltig / nicht gefunden
403API-Key ist abgelaufen

Rate Limiting

Die API ist auf 100 Requests pro Minute pro API-Key limitiert (Sliding Window). Bei Ueberschreitung wird ein 429 Fehler zurueckgegeben. Die folgenden Headers werden in jeder API-Response mitgesendet, damit du deinen Verbrauch ueberwachen kannst:

HeaderBeschreibung
X-RateLimit-LimitMaximale Requests pro Zeitfenster
X-RateLimit-RemainingVerbleibende Requests im aktuellen Zeitfenster
X-RateLimit-ResetUnix-Timestamp wann das Limit zurueckgesetzt wird
Retry-AfterSekunden bis zum naechsten erlaubten Request (nur bei 429)
Tipp: Bei Bulk-Endpoints (z.B. Bulk-Upsert mit 1.000 Produkten) zaehlt der gesamte Request als 1 Request gegen das Limit. Nutze Bulk-Endpoints statt vieler einzelner Requests.

Produkte

Die Produkt-Endpoints ermoeglichen das vollstaendige Management deiner Produkte — inklusive Preise, Bilder, Identifier, Attribute und Kategorie-Zuordnungen. Produkte werden ueber ihre eindeutige external_id identifiziert (z.B. die Produkt-ID aus deinem Shopsystem wie Shopify, WooCommerce, etc.).

GET/v1/products

Gibt eine paginierte Liste aller Produkte zurueck, inklusive aller Sub-Daten (Preise, Bilder, Identifier, Attribute, Kategorien).

Query-Parameter

FeldTypStatusBeschreibung
limitintegerOptionalErgebnisse pro Seite (1–1.000, Default: 50)
offsetintegerOptionalAnzahl zu ueberspringender Ergebnisse (Default: 0)
afterstringOptionalCursor-Pagination: next_cursor Wert der vorherigen Response (external_id). Schneller als offset bei grossen Datenmengen.

Beispiel (Offset)

curl -X GET "https://app.priceivy.com/api/v1/products?limit=50&offset=0" \
  -H "Authorization: Bearer rp_dein_api_key"

Beispiel (Cursor-Pagination)

# Seite 2+ (next_cursor aus vorheriger Response verwenden)
curl -X GET "https://app.priceivy.com/api/v1/products?limit=50&after=WM-2024" \
  -H "Authorization: Bearer rp_dein_api_key"

Response (200)

{
  "data": [
    {
      "external_id": "WM-2024",
      "sku": "WM-2024",
      "name": "Wireless Maus Pro",
      "gtin": "4012345678901",
      "import_excluded": false,
      "export_excluded": false,
      "tax_rate_group_external_id": "mwst-standard",
      "created_at": "2025-01-15T10:30:00.000Z",
      "updated_at": "2025-01-15T10:30:00.000Z",
      "created_by": { "type": "api_key", "key_prefix": "rp_a1b2..." },
      "prices": [...],
      "images": [...],
      "identifiers": [...],
      "attributes": [...],
      "categories": [...],
      "quantity_tiers": [...]
    }
  ],
  "pagination": {
    "limit": 50,
    "offset": 0,
    "total": null,
    "next_cursor": "WM-2024"
  }
}
GET/v1/products/{external_id}

Gibt ein einzelnes Produkt per external_id zurueck, inklusive aller Sub-Daten.

Pfad-Parameter

FeldTypStatusBeschreibung
external_idstringPflichtEindeutige external_id des Produkts (URL-encoded)

Beispiel

curl -X GET "https://app.priceivy.com/api/v1/products/WM-2024" \
  -H "Authorization: Bearer rp_dein_api_key"

Response (200)

{
  "data": {
    "external_id": "WM-2024",
    "sku": "WM-2024",
    "name": "Wireless Maus Pro",
    "gtin": "4012345678901",
    "import_excluded": false,
    "export_excluded": false,
    "tax_rate_group_external_id": "mwst-standard",
    "created_at": "2025-01-15T10:30:00.000Z",
    "updated_at": "2025-01-15T10:30:00.000Z",
    "created_by": { "type": "api_key", "key_prefix": "rp_a1b2..." },
    "prices": [...],
    "images": [...],
    "identifiers": [...],
    "attributes": [...],
    "categories": [...],
    "quantity_tiers": [...]
  }
}
PUT/v1/products/{external_id}

Idempotenter Upsert per external_id. Erstellt das Produkt falls es nicht existiert (201) oder aktualisiert es (200). Alle Sub-Ressourcen werden bei Angabe vollstaendig ersetzt (Replace-All).

Pfad-Parameter

FeldTypStatusBeschreibung
external_idstringPflichtexternal_id des Produkts (URL-encoded)

Beispiel

curl -X PUT "https://app.priceivy.com/api/v1/products/WM-2024" \
  -H "Authorization: Bearer rp_dein_api_key" \
  -H "Content-Type: application/json" \
  -d '{
    "name": "Wireless Maus Pro v2",
    "sku": "WM-2024-V2",
    "import_excluded": false,
    "export_excluded": false,
    "prices": [
      {
        "price_type": "ek",
        "currency": "EUR",
        "price_net": 2499
      }
    ],
    "images": [
      {
        "url": "https://example.com/maus-pro-v2.jpg",
        "sort": 0
      }
    ]
  }'

Response (200 oder 201)

{
  "data": {
    "external_id": "WM-2024",
    "sku": "WM-2024-V2",
    "name": "Wireless Maus Pro v2",
    "gtin": null,
    "import_excluded": false,
    "export_excluded": false,
    "tax_rate_group_external_id": null,
    "created_at": "2025-01-15T10:30:00.000Z",
    "updated_at": "2025-01-16T08:00:00.000Z",
    "created_by": { "type": "api_key", "key_prefix": "rp_a1b2..." },
    "prices": [...],
    "images": [...],
    "identifiers": [...],
    "attributes": [...],
    "categories": [...],
    "quantity_tiers": [...]
  }
}
Hinweis: Bei Angabe von prices, images, identifiers, attributes, categories oder quantity_tiers werden alle bestehenden Eintraege ersetzt (Replace-All).
import_excluded: Wenn das Produkt import_excluded: true gesetzt hat, wird es nicht aktualisiert. Die Response enthaelt dann ein zusaetzliches warning-Feld:
{
  "data": { ... },
  "warning": "Produkt wurde nicht aktualisiert, da import_excluded aktiviert ist. Deaktiviere den Import-Ausschluss im Dashboard, um Aenderungen per API zuzulassen."
}
DELETE/v1/products/{external_id}

Loescht ein Produkt per external_id (Soft-Delete).

Pfad-Parameter

FeldTypStatusBeschreibung
external_idstringPflichtexternal_id des Produkts (URL-encoded)

Beispiel

curl -X DELETE "https://app.priceivy.com/api/v1/products/WM-2024" \
  -H "Authorization: Bearer rp_dein_api_key"

Response (200)

{
  "data": {
    "success": true
  }
}
Cascade beim Loeschen: Beim Loeschen eines Produkts werden alle zugehoerigen Sub-Daten (Preise, Bilder, Identifier, Attribute, Kategorie-Zuordnungen, Staffelpreise) automatisch soft-deleted.
POST/v1/products/bulk-upsert

Erstellt oder aktualisiert bis zu 1.000 Produkte per external_id in einem Request. Alle Items werden vorab validiert — bei Fehlern wird kein Item verarbeitet.

Beispiel

curl -X POST "https://app.priceivy.com/api/v1/products/bulk-upsert" \
  -H "Authorization: Bearer rp_dein_api_key" \
  -H "Content-Type: application/json" \
  -d '{
    "items": [
      {
        "external_id": "WM-2024",
        "name": "Wireless Maus Pro",
        "sku": "WM-PRO-2024",
        "import_excluded": true,
        "prices": [
          { "price_type": "ek", "currency": "EUR", "price_gross": 2379 }
        ]
      },
      {
        "external_id": "KB-2024",
        "name": "Mechanische Tastatur"
      }
    ]
  }'

Response (200)

{
  "summary": {
    "total": 2,
    "created": 1,
    "updated": 0,
    "failed": 0,
    "duplicates": 0,
    "skipped": 1
  },
  "errors": [],
  "skipped_external_ids": ["WM-2024"],
  "warnings": ["Einige Produkte wurden uebersprungen, da import_excluded aktiviert ist. Deaktiviere den Import-Ausschluss im Dashboard."]
}

Das optionale warnings-Array erscheint bei Sub-Daten-Teilfehlern und wenn Produkte wegen import_excluded uebersprungen wurden. Das skipped_external_ids-Array listet die external_ids der uebersprungenen Produkte auf.

Limit: Maximal 1.000 Items pro Request. Jedes Item benoetigt ein external_id Feld. Alle Items werden vorab validiert — bei Validierungsfehlern wird ein 422 mit allen Fehlern auf einmal zurueckgegeben. Soft-deleted Produkte werden bei erneutem Upsert automatisch reaktiviert.
import_excluded: Produkte mit import_excluded: true werden beim Bulk-Upsert komplett uebersprungen und in der Summary als skipped gezaehlt. Die skipped_external_ids im Response listen alle uebersprungenen Produkte auf. Um das Flag zurueckzusetzen, nutzen Sie das Dashboard.

Struktur-Validierung (422)

Wenn der Request-Body nicht die erwartete Struktur hat:

// items fehlt oder ist kein Array
{
  "error": "items muss als Array gesendet werden"
}

// Array leer oder mehr als 1.000 Items
{
  "error": "items muss zwischen 1 und 1000 Eintraegen enthalten"
}

Item-Validierungsfehler (422)

Alle Items werden vorab validiert. Bei Fehlern wird kein Item verarbeitet — stattdessen werden alle Fehler gesammelt und auf einmal zurueckgegeben:

{
  "error": "2 von 5 Items haben Validierungsfehler",
  "details": {
    "validation_errors": [
      {
        "index": 1,
        "external_id": null,
        "error": "external_id ist erforderlich"
      },
      {
        "index": 3,
        "external_id": "X",
        "error": "prices[0].price_type ist ungueltig"
      }
    ]
  }
}
Doppelte external_ids: Wenn im selben Batch mehrere Items die gleiche external_id haben, wird nur das letzte Item mit dieser external_id verarbeitet. Fruehere Duplikate werden im summary.duplicates-Zaehler erfasst und im errors-Array mit einem Hinweis aufgefuehrt.
POST/v1/products/bulk-delete

Loescht bis zu 1.000 Produkte per external_id in einem Request. Nicht gefundene external_ids werden mit Fehler markiert.

Beispiel

curl -X POST "https://app.priceivy.com/api/v1/products/bulk-delete" \
  -H "Authorization: Bearer rp_dein_api_key" \
  -H "Content-Type: application/json" \
  -d '{
    "external_ids": ["WM-2024", "KB-2024", "NICHT-VORHANDEN"]
  }'

Response (200)

{
  "summary": {
    "total": 3,
    "succeeded": 2,
    "failed": 1
  },
  "errors": [
    { "external_id": "NICHT-VORHANDEN", "error": "Produkt nicht gefunden" }
  ]
}

Das optionale warnings-Array erscheint nur, wenn bei Sub-Daten Teilfehler aufgetreten sind.

Limit: Maximal 1.000 external_ids pro Request.

Validierungsfehler-Response (422)

Bei ungueltigem Input wird der Request abgelehnt, bevor Items verarbeitet werden:

// external_ids ist kein Array
{
  "error": "external_ids muss als Array gesendet werden"
}

// Array leer oder mehr als 1.000 Items
{
  "error": "external_ids muss zwischen 1 und 1000 Eintraegen enthalten"
}

// Ein Item ist kein String oder leer (mit Index)
{
  "error": "external_ids[0] muss ein nicht-leerer String sein"
}
Warnings-Feld bei Bulk-Responses: Das optionale warnings-Array erscheint nur, wenn bei Sub-Daten (Preise, Bilder, Identifier, etc.) Teilfehler aufgetreten sind. Die Hauptoperation (Produkt erstellen/aktualisieren/loeschen) war trotzdem erfolgreich.

Payload-Schema

Das folgende Schema gilt fuer PUT-Requests und Bulk-Upsert Items auf Produkt-Endpoints.

Strikte Validierung: Unbekannte Felder im Body werden abgelehnt (422). Nur die unten aufgefuehrten Felder sind erlaubt.

Basis-Felder

FeldTypStatusBeschreibung
external_idstringPflichtEindeutige ID aus deinem System (bei Bulk-Upsert im Item, bei PUT im Pfad). Max. 255 Zeichen.
skustring | nullOptionalOptionale Artikelnummer (SKU). Max. 255 Zeichen.
namestring | nullOptionalProduktname. Max. 500 Zeichen.
gtinstring | nullOptionalGTIN / Barcode. Max. 255 Zeichen.
import_excludedbooleanOptionalWenn true, wird dieses Produkt bei Import-Vorgaengen (PUT, Bulk-Upsert) komplett uebersprungen — kein Feld wird aktualisiert. Im Bulk-Upsert zaehlt es als 'skipped'. Dieses Flag kann nur ueber das Dashboard zurueckgesetzt werden, nicht per API. Default: false.
export_excludedbooleanOptionalMarkiert das Produkt als vom Export ausgeschlossen. Dieses Flag wird gespeichert und in der API zurueckgegeben, hat aber aktuell keine automatische Auswirkung. Es kann von Ihrem System genutzt werden, um Produkte beim Export zu filtern. Default: false.
tax_rate_group_external_idstring | nullOptionalExternal ID einer existierenden Steuersatzgruppe. Sende null um die Zuordnung zu entfernen.

prices

Array von Preis-Objekten. Bei Angabe werden alle bestehenden Preise ersetzt. Eigene Typen sind weiterhin erlaubt. Max. 50 Eintraege pro Produkt.

Die folgenden Kern-Preistypen werden von Priceivy zur Kalkulation und in den Standard-Ansichten verwendet.
KeyBeschreibung
ek_currentAktueller Einkaufspreis
ek_averageDurchschnittlicher Einkaufspreis
ek_latest_inboundEK letzter Wareneingang
ek_oldest_inboundEK aeltester Wareneingang
ek_cheapest_supplierEK guenstigster Lieferant
ek_most_expensive_supplierEK teuerster Lieferant
ek_default_supplierEK Standardlieferant
rrpUnverbindliche Preisempfehlung (UVP)
msrpManufacturer's Suggested Retail Price
Die folgenden price_type-Werte werden von der API abgelehnt (HTTP 400). Bitte den empfohlenen kanonischen Typ verwenden.
Blacklisted KeyVerwende stattdessenGrund
uvprrpUnverbindliche Preisempfehlung (UVP)
ek_aktuellek_currentAktueller Einkaufspreis
ek_durchschnittek_averageDurchschnittlicher Einkaufspreis
ek_letzter_wareneingangek_latest_inboundEK letzter Wareneingang
ek_aeltester_wareneingangek_oldest_inboundEK aeltester Wareneingang
ek_guenstigster_lieferantek_cheapest_supplierEK guenstigster Lieferant
ek_teuerster_lieferantek_most_expensive_supplierEK teuerster Lieferant
ek_standardlieferantek_default_supplierEK Standardlieferant
FeldTypStatusBeschreibung
price_typestringPflichtPreistyp — Kern-Typen: "ek_current", "ek_average", "ek_latest_inbound", "ek_oldest_inbound", "ek_cheapest_supplier", "ek_most_expensive_supplier", "ek_default_supplier", "rrp", "msrp". Kern-Typen werden zur Kalkulation und Anzeige im Dashboard verwendet. Eigene Typen sind ebenfalls erlaubt. Max. 50 Zeichen. Blacklistete Typen (z.B. "uvp") werden abgelehnt — siehe Tabelle oben.
currencystringPflichtISO-4217 Waehrungscode (3 Grossbuchstaben, z.B. "EUR", "USD", "GBP"). Wird eine andere Waehrung als die Basiswaehrung der Plattform uebergeben, rechnet Priceivy bei jeder Kalkulation automatisch zum aktuellen Wechselkurs um. Unbekannte Waehrungen werden abgelehnt.
price_netinteger | nullOptionalNettopreis in Cent, nicht-negative Ganzzahl (z.B. 2499 fuer 24,99 EUR). Optional, aber mindestens price_net oder price_gross muss angegeben werden.
price_grossinteger | nullOptionalBruttopreis in Cent, nicht-negative Ganzzahl (z.B. 2974 fuer 29,74 EUR). Optional, aber mindestens price_net oder price_gross muss angegeben werden.

images

Array von Bild-Objekten. Bei Angabe werden alle bestehenden Bilder ersetzt. Max. 100 Eintraege pro Produkt. URLs muessen gueltige HTTP(S)-URLs sein.

FeldTypStatusBeschreibung
urlstringPflichtGueltige HTTP(S)-URL des Bildes (max. 2.048 Zeichen). Andere Protokolle (z.B. javascript:, data:) werden abgelehnt.
sortnumberOptionalSortierreihenfolge. Wenn nicht angegeben, wird der Array-Index (0, 1, 2, ...) als Default verwendet.

identifiers

Array von Key-Value-Paaren fuer zusaetzliche Produktkennungen. Bei Angabe werden alle bestehenden Identifier ersetzt. Eigene Keys sind weiterhin erlaubt. Max. 50 Eintraege pro Produkt.

Die folgenden Kern-Identifier werden von Priceivy zum automatischen Scraping verwendet (Preisvergleich auf Marktplaetzen wie Amazon, Idealo, eBay etc.).
KeyBeschreibung
asinAmazon Standard Identification Number
isbnInternational Standard Book Number
mpnManufacturer Part Number (Herstellernummer)
Die folgenden key-Werte werden von der API abgelehnt (HTTP 400). Bitte den empfohlenen kanonischen Key verwenden.
Blacklisted KeyVerwende stattdessenGrund
hanmpn als identifiers[].keyPriceivy-Standard fuer die Herstellernummer ist mpn.
skuTop-Level-Feld sku am Produktsku ist ein Kernfeld am Produkt, kein Identifier.
nameTop-Level-Feld name am Produktname ist ein Kernfeld am Produkt, kein Identifier.
gtinTop-Level-Feld gtin am Produktgtin ist ein Kernfeld am Produkt, kein Identifier.
FeldTypStatusBeschreibung
keystringPflichtSchluessel — Kern-Keys: "asin", "isbn", "mpn". Eigene Keys sind ebenfalls erlaubt. Max. 255 Zeichen. Blacklistete Keys ("han", "sku", "name", "gtin") werden abgelehnt — siehe Tabelle oben.
valuestringPflichtWert. Max. 2.000 Zeichen.

attributes

Array von Key-Value-Paaren fuer Produkteigenschaften (z.B. Farbe, Gewicht). Bei Angabe werden alle bestehenden Attribute ersetzt. Max. 200 Eintraege pro Produkt.

FeldTypStatusBeschreibung
keystringPflichtSchluessel (z.B. "farbe", "gewicht", "material"). Max. 255 Zeichen.
valuestring | numberPflichtWert. Max. 2.000 Zeichen. JSON-Zahlen sind erlaubt und werden als String gespeichert. Bei Keys vom Typ "number" muss der Wert dem Zahlformat entsprechen (Punkt als Dezimaltrenner, z.B. "1.05") — sonst faellt nur dieses Produkt als failed aus dem Bulk.
value_type"text" | "number"OptionalOptional: setzt den org-weiten Typ dieses Attribut-Keys. Attribute vom Typ "number" koennen in Kalkulationsformeln verrechnet und numerisch gefiltert werden (>, <, >=, <=). Fehlt das Feld, bleibt der gespeicherte Typ unveraendert (KEIN Zuruecksetzen auf "text"). Widerspruechliche Angaben fuer denselben Key im selben Request → 422. Ein Typwechsel wird abgelehnt (422), solange bestehende Werte nicht numerisch sind (text→number) bzw. Preisregeln das Attribut verwenden (number→text).

category_external_ids

Ordnet das Produkt einer oder mehreren Kategorien zu. Bei Angabe werden alle bestehenden Kategorie-Zuordnungen ersetzt. Die Kategorien muessen vorher ueber den Kategorien-Endpoint erstellt werden. Max. 100 Eintraege pro Produkt.

FeldTypStatusBeschreibung
category_external_idsstring[]OptionalArray von externen Kategorie-IDs (verwendet die gleichen IDs wie in deinem Shopsystem)

quantity_tiers

Array von Staffelpreis-Definitionen. Bei Angabe werden alle bestehenden Staffelpreise ersetzt. Max. 200 Eintraege pro Produkt.

FeldTypStatusBeschreibung
external_idstringPflichtEindeutige ID der Staffel (max. 255 Zeichen). Muss innerhalb des Arrays eindeutig sein.
min_quantitynumberPflichtMindestmenge fuer diese Staffel (positive Zahl > 0, Dezimalwerte erlaubt)
customer_external_idstring | nullOptionalExternal ID eines Kunden (org_customers). Darf nicht zusammen mit customer_group_external_id gesetzt werden.
customer_group_external_idstring | nullOptionalExternal ID einer Kundengruppe (org_customer_groups). Darf nicht zusammen mit customer_external_id gesetzt werden.
Staffelpreise koennen optional an einen bestimmten Kunden oder eine Kundengruppe gebunden werden. Ohne Kunden-/Gruppen-Referenz gilt die Staffel als allgemeiner Staffelpreis.

quantity_tiers — Response-Felder

In der Response enthaelt jedes Quantity-Tier-Objekt zusaetzlich zu den Input-Feldern folgende Felder:

FeldTypStatusBeschreibung
external_idstringOptionalEindeutige ID der Staffel
min_quantitynumberOptionalMindestmenge fuer diese Staffel
customer_external_idstring | nullOptionalExternal ID des zugeordneten Kunden
customer_group_external_idstring | nullOptionalExternal ID der zugeordneten Kundengruppe
created_atstringOptionalISO 8601 Zeitstempel der Erstellung
Update-Verhalten bei Sub-Ressourcen (prices, images, identifiers, attributes, categories, quantity_tiers):
  • Feld weglassen — bestehende Daten bleiben unveraendert
  • Leeres Array senden ([]) — alle bestehenden Eintraege werden geloescht
  • Array mit Daten senden — bestehende Eintraege werden komplett ersetzt (Replace-All)

Vollstaendiges Payload-Beispiel

Hinweis: Bei Single PUT (/{external_id}) wird die external_id aus dem URL-Pfad genommen und muss nicht im Body stehen. Bei Bulk-Upsert muss external_id im Body angegeben werden.
{
  "external_id": "WM-2024",
  "sku": "WM-PRO-2024",
  "name": "Wireless Maus Pro",
  "gtin": "4012345678901",
  "import_excluded": false,
  "export_excluded": true,
  "tax_rate_group_external_id": "mwst-standard",
  "prices": [
    {
      "price_type": "rrp",
      "currency": "EUR",
      "price_net": 1999,
      "price_gross": 2379
    },
    {
      "price_type": "ek",
      "currency": "EUR",
      "price_net": 850,
      "price_gross": 1012
    }
  ],
  "images": [
    { "url": "https://example.com/maus-front.jpg", "sort": 0 },
    { "url": "https://example.com/maus-side.jpg", "sort": 1 }
  ],
  "identifiers": [
    { "key": "mpn", "value": "WM-PRO-2024" },
    { "key": "asin", "value": "B0XXXXXXXXX" }
  ],
  "attributes": [
    { "key": "farbe", "value": "Schwarz" },
    { "key": "gewicht", "value": "85g" }
  ],
  "category_external_ids": ["elektronik", "peripherie"],
  "quantity_tiers": [
    { "external_id": "tier-1", "min_quantity": 2.5 },
    { "external_id": "tier-2", "min_quantity": 50, "customer_group_external_id": "grosshandel" },
    { "external_id": "tier-3", "min_quantity": 100, "customer_external_id": "K-001" }
  ]
}

Kategorien

Kategorien ermoeglichen die hierarchische Organisation deiner Produkte. Jede Kategorie wird ueber eine eindeutige external_id pro Organisation identifiziert.

GET/v1/categories

Gibt eine paginierte Liste aller Kategorien zurueck, inklusive Attributes.

Query-Parameter

FeldTypStatusBeschreibung
limitintegerOptionalErgebnisse pro Seite (1–1.000, Default: 50)
offsetintegerOptionalAnzahl zu ueberspringender Ergebnisse (Default: 0)
afterstringOptionalCursor-Pagination: next_cursor Wert der vorherigen Response (external_id). Schneller als offset bei grossen Datenmengen.

Beispiel (Offset)

curl -X GET "https://app.priceivy.com/api/v1/categories?limit=50&offset=0" \
  -H "Authorization: Bearer rp_dein_api_key"

Beispiel (Cursor-Pagination)

# Seite 2+ (next_cursor aus vorheriger Response verwenden)
curl -X GET "https://app.priceivy.com/api/v1/categories?limit=50&after=KAT-001" \
  -H "Authorization: Bearer rp_dein_api_key"

Response (200)

{
  "data": [
    {
      "external_id": "elektronik",
      "name": "Elektronik",
      "parent_external_id": null,
      "created_at": "2025-01-15T10:30:00.000Z",
      "updated_at": "2025-01-15T10:30:00.000Z",
      "created_by": { "type": "api_key", "key_prefix": "rp_a1b2..." },
      "attributes": [
        { "key": "idealo_id", "value": "12345", "created_at": "2025-01-15T10:30:00.000Z" }
      ]
    }
  ],
  "pagination": {
    "limit": 50,
    "offset": 0,
    "total": null,
    "next_cursor": "elektronik"
  }
}
GET/v1/categories/{external_id}

Gibt eine einzelne Kategorie per external_id zurueck, inklusive Attributes.

Pfad-Parameter

FeldTypStatusBeschreibung
external_idstringPflichtexternal_id der Kategorie

Beispiel

curl -X GET "https://app.priceivy.com/api/v1/categories/elektronik" \
  -H "Authorization: Bearer rp_dein_api_key"

Response (200)

{
  "data": {
    "external_id": "elektronik",
    "name": "Elektronik",
    "parent_external_id": null,
    "created_at": "2025-01-15T10:30:00.000Z",
    "updated_at": "2025-01-15T10:30:00.000Z",
    "created_by": { "type": "api_key", "key_prefix": "rp_a1b2..." },
    "attributes": []
  }
}
PUT/v1/categories/{external_id}

Idempotenter Upsert einer Kategorie per external_id. Erstellt die Kategorie falls sie nicht existiert (201) oder aktualisiert sie (200). Attributes werden bei Angabe vollstaendig ersetzt.

Pfad-Parameter

FeldTypStatusBeschreibung
external_idstringPflichtexternal_id der Kategorie

Beispiel

curl -X PUT "https://app.priceivy.com/api/v1/categories/elektronik" \
  -H "Authorization: Bearer rp_dein_api_key" \
  -H "Content-Type: application/json" \
  -d '{
    "name": "Elektronik & Zubehoer",
    "attributes": [
      { "key": "idealo_id", "value": "12345" }
    ]
  }'

Response (200 oder 201)

{
  "data": {
    "external_id": "elektronik",
    "name": "Elektronik & Zubehoer",
    "parent_external_id": null,
    "created_at": "2025-01-15T10:30:00.000Z",
    "updated_at": "2025-01-16T08:00:00.000Z",
    "created_by": { "type": "api_key", "key_prefix": "rp_a1b2..." },
    "attributes": [
      { "key": "idealo_id", "value": "12345" }
    ]
  }
}
Hinweis: Die external_id wird aus dem URL-Pfad uebernommen. Ein external_id-Feld im Body wird ignoriert.
DELETE/v1/categories/{external_id}

Loescht eine Kategorie per external_id (Soft-Delete).

Pfad-Parameter

FeldTypStatusBeschreibung
external_idstringPflichtexternal_id der Kategorie

Beispiel

curl -X DELETE "https://app.priceivy.com/api/v1/categories/elektronik" \
  -H "Authorization: Bearer rp_dein_api_key"

Response (200)

{
  "data": {
    "success": true
  }
}
Cascade beim Loeschen: Beim Loeschen einer Kategorie werden zugehoerige Attribute und Produkt-Kategorie-Zuordnungen automatisch soft-deleted.
POST/v1/categories/bulk-upsert

Erstellt oder aktualisiert bis zu 1.000 Kategorien per external_id in einem Request. Parent-Referenzen werden batch-uebergreifend aufgeloest.

Beispiel

curl -X POST "https://app.priceivy.com/api/v1/categories/bulk-upsert" \
  -H "Authorization: Bearer rp_dein_api_key" \
  -H "Content-Type: application/json" \
  -d '{
    "items": [
      {
        "external_id": "elektronik",
        "name": "Elektronik"
      },
      {
        "external_id": "peripherie",
        "name": "Peripheriegeraete",
        "parent_external_id": "elektronik",
        "attributes": [
          { "key": "idealo_id", "value": "67890" }
        ]
      }
    ]
  }'

Response (200)

{
  "summary": {
    "total": 2,
    "created": 2,
    "updated": 0,
    "failed": 0,
    "duplicates": 0
  },
  "errors": []
}

Das optionale warnings-Array erscheint nur, wenn bei Sub-Daten Teilfehler aufgetreten sind.

Limit: Maximal 1.000 Items pro Request. Parent-Kategorien koennen im gleichen Batch referenziert werden — die Reihenfolge im Array ist egal, da Parent-Referenzen in einem separaten Schritt aufgeloest werden. Soft-deleted Kategorien werden bei erneutem Upsert automatisch reaktiviert.

Struktur-Validierung (422)

Wenn der Request-Body nicht die erwartete Struktur hat:

// items fehlt oder ist kein Array
{
  "error": "items muss als Array gesendet werden"
}

// Array leer oder mehr als 1.000 Items
{
  "error": "items muss zwischen 1 und 1000 Eintraegen enthalten"
}

Item-Validierungsfehler (422)

Alle Items werden vorab validiert — bei Fehlern wird kein Item verarbeitet. Stattdessen werden alle Fehler gesammelt und auf einmal zurueckgegeben:

{
  "error": "1 von 3 Items haben Validierungsfehler",
  "details": {
    "validation_errors": [
      {
        "index": 2,
        "external_id": null,
        "error": "external_id ist erforderlich"
      }
    ]
  }
}
POST/v1/categories/bulk-delete

Loescht bis zu 1.000 Kategorien per external_id in einem Request. Attributes werden automatisch mitgeloescht. Nicht gefundene external_ids werden mit Fehler markiert.

Beispiel

curl -X POST "https://app.priceivy.com/api/v1/categories/bulk-delete" \
  -H "Authorization: Bearer rp_dein_api_key" \
  -H "Content-Type: application/json" \
  -d '{
    "external_ids": ["elektronik", "peripherie", "nicht-vorhanden"]
  }'

Response (200)

{
  "summary": {
    "total": 3,
    "succeeded": 2,
    "failed": 1
  },
  "errors": [
    { "external_id": "nicht-vorhanden", "error": "Kategorie nicht gefunden" }
  ]
}

Das optionale warnings-Array erscheint nur, wenn bei Sub-Daten Teilfehler aufgetreten sind.

Limit: Maximal 1.000 external_ids pro Request.

Validierungsfehler-Response (422)

Bei ungueltigem Input wird der Request abgelehnt, bevor Items verarbeitet werden:

// external_ids ist kein Array
{
  "error": "external_ids muss als Array gesendet werden"
}

// Array leer oder mehr als 1.000 Items
{
  "error": "external_ids muss zwischen 1 und 1000 Eintraegen enthalten"
}

// Ein Item ist kein String oder leer (mit Index)
{
  "error": "external_ids[0] muss ein nicht-leerer String sein"
}

Payload-Schema

Das folgende Schema gilt fuer PUT-Requests und Bulk-Upsert Items auf Kategorie-Endpoints.

Strikte Validierung: Unbekannte Felder im Body werden abgelehnt (422). Nur die unten aufgefuehrten Felder sind erlaubt.

Felder

FeldTypStatusBeschreibung
external_idstringPflichtEindeutige externe ID innerhalb der Organisation (z.B. Slug oder Nummer aus deinem System). Max. 255 Zeichen.
namestringPflichtAnzeigename der Kategorie. Max. 500 Zeichen.
parent_external_idstring | nullOptionalexternal_id der uebergeordneten Kategorie (fuer Hierarchien). Max. 10 Ebenen tief. Zirkulaere Referenzen werden automatisch erkannt und abgelehnt (422). Sende null um die Parent-Zuordnung zu entfernen.
attributesarrayOptionalArray von Key-Value-Paaren fuer zusaetzliche Kennungen. Bei Angabe werden alle bestehenden Attribute ersetzt. Max. 200 Eintraege.

attributes

Struktur der Key-Value-Paare innerhalb des attributes-Arrays.

FeldTypStatusBeschreibung
keystringPflichtSchluesselname (z.B. "idealo_id", "google_id"). Max. 255 Zeichen.
valuestring | numberPflichtWert. Max. 2.000 Zeichen. JSON-Zahlen sind erlaubt und werden als String gespeichert. Bei Keys vom Typ "number" muss der Wert dem Zahlformat entsprechen (Punkt als Dezimaltrenner).
value_type"text" | "number"OptionalOptional: setzt den org-weiten Typ dieses Kategorie-Attribut-Keys (analog Produkt-Attribute). Fehlt das Feld, bleibt der gespeicherte Typ unveraendert. Widerspruechliche Angaben im selben Request oder geblockte Typwechsel → 422.

Payload-Beispiel

Hinweis: Bei Single PUT (/{external_id}) wird die external_id aus dem URL-Pfad genommen und muss nicht im Body stehen. Bei Bulk-Upsert muss external_id im Body angegeben werden.
{
  "external_id": "peripherie",
  "name": "Peripheriegeraete",
  "parent_external_id": "elektronik",
  "attributes": [
    { "key": "idealo_id", "value": "67890" },
    { "key": "google_id", "value": "cat-123" }
  ]
}
Hierarchien: Unterkategorien werden ueber parent_external_id verknuepft. Beim Bulk-Upsert koennen Parent-Kategorien im gleichen Batch referenziert werden — die Reihenfolge im Array ist egal, da Parent-Referenzen in einem separaten Schritt aufgeloest werden.

Kunden

Kunden koennen optional einer Kundengruppe zugeordnet werden. Jeder Kunde wird ueber eine eindeutige external_id und customer_number pro Organisation identifiziert.

GET/v1/customers

Gibt eine paginierte Liste aller Kunden zurueck.

Query-Parameter

FeldTypStatusBeschreibung
limitintegerOptionalErgebnisse pro Seite (1–1.000, Default: 50)
offsetintegerOptionalAnzahl zu ueberspringender Ergebnisse (Default: 0)
afterstringOptionalCursor-Pagination: next_cursor Wert der vorherigen Response (external_id). Schneller als offset bei grossen Datenmengen.

Beispiel (Offset)

curl -X GET "https://app.priceivy.com/api/v1/customers?limit=50&offset=0" \
  -H "Authorization: Bearer rp_dein_api_key"

Beispiel (Cursor-Pagination)

# Seite 2+ (next_cursor aus vorheriger Response verwenden)
curl -X GET "https://app.priceivy.com/api/v1/customers?limit=50&after=K-001" \
  -H "Authorization: Bearer rp_dein_api_key"

Response (200)

{
  "data": [
    {
      "external_id": "K-001",
      "customer_number": "10001",
      "name": "Max Mustermann GmbH",
      "customer_group_external_id": "grosshandel",
      "created_at": "2025-01-15T10:30:00.000Z",
      "updated_at": "2025-01-15T10:30:00.000Z",
      "created_by": { "type": "api_key", "key_prefix": "rp_a1b2..." }
    }
  ],
  "pagination": {
    "limit": 50,
    "offset": 0,
    "total": null,
    "next_cursor": "K-001"
  }
}
GET/v1/customers/{external_id}

Gibt einen einzelnen Kunden per external_id zurueck.

Pfad-Parameter

FeldTypStatusBeschreibung
external_idstringPflichtexternal_id des Kunden

Beispiel

curl -X GET "https://app.priceivy.com/api/v1/customers/K-001" \
  -H "Authorization: Bearer rp_dein_api_key"

Response (200)

{
  "data": {
    "external_id": "K-001",
    "customer_number": "10001",
    "name": "Max Mustermann GmbH",
    "customer_group_external_id": "grosshandel",
    "created_at": "2025-01-15T10:30:00.000Z",
    "updated_at": "2025-01-15T10:30:00.000Z",
    "created_by": { "type": "api_key", "key_prefix": "rp_a1b2..." }
  }
}
PUT/v1/customers/{external_id}

Idempotenter Upsert eines Kunden per external_id. Erstellt den Kunden falls er nicht existiert (201) oder aktualisiert ihn (200).

Pfad-Parameter

FeldTypStatusBeschreibung
external_idstringPflichtexternal_id des Kunden

Beispiel

curl -X PUT "https://app.priceivy.com/api/v1/customers/K-001" \
  -H "Authorization: Bearer rp_dein_api_key" \
  -H "Content-Type: application/json" \
  -d '{
    "customer_number": "10001",
    "name": "Max Mustermann GmbH",
    "customer_group_external_id": "grosshandel"
  }'

Response (200 oder 201)

{
  "data": {
    "external_id": "K-001",
    "customer_number": "10001",
    "name": "Max Mustermann GmbH",
    "customer_group_external_id": "grosshandel",
    "created_at": "2025-01-15T10:30:00.000Z",
    "updated_at": "2025-01-16T08:00:00.000Z",
    "created_by": { "type": "api_key", "key_prefix": "rp_a1b2..." }
  }
}
Hinweis: Die external_id wird aus dem URL-Pfad uebernommen. Ein external_id-Feld im Body wird ignoriert.
Kundengruppen-Validierung: Die customer_group_external_id muss einer existierenden, aktiven Kundengruppe entsprechen. Ist die Kundengruppe nicht vorhanden, wird ein 422-Fehler zurueckgegeben. Sende null um die Kundengruppen-Zuordnung zu entfernen.
DELETE/v1/customers/{external_id}

Loescht einen Kunden per external_id (Soft-Delete).

Pfad-Parameter

FeldTypStatusBeschreibung
external_idstringPflichtexternal_id des Kunden

Beispiel

curl -X DELETE "https://app.priceivy.com/api/v1/customers/K-001" \
  -H "Authorization: Bearer rp_dein_api_key"

Response (200)

{
  "data": {
    "success": true
  }
}
POST/v1/customers/bulk-upsert

Erstellt oder aktualisiert bis zu 1.000 Kunden per external_id in einem Request.

Beispiel

curl -X POST "https://app.priceivy.com/api/v1/customers/bulk-upsert" \
  -H "Authorization: Bearer rp_dein_api_key" \
  -H "Content-Type: application/json" \
  -d '{
    "items": [
      {
        "external_id": "K-001",
        "customer_number": "10001",
        "name": "Max Mustermann GmbH",
        "customer_group_external_id": "grosshandel"
      },
      {
        "external_id": "K-002",
        "customer_number": "10002",
        "name": "Erika Beispiel AG"
      }
    ]
  }'

Response (200)

{
  "summary": {
    "total": 2,
    "created": 2,
    "updated": 0,
    "failed": 0,
    "duplicates": 0
  },
  "errors": []
}
Limit: Maximal 1.000 Items pro Request. Soft-deleted Kunden werden bei erneutem Upsert automatisch reaktiviert.
Kundengruppen-Validierung: Die customer_group_external_id muss einer existierenden, aktiven Kundengruppe entsprechen. Ist die Kundengruppe nicht vorhanden, wird das Item mit einem Fehler markiert.

Struktur-Validierung (422)

Wenn der Request-Body nicht die erwartete Struktur hat:

// items fehlt oder ist kein Array
{
  "error": "items muss als Array gesendet werden"
}

// Array leer oder mehr als 1.000 Items
{
  "error": "items muss zwischen 1 und 1000 Eintraegen enthalten"
}

Item-Validierungsfehler (422)

Alle Items werden vorab validiert — bei Fehlern wird kein Item verarbeitet. Stattdessen werden alle Fehler gesammelt und auf einmal zurueckgegeben:

{
  "error": "2 von 5 Items haben Validierungsfehler",
  "details": {
    "validation_errors": [
      {
        "index": 1,
        "external_id": "K-003",
        "error": "customer_number ist erforderlich"
      },
      {
        "index": 4,
        "external_id": null,
        "error": "external_id ist erforderlich"
      }
    ]
  }
}
Doppelte external_ids: Wenn im selben Batch mehrere Items die gleiche external_id haben, wird nur das letzte Item mit dieser external_id verarbeitet. Fruehere Duplikate werden im summary.duplicates-Zaehler erfasst und im errors-Array mit einem Hinweis aufgefuehrt.
POST/v1/customers/bulk-delete

Loescht bis zu 1.000 Kunden per external_id in einem Request. Nicht gefundene external_ids werden mit Fehler markiert.

Beispiel

curl -X POST "https://app.priceivy.com/api/v1/customers/bulk-delete" \
  -H "Authorization: Bearer rp_dein_api_key" \
  -H "Content-Type: application/json" \
  -d '{
    "external_ids": ["K-001", "K-002", "nicht-vorhanden"]
  }'

Response (200)

{
  "summary": {
    "total": 3,
    "succeeded": 2,
    "failed": 1
  },
  "errors": [
    { "external_id": "nicht-vorhanden", "error": "Kunde nicht gefunden" }
  ]
}
Limit: Maximal 1.000 external_ids pro Request.

Validierungsfehler-Response (422)

Bei ungueltigem Input wird der Request abgelehnt, bevor Items verarbeitet werden:

// external_ids ist kein Array
{
  "error": "external_ids muss als Array gesendet werden"
}

// Array leer oder mehr als 1.000 Items
{
  "error": "external_ids muss zwischen 1 und 1000 Eintraegen enthalten"
}

// Ein Item ist kein String oder leer (mit Index)
{
  "error": "external_ids[0] muss ein nicht-leerer String sein"
}
Cascade beim Loeschen: Beim Loeschen eines Kunden werden zugehoerige Staffelpreise (quantity_tiers) automatisch soft-deleted.

Payload-Schema

Das folgende Schema gilt fuer PUT-Requests und Bulk-Upsert Items auf Kunden-Endpoints.

Strikte Validierung: Unbekannte Felder im Body werden abgelehnt (422). Nur die unten aufgefuehrten Felder sind erlaubt.

Felder

FeldTypStatusBeschreibung
external_idstringPflichtEindeutige ID aus deinem System (max. 255 Zeichen)
customer_numberstringPflichtKundennummer (max. 255 Zeichen, muss innerhalb der Organisation eindeutig sein)
namestringPflichtName des Kunden (max. 500 Zeichen)
customer_group_external_idstring | nullOptionalExternal ID einer existierenden Kundengruppe. Sende null um die Zuordnung zu entfernen.

Payload-Beispiel

Hinweis: Bei Single PUT (/{external_id}) wird die external_id aus dem URL-Pfad genommen und muss nicht im Body stehen. Bei Bulk-Upsert muss external_id im Body angegeben werden.
{
  "external_id": "K-001",
  "customer_number": "10001",
  "name": "Max Mustermann GmbH",
  "customer_group_external_id": "grosshandel"
}
Kundengruppen-Zuordnung: Die customer_group_external_id muss einer existierenden, aktiven Kundengruppe entsprechen. Ist die Kundengruppe nicht vorhanden, wird ein 422-Fehler zurueckgegeben. Sende null um die Kundengruppen-Zuordnung zu entfernen.

Kundengruppen

Kundengruppen ermoeglichen die Gruppierung deiner Kunden (z.B. "Grosshandel", "Endkunden", "VIP"). Jede Kundengruppe wird ueber eine eindeutige external_id pro Organisation identifiziert.

GET/v1/customer-groups

Gibt eine paginierte Liste aller Kundengruppen zurueck.

Query-Parameter

FeldTypStatusBeschreibung
limitintegerOptionalErgebnisse pro Seite (1–1.000, Default: 50)
offsetintegerOptionalAnzahl zu ueberspringender Ergebnisse (Default: 0)
afterstringOptionalCursor-Pagination: next_cursor Wert der vorherigen Response (external_id). Schneller als offset bei grossen Datenmengen.

Beispiel (Offset)

curl -X GET "https://app.priceivy.com/api/v1/customer-groups?limit=50&offset=0" \
  -H "Authorization: Bearer rp_dein_api_key"

Beispiel (Cursor-Pagination)

# Seite 2+ (next_cursor aus vorheriger Response verwenden)
curl -X GET "https://app.priceivy.com/api/v1/customer-groups?limit=50&after=haendler" \
  -H "Authorization: Bearer rp_dein_api_key"

Response (200)

{
  "data": [
    {
      "external_id": "grosshandel",
      "name": "Grosshandel",
      "created_at": "2025-01-15T10:30:00.000Z",
      "updated_at": "2025-01-15T10:30:00.000Z",
      "created_by": { "type": "api_key", "key_prefix": "rp_a1b2..." }
    }
  ],
  "pagination": {
    "limit": 50,
    "offset": 0,
    "total": null,
    "next_cursor": "grosshandel"
  }
}
GET/v1/customer-groups/{external_id}

Gibt eine einzelne Kundengruppe per external_id zurueck.

Pfad-Parameter

FeldTypStatusBeschreibung
external_idstringPflichtexternal_id der Kundengruppe

Beispiel

curl -X GET "https://app.priceivy.com/api/v1/customer-groups/grosshandel" \
  -H "Authorization: Bearer rp_dein_api_key"

Response (200)

{
  "data": {
    "external_id": "grosshandel",
    "name": "Grosshandel",
    "created_at": "2025-01-15T10:30:00.000Z",
    "updated_at": "2025-01-15T10:30:00.000Z",
    "created_by": { "type": "api_key", "key_prefix": "rp_a1b2..." }
  }
}
PUT/v1/customer-groups/{external_id}

Idempotenter Upsert einer Kundengruppe per external_id. Erstellt die Kundengruppe falls sie nicht existiert (201) oder aktualisiert sie (200).

Pfad-Parameter

FeldTypStatusBeschreibung
external_idstringPflichtexternal_id der Kundengruppe

Beispiel

curl -X PUT "https://app.priceivy.com/api/v1/customer-groups/grosshandel" \
  -H "Authorization: Bearer rp_dein_api_key" \
  -H "Content-Type: application/json" \
  -d '{
    "name": "Grosshandel Premium"
  }'

Response (200 oder 201)

{
  "data": {
    "external_id": "grosshandel",
    "name": "Grosshandel Premium",
    "created_at": "2025-01-15T10:30:00.000Z",
    "updated_at": "2025-01-16T08:00:00.000Z",
    "created_by": { "type": "api_key", "key_prefix": "rp_a1b2..." }
  }
}
Hinweis: Die external_id wird aus dem URL-Pfad uebernommen. Ein external_id-Feld im Body wird ignoriert.
DELETE/v1/customer-groups/{external_id}

Loescht eine Kundengruppe per external_id (Soft-Delete).

Pfad-Parameter

FeldTypStatusBeschreibung
external_idstringPflichtexternal_id der Kundengruppe

Beispiel

curl -X DELETE "https://app.priceivy.com/api/v1/customer-groups/grosshandel" \
  -H "Authorization: Bearer rp_dein_api_key"

Response (200)

{
  "data": {
    "success": true
  }
}
POST/v1/customer-groups/bulk-upsert

Erstellt oder aktualisiert bis zu 1.000 Kundengruppen per external_id in einem Request.

Beispiel

curl -X POST "https://app.priceivy.com/api/v1/customer-groups/bulk-upsert" \
  -H "Authorization: Bearer rp_dein_api_key" \
  -H "Content-Type: application/json" \
  -d '{
    "items": [
      {
        "external_id": "grosshandel",
        "name": "Grosshandel"
      },
      {
        "external_id": "endkunden",
        "name": "Endkunden"
      }
    ]
  }'

Response (200)

{
  "summary": {
    "total": 2,
    "created": 2,
    "updated": 0,
    "failed": 0,
    "duplicates": 0
  },
  "errors": []
}
Limit: Maximal 1.000 Items pro Request. Soft-deleted Kundengruppen werden bei erneutem Upsert automatisch reaktiviert.

Struktur-Validierung (422)

Wenn der Request-Body nicht die erwartete Struktur hat:

// items fehlt oder ist kein Array
{
  "error": "items muss als Array gesendet werden"
}

// Array leer oder mehr als 1.000 Items
{
  "error": "items muss zwischen 1 und 1000 Eintraegen enthalten"
}

Item-Validierungsfehler (422)

Alle Items werden vorab validiert — bei Fehlern wird kein Item verarbeitet. Stattdessen werden alle Fehler gesammelt und auf einmal zurueckgegeben:

{
  "error": "1 von 3 Items haben Validierungsfehler",
  "details": {
    "validation_errors": [
      {
        "index": 2,
        "external_id": null,
        "error": "external_id ist erforderlich"
      }
    ]
  }
}
Doppelte external_ids: Wenn im selben Batch mehrere Items die gleiche external_id haben, wird nur das letzte Item mit dieser external_id verarbeitet. Fruehere Duplikate werden im summary.duplicates-Zaehler erfasst und im errors-Array mit einem Hinweis aufgefuehrt.
POST/v1/customer-groups/bulk-delete

Loescht bis zu 1.000 Kundengruppen per external_id in einem Request. Nicht gefundene external_ids werden mit Fehler markiert.

Beispiel

curl -X POST "https://app.priceivy.com/api/v1/customer-groups/bulk-delete" \
  -H "Authorization: Bearer rp_dein_api_key" \
  -H "Content-Type: application/json" \
  -d '{
    "external_ids": ["grosshandel", "endkunden", "nicht-vorhanden"]
  }'

Response (200)

{
  "summary": {
    "total": 3,
    "succeeded": 2,
    "failed": 1
  },
  "errors": [
    { "external_id": "nicht-vorhanden", "error": "Kundengruppe nicht gefunden" }
  ]
}
Limit: Maximal 1.000 external_ids pro Request.

Validierungsfehler-Response (422)

Bei ungueltigem Input wird der Request abgelehnt, bevor Items verarbeitet werden:

// external_ids ist kein Array
{
  "error": "external_ids muss als Array gesendet werden"
}

// Array leer oder mehr als 1.000 Items
{
  "error": "external_ids muss zwischen 1 und 1000 Eintraegen enthalten"
}

// Ein Item ist kein String oder leer (mit Index)
{
  "error": "external_ids[0] muss ein nicht-leerer String sein"
}
Cascade beim Loeschen: Beim Loeschen einer Kundengruppe werden zugehoerige Staffelpreise (quantity_tiers) automatisch soft-deleted und die customer_group_id bei betroffenen Kunden auf null gesetzt.

Payload-Schema

Das folgende Schema gilt fuer PUT-Requests und Bulk-Upsert Items auf Kundengruppen-Endpoints.

Strikte Validierung: Unbekannte Felder im Body werden abgelehnt (422). Nur die unten aufgefuehrten Felder sind erlaubt.

Felder

FeldTypStatusBeschreibung
external_idstringPflichtEindeutige ID aus deinem System (max. 255 Zeichen)
namestringPflichtName der Kundengruppe (max. 500 Zeichen)

Payload-Beispiel

Hinweis: Bei Single PUT (/{external_id}) wird die external_id aus dem URL-Pfad genommen und muss nicht im Body stehen. Bei Bulk-Upsert muss external_id im Body angegeben werden.
{
  "external_id": "grosshandel",
  "name": "Grosshandel"
}

Steuersätze

Steuersätze ermoeglichen die Verwaltung von Steuersaetzen pro Land. Produkte referenzieren eine Gruppe ueber tax_rate_group_external_id und bekommen je nach Zielland den richtigen Steuersatz. Jede Steuersatzgruppe wird ueber eine eindeutige external_id pro Organisation identifiziert.

GET/v1/tax-rate-groups

Gibt eine paginierte Liste aller Steuersätze zurueck, inklusive der zugehoerigen Steuersaetze pro Land.

Query-Parameter

FeldTypStatusBeschreibung
limitintegerOptionalErgebnisse pro Seite (1–1.000, Default: 50)
offsetintegerOptionalAnzahl zu ueberspringender Ergebnisse (Default: 0)
afterstringOptionalCursor-Pagination: next_cursor Wert der vorherigen Response (external_id). Schneller als offset bei grossen Datenmengen.

Beispiel (Offset)

curl -X GET "https://app.priceivy.com/api/v1/tax-rate-groups?limit=50&offset=0" \
  -H "Authorization: Bearer rp_dein_api_key"

Beispiel (Cursor-Pagination)

# Seite 2+ (next_cursor aus vorheriger Response verwenden)
curl -X GET "https://app.priceivy.com/api/v1/tax-rate-groups?limit=50&after=mwst-standard" \
  -H "Authorization: Bearer rp_dein_api_key"

Response (200)

{
  "data": [
    {
      "external_id": "mwst-standard",
      "name": "MwSt Standard",
      "created_at": "2025-01-15T10:30:00.000Z",
      "updated_at": "2025-01-15T10:30:00.000Z",
      "created_by": { "type": "api_key", "key_prefix": "rp_a1b2..." },
      "tax_rates": [
        { "country_iso2": "DE", "rate": 1900 },
        { "country_iso2": "AT", "rate": 2000 },
        { "country_iso2": "FR", "rate": 2000 }
      ]
    }
  ],
  "pagination": {
    "limit": 50,
    "offset": 0,
    "total": null,
    "next_cursor": "mwst-standard"
  }
}
GET/v1/tax-rate-groups/{external_id}

Gibt eine einzelne Steuersatzgruppe per external_id zurueck, inklusive der zugehoerigen Steuersaetze.

Pfad-Parameter

FeldTypStatusBeschreibung
external_idstringPflichtexternal_id der Steuersatzgruppe

Beispiel

curl -X GET "https://app.priceivy.com/api/v1/tax-rate-groups/mwst-standard" \
  -H "Authorization: Bearer rp_dein_api_key"

Response (200)

{
  "data": {
    "external_id": "mwst-standard",
    "name": "MwSt Standard",
    "created_at": "2025-01-15T10:30:00.000Z",
    "updated_at": "2025-01-15T10:30:00.000Z",
    "created_by": { "type": "api_key", "key_prefix": "rp_a1b2..." },
    "tax_rates": [
      { "country_iso2": "DE", "rate": 1900 },
      { "country_iso2": "AT", "rate": 2000 }
    ]
  }
}
PUT/v1/tax-rate-groups/{external_id}

Idempotenter Upsert einer Steuersatzgruppe per external_id. Erstellt die Gruppe falls sie nicht existiert (201) oder aktualisiert sie (200). Bei Angabe von tax_rates werden alle bestehenden Steuersaetze ersetzt (Replace-All).

Pfad-Parameter

FeldTypStatusBeschreibung
external_idstringPflichtexternal_id der Steuersatzgruppe

Beispiel

curl -X PUT "https://app.priceivy.com/api/v1/tax-rate-groups/mwst-standard" \
  -H "Authorization: Bearer rp_dein_api_key" \
  -H "Content-Type: application/json" \
  -d '{
    "name": "MwSt Standard",
    "tax_rates": [
      { "country_iso2": "DE", "rate": 1900 },
      { "country_iso2": "AT", "rate": 2000 },
      { "country_iso2": "FR", "rate": 2000 }
    ]
  }'

Response (200 oder 201)

{
  "data": {
    "external_id": "mwst-standard",
    "name": "MwSt Standard",
    "created_at": "2025-01-15T10:30:00.000Z",
    "updated_at": "2025-01-16T08:00:00.000Z",
    "created_by": { "type": "api_key", "key_prefix": "rp_a1b2..." },
    "tax_rates": [
      { "country_iso2": "DE", "rate": 1900 },
      { "country_iso2": "AT", "rate": 2000 },
      { "country_iso2": "FR", "rate": 2000 }
    ]
  }
}
Hinweis: Die external_id wird aus dem URL-Pfad uebernommen. Ein external_id-Feld im Body wird ignoriert.
tax_rates Replace-All: Bei Angabe von tax_rates werden alle bestehenden Steuersaetze der Gruppe geloescht und durch die neuen ersetzt. Wird das Feld weggelassen, bleiben bestehende Steuersaetze unveraendert.
DELETE/v1/tax-rate-groups/{external_id}

Loescht eine Steuersatzgruppe per external_id (Soft-Delete).

Pfad-Parameter

FeldTypStatusBeschreibung
external_idstringPflichtexternal_id der Steuersatzgruppe

Beispiel

curl -X DELETE "https://app.priceivy.com/api/v1/tax-rate-groups/mwst-standard" \
  -H "Authorization: Bearer rp_dein_api_key"

Response (200)

{
  "data": {
    "success": true
  }
}
Cascade beim Loeschen: Beim Loeschen einer Steuersatzgruppe werden zugehoerige Steuersaetze automatisch soft-deleted und die tax_rate_group_external_id bei betroffenen Produkten auf null gesetzt.
POST/v1/tax-rate-groups/bulk-upsert

Erstellt oder aktualisiert bis zu 1.000 Steuersätze per external_id in einem Request.

Beispiel

curl -X POST "https://app.priceivy.com/api/v1/tax-rate-groups/bulk-upsert" \
  -H "Authorization: Bearer rp_dein_api_key" \
  -H "Content-Type: application/json" \
  -d '{
    "items": [
      {
        "external_id": "mwst-standard",
        "name": "MwSt Standard",
        "tax_rates": [
          { "country_iso2": "DE", "rate": 1900 },
          { "country_iso2": "AT", "rate": 2000 }
        ]
      },
      {
        "external_id": "mwst-ermaessigt",
        "name": "MwSt Ermaessigt",
        "tax_rates": [
          { "country_iso2": "DE", "rate": 700 },
          { "country_iso2": "AT", "rate": 1000 }
        ]
      }
    ]
  }'

Response (200)

{
  "summary": {
    "total": 2,
    "created": 2,
    "updated": 0,
    "failed": 0,
    "duplicates": 0
  },
  "errors": []
}
Limit: Maximal 1.000 Items pro Request. Soft-deleted Steuersätze werden bei erneutem Upsert automatisch reaktiviert.

Struktur-Validierung (422)

Wenn der Request-Body nicht die erwartete Struktur hat:

// items fehlt oder ist kein Array
{
  "error": "items muss als Array gesendet werden"
}

// Array leer oder mehr als 1.000 Items
{
  "error": "items muss zwischen 1 und 1000 Eintraegen enthalten"
}

Item-Validierungsfehler (422)

Alle Items werden vorab validiert — bei Fehlern wird kein Item verarbeitet. Stattdessen werden alle Fehler gesammelt und auf einmal zurueckgegeben:

{
  "error": "1 von 3 Items haben Validierungsfehler",
  "details": {
    "validation_errors": [
      {
        "index": 2,
        "external_id": null,
        "error": "external_id ist erforderlich"
      }
    ]
  }
}
Doppelte external_ids: Wenn im selben Batch mehrere Items die gleiche external_id haben, wird nur das letzte Item mit dieser external_id verarbeitet. Fruehere Duplikate werden im summary.duplicates-Zaehler erfasst und im errors-Array mit einem Hinweis aufgefuehrt.
POST/v1/tax-rate-groups/bulk-delete

Loescht bis zu 1.000 Steuersätze per external_id in einem Request. Nicht gefundene external_ids werden mit Fehler markiert.

Beispiel

curl -X POST "https://app.priceivy.com/api/v1/tax-rate-groups/bulk-delete" \
  -H "Authorization: Bearer rp_dein_api_key" \
  -H "Content-Type: application/json" \
  -d '{
    "external_ids": ["mwst-standard", "mwst-ermaessigt", "nicht-vorhanden"]
  }'

Response (200)

{
  "summary": {
    "total": 3,
    "succeeded": 2,
    "failed": 1
  },
  "errors": [
    { "external_id": "nicht-vorhanden", "error": "Steuersatzgruppe nicht gefunden" }
  ]
}
Limit: Maximal 1.000 external_ids pro Request.

Validierungsfehler-Response (422)

Bei ungueltigem Input wird der Request abgelehnt, bevor Items verarbeitet werden:

// external_ids ist kein Array
{
  "error": "external_ids muss als Array gesendet werden"
}

// Array leer oder mehr als 1.000 Items
{
  "error": "external_ids muss zwischen 1 und 1000 Eintraegen enthalten"
}

// Ein Item ist kein String oder leer (mit Index)
{
  "error": "external_ids[0] muss ein nicht-leerer String sein"
}

Payload-Schema

Das folgende Schema gilt fuer PUT-Requests und Bulk-Upsert Items auf Steuersätze-Endpoints.

Strikte Validierung: Unbekannte Felder im Body werden abgelehnt (422). Nur die unten aufgefuehrten Felder sind erlaubt.

Basis-Felder

FeldTypStatusBeschreibung
external_idstringPflichtEindeutige ID aus deinem System (max. 255 Zeichen)
namestringPflichtName der Steuersatzgruppe (max. 500 Zeichen)

tax_rates

Array von Steuersatz-Objekten pro Land. Bei Angabe werden alle bestehenden Steuersaetze ersetzt (Replace-All). Max. 600 Eintraege pro Gruppe.

FeldTypStatusBeschreibung
country_iso2stringPflichtISO 3166-1 alpha-2 Laendercode (z.B. "DE", "AT", "FR"). Muss genau 2 Grossbuchstaben sein.
rateintegerPflichtSteuersatz in Basispunkten (0–10.000). Beispiel: 1900 = 19%, 700 = 7%, 0 = steuerfrei.

Payload-Beispiel

Hinweis: Bei Single PUT (/{external_id}) wird die external_id aus dem URL-Pfad genommen und muss nicht im Body stehen. Bei Bulk-Upsert muss external_id im Body angegeben werden.
{
  "external_id": "mwst-standard",
  "name": "MwSt Standard",
  "tax_rates": [
    { "country_iso2": "DE", "rate": 1900 },
    { "country_iso2": "AT", "rate": 2000 },
    { "country_iso2": "CH", "rate": 810 }
  ]
}

Berechnete Preise

Berechnete Preise sind die Endpreise, die aus der Preiskalkulation resultieren. Dieser Endpoint ist read-only — Preise werden automatisch durch das Kalkulationssystem erzeugt und aktualisiert. Produkte mit export_excluded = true werden automatisch ausgeschlossen und nicht zurueckgegeben.

GET/v1/calculated-prices

Gibt berechnete Preise gruppiert nach Produkten zurueck. Pagination basiert auf Produkten, nicht einzelnen Preisen. Unterstuetzt Datum-Filter und Entity-Filter.

Query-Parameter

FeldTypStatusBeschreibung
limitintegerOptionalAnzahl der Produkte pro Seite (1–500, Standard: 50)
offsetintegerOptionalOffset fuer Pagination, basierend auf Produkten (Standard: 0)
afterstringOptionalCursor-Pagination: next_cursor Wert der vorherigen Response (product external_id). Schneller als offset bei grossen Datenmengen.
updated_afterstring (ISO 8601)OptionalNur Preise die nach diesem Datum aktualisiert wurden
updated_beforestring (ISO 8601)OptionalNur Preise die vor diesem Datum aktualisiert wurden

Beispiel (Offset)

curl -X GET "https://app.priceivy.com/api/v1/calculated-prices?limit=500" \
  -H "Authorization: Bearer rp_dein_api_key"

Beispiel (Cursor-Pagination)

# Seite 1
curl -X GET "https://app.priceivy.com/api/v1/calculated-prices?limit=500" \
  -H "Authorization: Bearer rp_dein_api_key"

# Seite 2+ (next_cursor aus vorheriger Response verwenden)
curl -X GET "https://app.priceivy.com/api/v1/calculated-prices?limit=500&after=SKU-12345" \
  -H "Authorization: Bearer rp_dein_api_key"

Response (200)

{
  "data": [
    {
      "product_external_id": "SKU-001",
      "platforms": [
        {
          "platform_name": "Idealo DE",
          "platform_provider": "idealo",
          "platform_country_iso2": "DE",
          "platform_currency_iso3": "EUR",
          "prices": {
            "price": {
              "base": {
                "price_net": 9999,
                "price_gross": 11899,
                "tax_rate": 1900,
                "created_at": "2024-01-15T10:30:00Z",
                "updated_at": "2024-01-15T10:30:00Z"
              },
              "customer_group_prices": [
                {
                  "customer_group_external_id": "haendler",
                  "price_net": 8999,
                  "price_gross": 10709,
                  "tax_rate": 1900,
                  "created_at": "2024-01-15T10:30:00Z",
                  "updated_at": "2024-01-15T10:30:00Z"
                }
              ],
              "customer_prices": [
                {
                  "customer_external_id": "K-001",
                  "price_net": 8500,
                  "price_gross": 10115,
                  "tax_rate": 1900,
                  "created_at": "2024-01-15T10:30:00Z",
                  "updated_at": "2024-01-15T10:30:00Z"
                }
              ],
              "quantity_tier_prices": [
                {
                  "quantity_tier_external_id": "ab-10",
                  "min_quantity": 10,
                  "customer_external_id": null,
                  "customer_group_external_id": "haendler",
                  "price_net": 7999,
                  "price_gross": 9519,
                  "tax_rate": 1900,
                  "created_at": "2024-01-15T10:30:00Z",
                  "updated_at": "2024-01-15T10:30:00Z"
                }
              ]
            },
            "min_price": {
              "base": {
                "price_net": 8499,
                "price_gross": 10114,
                "tax_rate": 1900,
                "created_at": "2024-01-15T10:30:00Z",
                "updated_at": "2024-01-15T10:30:00Z"
              },
              "customer_group_prices": [],
              "customer_prices": [],
              "quantity_tier_prices": []
            },
            "max_price": {
              "base": {
                "price_net": 12999,
                "price_gross": 15469,
                "tax_rate": 1900,
                "created_at": "2024-01-15T10:30:00Z",
                "updated_at": "2024-01-15T10:30:00Z"
              },
              "customer_group_prices": [],
              "customer_prices": [],
              "quantity_tier_prices": []
            },
            "special_price": {
              "base": {
                "price_net": 7499,
                "price_gross": 8924,
                "tax_rate": 1900,
                "valid_from": "2024-02-01T00:00:00Z",
                "valid_to": "2024-03-31T23:59:59Z",
                "created_at": "2024-01-15T10:30:00Z",
                "updated_at": "2024-01-15T10:30:00Z"
              },
              "customer_group_prices": [],
              "customer_prices": [],
              "quantity_tier_prices": []
            }
          }
        },
        {
          "platform_name": "Amazon DE",
          "platform_provider": "amazon",
          "platform_country_iso2": "DE",
          "platform_currency_iso3": "EUR",
          "prices": {
            "price": {
              "base": {
                "price_net": 10499,
                "price_gross": 12494,
                "tax_rate": 1900,
                "created_at": "2024-01-15T11:00:00Z",
                "updated_at": "2024-01-16T08:15:00Z"
              },
              "customer_group_prices": [],
              "customer_prices": [],
              "quantity_tier_prices": []
            },
            "min_price": {
              "base": {
                "price_net": 8999,
                "price_gross": 10709,
                "tax_rate": 1900,
                "created_at": "2024-01-15T11:00:00Z",
                "updated_at": "2024-01-16T08:15:00Z"
              },
              "customer_group_prices": [],
              "customer_prices": [],
              "quantity_tier_prices": []
            },
            "max_price": {
              "base": {
                "price_net": 12999,
                "price_gross": 15469,
                "tax_rate": 1900,
                "created_at": "2024-01-15T11:00:00Z",
                "updated_at": "2024-01-16T08:15:00Z"
              },
              "customer_group_prices": [],
              "customer_prices": [],
              "quantity_tier_prices": []
            },
            "special_price": {
              "base": {
                "price_net": 7999,
                "price_gross": 9519,
                "tax_rate": 1900,
                "valid_from": "2024-02-01T00:00:00Z",
                "valid_to": "2024-06-30T23:59:59Z",
                "created_at": "2024-01-16T08:15:00Z",
                "updated_at": "2024-01-16T08:15:00Z"
              },
              "customer_group_prices": [],
              "customer_prices": [],
              "quantity_tier_prices": []
            }
          }
        }
      ]
    },
    {
      "product_external_id": "SKU-002",
      "platforms": [
        {
          "platform_name": "eBay DE",
          "platform_provider": "ebay",
          "platform_country_iso2": "DE",
          "platform_currency_iso3": "EUR",
          "prices": {
            "special_price": {
              "base": {
                "price_net": 4999,
                "price_gross": 5949,
                "tax_rate": 1900,
                "valid_from": "2024-02-01T00:00:00Z",
                "valid_to": "2024-06-30T23:59:59Z",
                "created_at": "2024-02-01T09:00:00Z",
                "updated_at": "2024-02-01T09:00:00Z"
              },
              "customer_group_prices": [],
              "customer_prices": [],
              "quantity_tier_prices": [
                {
                  "quantity_tier_external_id": "ab-5",
                  "min_quantity": 5,
                  "customer_external_id": null,
                  "customer_group_external_id": null,
                  "price_net": 4499,
                  "price_gross": 5354,
                  "tax_rate": 1900,
                  "valid_from": "2024-02-01T00:00:00Z",
                  "valid_to": "2024-06-30T23:59:59Z",
                  "created_at": "2024-02-01T09:00:00Z",
                  "updated_at": "2024-02-01T09:00:00Z"
                },
                {
                  "quantity_tier_external_id": "ab-20",
                  "min_quantity": 20,
                  "customer_external_id": null,
                  "customer_group_external_id": null,
                  "price_net": 3999,
                  "price_gross": 4759,
                  "tax_rate": 1900,
                  "valid_from": "2024-02-01T00:00:00Z",
                  "valid_to": "2024-06-30T23:59:59Z",
                  "created_at": "2024-02-01T09:00:00Z",
                  "updated_at": "2024-02-01T09:00:00Z"
                }
              ]
            }
          }
        },
        {
          "platform_name": "Kaufland DE",
          "platform_provider": "kaufland",
          "platform_country_iso2": "DE",
          "platform_currency_iso3": "EUR",
          "prices": {
            "price": {
              "base": {
                "price_net": 5199,
                "price_gross": 6187,
                "tax_rate": 1900,
                "created_at": "2024-01-20T14:00:00Z",
                "updated_at": "2024-03-10T16:45:00Z"
              },
              "customer_group_prices": [],
              "customer_prices": [],
              "quantity_tier_prices": []
            }
          }
        }
      ]
    }
  ],
  "pagination": {
    "limit": 500,
    "offset": 0,
    "total": null,
    "next_cursor": "SKU-12345"
  }
}
Preise werden als Integer in der kleinsten Waehrungseinheit gespeichert (z.B. Cent). 9999 = 99,99 EUR. tax_rate ist in Basispunkten: 1900 = 19,00%. Datum-Filter verwenden ISO 8601 Format (z.B. 2024-01-01T00:00:00Z). Die Pagination bezieht sich auf Produktetotal ist die Gesamtanzahl der Produkte mit berechneten Preisen. Preise sind hierarchisch gruppiert: Produkt → Plattform → Preistyp → Basis/Kundengruppe/Kunde/Staffel. Staffelpreise zeigen zusaetzlich min_quantity und die optionale Zuordnung zu Kunde oder Kundengruppe. Produkte mit export_excluded = true werden automatisch uebersprungen.
GET/v1/calculated-prices/by-product/{external_id}

Gibt alle berechneten Preise fuer ein einzelnes Produkt zurueck, gruppiert nach Plattform und Preistyp. Gibt 404 zurueck wenn das Produkt export_excluded ist.

Pfad-Parameter

FeldTypStatusBeschreibung
external_idstringPflichtEindeutige external_id des Produkts (URL-encoded)

Beispiel

curl -X GET "https://app.priceivy.com/api/v1/calculated-prices/by-product/SKU-001" \
  -H "Authorization: Bearer rp_dein_api_key"

Response (200)

{
  "data": {
    "product_external_id": "SKU-001",
    "platforms": [
      {
        "platform_name": "Idealo DE",
        "platform_provider": "idealo",
        "platform_country_iso2": "DE",
        "platform_currency_iso3": "EUR",
        "prices": {
          "price": {
            "base": {
              "price_net": 9999,
              "price_gross": 11899,
              "tax_rate": 1900,
              "created_at": "2024-01-15T10:30:00Z",
              "updated_at": "2024-01-15T10:30:00Z"
            },
            "customer_group_prices": [],
            "customer_prices": [],
            "quantity_tier_prices": []
          },
          "min_price": {
            "base": {
              "price_net": 8499,
              "price_gross": 10114,
              "tax_rate": 1900,
              "created_at": "2024-01-15T10:30:00Z",
              "updated_at": "2024-01-15T10:30:00Z"
            },
            "customer_group_prices": [],
            "customer_prices": [],
            "quantity_tier_prices": []
          },
          "max_price": {
            "base": {
              "price_net": 12499,
              "price_gross": 14874,
              "tax_rate": 1900,
              "created_at": "2024-01-15T10:30:00Z",
              "updated_at": "2024-01-15T10:30:00Z"
            },
            "customer_group_prices": [],
            "customer_prices": [],
            "quantity_tier_prices": []
          },
          "special_price": {
            "base": {
              "price_net": 6999,
              "price_gross": 8329,
              "tax_rate": 1900,
              "valid_from": "2024-03-01T00:00:00Z",
              "valid_to": "2024-03-31T23:59:59Z",
              "created_at": "2024-01-15T10:30:00Z",
              "updated_at": "2024-01-15T10:30:00Z"
            },
            "customer_group_prices": [],
            "customer_prices": [],
            "quantity_tier_prices": []
          }
        }
      }
    ]
  }
}
Die Response-Struktur ist identisch zu einem einzelnen Element aus dem Listen-Endpoint. Gibt 404 zurueck wenn das Produkt nicht existiert oder keine berechneten Preise hat.

Response-Felder (hierarchische Struktur)

FeldTypStatusBeschreibung
product_external_idstringPflichtExternal ID des Produkts
platformsarrayPflichtListe der Plattformen mit Preisen

platforms[]

FeldTypStatusBeschreibung
platform_namestringPflichtName der Plattform
platform_providerstringPflichtProvider der Plattform (z.B. idealo, amazon)
platform_country_iso2stringPflichtLaendercode (ISO 3166-1 alpha-2, z.B. DE)
platform_currency_iso3stringPflichtWaehrung (ISO 4217, z.B. EUR)
pricesobjectPflichtPreise gruppiert nach Preistyp (z.B. price, min_price, max_price, special_price). Jeder Key ist ein Preistyp.

prices.{preistyp}

FeldTypStatusBeschreibung
baseobject | nullOptionalBasispreis (ohne Kunden-/Staffelzuordnung)
customer_group_pricesarrayOptionalKundengruppen-spezifische Preise
customer_pricesarrayOptionalKunden-spezifische Preise
quantity_tier_pricesarrayOptionalMengenstaffel-Preise

Basis-Preisfelder (base, und in allen Preis-Arrays)

FeldTypStatusBeschreibung
price_netinteger | nullOptionalNettopreis in kleinster Waehrungseinheit (z.B. 9999 = 99,99 EUR)
price_grossinteger | nullOptionalBruttopreis in kleinster Waehrungseinheit
tax_rateinteger | nullOptionalSteuersatz in Basispunkten (1900 = 19,00%)
valid_fromstring (ISO 8601) | nullOptionalGueltig ab – nur bei special_price vorhanden
valid_tostring (ISO 8601) | nullOptionalGueltig bis – nur bei special_price vorhanden
created_atstring (ISO 8601)PflichtErstellungsdatum
updated_atstring (ISO 8601)PflichtLetztes Aktualisierungsdatum

Zusatzfelder in customer_group_prices[]

FeldTypStatusBeschreibung
customer_group_external_idstringPflichtExternal ID der Kundengruppe

Zusatzfelder in customer_prices[]

FeldTypStatusBeschreibung
customer_external_idstringPflichtExternal ID des Kunden

Zusatzfelder in quantity_tier_prices[]

FeldTypStatusBeschreibung
quantity_tier_external_idstringPflichtExternal ID der Mengenstaffel
min_quantitynumberPflichtMindestmenge
customer_external_idstring | nullOptionalExternal ID des Kunden (falls kundenspezifisch)
customer_group_external_idstring | nullOptionalExternal ID der Kundengruppe (falls gruppenspezifisch)

Response-Formate

created_by Feld

Alle GET-Responses (Produkte, Kategorien, Kundengruppen, Kunden, Steuersätze) enthalten ein created_by-Objekt, das anzeigt, wer die Ressource erstellt hat.

// Erstellt ueber API-Key:
"created_by": { "type": "api_key", "key_prefix": "rp_a1b2..." }

// Erstellt ueber Dashboard (User):
"created_by": { "type": "user" }

// Unbekannt (z.B. migrierte Daten):
"created_by": null
FeldTypStatusBeschreibung
type"user" | "api_key"OptionalArt des Erstellers — User (Dashboard) oder API-Key
key_prefixstringOptionalNur bei type="api_key": Prefix des API-Keys (z.B. "rp_a1b2...")

Produkt Sub-Resource Formate

Die folgenden Formate gelten fuer die Sub-Ressourcen in Produkt-Responses (prices, images, identifiers, attributes, categories, quantity_tiers).

// prices
{ "price_type": "ek", "currency": "EUR", "price_net": 2499, "price_gross": 2974, "created_at": "2025-01-15T10:30:00.000Z" }

// images
{ "url": "https://example.com/bild.jpg", "sort": 0, "created_at": "2025-01-15T10:30:00.000Z" }

// identifiers
{ "key": "asin", "value": "B08N5WRWNW", "created_at": "2025-01-15T10:30:00.000Z" }

// attributes
{ "key": "farbe", "value": "Schwarz", "created_at": "2025-01-15T10:30:00.000Z" }

// categories
{ "external_id": "elektronik", "name": "Elektronik" }

// quantity_tiers
{ "external_id": "staffel-1", "min_quantity": 10, "customer_external_id": null, "customer_group_external_id": "grosshandel", "created_at": "2025-01-15T10:30:00.000Z" }

Standard-Response (Einzelnes Objekt)

{
  "data": {
    "external_id": "WM-2024",
    "name": "Wireless Maus Pro"
  }
}

Listen-Response (mit Pagination)

{
  "data": [
    { "external_id": "WM-2024", "name": "Wireless Maus Pro" },
    { "external_id": "KB-2024", "name": "Mechanische Tastatur" }
  ],
  "pagination": {
    "limit": 50,
    "offset": 0,
    "total": 127,
    "next_cursor": "KB-2024"
  }
}

Bulk-Upsert-Response

Alle Bulk-Upsert-Endpoints geben immer ein Summary-Format zurueck.

{
  "summary": {
    "total": 100,
    "created": 40,
    "updated": 55,
    "failed": 3,
    "duplicates": 2,
    "skipped": 0
  },
  "errors": [
    { "external_id": "prod-x", "error": "Fehlermeldung" }
  ]
}

Das optionale warnings-Array erscheint nur bei Produkt- und Kategorie-Bulk-Endpoints, wenn bei Sub-Daten (Preise, Bilder, Attribute etc.) Teilfehler aufgetreten sind. Kundengruppen- und Kunden-Bulk-Endpoints geben kein warnings-Array zurueck. Beim Produkt-Bulk-Upsert enthaelt die Summary zusaetzlich skipped und optional ein skipped_external_ids-Array fuer Produkte mit aktiviertem Import-Ausschluss.

Bulk-Delete-Response

Alle Bulk-Delete-Endpoints geben immer ein Summary-Format zurueck.

{
  "summary": {
    "total": 50,
    "succeeded": 48,
    "failed": 2
  },
  "errors": [
    { "external_id": "prod-x", "error": "Produkt nicht gefunden" }
  ]
}

Das optionale warnings-Array erscheint nur bei Produkt- und Kategorie-Bulk-Delete-Endpoints, wenn bei Sub-Daten Teilfehler aufgetreten sind.

Fehler-Response

Einfacher Fehler:

{
  "error": "Beschreibung des Fehlers"
}

Fehler mit Details (z.B. bei Bulk-Validierung):

{
  "error": "2 von 5 Items haben Validierungsfehler",
  "details": {
    "validation_errors": [
      { "index": 0, "external_id": null, "error": "external_id ist erforderlich" }
    ]
  }
}

Delete-Response

{
  "data": {
    "success": true
  }
}

Fehlercodes

CodeTitelBeschreibung
400Bad RequestUngueltiges JSON im Request-Body
401UnauthorizedKein API-Key im Authorization-Header oder Key ist ungueltig
403ForbiddenAPI-Key ist abgelaufen
404Not FoundRessource nicht gefunden (Produkt, Kategorie, etc.)
409ConflictDuplikat — ein Eintrag mit gleicher external_id existiert bereits (seltener Edge-Case bei parallelen Requests, da PUT idempotent ist)
429Too Many RequestsRate Limit ueberschritten — max. 100 Requests pro Minute pro API-Key. Siehe Retry-After Header.
422UnprocessableValidierungsfehler — fehlende Pflichtfelder, unbekannte Felder oder ungueltige Referenzen
500Server ErrorInterner Serverfehler — bitte kontaktiere den Support

Fehler-Response Format

Alle Fehler werden als JSON mit einem error Feld zurueckgegeben:

// 422 — Validierungsfehler (Einzel-Endpoint)
{
  "error": "external_id ist erforderlich"
}

// 422 — Validierungsfehler (Bulk mit Details)
{
  "error": "2 von 5 Items haben Validierungsfehler",
  "details": {
    "validation_errors": [
      { "index": 1, "external_id": null, "error": "external_id ist erforderlich" },
      { "index": 3, "external_id": "X", "error": "prices[0].price_type ist ungueltig" }
    ]
  }
}

// 409 — Duplikat
{
  "error": "Produkt mit dieser external_id existiert bereits"
}

// 401 — Nicht autorisiert
{
  "error": "API-Key ist ungueltig"
}