Entwickler

4pricing-API für Entwickler

Verbinden Sie Ihren Onlineshop, Ihr ERP oder eine Tabelle mit 4pricing: Sie lesen die Preise Ihrer Wettbewerber, senden Ihre eigenen Preise und Verkäufe und erhalten Preisänderungen über einen signierten Webhook. Sie müssen kein Programmierer sein, um loszulegen — der Schnellstart unten liefert Ihnen eine fertige Datei, die Sie nur noch hochladen müssen.

Basis-URL: https://4pricing.net/api/v1/pricing · OpenAPI-Spezifikation (JSON)

Schnelle Anbindung in 3 Schritten

Das ist der kürzeste Weg, Ihre 4pricing-Daten auf Ihrer eigenen Website zu sehen. Sie kopieren eine Datei, tragen Ihren Schlüssel darin ein und laden sie auf Ihr Hosting hoch — ohne Framework, ohne Installation.

Was Sie brauchen
  • Ein aktives 4pricing-Abonnement (die API ist in jedem Tarif enthalten).
  • Ein Hosting mit PHP — fast jedes Shared Hosting bietet es (cPanel, Plesk und ähnliche).
  • Eine Möglichkeit, eine Datei hochzuladen: den Dateimanager Ihres Hosters oder ein FTP-Programm.
  1. Schritt 1: API-Schlüssel erstellen

    Melden Sie sich bei panel.4pricing.net an und öffnen Sie Preisüberwachung → API & Schlüssel.

    Klicken Sie auf „Schlüssel generieren“, vergeben Sie einen Namen (zum Beispiel „mein Shop“) und kopieren Sie den Schlüssel, der mit prc_live_ beginnt. Er wird nur ein einziges Mal angezeigt — wenn Sie ihn verlieren, erstellen Sie einen neuen und widerrufen den alten.

    API & Schlüssel im Panel öffnen →

  2. Schritt 2: Fertige Datei kopieren und Schlüssel einfügen

    Kopieren Sie die PHP-Datei unten in einen Texteditor (Notepad, TextEdit oder VS Code) und speichern Sie sie unter dem Namen 4pricing-preise.php.

    php4pricing-preise.php
    <?php
    // =====================================================================
    // HIER IHREN API-SCHLÜSSEL EINFÜGEN (panel.4pricing.net → API & Schlüssel), zwischen den Anführungszeichen
    $apiKey = 'HIER_IHREN_SCHLUESSEL_EINFUEGEN';
    // =====================================================================
    
    header('Content-Type: text/html; charset=utf-8');
    
    function h($text) { return htmlspecialchars((string) $text, ENT_QUOTES, 'UTF-8'); }
    function money($cents) {
        if ($cents === null) { return '—'; }
        return number_format($cents / 100, 2, ',', '.');
    }
    
    if (strpos($apiKey, 'prc_') !== 0) {
        exit('<p>' . h('Der API-Schlüssel fehlt: Öffnen Sie die Datei und fügen Sie Ihren Schlüssel in der markierten Zeile ein.') . '</p>');
    }
    
    $ch = curl_init('https://4pricing.net/api/v1/pricing/groups/');
    curl_setopt_array($ch, [
        CURLOPT_RETURNTRANSFER => true,
        CURLOPT_USERAGENT => 'my-shop-integration/1.0',
        CURLOPT_TIMEOUT => 30,
        CURLOPT_HTTPHEADER => ['X-API-Key: ' . $apiKey, 'Accept: application/json'],
    ]);
    $body = curl_exec($ch);
    $status = curl_getinfo($ch, CURLINFO_HTTP_CODE);
    
    if ($body === false) {
        exit('<p>' . h('Verbindung zu 4pricing nicht möglich:' . ' ' . curl_error($ch)) . '</p>');
    }
    if ($status !== 200) {
        $hints = [401 => 'der API-Schlüssel ist falsch oder wurde widerrufen', 402 => 'das Konto hat kein aktives 4pricing-Abonnement (oder nicht genügend Credits)', 429 => 'zu viele Anfragen in einer Minute, versuchen Sie es in einer Minute erneut'];
        $hint = isset($hints[$status]) ? ' — ' . $hints[$status] : '';
        exit('<p>' . h('4pricing hat mit einem Fehler geantwortet' . ' ' . $status . $hint) . '</p><pre>' . h($body) . '</pre>');
    }
    
    $groups = json_decode($body, true);
    $verdicts = [
        'cheapest' => 'Sie sind der Günstigste',
        'too_cheap' => 'Deutlich günstiger als der Markt — Sie können den Preis erhöhen',
        'competitive' => 'Wettbewerbsfähig',
        'too_expensive' => 'Teurer als die meisten Wettbewerber',
        'no_competitors' => 'Noch kein Wettbewerberpreis',
        'no_own_price' => 'Ihr Preis fehlt',
    ];
    
    echo '<!doctype html><html><head><meta charset="utf-8"><title>' . h('Meine überwachten Produkte') . '</title>';
    echo '<style>body{font-family:Arial,sans-serif;margin:24px}table{border-collapse:collapse}';
    echo 'th,td{border:1px solid #ddd;padding:6px 10px;text-align:left}th{background:#f5f5f5}</style>';
    echo '</head><body><h1>' . h('Meine überwachten Produkte') . '</h1>';
    
    if (!$groups) {
        echo '<p>' . h('Sie haben noch keine verglichenen Produkte.') . '</p>';
    } else {
        echo '<table><tr><th>' . h('Produkt') . '</th><th>' . h('SKU') . '</th>';
        echo '<th>' . h('Ihr Preis') . '</th><th>' . h('Günstigster Wettbewerber') . '</th>';
        echo '<th>' . h('Differenz') . '</th><th>' . h('Einschätzung') . '</th></tr>';
        foreach ($groups as $g) {
            $yours = $g['own_price_cents_effective'];
            $cheapest = $g['min_competitor_cents'];
            $diff = '—';
            if ($yours !== null && $cheapest !== null) {
                $diff = ($yours > $cheapest ? '+' : '') . money($yours - $cheapest);
            }
            $verdict = isset($verdicts[$g['verdict']]) ? $verdicts[$g['verdict']] : $g['verdict'];
            echo '<tr><td>' . h($g['name']) . '</td><td>' . h($g['sku']) . '</td>';
            echo '<td>' . money($yours) . '</td><td>' . money($cheapest) . '</td>';
            echo '<td>' . $diff . '</td><td>' . h($verdict) . '</td></tr>';
        }
        echo '</table>';
    }
    echo '</body></html>';
    
    Ersetzen Sie HIER_IHREN_SCHLUESSEL_EINFUEGEN durch Ihren Schlüssel und behalten Sie die Anführungszeichen drumherum bei. Das ist die einzige Zeile, die Sie ändern müssen.
  3. Schritt 3: Datei hochladen und im Browser öffnen

    Laden Sie 4pricing-preise.php per Dateimanager oder FTP auf Ihre Website hoch, in denselben Ordner wie Ihre Seite (meist public_html).

    Öffnen Sie https://ihre-website/4pricing-preise.php im Browser. Sie sehen eine Tabelle mit jedem verglichenen Produkt: Ihr Preis, den günstigsten Preis der Wettbewerber, die Differenz und die Einschätzung.

Die Datei: Ihre Produkte mit dem günstigsten Wettbewerberpreis auflisten

Die Datei fragt bei 4pricing Ihre verglichenen Produkte ab (GET /groups/) und zeigt sie als Tabelle an. Das Lesen von Daten ist kostenlos und verbraucht keine Credits.

  • „Ihr Preis“ ist der Preis, den 4pricing für Sie kennt; „Günstigster Wettbewerber“ ist der niedrigste Preis unter den Wettbewerbern, die Sie überwachen.
  • Preise werden in ganzen Währungseinheiten angezeigt (12999 Cent werden zu 129,99); ein Strich (—) bedeutet, dass 4pricing noch keinen Preis hat, nicht dass der Preis null ist.
  • Wenn Sie statt der Tabelle eine Fehlermeldung sehen, sagt Ihnen die Meldung, was zu beheben ist: falscher Schlüssel, kein aktives Abonnement oder zu viele Anfragen in einer Minute.

Zweites Rezept: Ihren Preis senden

Nutzen Sie es, wenn 4pricing Ihren eigenen Preis kennen soll, ohne ihn von Ihrer Shopseite zu lesen — zum Beispiel direkt aus der Datenbank Ihres Shops. Das Senden Ihrer Preise ist kostenlos (keine Credits) und zählt nicht zum Limit überwachter URLs Ihres Tarifs.

FeldBedeutung
skuIhre Artikelnummer; 4pricing findet das Produkt darüber oder legt es beim ersten Mal an
nameder Produktname, so wie Sie ihn in 4pricing sehen möchten
urloptional: die Adresse der Produktseite in Ihrem Shop (sie wird nie gelesen)
price_centsder Preis mal 100, ohne Dezimalstellen: 49,99 → 4999
currencyder Währungscode, zum Beispiel EUR, GBP oder RON (RON, wenn er fehlt)
php4pricing-preis-senden.php
<?php
// =====================================================================
// HIER IHREN API-SCHLÜSSEL EINFÜGEN (panel.4pricing.net → API & Schlüssel), zwischen den Anführungszeichen
$apiKey = 'HIER_IHREN_SCHLUESSEL_EINFUEGEN';
// =====================================================================

// IHRE PRODUKTE: ein Block pro Produkt. price_cents = Preis x 100 (49,99 wird zu 4999).
$products = [
    [
        'sku' => 'T-SHIRT-WEISS-M',
        'name' => 'Weißes T-Shirt, Größe M',
        'url' => 'https://ihr-shop.example/weisses-t-shirt-m',
        'price_cents' => 4999,
        'currency' => 'EUR',
    ],
];

header('Content-Type: text/html; charset=utf-8');

function h($text) { return htmlspecialchars((string) $text, ENT_QUOTES, 'UTF-8'); }

if (strpos($apiKey, 'prc_') !== 0) {
    exit('<p>' . h('Der API-Schlüssel fehlt: Öffnen Sie die Datei und fügen Sie Ihren Schlüssel in der markierten Zeile ein.') . '</p>');
}

$ch = curl_init('https://4pricing.net/api/v1/pricing/own-products/bulk');
curl_setopt_array($ch, [
    CURLOPT_RETURNTRANSFER => true,
    CURLOPT_USERAGENT => 'my-shop-integration/1.0',
    CURLOPT_TIMEOUT => 60,
    CURLOPT_POST => true,
    CURLOPT_HTTPHEADER => ['X-API-Key: ' . $apiKey, 'Content-Type: application/json', 'Accept: application/json'],
    CURLOPT_POSTFIELDS => json_encode(['items' => $products], JSON_UNESCAPED_UNICODE | JSON_UNESCAPED_SLASHES),
]);
$body = curl_exec($ch);
$status = curl_getinfo($ch, CURLINFO_HTTP_CODE);

if ($body === false) {
    exit('<p>' . h('Verbindung zu 4pricing nicht möglich:' . ' ' . curl_error($ch)) . '</p>');
}
if ($status !== 200) {
    $hints = [401 => 'der API-Schlüssel ist falsch oder wurde widerrufen', 402 => 'das Konto hat kein aktives 4pricing-Abonnement (oder nicht genügend Credits)', 429 => 'zu viele Anfragen in einer Minute, versuchen Sie es in einer Minute erneut'];
    $hint = isset($hints[$status]) ? ' — ' . $hints[$status] : '';
    exit('<p>' . h('4pricing hat mit einem Fehler geantwortet' . ' ' . $status . $hint) . '</p><pre>' . h($body) . '</pre>');
}

$result = json_decode($body, true);
echo '<h1>' . h('An 4pricing gesendete Preise') . '</h1>';
echo '<p>' . h('Neu angelegte Produkte:') . ' ' . (int) $result['created'] . '</p>';
echo '<p>' . h('Aktualisierte Produkte:') . ' ' . (int) $result['updated'] . '</p>';
if (!empty($result['errors'])) {
    echo '<p>' . h('Zeilen mit Problemen:') . '</p><ul>';
    foreach ($result['errors'] as $error) {
        echo '<li>' . h($error) . '</li>';
    }
    echo '</ul>';
}
  • Speichern Sie die Datei als 4pricing-preis-senden.php, fügen Sie Ihren Schlüssel ein, passen Sie die Produktzeilen an, laden Sie sie hoch und öffnen Sie sie einmal: Die Seite zeigt, wie viele Produkte angelegt und wie viele aktualisiert wurden.
  • Jede Anfrage kann bis zu 2.000 Produkte enthalten; eine fehlerhafte Zeile wird gemeldet, die übrigen werden trotzdem gespeichert. Wenn Sie dieselbe sku erneut senden, wird der Preis aktualisiert.

Dieselben Aufrufe mit curl

Wenn Sie das Terminal bevorzugen: Diese zwei Befehle tun genau dasselbe wie die beiden PHP-Dateien:

bash
curl https://4pricing.net/api/v1/pricing/groups/ \
  -H "X-API-Key: HIER_IHREN_SCHLUESSEL_EINFUEGEN"
bash
curl -X POST https://4pricing.net/api/v1/pricing/own-products/bulk \
  -H "X-API-Key: HIER_IHREN_SCHLUESSEL_EINFUEGEN" \
  -H "Content-Type: application/json" \
  -d '{"items":[{"sku":"T-SHIRT-WEISS-M","name":"Weißes T-Shirt, Größe M","url":"https://ihr-shop.example/weisses-t-shirt-m","price_cents":4999,"currency":"EUR"}]}'
Schlüssel sicher aufbewahren
  • Der Schlüssel gewährt Zugriff auf Ihr gesamtes 4pricing-Konto. Bewahren Sie ihn nur in serverseitigen Dateien auf (PHP, Ihr Backend) — niemals in JavaScript im Browser oder in einem öffentlichen Repository.
  • Jeder, der die Adresse der hochgeladenen Seite kennt, kann die Preistabelle sehen (nicht den Schlüssel). Geben Sie der Datei einen schwer zu erratenden Namen, schützen Sie den Ordner mit einem Passwort oder löschen Sie die Datei, wenn Sie sie nicht mehr brauchen.
  • Wenn ein Schlüssel in falsche Hände gerät, widerrufen Sie ihn unter API & Schlüssel — er funktioniert sofort nicht mehr — und erstellen Sie einen neuen.

Authentifizierung

  • Jede Anfrage trägt Ihren Schlüssel im Header X-API-Key. Auch Authorization: Bearer prc_live_… funktioniert (nur für Schlüssel, die mit prc_ beginnen).
  • Es gibt keine Scopes: Ein Schlüssel kann alles in Ihrem 4pricing-Konto lesen und ändern. Erstellen Sie pro Integration einen eigenen Schlüssel (Shop, ERP, Bericht), damit Sie einen widerrufen können, ohne die anderen zu stoppen.
  • Ein fehlender, falscher oder widerrufener Schlüssel erhält 401. Ein Widerruf wirkt sofort. Zu viele ungültige Schlüssel in einer Minute erhalten 429.
  • Schlüssel werden ausschließlich im Panel erstellt, aufgelistet und widerrufen (Preisüberwachung → API & Schlüssel); die API selbst kann keine Schlüssel verwalten. Zum Erstellen eines Schlüssels ist ein aktives 4pricing-Abonnement erforderlich.
http
X-API-Key: prc_live_…
# or
Authorization: Bearer prc_live_…

Basis-URL und Konventionen

  • Jeder Pfad in dieser Dokumentation ist relativ zur Basis-URL — /groups/ bedeutet https://4pricing.net/api/v1/pricing/groups/.
  • Anfragen und Antworten sind JSON (Content-Type: application/json).
  • Beträge sind ganze Zahlen in der kleinsten Einheit (Cent): price_cents = 12999 bedeutet 129,99. Prozentwerte werden in Basispunkten angegeben (100 = 1 %).
  • Ein unbekannter Wert ist null, niemals 0 — zeigen Sie ihn als „—“ an.
  • Sammlungen werden mit einem abschließenden Schrägstrich aufgerufen (/products/, /groups/, /insights/).
  • Paginierte Listen liefern die Gesamtzahl im Header X-Total-Count (zum Beispiel GET /products/?skip=0&limit=200).
  • Senden Sie einen User-Agent-Header, der Ihre Integration benennt (zum Beispiel my-shop-integration/1.0). Die Firewall vor der API antwortet auf manche generischen Bibliotheks-Standardwerte, etwa Python-urllib, mit 403.

Anfragelimit, Abonnement und Plangrenzen

Anfragelimit

  • 60 Anfragen pro Minute und KONTO, in einem gleitenden Fenster — alle Schlüssel desselben Kontos teilen sich dieselben 60.
  • Jede Antwort enthält X-RateLimit-Limit, X-RateLimit-Remaining und X-RateLimit-Reset (die Fensterlänge in Sekunden).
  • Wird das Limit überschritten, erhalten Sie 429 mit einem Retry-After-Header (Sekunden). Warten Sie so lange und versuchen Sie es dann erneut — die Beispiele unten erledigen das für Sie.
http
HTTP/2 200
x-ratelimit-limit: 60
x-ratelimit-remaining: 59
x-ratelimit-reset: 60

HTTP/2 429
retry-after: 60
{"detail":"Rate limit exceeded"}

Abonnement und Plangrenzen

  • Die API erfordert ein aktives 4pricing-Abonnement; ohne eines erhält jede Anfrage 402 mit dem Code plan_required.
  • Jeder Tarif enthält die API mit denselben Limits wie das Panel. Wenn Sie beim Hinzufügen oder Reaktivieren ein Limit überschreiten, erhalten Sie 402 mit dem Code plan_limit und einer Meldung, die nennt, um welches Limit es geht.
LimitBedeutung
Überwachte URLsJede Produktseiten-Adresse, die 4pricing liest, zählt einzeln: Ihre eigene Seite und jede Wettbewerberseite. Preise, die Sie mit /own-products senden, zählen nicht.
Wettbewerber-ShopsDie Anzahl der verschiedenen Wettbewerber-Websites (Domains), die Sie überwachen.
Minimales PrüfintervallWie oft dieselbe URL geprüft werden darf. Kürzere Intervalle werden automatisch auf das Minimum Ihres Tarifs angehoben; eine zu frühe Aktualisierung einer URL erhält 402 plan_limit.

Welche Aufrufe Credits verbrauchen

Das Lesen einer Shopseite kostet Credits aus dem Guthaben Ihres Kontos. Die folgenden Aufrufe prüfen das Guthaben, BEVOR etwas gelesen wird: Reicht es nicht, erhalten Sie 402 insufficient_credits, und lässt sich das Guthaben gerade nicht abrufen, erhalten Sie 503 credit_wallet_unavailable (später erneut versuchen). In beiden Fällen wird nichts gelesen und nichts berechnet.

Aufrufe, die Credits verbrauchen

MethodeEndpunktWas er tutKosten
POST/groups/{group_id}/membersEine URL zur Gruppe hinzufügen, per product_id oder über eine neue Adresse (eine neue Adresse wird sofort gelesen)Credits
POST/groups/{group_id}/refreshJede URL der Gruppe jetzt prüfenCredits
POST/groups/{group_id}/suggestions„Wettbewerber finden“: vorgeschlagene Wettbewerber-URLs mit Score und BegründungCredits
POST/products/Eine URL zu überwachen beginnen (url, name, Rolle own oder competitor) — sie wird sofort gelesenCredits
POST/products/{product_id}/refreshDen Preis dieser URL jetzt prüfen (unter Beachtung des Mindestintervalls Ihres Tarifs)Credits
POST/search/Den Live-Preis eines Produkts bei Händlern suchen (Credits für jeden durchsuchten Händler)Credits

Kostenlose Aufrufe

  • Jeder lesende Aufruf (GET): Produkte, Gruppen, Vergleiche, Verlauf, Alarme, Insights, Briefings, Credits, Statistiken.
  • POST /own-products/ und POST /own-products/bulk — Ihre eigenen Preise.
  • POST /sales/bulk — Ihre Verkäufe.
  • Alarme, Einstellungen, Bestätigungen und alles andere, was keine Shopseite liest.
  • Auch die geplante Überwachung der URLs, die Sie verfolgen, verbraucht bei jeder Prüfung Credits; GET /credits/ zeigt Ihr Guthaben und die Prognose.
  • POST /products/import fügt viele URLs auf einmal hinzu, ohne sie sofort zu lesen: Sie werden von der geplanten Überwachung geprüft und dort berechnet.

Endpunkt-Referenz

Jede Operation, die ein Schlüssel erreichen kann, gruppiert nach ihrem Zweck. Die OpenAPI-Spezifikation beschreibt jede einzelne Feld für Feld, mit den genauen Request- und Response-Bodys.

Ihre eigenen Preise

Teilen Sie 4pricing Ihren Preis direkt mit, ohne Ihre Shopseite zu lesen. Kostenlos.

MethodeEndpunktWas er tutKosten
POST/own-products/Aktuellen Preis für ein Produkt senden (gefunden über sku, sonst über den Namen; wird angelegt, falls es fehlt)Kostenlos
POST/own-products/bulkPreise für bis zu 2.000 Produkte in einer Anfrage senden; fehlerhafte Zeilen werden gemeldet, der Rest wird gespeichertKostenlos

Verglichene Produkte (Gruppen)

Eine Gruppe ist ein Produkt von Ihnen zusammen mit den Wettbewerberseiten, die dasselbe verkaufen. Sie enthält die Einschätzung und den empfohlenen Preis.

MethodeEndpunktWas er tutKosten
GET/groups/Alle verglichenen Produkte, jeweils mit Ihrem Preis, dem günstigsten Wettbewerberpreis, der Einschätzung und dem empfohlenen PreisKostenlos
POST/groups/Ein verglichenes Produkt anlegen (Name, sku, Ihr Preis, Einkaufspreis, Preisstrategie)Kostenlos
GET/groups/{group_id}Ein verglichenes ProduktKostenlos
PUT/groups/{group_id}Preis, Einkaufspreis, Strategie, Prüfintervall oder die Shop-Verknüpfung (store_kind) aktualisierenKostenlos
DELETE/groups/{group_id}Die Gruppe löschen; ihre URLs bleiben überwachtKostenlos
GET/groups/{group_id}/comparisonIhre Position gegenüber jedem Wettbewerber, mit dem empfohlenen Preis und seiner BerechnungKostenlos
GET/groups/{group_id}/historyPreisverlauf jeder URL der GruppeKostenlos
GET/groups/seriesIhre Marktposition, Tag für Tag, über alle Produkte hinwegKostenlos
POST/groups/{group_id}/membersEine URL zur Gruppe hinzufügen, per product_id oder über eine neue Adresse (eine neue Adresse wird sofort gelesen)Credits
DELETE/groups/{group_id}/members/{product_id}Eine URL aus der Gruppe entfernen (sie bleibt überwacht)Kostenlos
POST/groups/{group_id}/refreshJede URL der Gruppe jetzt prüfenCredits
POST/groups/{group_id}/apply-recommendedDen empfohlenen Preis in 4pricing zu Ihrem eigenen Preis machen (den gesehenen Preis mitsenden; 409, wenn er sich geändert hat)Kostenlos
GET/groups/suggestions/sourcesFür „Wettbewerber finden“ verfügbare QuellenKostenlos
POST/groups/{group_id}/suggestions„Wettbewerber finden“: vorgeschlagene Wettbewerber-URLs mit Score und BegründungCredits

Überwachte URLs

Eine Zeile pro Seitenadresse, die 4pricing liest, Ihre eigene oder die eines Wettbewerbers (Rolle own oder competitor).

MethodeEndpunktWas er tutKosten
GET/products/Überwachte URLs, paginiert (skip, limit bis 500; Gesamtzahl in X-Total-Count)Kostenlos
POST/products/Eine URL zu überwachen beginnen (url, name, Rolle own oder competitor) — sie wird sofort gelesenCredits
POST/products/importViele URLs auf einmal hinzufügen; sie werden später von der geplanten Überwachung gelesenKostenlos
GET/products/exportCSV-Export der aktiven URLsKostenlos
GET/products/{product_id}Eine überwachte URL mit ihrem letzten PreisKostenlos
PATCH/products/{product_id}Name, Kategorie oder Prüfintervall ändernKostenlos
DELETE/products/{product_id}Die Überwachung einer URL beenden (sie bleibt als inaktiv erhalten)Kostenlos
POST/products/{product_id}/refreshDen Preis dieser URL jetzt prüfen (unter Beachtung des Mindestintervalls Ihres Tarifs)Credits
GET/products/{product_id}/historyPreisverlauf einer URLKostenlos
GET/products/sparklinesEin kurzer Preisverlauf für mehrere URLs gleichzeitigKostenlos
GET/products/price-changesURLs, deren Preis sich bei der letzten Prüfung geändert hatKostenlos

Den Preis eines Produkts sofort bei Händlern nachschlagen.

MethodeEndpunktWas er tutKosten
POST/search/Den Live-Preis eines Produkts bei Händlern suchen (Credits für jeden durchsuchten Händler)Credits

Alarme

Preisregeln und der Posteingang der ausgelösten Alarme.

MethodeEndpunktWas er tutKosten
GET/alerts/Ihre PreisalarmeKostenlos
POST/alerts/Einen Alarm anlegen (Preis unter/über einem Wert, Rückgang in %, wieder auf Lager, Unterbietung durch einen Wettbewerber …)Kostenlos
DELETE/alerts/{alert_id}Einen Alarm löschenKostenlos
POST/alerts/{alert_id}/rearmEinen ausgelösten Alarm erneut scharf schaltenKostenlos
GET/alerts/eventsPosteingang der ausgelösten AlarmeKostenlos
GET/alerts/events/unread-countWie viele ungelesene Alarme Sie habenKostenlos
POST/alerts/events/read-allDie Alarme als gelesen markieren (optional nur die vor einem bestimmten Zeitpunkt)Kostenlos
POST/alerts/events/{event_id}/readEinen Alarm als gelesen markierenKostenlos

Credits

Guthaben, Prognose und jede Credit-Bewegung.

MethodeEndpunktWas er tutKosten
GET/credits/Credit-Guthaben und VerbrauchsprognoseKostenlos
GET/credits/ledgerJede Credit-BewegungKostenlos
GET/credits/by-productVerbrauchte Credits pro URL (gesamt und letzte 30 Tage)Kostenlos

Ihre Verkäufe

Tägliche Verkäufe pro Produkt, mit denen der Wert jeder Chance berechnet wird. Kostenlos.

MethodeEndpunktWas er tutKosten
POST/sales/bulkTägliche Verkäufe pro Produkt (sku oder group_id, day, units_sold, revenue_cents; optional stock_units, cost_cents), bis zu 2.000 Zeilen; wer dasselbe Produkt und denselben Tag erneut sendet, überschreibt den EintragKostenlos

Insights, Chancen und Briefings

Was sich geändert hat, warum es wichtig ist und was zu tun ist — dazu das tägliche Briefing.

MethodeEndpunktWas er tutKosten
GET/insights/Insights mit Belegen und Preisvorschlägen (X-Total-Count)Kostenlos
GET/insights/{insight_id}Ein Insight im DetailKostenlos
POST/insights/{insight_id}/dismissEin Insight verwerfenKostenlos
GET/opportunities/Zusammenfassung der Chancen: Wert aus Ihren Verkäufen, getrennt von der MarktschätzungKostenlos
GET/briefings/Verlauf der täglichen BriefingsKostenlos
GET/briefings/latestDas aktuellste tägliche BriefingKostenlos
POST/briefings/generateDas heutige Briefing aus den offenen Insights neu erstellen (es versendet nichts)Kostenlos

Preisaktionen

Preisänderungen, die vorgeschlagen, gesendet, angewendet oder zurückgesetzt wurden. Über die API können Sie sie lesen und die per Webhook empfangenen bestätigen.

MethodeEndpunktWas er tutKosten
GET/actions/Preisaktionen: vorgeschlagen, gesendet, angewendet, zurückgesetztKostenlos
POST/actions/{action_id}/confirmBestätigen, dass Ihr System einen über price.apply oder price.revert empfangenen Preis angewendet hatKostenlos

Einstellungen

Kontoeinstellungen, einschließlich Webhook-Adresse und Secret.

MethodeEndpunktWas er tutKosten
GET/settings/Kontoeinstellungen (Händler, Repricing-Strategie, Alarm-Zustellung, Webhook)Kostenlos
PUT/settings/Einstellungen ändern, einschließlich alert_webhook_url, alert_webhook_secret und alert_webhook_enabledKostenlos

Statistiken

Kontoübersicht und Zustand der Preisprüfungen.

MethodeEndpunktWas er tutKosten
GET/stats/Kontostatistiken: URLs, Alarme, Änderungen der letzten 24 Stunden, GruppenKostenlos
GET/stats/scrapersZustand der Preisprüfungen pro HändlerKostenlos

53 endpoints · https://4pricing.net/api/v1/pricing/openapi.json

Was die API nicht kann

Manche Dinge bleiben bewusst im Panel, wo eine angemeldete Person entscheidet. Über die API antworten diese Pfade mit 404:

PfadGrund
/keys/…Schlüssel erstellen und widerrufen — ein Schlüssel kann keine weiteren Schlüssel erstellen.
/autopilot/…Die Autopilot-Richtlinie, die festlegt, was sich ohne menschliches Zutun ändern darf; ein geleakter Schlüssel darf sie nicht erweitern können.
/watchlists/…Watchlists, die bei jedem Durchlauf Credits verbrauchen.
/actions/{action_id}/approve · reject · revertEine Preisänderung zu genehmigen, abzulehnen oder zurückzusetzen ist eine Entscheidung, die eine Person im Panel trifft. Die API kann Aktionen nur lesen und bestätigen.
/insights/{insight_id}/act · /insights/runAuf ein Insight reagieren (es schreibt Preise) und Insights neu berechnen.
/admin/… · /internal/…Interne Administration der Plattform.

Webhooks

4pricing kann Ereignisse an eine Adresse von Ihnen senden (einen Webhook): Bei jedem Vorfall wird ein JSON-POST abgesetzt, damit Ihr System nicht ständig nachfragen muss.

Es gibt eine Webhook-Adresse pro Konto; jede Ereignisart geht dorthin. Unterscheiden Sie sie über das Feld event — der Alarm ist das einzige Ereignis ohne dieses Feld.

Aktivieren

  • Setzen Sie alert_webhook_url (eine öffentliche http/https-Adresse auf Port 80 oder 443), alert_webhook_secret und alert_webhook_enabled: true — im Panel oder mit PUT /settings/.
  • Eine Adresse, die auf ein privates oder internes Netz auflöst, wird mit 422 abgelehnt. Weiterleitungen werden nicht verfolgt.
  • Für briefing.ready aktivieren Sie zusätzlich briefing_webhook_enabled. price.apply und price.revert werden nur für Gruppen gesendet, die mit store_kind = webhook mit Ihrem Shop verknüpft sind, und nur wenn ein Secret gesetzt ist.
bash
curl -X PUT https://4pricing.net/api/v1/pricing/settings/ \
  -H "X-API-Key: HIER_IHREN_SCHLUESSEL_EINFUEGEN" \
  -H "Content-Type: application/json" \
  -d '{"alert_webhook_url":"https://your-shop.example/4pricing-webhook.php","alert_webhook_secret":"IHR_WEBHOOK_SECRET","alert_webhook_enabled":true,"briefing_webhook_enabled":true}'

Ereignisse

EreignisBedeutung
alertEin Preisalarm wurde ausgelöst. Body: event_id (darüber deduplizieren), alert_id, alert_type, message, message_code, message_params, price_cents, currency, triggered_at, product, group, panel_url. Kein Feld event.
price.applyEin freigegebener Preis, der in Ihrem Shop anzuwenden ist: action_id, group (id, name, sku, ean, store_product_id), old_price_cents, new_price_cents, currency, reason_code, mode und confirm.path.
price.revertZum vorherigen Preis zurückkehren. Gleicher Body wie price.apply; wenden Sie ihn auf dieselbe Weise an und bestätigen Sie ihn.
briefing.readyDas tägliche Briefing ist fertig: day, headline, summary, sections, total_value_cents (nur aus Ihren Verkäufen), currency, panel_url.

Header jeder Webhook-Anfrage

HeaderBedeutung
X-4Pricing-TimestampWann die Anfrage gesendet wurde, in Unix-Sekunden. Weisen Sie zu alte Anfragen ab (zum Beispiel älter als 5 Minuten).
X-4Pricing-Signaturesha256= gefolgt vom hexadezimalen HMAC-SHA256 des Textes „<timestamp>.<raw body>“, berechnet mit Ihrem Webhook-Secret. Vorhanden, wenn ein Secret gesetzt ist (bei price.apply und price.revert immer).
Content-Typeapplication/json; charset=utf-8
User-Agent4pricing-alerts/1.0

Signatur prüfen

Berechnen Sie die Signatur aus dem Timestamp-Header und dem ROHEN Body, den Sie erhalten haben, neu, vergleichen Sie sie in konstanter Zeit und prüfen Sie den Zeitstempel. Erst dann verarbeiten Sie das Ereignis. Antworten Sie mit einem beliebigen 2xx, wenn Sie es angenommen haben.

php
<?php
$secret = 'IHR_WEBHOOK_SECRET';

// Den ROHEN Body verwenden, genau so, wie er empfangen wurde — kein neu kodiertes JSON
$body = file_get_contents('php://input');
$timestamp = isset($_SERVER['HTTP_X_4PRICING_TIMESTAMP']) ? $_SERVER['HTTP_X_4PRICING_TIMESTAMP'] : '';
$signature = isset($_SERVER['HTTP_X_4PRICING_SIGNATURE']) ? $_SERVER['HTTP_X_4PRICING_SIGNATURE'] : '';
$expected = 'sha256=' . hash_hmac('sha256', $timestamp . '.' . $body, $secret);

// Falsche Signatur oder älter als 5 Minuten: ablehnen
if (!hash_equals($expected, $signature) || abs(time() - (int) $timestamp) > 300) {
    http_response_code(401);
    exit;
}

$event = json_decode($body, true);
if (isset($event['event']) && ($event['event'] === 'price.apply' || $event['event'] === 'price.revert')) {
    // new_price_cents auf das Produkt in Ihrem Shop anwenden (Zuordnung über sku oder store_product_id)
    // $event['group']['sku'], $event['new_price_cents'], $event['currency']
    // Anschließend bestätigen: POST /actions/{action_id}/confirm mit Ihrem API-Schlüssel
}
http_response_code(200);
echo 'ok';
javascript
// Node.js, no package needed
const http = require("http");
const crypto = require("crypto");
const SECRET = process.env.WEBHOOK_SECRET; // IHR_WEBHOOK_SECRET

http.createServer((req, res) => {
  const chunks = [];
  req.on("data", (c) => chunks.push(c));
  req.on("end", () => {
    // Den ROHEN Body verwenden, genau so, wie er empfangen wurde — kein neu kodiertes JSON
    const body = Buffer.concat(chunks);
    const ts = String(req.headers["x-4pricing-timestamp"] || "");
    const sig = String(req.headers["x-4pricing-signature"] || "");
    const expected = "sha256=" + crypto.createHmac("sha256", SECRET).update(ts + ".").update(body).digest("hex");
    const fresh = Math.abs(Date.now() / 1000 - Number(ts)) <= 300;
    const same = sig.length === expected.length && crypto.timingSafeEqual(Buffer.from(sig), Buffer.from(expected));
    if (!same || !fresh) {
      // Falsche Signatur oder älter als 5 Minuten: ablehnen
      res.writeHead(401);
      return res.end();
    }
    const event = JSON.parse(body.toString("utf8"));
    if (event.event === "price.apply" || event.event === "price.revert") {
      // new_price_cents auf das Produkt in Ihrem Shop anwenden (Zuordnung über sku oder store_product_id)
      // Anschließend bestätigen: POST /actions/{action_id}/confirm mit Ihrem API-Schlüssel
    }
    res.writeHead(200);
    res.end("ok");
  });
}).listen(3000);
python
# Python 3, standard library only
import hashlib
import hmac
import time

SECRET = "IHR_WEBHOOK_SECRET"


def is_valid(raw_body: bytes, timestamp: str, signature: str) -> bool:
    # Den ROHEN Body verwenden, genau so, wie er empfangen wurde — kein neu kodiertes JSON
    if not timestamp.isdigit() or abs(time.time() - int(timestamp)) > 300:
        return False
    expected = "sha256=" + hmac.new(
        SECRET.encode(), timestamp.encode() + b"." + raw_body, hashlib.sha256
    ).hexdigest()
    return hmac.compare_digest(expected, signature)

Zustellung und Wiederholungen

  • Alarme: Bei einem Verbindungs- oder DNS-Fehler, 429 oder 5xx wird die Anfrage mit exponentiellem Backoff wiederholt, höchstens 5 Versuche. Jedes andere 4xx ist endgültig.
  • Wurde die Anfrage gesendet, aber innerhalb von 10 Sekunden keine Antwort empfangen, wird sie nicht erneut gesendet (um ein Duplikat zu vermeiden) — in seltenen Fällen kann dennoch ein Duplikat eintreffen, deduplizieren Sie daher über event_id.
  • price.apply und price.revert werden nur einmal gesendet: Schlägt die Zustellung fehl, wird die Aktion auf failed gesetzt. Deduplizieren Sie über action_id.
  • briefing.ready wird einmal am Tag gesendet.

Einen angewendeten Preis bestätigen

  • Ein price.apply gilt erst als angewendet, wenn Ihr System es meldet. Nachdem Sie den Preis in Ihrem Shop geändert haben, rufen Sie POST /actions/{action_id}/confirm mit Ihrem API-Schlüssel auf: Die Aktion wechselt von „gesendet“ zu „angewendet“.
  • Doppeltes Bestätigen schadet nicht — eine bereits angewendete Aktion wird unverändert zurückgegeben.
bash
curl -X POST https://4pricing.net/api/v1/pricing/actions/ACTION_ID/confirm \
  -H "X-API-Key: HIER_IHREN_SCHLUESSEL_EINFUEGEN"

Beispiel-Bodys

json · price.apply
{
  "event": "price.apply",
  "action_id": "8d0f2c4e-0b7a-4f7e-9d61-3c2b1a0e9f55",
  "tenant_id": "…",
  "group": {
    "id": "2fa912df-440c-4ddf-896a-5d558d56085f",
    "name": "Canon RF 50mm F1.8 STM",
    "sku": "4515C005AA",
    "ean": "4549292181623",
    "store_product_id": "1042"
  },
  "old_price_cents": 124900,
  "new_price_cents": 118699,
  "currency": "RON",
  "reason_code": "undercut",
  "mode": "manual",
  "confirm": { "method": "POST", "path": "/api/v1/pricing/actions/8d0f2c4e-0b7a-4f7e-9d61-3c2b1a0e9f55/confirm" }
}
json · alert
{
  "event_id": 18342,
  "alert_id": "c1b5…",
  "alert_type": "competitor_undercut",
  "tenant_id": "…",
  "message_code": "competitor_undercut",
  "message": "…",
  "message_params": { "…": "…" },
  "price_cents": 118990,
  "currency": "RON",
  "triggered_at": "2026-10-13T07:05:12",
  "product": { "id": "…", "name": "…", "url": "https://…", "retailer": "…", "current_price_cents": 118990, "in_stock": true },
  "group": { "id": "…", "name": "Canon RF 50mm F1.8 STM", "sku": "4515C005AA" },
  "panel_url": "https://panel.4pricing.net/…"
}

Fehler

Fehler kommen mit dem passenden HTTP-Status und einem JSON-Body {"detail": …}. detail ist ein Text, ein Objekt mit einem Code, den Sie in Ihrem Programm behandeln können, oder — bei 422 — die Liste der ungültigen Felder.

StatusCodeBedeutung
401—Der API-Schlüssel fehlt, ist falsch oder wurde widerrufen.
402plan_requiredDas Konto hat kein aktives 4pricing-Abonnement.
402plan_limitEin Plan-Limit würde überschritten (überwachte URLs, Wettbewerber-Shops) oder eine Aktualisierung kam vor dem Mindestintervall. Die Meldung nennt, welches.
402insufficient_creditsNicht genügend Credits für einen Aufruf, der eine Shopseite liest. Es wurde nichts gelesen oder berechnet.
403—Von der Firewall blockiert, bevor die API erreicht wurde — meist ein generischer User-Agent wie Python-urllib. Senden Sie Ihren eigenen User-Agent.
404—Die Ressource existiert nicht, gehört nicht zu Ihrem Konto, oder der Pfad ist über die API nicht verfügbar.
409recommendation_moved · own_from_listing · invalid_state · webhook_secret_requiredKonflikt: Der empfohlene Preis hat sich geändert (recommendation_moved), die Aktion ist in einem anderen Zustand (invalid_state), ein Webhook-Secret ist erforderlich, oder die Operation gilt nicht für dieses Element.
422—Ungültige Daten, zum Beispiel eine URL ohne http/https oder ein fehlendes Pflichtfeld. detail listet die Felder auf.
429—Mehr als 60 Anfragen pro Minute für das Konto (oder zu viele ungültige Schlüssel). Warten Sie Retry-After Sekunden.
503credit_wallet_unavailableDas Credit-Guthaben lässt sich gerade nicht abrufen. Versuchen Sie es später erneut; es wurde nichts berechnet.

Fehler-Bodys

json
{"detail": "Invalid or missing API key"}
{"detail": {"code": "plan_required", "message": "…"}}
{"detail": {"code": "insufficient_credits", "message": "…"}}
{"detail": [{"loc": ["body", "price_cents"], "msg": "…", "type": "…"}]}

Codebeispiele

Dieselbe Abfrage in vier Sprachen, mit Pause und erneutem Versuch bei 429, anschließend das Senden von Verkäufen. Ersetzen Sie HIER_IHREN_SCHLUESSEL_EINFUEGEN durch Ihren Schlüssel (oder setzen Sie die Umgebungsvariable PRICING_API_KEY).

Node.js: verglichene Produkte lesen

javascript
// Node.js 18+ (fetch is built in, no package needed)
const API_KEY = process.env.PRICING_API_KEY; // HIER_IHREN_SCHLUESSEL_EINFUEGEN
const BASE = "https://4pricing.net/api/v1/pricing";

async function call(path, options = {}) {
  for (let attempt = 0; attempt < 3; attempt++) {
    const res = await fetch(BASE + path, {
      ...options,
      headers: { "X-API-Key": API_KEY, "Content-Type": "application/json", ...(options.headers || {}) },
    });
    if (res.status === 429) {
      // Über 60 Anfragen/Minute: so viele Sekunden warten, wie Retry-After angibt, dann erneut versuchen
      const wait = Number(res.headers.get("Retry-After") || 60);
      await new Promise((r) => setTimeout(r, wait * 1000));
      continue;
    }
    if (!res.ok) throw new Error(res.status + " " + (await res.text()));
    return res.status === 204 ? null : res.json();
  }
  throw new Error("rate limited");
}

async function main() {
  // Ihre verglichenen Produkte: Ihr Preis, der günstigste Wettbewerber, die Einschätzung
  const groups = await call("/groups/");
  for (const g of groups) {
    console.log(g.name, g.own_price_cents_effective, g.min_competitor_cents, g.verdict);
  }
}

main().catch((err) => {
  console.error(err.message);
  process.exit(1);
});

Python: verglichene Produkte lesen

python
# Python 3, standard library only
import json
import os
import time
import urllib.error
import urllib.request

API_KEY = os.environ["PRICING_API_KEY"]  # HIER_IHREN_SCHLUESSEL_EINFUEGEN
BASE = "https://4pricing.net/api/v1/pricing"


def call(path, method="GET", payload=None):
    data = json.dumps(payload).encode() if payload is not None else None
    for _ in range(3):
        req = urllib.request.Request(BASE + path, data=data, method=method, headers={
            "X-API-Key": API_KEY, "Content-Type": "application/json", "Accept": "application/json",
            # Setzen Sie Ihren eigenen User-Agent: Der Standardwert mancher HTTP-Bibliotheken (Python urllib) wird mit 403 blockiert
            "User-Agent": "my-shop-integration/1.0",
        })
        try:
            with urllib.request.urlopen(req, timeout=30) as res:
                body = res.read()
                return json.loads(body) if body else None
        except urllib.error.HTTPError as err:
            if err.code == 429:
                # Über 60 Anfragen/Minute: so viele Sekunden warten, wie Retry-After angibt, dann erneut versuchen
                time.sleep(int(err.headers.get("Retry-After", "60")))
                continue
            raise
    raise RuntimeError("rate limited")


# Ihre verglichenen Produkte: Ihr Preis, der günstigste Wettbewerber, die Einschätzung
for g in call("/groups/"):
    print(g["name"], g["own_price_cents_effective"], g["min_competitor_cents"], g["verdict"])

curl: tägliche Verkäufe senden

bash
curl -X POST https://4pricing.net/api/v1/pricing/sales/bulk \
  -H "X-API-Key: HIER_IHREN_SCHLUESSEL_EINFUEGEN" \
  -H "Content-Type: application/json" \
  -d '{"rows":[{"sku":"T-SHIRT-WEISS-M","day":"2026-10-12","units_sold":7,"revenue_cents":34993}]}'

PHP: tägliche Verkäufe senden

php
<?php
$apiKey = 'HIER_IHREN_SCHLUESSEL_EINFUEGEN';

// Tägliche Verkäufe pro Produkt (nach sku oder group_id), bis zu 2.000 Zeilen pro Anfrage
$rows = [
    ['sku' => 'T-SHIRT-WEISS-M', 'day' => '2026-10-12', 'units_sold' => 7, 'revenue_cents' => 34993],
];

$ch = curl_init('https://4pricing.net/api/v1/pricing/sales/bulk');
curl_setopt_array($ch, [
    CURLOPT_RETURNTRANSFER => true,
    CURLOPT_USERAGENT => 'my-shop-integration/1.0',
    CURLOPT_POST => true,
    CURLOPT_HTTPHEADER => ['X-API-Key: ' . $apiKey, 'Content-Type: application/json'],
    CURLOPT_POSTFIELDS => json_encode(['rows' => $rows]),
]);
$body = curl_exec($ch);
echo curl_getinfo($ch, CURLINFO_HTTP_CODE) . ' ' . $body;   // 200 {"upserted": 1, "skipped": []}

Häufig gestellte Fragen

Muss ich Programmierer sein, um die 4pricing-API zu nutzen?

Nein. Der Schnellstart liefert Ihnen eine fertige PHP-Datei: Sie erstellen im Panel einen Schlüssel, fügen ihn in die Datei ein, laden die Datei auf Ihr Hosting hoch und öffnen sie im Browser. Für tiefere Integrationen (ein ERP, eine Shopplattform) kann ein Entwickler die Endpunkt-Referenz und die OpenAPI-Spezifikation verwenden.

Was kostet die 4pricing-API?

Die API ist in jedem 4pricing-Abonnement enthalten, mit denselben Limits wie das Panel. Das Lesen Ihrer Daten ist kostenlos; nur Aufrufe, die eine Shopseite lesen (neue URL hinzufügen, aktualisieren, Live-Suche, Wettbewerber finden), verbrauchen Credits, genau wie im Panel.

Welche Aufrufe verbrauchen Credits?

POST /products/, POST /products/{product_id}/refresh, POST /groups/{group_id}/refresh, POST /groups/{group_id}/members mit einer neuen URL, POST /groups/{group_id}/suggestions und POST /search/. Reicht das Guthaben nicht, erhalten Sie 402 insufficient_credits, und es wird nichts gelesen.

Zählen die Preise, die ich über die API sende, zum URL-Limit meines Tarifs?

Nein. Nur Adressen, die 4pricing von einer Seite liest, zählen — Ihre eigenen Produktseiten und jede Wettbewerberseite einzeln. Preise, die mit POST /own-products/ oder /own-products/bulk gesendet werden, zählen weder als URLs noch als Credits.

Kann ich einschränken, worauf ein Schlüssel zugreifen darf?

Nein, es gibt keine Scopes: Ein Schlüssel sieht und ändert Ihr gesamtes 4pricing-Konto. Verwenden Sie für jede Integration einen eigenen Schlüssel und widerrufen Sie jeden Schlüssel, den Sie nicht mehr nutzen; ein Widerruf wirkt sofort.

Was passiert, wenn ich mehr als 60 Anfragen pro Minute sende?

Sie erhalten 429 mit einem Retry-After-Header. Das Limit gilt pro Konto und wird von allen Ihren Schlüsseln geteilt. Warten Sie die in Retry-After angegebene Anzahl Sekunden und versuchen Sie es erneut; für viele Produkte nutzen Sie die Bulk-Aufrufe (bis zu 2.000 Zeilen pro Anfrage).

Wie bekomme ich den empfohlenen Preis automatisch in meinen Shop?

Verknüpfen Sie die Gruppe mit store_kind = webhook mit Ihrem Shop, legen Sie eine Webhook-Adresse und ein Secret fest und verarbeiten Sie das Ereignis price.apply: Ändern Sie den Preis in Ihrem Shop und rufen Sie dann POST /actions/{action_id}/confirm auf. Eine Preisänderung zu genehmigen bleibt eine Entscheidung, die im Panel getroffen wird.

Gibt es ein SDK oder ein fertiges Plugin?

Es gibt kein offizielles SDK und kein Plugin. Die API ist schlichtes REST mit JSON, daher funktioniert jede Sprache, die HTTPS-Anfragen senden kann; die OpenAPI-Spezifikation lässt sich in Werkzeuge laden, die automatisch einen Client generieren.