API

Dokumentation zu Schnittstelle und Webhooks

Bauen Sie Anbindungen an NavyFlame: lesen und schreiben Sie Bestellungen, Lager, Rechnungen und Sendungen über eine REST-Schnittstelle und empfangen Sie signierte Webhooks zu Ereignissen nahezu in Echtzeit.

Einführung

Die öffentliche NavyFlame-Schnittstelle ist eine Server-zu-Server-Schnittstelle. Jeden Aufruf autorisieren Sie mit einem Schlüssel, und die Antworten haben eine stabile, versionierte Form. Die Basisadresse liegt auf Ihrer eigenen Kontodomain:

https://{your-slug}.navyflame.com/api/public/v1

Die vollständige maschinenlesbare Spezifikation (OpenAPI 3.1) finden Sie unter /openapi-public-v1.yaml und importieren sie in Postman, Insomnia oder einen beliebigen OpenAPI-Client.

Schnellstart

Legen Sie zuerst in der Oberfläche einen Schlüssel an (Konto - API) und prüfen Sie die Verbindung mit GET /me - das verlangt keinen Bereich, ein gültiger Schlüssel genügt. Es liefert Ihren Tarif, Ihre Limits und die Bereiche des Schlüssels.

curl https://{your-slug}.navyflame.com/api/public/v1/me \
  -H "Authorization: Bearer nf_live_your_key"

Eine Beispielantwort:

{
  "tenant": "your-slug",
  "keyPrefix": "nf_live_abc123",
  "scopes": ["orders:read", "orders:write"],
  "plan": "Professional",
  "rateLimitPerMin": 3000,
  "apiVersion": "v1"
}

Anmeldung

Den Schlüssel übergeben Sie im Kopfteil Authorization als Bearer-Token (empfohlen). Für Werkzeuge ohne Bearer-Unterstützung gibt es den Alias X-API-Key:

Authorization: Bearer nf_live_your_key
# or
X-API-Key: nf_live_your_key

Schlüssel legen Sie in der Oberfläche an, erneuern und widerrufen sie dort. Wir speichern nur einen Hash des Schlüssels (SHA-256) - den vollen Wert sehen Sie einmal, beim Anlegen. Der Schlüssel wird aus allen Protokollen entfernt. Behandeln Sie ihn wie ein Passwort und legen Sie ihn nie im Browser ab.

Bereiche (Scopes)

Jeder Schlüssel trägt Bereiche. Ein Bereich :write schliesst den passenden :read ein. Fehlt ein nötiger Bereich, kommt 403 missing_scope zurück.

BereichBerechtigt zu
orders:readBestellungen lesen (Liste, Details, Auswertungen, Statusverlauf).
orders:writeStatus ändern, Bestellungen anlegen, Rechnungsstellung auslösen.
catalog:readKatalog lesen: Artikel, Lager, Lagerorte, Reservierungen, Lagerdokumente, Bündel.
catalog:writeVollständiger Katalogschreibzugriff: Artikel (anlegen, lesen, ändern, löschen), Bestände und Lagerorte, Lager, Reservierungen, Lagerdokumente, Bündel.
invoices:readRechnungen und Rechnungsauswertungen lesen.
shipments:readSendungen und Versandauswertungen lesen, dazu unterstützende Abfragen beim Transporteur (Etiketten-PDF, Abholstellen, Dienste, Aufgabezeiten).
shipments:writeLebenszyklus der Sendung: anlegen, Etikett kaufen (beim Transporteur kostenpflichtig), stornieren, Verfolgung auffrischen, Sendungsnummer an Allegro übergeben.
shipping:readVersandeinrichtung lesen: Regeln, Zonen mit Tarifen, Zustelloptionen, Ausnahmen je Artikel, dazu der Kostenrechner.
shipping:writeVersandeinrichtung schreiben: Regeln, Zonen und Tarife je Zone, Zustelloptionen, Versandausnahmen je Artikel.
integrations:readDie Anbindungsliste des Kontos lesen (ohne Geheimnisse): Schlüssel, Kennung der Einrichtung, Name, Zustand von Aktivierung und Verbindung. Gibt nie Zugangsdaten zurück.
offers:readMarktplatzangebote lesen: Zuordnungen Artikel zu Kanal je Artikel, Kategoriezuordnungen und Live-Abfragen bei der Anbindung (Artikel, Kategorien, Merkmale, GPSR-Einheiten). Live-Abfragen sind kostenpflichtig (sie zählen auf das Limit der Anbindung), aber nur lesend.
offers:writeMarktplatzangebote schreiben: Kategoriezuordnungen (anlegen, in Mengen, umleiten, löschen, Zwischenspeicher abgleichen) sowie Veröffentlichen, Abgleichen, Abholen, Status auffrischen und Import echter Angebote. Veröffentlichen und Abgleich sind kostenpflichtig (ein echter Aufruf beim Marktplatz).
reports:readAuswertungen zu Verkauf, Artikeln und Vorgängen samt CSV/XLSX-Export. Geschäftlich sensible Daten.
analytics:readKI-Auswertungen: Bestandsprognosen, Preisvorschläge, Auffälligkeiten, Verkaufsprognose, Erkenntnisse.
monitoring:readÜberwachung der Anbindungen (Webhooks, Rechnungen, Fehlerliste) und Verbrauch des Kontos. Die Details enthalten personenbezogene Daten.
monitoring:writeEinen Eintrag der Fehlerliste erneut verarbeiten - das startet den ursprünglichen Ablauf (bei Rechnungen entsteht eine echte Rechnung; kostenpflichtig).
customers:readKundschaft (aus Bestellungen zusammengeführt), Auswertungen, Verlauf und CSV-Export. Vollständige personenbezogene Daten.
email:readE-Mail-Vorlagen und -Protokolle. Die Protokolle enthalten Empfangsadressen und Betreffzeilen.
email:writeE-Mail-Vorlagen schreiben (Tarifgrenze) und Nachrichten senden (beim Anbieter kostenpflichtig; eigenes Limit von etwa 10 pro Stunde).
notifications:readBenachrichtigungen in der Anwendung und Einstellungen dazu.
notifications:writeBenachrichtigungen in der Anwendung anlegen (die empfangende Person muss Mitglied des Kontos sein) und als gelesen markieren.
alerts:readRegeln für Warnungen und der Verlauf ihrer Auslösungen.
alerts:writeRegeln für Warnungen schreiben (ein E-Mail-Kanal erzeugt mittelbar Versand).
postsale:readNachverkaufsbearbeitung: Nachrichten, Streitfälle, Rücksendungen, Ansprüche (nur lesend). Personenbezogene Daten der Käuferschaft.
postsale:writeNachverkaufsschreibzugriff ohne Geldbewegung: Antworten in Verläufen und Streitfällen, Entscheidung in einem Streitfall, Annahme oder Ablehnung einer Rücksendung (je Anbindung von deren Fähigkeiten abhängig).
postsale:refunds:writeEin eigener Geldbereich: echte Rückzahlung an die Käuferschaft und Rückerstattung der Provision. Abgetrennt, damit ein durchgesickerter Schlüssel ohne ihn kein Geld bewegt.
templates:readBeschreibungs- und Artikelvorlagen lesen (mit Varianten).
templates:writeBeschreibungs- und Artikelvorlagen schreiben; das Anwenden einer Vorlage legt einen Artikel an (verlangt zusätzlich catalog:write).
ai:readDie KI-Einstellungen und den Verlauf der Inhaltserzeugung lesen.
ai:writeInhalte mit KI erzeugen und übersetzen (bei Ihrem eigenen Anbieter kostenpflichtig). Das Schreiben in einen Artikel verlangt zusätzlich catalog:write.

Limits je Tarif

Limits gelten je Konto, nicht je Schlüssel. Die Kopfteile X-RateLimit-Limit, X-RateLimit-Remaining und X-RateLimit-Reset in jeder Antwort nennen den Stand des Zeitfensters. Ist das Limit überschritten, erhalten Sie 429 mit dem Kopfteil Retry-After.

TarifSchlüsselAnfragenWebhooks
Basic51000 / Min.15
Professional303000 / Min.50
EnterpriseOhne LimitOhne LimitOhne Limit

Ressourcen und Vorgänge

Lesen (seitenweise Abfrage über Cursor, Filter, Sortierung):

GET /orders            GET /orders/{id}          GET /orders/stats
GET /orders/{id}/status-history
GET /warehouse-items   GET /warehouse-items/{id}
GET /invoices          GET /invoices/{id}        GET /invoices/stats
GET /shipments         GET /shipments/{id}       GET /shipments/stats

Schreiben:

PUT   /orders/{id}/status            # change the status (transition matrix)
POST  /orders                        # create an order (source: api)
POST  /orders/{id}/invoice           # trigger invoicing
PATCH /warehouse-items/{id}/stock    # stock correction (set / adjust)

Ein Beispiel: die letzten Bestellungen.

curl "https://{your-slug}.navyflame.com/api/public/v1/orders?limit=25" \
  -H "Authorization: Bearer nf_live_your_key"

Ein Beispiel: den Bestand um 3 Stück verringern (atomar).

curl -X PATCH \
  "https://{your-slug}.navyflame.com/api/public/v1/warehouse-items/{id}/stock" \
  -H "Authorization: Bearer nf_live_your_key" \
  -H "Content-Type: application/json" \
  -H "Idempotency-Key: 6f9a...-unikat" \
  -d '{"operation":"adjust","quantity":-3}'

Auswertungen, Berichte und Überwachung

Nur lesende Auswertungsressourcen (die Bereiche reports:read, analytics:read, monitoring:read). Beträge in Berichten und Auswertungen sind Zahlen (Summen), anders als bei den Transaktionsressourcen, wo ein Betrag Text mit zwei Nachkommastellen ist.

GET /reports/sales                 GET /reports/sales/channels
GET /reports/sales/countries       GET /reports/products/bestsellers
GET /reports/products/high-returns GET /reports/products/low-rotation
GET /reports/operations/sla        GET /reports/operations/fulfillment
GET /reports/export/csv            GET /reports/export/xlsx     # binary files

GET /ai-ops/status                 GET /ai-ops/stock-predictions
GET /ai-ops/price-optimizations    GET /ai-ops/anomalies
GET /ai-ops/sales-forecast         GET /ai-ops/insights         # billable (LLM)

GET /monitoring/webhooks           GET /monitoring/webhooks/{id}
GET /monitoring/invoice-links      GET /monitoring/dlq
GET /monitoring/dlq/{id}           GET /monitoring/stats
GET /usage                         # counters, storage used, plan limits

Die Exporte /reports/export/csv und /xlsx sind die binäre Ausnahme von JSON - sie liefern eine Datei mit dem Kopfteil Content-Disposition: attachment (CSV in UTF-8 mit BOM, Semikolon als Trenner). Fehler kommen weiterhin als application/problem+json.

Die Details unter /monitoring/webhooks/{id} und /monitoring/dlq/{id} enthalten den rohen Inhalt der Anbindung (personenbezogene Daten der Käuferschaft), der Bereich monitoring:read ist deshalb als sensibel gekennzeichnet. Die Listen dieser Ressourcen geben keinen Inhalt zurück.

Ein Beispiel: eine Verkaufsübersicht der letzten 30 Tage.

curl "https://{your-slug}.navyflame.com/api/public/v1/reports/sales?periodDays=30" \
  -H "Authorization: Bearer nf_live_your_key"

Kundschaft, E-Mail, Benachrichtigungen und Nachverkaufsbearbeitung

Ressourcen mit personenbezogenen Daten (die Bereiche customers:read, email:read, notifications:read, alerts:read, postsale:read). Nur lesend.

GET /customers                     GET /customers/{email}
GET /customers/stats               GET /customers/{email}/orders
GET /customers/growth              GET /customers/export        # CSV

GET /email-templates(/{id})        GET /email-logs
GET /notifications(/{id})          GET /notifications/unread-count
GET /notification-preferences      # needs ?userId=

GET /alert-rules(/{id})            GET /alert-rules/history

GET /post-sale/capabilities        GET /post-sale/inbox
GET /post-sale/conversations(/{id})(/messages)
GET /post-sale/disputes(/{id})(/messages)
GET /post-sale/returns(/{id})      GET /post-sale/refunds

Eine Kundin oder ein Kunde ist eine gedachte Einheit (aus Bestellungen zusammengeführt), angesprochen über die E-Mail-Adresse. Benachrichtigungen gelten für das ganze Konto (ein Schlüssel steht nicht für eine einzelne Person); das optionale ?userId= grenzt sie auf eine empfangende Person ein, und die Einstellungen verlangen es. Die Nachverkaufsbearbeitung liest nur, was im System gespeichert ist (keine Aufrufe beim Marktplatz auf Ihre Kosten); die Verfügbarkeit sehen Sie unter /post-sale/capabilities.

Die Bereiche customers:read, email:read und postsale:read geben personenbezogene Daten preis - vergeben Sie sie nur an Anbindungen, denen Sie vertrauen, und verarbeiten Sie die Daten im Einklang mit der DSGVO.

Katalog, Vorlagen und KI

Vollständiges Schreiben im Katalog (die Bereiche catalog:read / catalog:write). Anlegende und unumkehrbare Vorgänge verlangen den Kopfteil Idempotency-Key - eine Wiederholung mit demselben Schlüssel gibt das gespeicherte Ergebnis zurück, statt den Vorgang erneut auszuführen.

# Products
POST/PUT/DELETE /warehouse-items(/{id})   POST /warehouse-items/{id}/backorder
GET  /warehouse-items/by-barcode          GET  /warehouse-items/{id}/stock-history
# Warehouses and locations
GET/POST/PUT/DELETE /warehouses(/{id})
GET /warehouse-items/{id}/locations       PUT /warehouse-items/{id}/locations/{warehouseId}
GET/PUT /warehouse-settings
# Reservations and stock documents
GET/POST /reservations                    DELETE /reservations/{id}
GET/POST /stock-documents(/{id})          POST /stock-documents/{id}/lines
POST /stock-documents/{id}/commit         POST /stock-documents/{id}/cancel
# Bundles
GET /bundles(/{id})   PUT /bundles/{id}   DELETE /bundles/{id}

Beschreibungs- und Artikelvorlagen (die Bereiche templates:read / templates:write). Das Anwenden einer Vorlage legt einen Artikel an, deshalb verlangt POST /product-templates/{id}/apply zusätzlich catalog:write.

GET/POST/PUT/DELETE /description-templates(/{id})
GET/POST/PUT/DELETE /product-templates(/{id})
PUT  /product-templates/{id}/variants                  # replace the whole set of variants
POST /product-templates/{id}/variants                  # add a variant
PATCH/DELETE /product-templates/{id}/variants/{variantId}
POST /product-templates/{id}/apply                     # + catalog:write

KI-Inhalte (die Bereiche ai:read / ai:write). Erzeugen und Übersetzen sind bei Ihrem eigenen KI-Anbieter kostenpflichtige Vorgänge (den Schlüssel richten Sie unter Anbindungen ein), deshalb ist Idempotency-Key erforderlich - eine Wiederholung gibt das Ergebnis zurück und rechnet es nicht erneut ab. Das Schreiben des Ergebnisses in einen Artikel (applyToProduct / createNewProducts) verlangt zusätzlich catalog:write. Mengenvorgänge geben je Position eine gekürzte Vorschau zurück - den vollen Text holen Sie aus /ai/generation-logs oder aus dem Artikel.

GET/PUT /ai/settings                 GET /ai/generation-logs
POST /ai/generate-description        POST /ai/translate
POST /ai/batch-generate              POST /ai/batch-translate     # up to 50 items
POST /ai/preview-template            # no AI; templates:read + catalog:read

Ein Beispiel: eine Beschreibungsvorlage anlegen (idempotent).

curl -X POST \
  "https://{your-slug}.navyflame.com/api/public/v1/description-templates" \
  -H "Authorization: Bearer nf_live_your_key" \
  -H "Content-Type: application/json" \
  -H "Idempotency-Key: 6f1e-tpl-001" \
  -d '{"name":"Premium description","templateBody":"{{productName}} - {{price}} {{currency}}"}'

Versandeinrichtung

Versandeinrichtung (die Bereiche shipping:read / shipping:write): Versandregeln, Zonen mit Tarifen, Zustelloptionen und Ausnahmen je Artikel, dazu der Kostenrechner. Anlegende Vorgänge verlangen den Kopfteil Idempotency-Key. Beträge und Gewicht übergeben Sie beim Schreiben als Zahlen (nicht als Text). Das ist die Einrichtung, nicht die Abwicklung beim Transporteur - das Aufgeben von Sendungen und die Etiketten kommen in einer eigenen Phase.

# Shipping rules
GET/POST/PUT/DELETE /shipping-rules(/{id})
# Zones and rates (a rate belongs to its owning zone)
GET/POST/PUT/DELETE /shipping-zones(/{id})
POST /shipping-zones/{id}/rates       PUT/DELETE /shipping-zones/{id}/rates/{rateId}
# Delivery options
GET/POST/PUT/DELETE /delivery-options(/{id})
# Per-product shipping overrides
GET/POST /products/{productId}/shipping-overrides
PUT/DELETE /product-shipping-overrides/{id}
# Cost calculator (a POST, but it only needs shipping:read)
POST /shipping/calculate

Namen sind nicht eindeutig, ein Konflikt durch Doppelung (409) entsteht also nicht. Die deliveryOptionId an einem Tarif oder einer Ausnahme muss auf Ihre eigene Zustelloption zeigen (sonst 422), und ein Tarif ausserhalb Ihrer Zone gibt 404. Der Rechner liefert die Optionen aufsteigend nach Kosten sortiert.

Ein Beispiel: die Versandkosten nach Polen berechnen.

curl -X POST \
  "https://{your-slug}.navyflame.com/api/public/v1/shipping/calculate" \
  -H "Authorization: Bearer nf_live_your_key" \
  -H "Content-Type: application/json" \
  -d '{"countryCode":"PL","orderValue":199.99,"totalWeightKg":1.5,"itemCount":2}'

Sendungen, Etiketten und Transporteur

Lebenszyklus der Sendung (der Bereich shipments:write) und unterstützende Abfragen beim Transporteur (der Bereich shipments:read): Sie legen eine Sendung an, bestellen ein Etikett beim Transporteur, stornieren, frischen die Verfolgung auf und übergeben die Sendungsnummer an Allegro. Gewicht, Masse und Beträge übergeben Sie als Zahlen.

# Creating a shipment (status Draft; costs nothing)
POST   /shipments                    # one at a time
POST   /shipments/bulk               # in bulk, up to 100 (partial success)
# The carrier label
POST   /shipments/{id}/label         # BILLABLE - buying a label (Idempotency-Key required)
GET    /shipments/{id}/label         # fetch the label (PDF, binary)
# The rest of the lifecycle
DELETE /shipments/{id}               # delete a draft or cancel with the carrier
POST   /shipments/{id}/refresh-tracking
POST   /shipments/{id}/push-tracking
# Helper reads (shipments:read)
GET    /shipments/points                       # pickup points (InPost, Poczta Polska, Furgonetka)
GET    /couriers/{provider}/services           # carrier services (Apaczka, Furgonetka)
GET    /shipments/allegro/delivery-services    # Allegro Delivery services
POST   /shipments/available-dates              # pickup dates (DHL; a POST, but shipments:read)

Ein Etikett zu bestellen ist kostenpflichtig - es kauft eine echte Sendung beim Transporteur. Deshalb verlangt POST /shipments/{id}/label den Kopfteil Idempotency-Key: eine Wiederholung mit demselben Schlüssel gibt das gespeicherte Ergebnis zurück und kauft nie ein zweites Etikett (der Schutz liegt auf dem Server). Ein Etikett bestellen Sie nur für eine Sendung im Entwurf. Das Herunterladen des Etiketts (GET .../label) ist die binäre Ausnahme - es liefert application/pdf, nicht JSON.

Eine Transporteur- oder Allegro-Anbindung, die nicht verbunden ist, gibt 403 not_supported zurück (nie ein 500), ein Fehler beim Transporteur oder bei Allegro gibt 502 bad_gateway. Unterstützende Abfragen bei einem nicht unterstützten Anbieter geben { "supported": false } zurück statt eines Fehlers. Eine Stornierung ändert den lokalen Status nicht, wenn der Transporteur den Vorgang ablehnt.

Ein Beispiel: ein Etikett bestellen (idempotent, kostenpflichtig).

curl -X POST \
  "https://{your-slug}.navyflame.com/api/public/v1/shipments/{id}/label" \
  -H "Authorization: Bearer nf_live_your_key" \
  -H "Idempotency-Key: 6f9a...-label-001"

Anbindungen und Marktplatzangebote

Anbindungen entdecken (der Bereich integrations:read) sowie Lese- und Schreibvorgänge für Marktplatzangebote (die Bereiche offers:read / offers:write). Ein Teil der Vorgänge ist lokal (aus Ihren eigenen Daten, ohne Kosten), ein anderer sind Live-Aufrufe gegen Entgelt bei der Anbindung - unten gekennzeichnet.

Entdecken und lokale Abfragen (ohne Kosten):

GET /connectors                          # the list of connectors (no secrets)
GET /warehouse-items/{id}/listings       # the product's marketplace offers (keyset)
GET /category-mappings                   # category mappings (keyset)

GET /connectors gibt einen streng begrenzten Satz an Feldern zurück - key, configId, displayName, enabled und connected - und gibt nie Zugangsdaten zurück (keine Schlüssel, Tokens oder Passwörter der Anbindung). Das Feld connected ist ein errechneter Zustand: die Anbindung ist aktiviert und hat gespeicherte Zugangsdaten. Den Wert configId übergeben Sie in Kategoriezuordnungen als Filter ?sourceConfigId= oder ?destConfigId=.

Die Angebote eines Artikels (/warehouse-items/{id}/listings) verbinden eine Lagerposition mit einem Angebot im Kanal (die fremde Kennung, Preis und Status auf Seiten des Marktplatzes, eine mögliche Preisausnahme je Kanal). Jedes Angebotsobjekt trägt eine instanceId, also die dauerhafte Kennung einer bestimmten Verbindung, sowie einen instanceName zur Anzeige. So kann derselbe Artikel unabhängige Angebote, Preise und Abgleichszustände etwa auf ebay.de und ebay.com haben. Das Feld lastSyncError wird von Mustern bereinigt, die wie Zugangsdaten aussehen und in einem Fehler der Anbindung stecken könnten.

Ein Beispiel: die Anbindungen des Kontos.

curl "https://{your-slug}.navyflame.com/api/public/v1/connectors" \
  -H "Authorization: Bearer nf_live_your_key"

Live-Abfragen beim Marktplatz (der Bereich offers:read) führen einen echten Aufruf bei der Anbindung aus - sie sind kostenpflichtig (sie zählen auf das Limit der Anbindung), aber ausschliesslich lesend (sie veröffentlichen und ändern kein Angebot). Eine nicht verbundene Anbindung gibt 403 not_supported zurück (nie 500), ein Fehler auf Seiten des Marktplatzes gibt 502 bad_gateway. Die Form der Daten hängt von der Anbindung ab.

GET /marketplace/{connectorKey}/products
GET /marketplace/{connectorKey}/products/{externalProductId}
GET /marketplace/{connectorKey}/categories?q=fraza
GET /marketplace/{connectorKey}/categories/{categoryId}/parameters
GET /marketplace/{connectorKey}/responsible-producers
GET /marketplace/{connectorKey}/responsible-persons

Das Schreiben von Kategoriezuordnungen (der Bereich offers:write) sind lokale Schreibvorgänge - keiner davon veröffentlicht oder ändert ein echtes, für die Käuferschaft sichtbares Angebot (das Veröffentlichen echter Angebote ist unten beschrieben). POST /category-mappings verlangt den Kopfteil Idempotency-Key (eine Doppelung gibt 409); sync frischt den lokalen Zwischenspeicher der Kategorien aus der Anbindung auf (kostenpflichtig, aber idempotent).

POST   /category-mappings           # create (Idempotency-Key required; a duplicate -> 409)
POST   /category-mappings/bulk      # in bulk (up to 1000; duplicates skipped)
PUT    /category-mappings/{id}       # repoint the mapping at another target
DELETE /category-mappings/{id}       # delete the mapping
POST   /category-mappings/sync      # refresh the local category cache (billable, idempotent)

Das Veröffentlichen und Abgleichen echter Angebote (der Bereich offers:write) legt ein für die Käuferschaft sichtbares Angebot im Kanal an oder aktualisiert es - kostenpflichtige Vorgänge (ein echter Aufruf beim Marktplatz). publish und sync verlangen den Kopfteil Idempotency-Key (eine Wiederholung mit demselben Schlüssel gibt die gespeicherte Antwort zurück, statt den kostenpflichtigen Aufruf zu wiederholen). publish gibt 409 zurück, wenn der Artikel auf genau dieser Verbindung bereits veröffentlicht ist (oder seine Veröffentlichung läuft) - ein Angebot auf einer anderen Instanz derselben Anbindung erzeugt keinen Konflikt. Nutzen Sie dann sync für dieselbe configId. Eine nicht verbundene Anbindung gibt 403 not_supported, ein Fehler auf Seiten des Marktplatzes gibt 502 bad_gateway.

Übergeben Sie im Inhalt von publish, sync und PUT .../pricing die configId, die Sie von GET /connectors erhalten haben. Hat eine Anbindung mehrere aktivierte Verbindungen, endet ein Weglassen des Feldes mit 422 validation_failed. Die Schnittstelle wählt kein Standardkonto blind aus. Gibt es genau eine aktivierte Verbindung, kann sie diese selbst auflösen.

Wichtig bei einem 502 beim Veröffentlichen: eine Zeitüberschreitung oder ein 5xx des Marktplatzes ist mehrdeutig - das Angebot kann entstanden sein. Eine Wiederholung mit demselben Idempotency-Key gibt dasselbe 502 zurück (sie veröffentlicht nicht erneut). Prüfen Sie das Angebot im Kanal und wiederholen Sie mit einem neuen Idempotency-Key erst, wenn Sie wissen, dass das Angebot nicht entstanden ist.

POST /warehouse-items/{id}/publish/{connectorKey}          # publish the offer (billable; Idempotency-Key required)
POST /warehouse-items/{id}/sync/{connectorKey}             # update the offer (billable; Idempotency-Key required)
POST /warehouse-items/{id}/pull/{connectorKey}             # pull the offer from the channel into the catalogue
POST /warehouse-items/{id}/refresh-status/{connectorKey}   # refresh the status of one offer
POST /warehouse-items/refresh-status                       # in bulk (up to 100 products)
PUT  /warehouse-items/{id}/listings/{connectorKey}/pricing # price per instance (local, no outbound call)

# Body for publish / sync:
{ "configId": "8d1ec28d-..." }

# Body for pricing:
{ "configId": "8d1ec28d-...", "mode": "markup", "value": 12.5 }

Ein Angebot ins Lager importieren ( POST /catalog/import) legt aus einem Marktplatzartikel eine Lagerposition an. Es verlangt zwei Bereiche zugleich - offers:write und catalog:write (fehlt einer, gibt es 403 missing_scope) - sowie den Kopfteil Idempotency-Key. Eine doppelte Artikelnummer oder ein doppelter Strichcode geben 409 conflict.

POST /catalog/import   # import a marketplace product -> a stock item (offers:write + catalog:write)

Schreiben: Benachrichtigungen, Warnungen, E-Mail und Nachverkauf

Schreibvorgänge für Kommunikation, erneute Verarbeitung und Nachverkauf (die Bereiche notifications:write, alerts:write, email:write, monitoring:write, postsale:write und postsale:refunds:write). Anlegende und unumkehrbare Vorgänge verlangen den Kopfteil Idempotency-Key; von Natur aus idempotente Vorgänge (als gelesen markieren, umschalten) beachten ihn wahlweise.

# Notifications (notifications:write)
POST /notifications                  # create (the recipient must be a member of the account; Idempotency-Key required)
POST /notifications/{id}/read        # mark one as read
POST /notifications/read-all         # mark all (needs ?userId=)
# Alerts (alerts:write)
POST /alert-rules                    # create a rule (Idempotency-Key required)
PUT/DELETE /alert-rules/{id}         # update / delete
POST /alert-rules/{id}/toggle        # enable / disable
# E-mail (email:write)
POST/PUT/DELETE /email-templates(/{id})   # templates (plan limit; a duplicate name -> 409)
POST /emails/send                    # BILLABLE - a real send (Idempotency-Key required)

Das Anlegen einer Benachrichtigung prüft, ob recipientUserId Mitglied des Kontos ist (keine Mitgliedschaft gibt 422, eine unsichere Prüfung gibt 503) - ein Schlüssel darf nicht das Postfach einer beliebigen Person fluten. E-Mail-Vorlagen unterliegen der Tarifgrenze (Basic 10, Professional 24, Enterprise ohne Limit) und geben sonst 403 plan_limit, ein doppelter Name gibt 409. Der E-Mail-Versand (`POST /emails/send`) ist kostenpflichtig und hat ein eigenes Limit von etwa 10 pro Stunde je Konto ( 429); ein Anbieter ohne Einrichtung gibt 403 not_supported, ein Übertragungsfehler gibt 502 bad_gateway. Eine Warnregel mit dem Kanal email oder both erzeugt beim Auslösen mittelbar Versand.

Die erneute Verarbeitung der Fehlerliste (der Bereich monitoring:write) startet den ursprünglichen Ablauf eines Eintrags - bei Quellen der Rechnungsstellung entsteht eine echte Rechnung, sie ist also kostenpflichtig und folgenreich, und Idempotency-Key ist erforderlich. Wiederholbar sind nur drei Quellen (shopify_to_wfirma_pipeline, shopify, wfirma_invoice) - andere geben 422; ein nicht erreichbares Temporal gibt 503. Eine Wiederholung ist über eine feste Prozesskennung idempotent (sie gibt alreadyRunning zurück).

POST /monitoring/dlq/{id}/retry      # BILLABLE - runs the original process (Idempotency-Key required)

Nachverkaufsbearbeitung (der Bereich postsale:write): Sie antworten in Verläufen und Streitfällen, ändern den Status eines Streitfalls und nehmen eine Rücksendung an oder lehnen sie ab. Die Zugehörigkeit von Verlauf, Streitfall oder Rücksendung wird vor dem Aufruf des Kanals geprüft (eine fremde oder nicht vorhandene Kennung gibt 404), und die Vorgänge hängen je Anbindung von deren Fähigkeiten ab - fehlt eine Fähigkeit oder Methode, kommt 403 not_supported (nie 500). Ein Fehler des Kanals gibt 502 bad_gateway.

# Post-sale handling with no movement of money (postsale:write)
POST /post-sale/conversations/{id}/messages   # reply to the buyer (Idempotency-Key required)
POST /post-sale/conversations/{id}/read        # mark the thread read
POST /post-sale/disputes/{id}/messages         # reply in a dispute (Idempotency-Key required)
POST /post-sale/disputes/{id}/status           # a decision in a dispute (see money isolation)
POST /post-sale/returns/{id}/accept            # accept the return
POST /post-sale/returns/{id}/reject            # reject the return
# Refunds - a SEPARATE money scope (postsale:refunds:write)
POST /post-sale/refunds/issue                  # a REAL refund to the buyer
POST /post-sale/refunds/commission-claim       # a commission refund

Geld ist abgetrennt. Eine Rückzahlung hat einen eigenen Bereich `postsale:refunds:write`, getrennt von postsale:write, damit ein durchgesickerter Schlüssel ohne ihn kein Geld bewegen kann. Die Route POST /post-sale/disputes/{id}/status gehört zu postsale:write, doch wenn die Entscheidung Geld an die Käuferschaft bewegt (ein vorhandenes partialRefund oder der Status ACCEPTED_REFUND / ACCEPTED_PARTIAL_REFUND), muss der Schlüssel zusätzlich `postsale:refunds:write` tragen - sonst gibt die Anfrage 403 missing_scope zurück und es geschieht nichts.

Rückzahlungen wiederholen. refunds/issue und commission-claim sind auf Seiten des Kanals idempotent (Ihr Idempotency-Key wird zur Kennung des Vorgangs beim Kanal) - wiederholen Sie bei einem 502 mit demselben Schlüssel, der Kanal entfernt die Doppelung. Eine Entscheidung im Streitfall, die Geld bewegt, hat dagegen beim Kanal keine Idempotenz - prüfen Sie bei einem unklaren Fehler das Ergebnis im Verkaufskanal und wiederholen Sie erst mit einem neuen Idempotency-Key (für denselben Schlüssel kommt dasselbe 502 zurück).

Ein Beispiel: eine echte Rückzahlung (idempotent, kostenpflichtig).

curl -X POST \
  "https://{your-slug}.navyflame.com/api/public/v1/post-sale/refunds/issue" \
  -H "Authorization: Bearer nf_live_your_key" \
  -H "Content-Type: application/json" \
  -H "Idempotency-Key: 6f9a...-refund-001" \
  -d '{"connectorKey":"shopify","instanceId":"shop-1","orderExternalId":"1234","amount":49.99,"currency":"PLN"}'

Die vollständige Liste der Vorgänge (je Ressource)

Ein vollständiges, begehbares Verzeichnis aller öffentlichen v1-Endpunkte, nach Ressourcen gruppiert. Das ist die Ebene für Menschen - die vollständigen Schemata für Anfragen und Antworten bis auf Feldebene (179 Stück) stehen in der OpenAPI-Spezifikation . Jeder lebende Endpunkt ist hier aufgeführt.

  • Bereich - der nötige Bereich des Schlüssels. Ein Bereich :write schliesst den passenden :read ein. Die Schreibweise a + b heisst bereichsübergreifend (beide zugleich nötig).
  • Idem. - K! = der Kopfteil Idempotency-Key ist erforderlich; K? = wird beachtet (optional); leer = nicht zutreffend (Lesevorgang).
  • Fehler - die wichtigen Codes ausser den überall möglichen 401, 403 und 429 (sowie 500/503, die überall auftreten können).

Meta

VorgangBereichIdem.ZweckFehler
GET /me(brak)-Prüfung des Schlüssels: Tarif, Limits, Bereiche. Braucht keinen Bereich.-

Bestellungen

VorgangBereichIdem.ZweckFehler
GET /ordersorders:read-Bestellungen auflisten (Cursor; Filter nach Status / Quelle / Datum / Suche).422
POST /ordersorders:writeK!Eine Bestellung anlegen (source=api); die Beträge rechnet der Server.409,413,415,422
GET /orders/{id}orders:read-Details der Bestellung.404
PUT /orders/{id}/statusorders:writeK?Status ändern (Übergangsmatrix; Rückschreiben an Allegro).404,415,422
POST /orders/{id}/invoiceorders:writeK!Rechnungsstellung auslösen (asynchron).404,409,422
GET /orders/statsorders:read-Auswertung der Bestellungen (Zähler je Status und Erlös aus Paid).422
GET /orders/{id}/status-historyorders:read-Verlauf der echten Statuswechsel einer Bestellung.404,422

Katalog: Artikel

VorgangBereichIdem.ZweckFehler
GET /warehouse-itemscatalog:read-Artikel auflisten (Cursor; Filter nach Status / Artikelnummer / Strichcode).422
POST /warehouse-itemscatalog:writeK!Einen Lagerartikel anlegen.409,413,415,422
GET /warehouse-items/{id}catalog:read-Details des Artikels (mit Varianten).404
PUT /warehouse-items/{id}catalog:writeK!Einen Artikel aktualisieren.404,409,413,415,422
DELETE /warehouse-items/{id}catalog:writeK!Einen Artikel archivieren (weiches Löschen).404,409,422
PATCH /warehouse-items/{id}/stockcatalog:writeK?Bestand setzen oder korrigieren (set / adjust, atomar).404,415,422
GET /warehouse-items/by-barcodecatalog:read-Einen Artikel oder eine Variante über den Strichcode finden.404,422
GET /warehouse-items/{id}/stock-historycatalog:read-Verlauf der Bestandsänderungen eines Artikels (Cursor).404,422
POST /warehouse-items/{id}/backordercatalog:writeK!Nachbestellung für einen Artikel ein- oder ausschalten.404,409,415,422

Katalog: Lager und Lagerorte

VorgangBereichIdem.ZweckFehler
GET /warehousescatalog:read-Lager und Lagerorte auflisten.-
POST /warehousescatalog:writeK!Ein Lager oder einen Lagerort anlegen.409,415,422
PUT /warehouses/{id}catalog:writeK!Ein Lager aktualisieren.404,409,415,422
DELETE /warehouses/{id}catalog:writeK!Ein Lager löschen.404,409,422
GET /warehouse-items/{id}/locationscatalog:read-Bestand eines Artikels nach Lagerorten aufgeschlüsselt.404
PUT /warehouse-items/{id}/locations/{warehouseId}catalog:writeK!Bestand eines Artikels an einem Lagerort setzen.404,409,415,422
GET /warehouse-settingscatalog:read-Einstellungen der Lagerautomatisierung.-
PUT /warehouse-settingscatalog:writeK!Einstellungen der Lagerautomatisierung ändern.409,415,422

Katalog: Reservierungen und Lagerdokumente

VorgangBereichIdem.ZweckFehler
GET /reservationscatalog:read-Bestandsreservierungen auflisten (Cursor).422
POST /reservationscatalog:writeK!Bestand eines Artikels reservieren.404,409,415,422
DELETE /reservations/{id}catalog:writeK!Eine Reservierung freigeben.404,409
GET /stock-documentscatalog:read-Lagerdokumente auflisten (Cursor).422
POST /stock-documentscatalog:writeK!Ein Lagerdokument anlegen (Entwurf).409,415,422
GET /stock-documents/{id}catalog:read-Details des Dokuments (mit Positionen).404
POST /stock-documents/{id}/linescatalog:writeK!Eine Position zum Dokument hinzufügen.404,409,415,422
DELETE /stock-documents/{id}/lines/{lineId}catalog:writeK!Eine Position aus dem Dokument entfernen.404,409,422
POST /stock-documents/{id}/commitcatalog:writeK!Das Dokument bestätigen (Bestand anwenden).404,409,422
POST /stock-documents/{id}/cancelcatalog:writeK!Ein Lagerdokument stornieren.404,409,422

Katalog: Bündel

VorgangBereichIdem.ZweckFehler
GET /bundlescatalog:read-Bündel auflisten (Cursor).422
GET /bundles/{id}catalog:read-Details des Bündels (Bestandteile und errechneter Bestand).404
PUT /bundles/{id}catalog:writeK!Bestandteile eines Bündels setzen.404,409,415,422
DELETE /bundles/{id}catalog:writeK!Ein Bündel löschen (Bestandteile leeren).404,409,422

Vorlagen (Beschreibungen und Artikel)

VorgangBereichIdem.ZweckFehler
GET /description-templatestemplates:read-Beschreibungsvorlagen auflisten (Cursor).422
POST /description-templatestemplates:writeK!Eine Beschreibungsvorlage anlegen.409,413,415,422
GET /description-templates/{id}templates:read-Details der Beschreibungsvorlage.404
PUT /description-templates/{id}templates:writeK?Eine Beschreibungsvorlage aktualisieren.404,409,413,415,422
DELETE /description-templates/{id}templates:writeK?Eine Beschreibungsvorlage löschen.404
GET /product-templatestemplates:read-Artikelvorlagen auflisten (Cursor).422
POST /product-templatestemplates:writeK!Eine Artikelvorlage anlegen.409,413,415,422
GET /product-templates/{id}templates:read-Details der Artikelvorlage (mit Varianten).404
PUT /product-templates/{id}templates:writeK?Eine Artikelvorlage aktualisieren.404,409,413,415,422
DELETE /product-templates/{id}templates:writeK?Eine Artikelvorlage löschen.404
PUT /product-templates/{id}/variantstemplates:writeK?Den gesamten Variantensatz einer Vorlage ersetzen (in Mengen).404,409,413,415,422
POST /product-templates/{id}/variantstemplates:writeK!Eine Variante zur Vorlage hinzufügen.404,409,415,422
PATCH /product-templates/{id}/variants/{variantId}templates:writeK?Eine Variante der Vorlage aktualisieren.404,409,415,422
DELETE /product-templates/{id}/variants/{variantId}templates:writeK?Eine Variante der Vorlage löschen.404
POST /product-templates/{id}/applytemplates:write + catalog:writeK!Einen Artikel aus einer Vorlage anlegen (bereichsübergreifend).404,409,422

KI: Inhalte erzeugen

VorgangBereichIdem.ZweckFehler
GET /ai/settingsai:read-Globale Einstellungen der KI-Erzeugung.-
PUT /ai/settingsai:writeK?Globale KI-Einstellungen ändern.409,415,422
GET /ai/generation-logsai:read-Verlauf der KI-Aufrufe (Cursor).422
POST /ai/generate-descriptionai:writeK!Eine Artikelbeschreibung erzeugen (kostenpflichtig).404,409,415,422
POST /ai/translateai:writeK!Einen Artikel übersetzen (kostenpflichtig).404,409,415,422
POST /ai/batch-generateai:writeK!Beschreibungen in Mengen erzeugen (kostenpflichtig; höchstens 50).409,413,415,422
POST /ai/batch-translateai:writeK!In Mengen übersetzen (kostenpflichtig; höchstens 50).409,413,415,422
POST /ai/preview-templatetemplates:read + catalog:read-Vorschau einer Vorlage mit Artikeldaten (ohne Sprachmodell; bereichsübergreifend).404,413,415,422

KI-Auswertungen (AI-Ops)

VorgangBereichIdem.ZweckFehler
GET /ai-ops/statusanalytics:read-Zustand der KI-Einrichtung und Datenabdeckung.-
GET /ai-ops/stock-predictionsanalytics:read-Prognose, wann der Bestand je Artikelnummer ausgeht (5 Min. zwischengespeichert).422
GET /ai-ops/price-optimizationsanalytics:read-Preisvorschläge aus dem Verlauf der Preisänderungen (5 Min. zwischengespeichert).422
GET /ai-ops/anomaliesanalytics:read-Auffälligkeiten gegenüber dem gleitenden Mittel (5 Min. zwischengespeichert).422
GET /ai-ops/sales-forecastanalytics:read-Verkaufsprognose (Regression; days = Horizont).422
GET /ai-ops/insightsanalytics:read-Erkenntnisse (kostenpflichtig über das Sprachmodell des Kontos; 30 Min. zwischengespeichert; regelbasierter Ersatz).-

Rechnungen

VorgangBereichIdem.ZweckFehler
GET /invoicesinvoices:read-Rechnungen auflisten (Cursor; issueDate absteigend).422
GET /invoices/{id}invoices:read-Details der Rechnung (mit Positionen und dem Eintrag bei der Steuerverwaltung).404
GET /invoices/statsinvoices:read-Auswertung der Rechnungen (Kennzahlen über die gesamte Zeit).-

Sendungen und Transporteur

VorgangBereichIdem.ZweckFehler
GET /shipmentsshipments:read-Sendungen auflisten (Cursor).422
GET /shipments/{id}shipments:read-Details der Sendung (mit Verfolgungsverlauf).404
GET /shipments/statsshipments:read-Auswertung der Sendungen (Zähler je Status).-
POST /shipmentsshipments:writeK!Eine Sendung anlegen (Status Entwurf; ohne Kosten).409,415,422
POST /shipments/bulkshipments:writeK!Sendungen in Mengen anlegen (höchstens 100, teilweiser Erfolg möglich).409,413,415,422
POST /shipments/{id}/labelshipments:writeK!Ein Transporteuretikett bestellen (kostenpflichtig - echte Kosten).404,409
GET /shipments/{id}/labelshipments:read-Das Transporteuretikett herunterladen (PDF, binär).404,409,502
DELETE /shipments/{id}shipments:writeK!Einen nicht versandten Entwurf löschen oder eine Sendung beim Transporteur stornieren.404,409,502
POST /shipments/{id}/refresh-trackingshipments:writeK?Status und Verfolgung beim Transporteur auffrischen.404,409,502
POST /shipments/{id}/push-trackingshipments:writeK!Die Sendungsnummer an die Bestellung im Marktplatz übergeben, aus dem sie stammt (Allegro, TikTok Shop).404,400,502
POST /shipments/{id}/push-to-allegroshipments:writeK!Dasselbe, aber nur für Allegro. Aus Gründen der Abwärtskompatibilität erhalten - nutzen Sie in neuen Anbindungen push-tracking.404,409,422,502
POST /shipments/available-datesshipments:read-Verfügbare Aufgabetermine (DHL; POST, aber lesend).415,422,502
GET /shipments/pointsshipments:read-Abholstellen und Paketautomaten (InPost, Poczta Polska, Furgonetka; der Parameter service grenzt die Treffer von Furgonetka auf den Transporteur des Dienstes ein).502
GET /couriers/{provider}/servicesshipments:read-Dienste eines Transporteurs auflisten (Apaczka, Furgonetka).502
GET /shipments/allegro/delivery-servicesshipments:read-Dienste von Allegro Delivery auflisten.502

Versandeinrichtung

VorgangBereichIdem.ZweckFehler
GET /shipping-rulesshipping:read-Versandregeln auflisten (Cursor).422
POST /shipping-rulesshipping:writeK!Eine Versandregel anlegen.409,415,422
GET /shipping-rules/{id}shipping:read-Details der Versandregel.404
PUT /shipping-rules/{id}shipping:writeK?Eine Versandregel aktualisieren.404,409,415,422
DELETE /shipping-rules/{id}shipping:writeK?Eine Versandregel löschen.404
GET /shipping-zonesshipping:read-Versandzonen auflisten (mit eingebetteten Tarifen).422
POST /shipping-zonesshipping:writeK!Eine Versandzone anlegen.409,415,422
GET /shipping-zones/{id}shipping:read-Details der Zone (mit eingebetteten Tarifen).404
PUT /shipping-zones/{id}shipping:writeK?Eine Versandzone aktualisieren.404,409,415,422
DELETE /shipping-zones/{id}shipping:writeK?Eine Versandzone löschen.404
POST /shipping-zones/{id}/ratesshipping:writeK!Einen Tarif zur Zone hinzufügen.404,409,415,422
PUT /shipping-zones/{id}/rates/{rateId}shipping:writeK?Einen Tarif in der Zone aktualisieren.404,409,415,422
DELETE /shipping-zones/{id}/rates/{rateId}shipping:writeK?Einen Tarif aus der Zone löschen.404
GET /delivery-optionsshipping:read-Zustelloptionen auflisten (Cursor).422
POST /delivery-optionsshipping:writeK!Eine Zustelloption anlegen.409,415,422
GET /delivery-options/{id}shipping:read-Details der Zustelloption.404
PUT /delivery-options/{id}shipping:writeK?Eine Zustelloption aktualisieren.404,409,415,422
DELETE /delivery-options/{id}shipping:writeK?Eine Zustelloption löschen.404
GET /products/{productId}/shipping-overridesshipping:read-Versandausnahmen für einen Artikel (Cursor).404,422
POST /products/{productId}/shipping-overridesshipping:writeK!Eine Versandausnahme für einen Artikel anlegen.404,409,415,422
PUT /product-shipping-overrides/{id}shipping:writeK?Eine Versandausnahme eines Artikels aktualisieren.404,409,415,422
DELETE /product-shipping-overrides/{id}shipping:writeK?Eine Versandausnahme eines Artikels löschen.404
POST /shipping/calculateshipping:read-Zustelloptionen und Versandkosten berechnen (POST, aber lesend).415,422

Kundschaft

VorgangBereichIdem.ZweckFehler
GET /customerscustomers:read-Kundschaft auflisten (nach E-Mail zusammengeführt; Cursor).422
GET /customers/statscustomers:read-Auswertung der Kundschaft (Kennzahlen).-
GET /customers/growthcustomers:read-Zuwachs der Kundschaft über die Zeit (Monatsreihe).422
GET /customers/exportcustomers:read-Kundschaft nach CSV exportieren (binär).422
GET /customers/{email}customers:read-Details zur Kundschaft (Zusammenführung und Adressen).404
GET /customers/{email}/orderscustomers:read-Bestellungen einer Person (Cursor).404,422

E-Mail

VorgangBereichIdem.ZweckFehler
GET /email-templatesemail:read-E-Mail-Vorlagen auflisten (Cursor).422
GET /email-templates/{id}email:read-Details der E-Mail-Vorlage.404
GET /email-logsemail:read-Protokolle gesendeter E-Mails auflisten (Cursor; personenbezogene Daten).422
POST /email-templatesemail:writeK!Eine E-Mail-Vorlage anlegen (Tarifgrenze).409,413,415,422
PUT /email-templates/{id}email:writeK?Eine E-Mail-Vorlage aktualisieren.404,409,413,415,422
DELETE /email-templates/{id}email:writeK?Eine E-Mail-Vorlage löschen.404,409
POST /emails/sendemail:writeK!Eine E-Mail senden (kostenpflichtig; etwa 10 pro Stunde).409,413,415,422,502

Benachrichtigungen

VorgangBereichIdem.ZweckFehler
GET /notificationsnotifications:read-Benachrichtigungen des ganzen Kontos auflisten (Cursor; ?userId grenzt ein).422
GET /notifications/{id}notifications:read-Details der Benachrichtigung.404
GET /notifications/unread-countnotifications:read-Zahl der ungelesenen Benachrichtigungen.422
GET /notification-preferencesnotifications:read-Einstellungen zu Benachrichtigungen (verlangt ?userId=).422
POST /notificationsnotifications:writeK!Eine Benachrichtigung anlegen (die empfangende Person muss Mitglied des Kontos sein).413,415,422
POST /notifications/{id}/readnotifications:writeK?Eine Benachrichtigung als gelesen markieren.404,409
POST /notifications/read-allnotifications:writeK?Alle als gelesen markieren (verlangt ?userId=).409,422

Warnungen

VorgangBereichIdem.ZweckFehler
GET /alert-rulesalerts:read-Regeln für Warnungen auflisten (Cursor).422
GET /alert-rules/historyalerts:read-Verlauf der ausgelösten Warnungen (Cursor).422
GET /alert-rules/{id}alerts:read-Details der Regel für Warnungen.404
POST /alert-rulesalerts:writeK!Eine Regel für Warnungen anlegen.413,415,422
PUT /alert-rules/{id}alerts:writeK?Eine Regel für Warnungen aktualisieren.404,413,415,422
DELETE /alert-rules/{id}alerts:writeK?Eine Regel für Warnungen löschen.404,409
POST /alert-rules/{id}/togglealerts:writeK?Eine Regel für Warnungen ein- oder ausschalten.404,409,422

Nachverkaufsbearbeitung

VorgangBereichIdem.ZweckFehler
GET /post-sale/capabilitiespostsale:read-Übersicht der Nachverkaufsfähigkeiten je Anbindungsinstanz.-
GET /post-sale/inboxpostsale:read-Gesammelter Posteingang (Zusammenfassung von Verläufen und Streitfällen).-
GET /post-sale/conversationspostsale:read-Verläufe auflisten (Cursor).422
GET /post-sale/conversations/{id}postsale:read-Details des Verlaufs.404
GET /post-sale/conversations/{id}/messagespostsale:read-Nachrichten in einem Verlauf (Cursor).404,422
GET /post-sale/disputespostsale:read-Streitfälle und Reklamationen auflisten (Cursor).422
GET /post-sale/disputes/{id}postsale:read-Details des Streitfalls.404
GET /post-sale/disputes/{id}/messagespostsale:read-Nachrichten in einem Streitfall (Cursor).404,422
GET /post-sale/returnspostsale:read-Rücksendungen auflisten (Cursor).422
GET /post-sale/returns/{id}postsale:read-Details der Rücksendung.404
GET /post-sale/refundspostsale:read-Rückzahlungen auflisten (Cursor).422
POST /post-sale/conversations/{id}/messagespostsale:writeK!Der Käuferschaft in einem Verlauf antworten.404,413,415,422,502
POST /post-sale/conversations/{id}/readpostsale:writeK?Einen Verlauf als gelesen markieren.404,409
POST /post-sale/disputes/{id}/messagespostsale:writeK!In einem Streitfall antworten.404,413,415,422,502
POST /post-sale/disputes/{id}/statuspostsale:writeK!Status eines Streitfalls ändern (eine Geldbewegung verlangt refunds:write).404,413,415,422,502
POST /post-sale/returns/{id}/acceptpostsale:writeK!Eine Rücksendung annehmen.404,409,502
POST /post-sale/returns/{id}/rejectpostsale:writeK!Eine Rücksendung ablehnen.404,413,415,422,502

Rückzahlungen (ein abgetrennter Geldbereich)

VorgangBereichIdem.ZweckFehler
POST /post-sale/refunds/issuepostsale:refunds:writeK!Echte Rückzahlung an die Käuferschaft (je Kanal idempotent).413,415,422,502
POST /post-sale/refunds/commission-claimpostsale:refunds:writeK!Eine Rückerstattung der Provision beantragen.413,415,422,502

Auswertungen

VorgangBereichIdem.ZweckFehler
GET /reports/salesreports:read-Verkaufsbericht (Zeitreihe, Summen und Marge).422
GET /reports/sales/channelsreports:read-Verkauf nach Kanälen aufgeteilt.422
GET /reports/sales/countriesreports:read-Verkauf nach Ländern aufgeteilt.422
GET /reports/products/bestsellersreports:read-Meistverkaufte Artikel (Verkauf und Bruttomarge).422
GET /reports/products/high-returnsreports:read-Artikel mit hoher Rücksendequote.422
GET /reports/products/low-rotationreports:read-Artikel mit geringem Umschlag.422
GET /reports/operations/slareports:read-Kennzahlen zur Abwicklungszusage.422
GET /reports/operations/fulfillmentreports:read-Abwicklungsdauer je Kanal.422
GET /reports/export/csvreports:read-Einen Bericht nach CSV exportieren (binär).422
GET /reports/export/xlsxreports:read-Einen Bericht nach XLSX exportieren (binär).422

Überwachung und Verbrauch

VorgangBereichIdem.ZweckFehler
GET /monitoring/webhooksmonitoring:read-Eingehende Webhooks auflisten (ohne Inhalt).422
GET /monitoring/webhooks/{id}monitoring:read-Details eines Webhooks (roher Inhalt - personenbezogene Daten).404
GET /monitoring/invoice-linksmonitoring:read-Verknüpfungen der Rechnungsstellung (Bestellung zu Rechnung).422
GET /monitoring/dlqmonitoring:read-Die Fehlerliste (unzustellbare Vorgänge, ohne Inhalt).422
GET /monitoring/dlq/{id}monitoring:read-Ein Eintrag der Fehlerliste (ursprünglicher Inhalt - personenbezogene Daten).404
GET /monitoring/statsmonitoring:read-Gesammelte Auswertung der Anbindungen.-
GET /usagemonitoring:read-Verbrauch des Kontos (Zähler, Speicherplatz, Tariflimits).-
POST /monitoring/dlq/{id}/retrymonitoring:writeK!Einen Eintrag der Fehlerliste wiederholen (kostenpflichtig; startet den ursprünglichen Ablauf).404,409,422

Anbindungen und Marktplatzangebote

VorgangBereichIdem.ZweckFehler
GET /connectorsintegrations:read-Die Anbindungen des Kontos auflisten (Projektion ohne Geheimnisse).-
GET /warehouse-items/{id}/listingsoffers:read-Marktplatzangebote eines Artikels, getrennt je Instanz (Cursor).404,422
GET /category-mappingsoffers:read-Kategoriezuordnungen auflisten (Cursor).422
POST /category-mappingsoffers:writeK!Eine Kategoriezuordnung anlegen (lokal).409,413,415,422
POST /category-mappings/bulkoffers:writeK?Zuordnungen in Mengen anlegen (höchstens 1000).409,413,415,422
PUT /category-mappings/{id}offers:writeK?Eine Zuordnung auf ein anderes Ziel umleiten.404,409,413,415,422
DELETE /category-mappings/{id}offers:writeK?Eine Kategoriezuordnung löschen.404,409
POST /category-mappings/syncoffers:writeK?Den lokalen Zwischenspeicher der Kategorien auffrischen (kostenpflichtig).409,413,415,422,502
GET /marketplace/{connectorKey}/productsoffers:read-Eine Live-Liste der Artikel aus der Anbindung (kostenpflichtig).422,502
GET /marketplace/{connectorKey}/products/{externalProductId}offers:read-Ein einzelner Artikel live aus der Anbindung (kostenpflichtig).502
GET /marketplace/{connectorKey}/categoriesoffers:read-Eine Live-Suche in den Kategorien der Anbindung (kostenpflichtig).502
GET /marketplace/{connectorKey}/categories/{categoryId}/parametersoffers:read-Live-Merkmale einer Kategorie (kostenpflichtig).502
GET /marketplace/{connectorKey}/responsible-producersoffers:read-Eine Live-Liste der GPSR-Herstellerfirmen (kostenpflichtig).502
GET /marketplace/{connectorKey}/responsible-personsoffers:read-Eine Live-Liste der GPSR-Verantwortlichen (kostenpflichtig).502
POST /warehouse-items/{id}/publish/{connectorKey}offers:writeK!Ein Angebot auf der über configId genannten Instanz veröffentlichen (kostenpflichtig, echtes Angebot).404,409,413,415,422,502
POST /warehouse-items/{id}/sync/{connectorKey}offers:writeK!Ein Angebot auf der über configId genannten Instanz aktualisieren (kostenpflichtig).404,409,413,415,422,502
POST /warehouse-items/{id}/pull/{connectorKey}offers:writeK?Ein Angebot aus der Anbindung in den Katalog holen (kostenpflichtig).404,409,502
POST /warehouse-items/{id}/refresh-status/{connectorKey}offers:writeK?Den Status eines Angebots auffrischen (kostenpflichtig).404,409,502
POST /warehouse-items/refresh-statusoffers:writeK?Den Status von Angeboten in Mengen auffrischen (höchstens 100).409,413,415,422
PUT /warehouse-items/{id}/listings/{connectorKey}/pricingoffers:writeK?Den Preis für eine bestimmte Instanz aus configId setzen (lokal, ohne Aufruf).404,409,413,415,422
POST /catalog/importoffers:write + catalog:writeK!Einen Marktplatzartikel ins Lager importieren (bereichsübergreifend).409,413,415,422

Seitenweise Abfrage und Filter

Listen geben wir seitenweise über Cursor aus (ohne Offset). Die Antwort trägt pagination.nextCursor - übergeben Sie ihn im Parameter cursor, um die nächste Seite zu holen. Der Parameter updatedSince (ein Zeitpunkt nach ISO mit Zone) liefert Datensätze, die seit diesem Moment geändert wurden. Fragen Sie für einen abholenden Abgleich mit überlappendem Fenster ab und entfernen Sie Doppel über die id.

GET /orders?limit=50&cursor=eyJjIjoi...&updatedSince=2026-07-01T00:00:00Z

Idempotenz

Schreibvorgänge schützt der Kopfteil Idempotency-Key (ein beliebiger eindeutiger Wert, empfohlen ist eine UUID, bis 255 Zeichen). Er ist bei POST /orders und POST /orders/{id}/invoice erforderlich und wird bei PUT und PATCH beachtet.

  • Eine Wiederholung mit demselben Schlüssel und demselben Inhalt gibt das gespeicherte Ergebnis zurück (Kopfteil Idempotency-Replayed: true), ohne doppelte Wirkung.
  • Derselbe Schlüssel mit anderem Inhalt gibt 409 idempotency_conflict zurück.
  • Ein gleichzeitiges Duplikat in Bearbeitung gibt 409 idempotency_in_progress mit Retry-After zurück.
  • Schlüssel laufen nach 24 Stunden ab.

Beispiele im Code

Fertige Ausschnitte in drei Varianten: curl, JavaScript (fetch, Node 20+) und Python (die Bibliothek requests). Die Varianten für JS und Python setzen die Konstanten BASE (Basisadresse) und KEY (der Schlüssel aus einem sicheren Speicher) voraus, gesetzt im Beispiel zur Anmeldung.

Anmeldung (Bearer und X-API-Key)

curl

# Bearer (recommended)
curl https://{your-slug}.navyflame.com/api/public/v1/me \
  -H "Authorization: Bearer nf_live_your_key"

# The X-API-Key alias (tools without Bearer support)
curl https://{your-slug}.navyflame.com/api/public/v1/me \
  -H "X-API-Key: nf_live_your_key"

JavaScript

const BASE = "https://my-shop.navyflame.com/api/public/v1";
const KEY = process.env.NAVYFLAME_API_KEY;

const res = await fetch(BASE + "/me", {
  headers: { Authorization: "Bearer " + KEY },
});
if (!res.ok) throw new Error("HTTP " + res.status);
const me = await res.json();
console.log(me.plan, me.scopes);

Python

import os, requests

BASE = "https://my-shop.navyflame.com/api/public/v1"
KEY = os.environ["NAVYFLAME_API_KEY"]

r = requests.get(BASE + "/me", headers={"Authorization": "Bearer " + KEY})
r.raise_for_status()
me = r.json()
print(me["plan"], me["scopes"])

Seitenweise Abfrage über Cursor (Schleife und Entdopplung)

curl

curl "https://{your-slug}.navyflame.com/api/public/v1/orders?limit=100&updatedSince=2026-07-01T00:00:00Z" \
  -H "Authorization: Bearer nf_live_your_key"
# the response carries pagination.nextCursor -> pass it as &cursor=... on the next call

JavaScript

async function* paginate(path) {
  let cursor = null;
  do {
    const url = new URL(BASE + path);
    url.searchParams.set("limit", "100");
    if (cursor) url.searchParams.set("cursor", cursor);
    const res = await fetch(url, {
      headers: { Authorization: "Bearer " + KEY },
    });
    if (res.status === 429) {
      const wait = Number(res.headers.get("Retry-After") || 1);
      await new Promise((r) => setTimeout(r, wait * 1000));
      continue;
    }
    if (!res.ok) throw new Error("HTTP " + res.status);
    const page = await res.json();
    for (const row of page.data) yield row;
    cursor = page.pagination.nextCursor;
  } while (cursor);
}

const seen = new Set();
for await (const order of paginate("/orders?updatedSince=2026-07-01T00:00:00Z")) {
  if (seen.has(order.id)) continue; // deduplicate by id
  seen.add(order.id);
  // ... process the order
}

Python

import time

def paginate(path, params=None):
    params = dict(params or {})
    params["limit"] = 100
    while True:
        r = requests.get(BASE + path, params=params,
                         headers={"Authorization": "Bearer " + KEY})
        if r.status_code == 429:
            time.sleep(int(r.headers.get("Retry-After", "1")))
            continue
        r.raise_for_status()
        page = r.json()
        for row in page["data"]:
            yield row
        cursor = page["pagination"]["nextCursor"]
        if not cursor:
            break
        params["cursor"] = cursor

seen = set()
for order in paginate("/orders", {"updatedSince": "2026-07-01T00:00:00Z"}):
    if order["id"] in seen:  # deduplicate by id
        continue
    seen.add(order["id"])
    # ... process the order

Ein idempotenter Schreibvorgang (Idempotency-Key und wachsende Abstände)

curl

curl -X POST "https://{your-slug}.navyflame.com/api/public/v1/orders" \
  -H "Authorization: Bearer nf_live_your_key" \
  -H "Content-Type: application/json" \
  -H "Idempotency-Key: 3f1c9a20-7b2e-4c6d-9f10-000000000001" \
  -d '{"customer":{"name":"Jan Kowalski"},"lineItems":[{"title":"Kubek 300 ml","sku":"KUB-300-BIA","quantity":2,"unitPrice":"39.99","taxRate":"23"}],"currency":"PLN"}'

JavaScript

import { randomUUID } from "node:crypto";

async function createOrder(body) {
  const key = randomUUID(); // the same key on every retry
  for (let attempt = 0; attempt < 5; attempt++) {
    const res = await fetch(BASE + "/orders", {
      method: "POST",
      headers: {
        Authorization: "Bearer " + KEY,
        "Content-Type": "application/json",
        "Idempotency-Key": key,
      },
      body: JSON.stringify(body),
    });
    if (res.status === 429 || res.status === 502 || res.status === 503) {
      const wait = Number(res.headers.get("Retry-After") || 2 ** attempt);
      await new Promise((r) => setTimeout(r, wait * 1000));
      continue; // transient - retry with the same key
    }
    if (res.status === 409) {
      const problem = await res.json();
      if (problem.code === "idempotency_in_progress") {
        await new Promise((r) => setTimeout(r, 1000));
        continue;
      }
      throw new Error("idempotency conflict: " + problem.code); // a different body
    }
    if (!res.ok) throw new Error("HTTP " + res.status);
    return res.json(); // 201 or replayed (Idempotency-Replayed: true)
  }
  throw new Error("wyczerpano proby ponowienia");
}

Python

import time
from uuid import uuid4

def create_order(body):
    key = str(uuid4())  # the same key on every retry
    for attempt in range(5):
        r = requests.post(BASE + "/orders", json=body, headers={
            "Authorization": "Bearer " + KEY,
            "Idempotency-Key": key,
        })
        if r.status_code in (429, 502, 503):
            time.sleep(int(r.headers.get("Retry-After", 2 ** attempt)))
            continue  # transient - retry with the same key
        if r.status_code == 409:
            code = r.json().get("code")
            if code == "idempotency_in_progress":
                time.sleep(int(r.headers.get("Retry-After", "1")))
                continue
            raise RuntimeError("idempotency conflict: " + str(code))
        r.raise_for_status()
        return r.json()  # 201 or replayed
    raise RuntimeError("wyczerpano proby ponowienia")

Die Prüfung der Webhook-Signatur (JavaScript und Python) finden Sie im Abschnitt Ausgehende Webhooks .

Format der Fehler

Fehler geben wir nach RFC 9457 zurück (application/problem+json). Jeder trägt einen stabilen code und eine requestId zur Zuordnung beim Support.

{
  "type": "https://navyflame.com/dokumentacja/api/bledy#validation_failed",
  "title": "Validation failed",
  "status": 422,
  "detail": "Invalid order input.",
  "code": "validation_failed",
  "requestId": "req_abc123",
  "errors": [{ "field": "lineItems[0].unitPrice", "message": "Kwota >= 0 (jako string)." }]
}
CodeHTTPWannWas zu tun ist
unauthorized401Ein fehlender, ungültiger, abgelaufener oder widerrufener Schlüssel.Prüfen Sie den Kopfteil Authorization / X-API-Key. Wurde der Schlüssel widerrufen oder ist er abgelaufen, legen Sie in der Oberfläche einen neuen an.
missing_scope403Dem Schlüssel fehlt ein nötiger Bereich (etwa orders:write), auch wenn ein Vorgang zwei Bereiche verlangt.Vergeben Sie den fehlenden Bereich, indem Sie den Schlüssel mit dem vollständigen Satz erneuern. Die Bereiche eines bestehenden Schlüssels lassen sich nicht nachträglich ändern.
plan_limit403Der Tarif enthält die Schnittstelle nicht, das Tariflimit ist erschöpft, oder das Abo ist abgelaufen oder gekündigt.Verlängern oder erweitern Sie den Tarif. Die Schnittstelle kehrt nach der Freischaltung von selbst zurück (das Limit wird in etwa 5 Minuten verteilt).
not_supported403Der Vorgang braucht eine Transporteur- oder Marktplatzanbindung, die nicht verbunden ist (Fähigkeitsprüfung; nie ein 500).Verbinden und aktivieren Sie die richtige Anbindung in der Oberfläche (Anbindungen). Die Verfügbarkeit sehen Sie unter /post-sale/capabilities oder /connectors.
not_found404Die Ressource gibt es in Ihrem Konto nicht (oder sie gehört einem anderen Konto, was ununterscheidbar bleibt, als Schutz vor Zugriff über fremde Kennungen).Prüfen Sie die Kennung. Eine fremde Kennung sieht immer aus wie eine nicht vorhandene.
conflict409Ein Zustandskonflikt der Ressource: das Angebot ist bereits veröffentlicht, eine doppelte Artikelnummer, ein doppelter Strichcode oder Name, kein Bestand, oder ein Dokument nicht im Entwurf.Lösen Sie den Konflikt: nutzen Sie beim Veröffentlichen sync statt publish; ändern Sie Artikelnummer oder Namen; prüfen Sie den Status der Ressource.
idempotency_conflict409Derselbe Idempotency-Key mit einem anderen Anfrageinhalt verwendet.Nutzen Sie für einen neuen Inhalt einen neuen Idempotency-Key. Derselbe Schlüssel muss denselben Inhalt tragen.
idempotency_in_progress409Eine Anfrage mit diesem Schlüssel wird gerade verarbeitet (ein gleichzeitiges Duplikat).Warten Sie gemäss dem Kopfteil Retry-After und wiederholen Sie mit demselben Schlüssel.
payload_too_large413Der Anfrageinhalt überschreitet 2 MB.Verkleinern Sie den Inhalt (etwa kleinere Mengen bei Massenvorgängen).
unsupported_media_type415Ein Schreibvorgang ohne den Kopfteil Content-Type: application/json.Setzen Sie bei Schreibvorgängen Content-Type: application/json.
validation_failed422Fehlerhafte Eingabe: ein falscher Wert, ein unzulässiger Statuswechsel, ein falscher Cursor, ein Zeitpunkt ohne Zeitzone.Korrigieren Sie die Daten gemäss dem Feld errors in der Antwort (Feld und Meldung).
rate_limited429Ein Limit wurde überschritten (Tariflimit je Konto, je IP-Adresse, gleichzeitige Anfragen oder das eigene Limit für E-Mail-Versand).Drosseln Sie das Tempo, beachten Sie Retry-After und warten Sie exponentiell länger. Prüfen Sie die Kopfteile X-RateLimit-*.
internal500Ein Fehler auf Seiten von NavyFlame.Wiederholen Sie mit wachsendem Abstand. Tritt er wiederholt auf, melden Sie die requestId dem Support.
bad_gateway502Ein Fehler bei einem fremden Dienst (Transporteur, Allegro oder ein anderer Marktplatz) - als vorübergehend behandeln.Wiederholen Sie mit wachsendem Abstand. Bei einem Schreibvorgang mit demselben Idempotency-Key (der Kanal entfernt Doppel). Siehe die Hinweise zu Veröffentlichung und Rückzahlungen.
service_unavailable503Ein Neustart, eine Auslieferung oder eine noch nicht fertige Einrichtung (laufende Auslieferungen).Wiederholen Sie mit wachsendem Abstand, dieser Zustand ist vorübergehend.

Die Codes 500 (internal) und 503 (service_unavailable) können bei jedem Vorgang auftreten und werden nicht je Endpunkt aufgeführt. Auslieferungen laufen fortlaufend - ein Client sollte vereinzelte 502/503 als vorübergehend behandeln (Wiederholung mit wachsendem Abstand) und Schreibvorgänge mit einem Idempotency-Key absichern. Das Feld type in problem+json zeigt auf den Anker dieses Abschnitts (etwa #validation_failed).

Ausgehende Webhooks

Sie abonnieren ein Ereignis und geben eine HTTPS-Adresse an, dann senden wir dorthin eine signierte Benachrichtigung. Die Ereignisse in v1 sind order.synced, order.status_changed, invoice.issued, shipment.status_updated und catalog.updated. Jede Zustellung trägt die Kopfteile X-NavyFlame-Event, X-NavyFlame-Delivery-Id und X-NavyFlame-Signature. Erfolg ist eine 2xx-Antwort innerhalb von 5 Sekunden; bei einem Fehlschlag wiederholen wir mit wachsendem Abstand etwa 24 Stunden lang, und den Zustellverlauf sehen Sie in der Oberfläche.

Die Form des Inhalts (der gemeinsame Rahmen):

{
  "id": "evt_9f4c2f6a-...",
  "type": "order.synced",
  "apiVersion": "v1",
  "occurredAt": "2026-07-07T12:00:00Z",
  "tenant": "your-slug",
  "origin": { "channel": "api", "apiKeyPrefix": "nf_live_abc123" },
  "data": { "order": { }, "isNew": true }
}

Das Feld origin.channel (api | panel | sync | automation) erlaubt es, eine Rückkopplung zu unterbrechen - haben Sie die Änderung selbst mit einem Schlüssel ausgelöst, erkennen Sie das an apiKeyPrefix und überspringen das Ereignis. Die empfangende Seite entfernt Doppel über die id des Ereignisses und über den Kopfteil X-NavyFlame-Delivery-Id (Zustellung mindestens einmal, ohne Zusage zur Reihenfolge).

Der Ereigniskatalog (v1)

Eine geschlossene Liste der Ereignisse in v1 - neue Typen sind eine ergänzende Änderung, die empfangende Seite muss also unbekannte Felder und Typen übergehen. Jedes Ereignis trägt den gemeinsamen Rahmen (oben); der typspezifische Inhalt steht im Feld data:

order.synced - Nach dem Speichern einer Bestellung, nur bei einer echten Datenänderung (neue Bestellung oder Statuswechsel). Das Feld isNew unterscheidet neu von aktualisiert.

{
  "id": "evt_9f4c2f6a-1b2c-4d3e-8a9b-000000000001",
  "type": "order.synced",
  "apiVersion": "v1",
  "occurredAt": "2026-07-09T12:00:00Z",
  "tenant": "my-shop",
  "origin": { "channel": "sync" },
  "data": {
    "order": { "id": "0e6b7c...", "orderNumber": "2026/07/000123",
               "status": "Processing", "totalPrice": "129.99", "currency": "PLN" },
    "isNew": false
  }
}

order.status_changed - Nach dem bestätigten Speichern einer echten Statusänderung, unabhängig von der Quelle. Denselben Status erneut zu setzen und ein abgelehnter Wechsel senden kein Ereignis. Das Feld order enthält den Zustand nach dem Speichern, previousStatus den Status davor, und origin nennt die Quelle der Änderung.

{
  "id": "evt_2b3c4d5e-6f70-4a8b-9c0d-000000000005",
  "type": "order.status_changed",
  "apiVersion": "v1",
  "occurredAt": "2026-08-30T10:30:00Z",
  "tenant": "my-shop",
  "origin": { "channel": "api", "apiKeyPrefix": "nf_live_abc123" },
  "data": {
    "order": { "id": "0e6b7c...", "orderNumber": "2026/08/000321",
               "status": "Processing", "totalPrice": "129.99", "currency": "PLN" },
    "previousStatus": "New"
  }
}

invoice.issued - Nachdem im Buchhaltungssystem des Kontos eine Rechnung ausgestellt wurde.

{
  "id": "evt_1a2b3c4d-5e6f-4a7b-8c9d-000000000002",
  "type": "invoice.issued",
  "apiVersion": "v1",
  "occurredAt": "2026-07-09T12:03:00Z",
  "tenant": "my-shop",
  "origin": { "channel": "automation" },
  "data": {
    "invoice": { "id": "7a1c9e...", "number": "FV/2026/07/45",
                 "status": "Issued", "grossAmount": "129.99", "currency": "PLN" }
  }
}

shipment.status_updated - Nachdem sich der Status einer Sendung beim Transporteur geändert hat. Das Feld previousStatus trägt den vorherigen Status (oder null).

{
  "id": "evt_2b3c4d5e-6f7a-4b8c-9d0e-000000000003",
  "type": "shipment.status_updated",
  "apiVersion": "v1",
  "occurredAt": "2026-07-09T12:10:00Z",
  "tenant": "my-shop",
  "origin": { "channel": "sync" },
  "data": {
    "shipment": { "id": "b2d9f1...", "courierProvider": "inpost",
                  "status": "InTransit", "trackingNumber": "6800000000001" },
    "previousStatus": "PickedUp"
  }
}

catalog.updated - Nachdem sich ein Artikel oder ein Bestand geändert hat. Einzelne Änderungen je Position; ausdrücklich massenhafte Vorgänge (Import aus dem Grosshandel, Mengenaufruf) als ein gesammeltes Ereignis (bulk: true).

{
  "id": "evt_3c4d5e6f-7a8b-4c9d-0e1f-000000000004",
  "type": "catalog.updated",
  "apiVersion": "v1",
  "occurredAt": "2026-07-09T12:15:00Z",
  "tenant": "my-shop",
  "origin": { "channel": "api", "apiKeyPrefix": "nf_live_abc123" },
  "data": {
    "warehouseItemId": "c4e1a2...", "sku": "KUB-300-BIA",
    "changeType": "updated", "stockQuantity": 42
  }
}
// The bulk variant (data):
// { "bulk": true, "source": "wholesale-import", "itemsChanged": 128 }

Prüfung der Signatur

Der Kopfteil X-NavyFlame-Signature hat die Form t=<unix>,v1=<hex>, wobei v1 = HMAC-SHA256(Geheimnis, "<t>." + roher_Inhalt). Der Kopfteil kann mehrere Paare v1= tragen (ein Zeitfenster für den Wechsel des Geheimnisses - altes und neues Geheimnis signieren 24 h parallel) - nehmen Sie jedes an, das passt. Prüfen Sie, ob der Zeitstempel stimmt (Toleranz 300 s), um sich gegen eine Wiedereinspielung zu schützen.

JavaScript (Node)

import crypto from "node:crypto";

function verify(signatureHeader, rawBody, secret) {
  const parts = Object.create(null);
  const sigs = [];
  for (const p of String(signatureHeader).split(",")) {
    const [k, v] = p.split("=");
    if (k === "t") parts.t = v;
    if (k === "v1" && v) sigs.push(v);
  }
  if (!parts.t || sigs.length === 0) return false;
  if (Math.abs(Date.now() / 1000 - Number(parts.t)) > 300) return false;
  const computed = crypto
    .createHmac("sha256", secret)
    .update(parts.t + "." + rawBody)
    .digest("hex");
  return sigs.some(
    (s) =>
      s.length === computed.length &&
      crypto.timingSafeEqual(
        Buffer.from(computed, "hex"),
        Buffer.from(s, "hex"),
      ),
  );
}

Python

import hashlib, hmac, time

def verify(signature_header, raw_body, secret):
    t = None
    sigs = []
    for part in signature_header.split(","):
        k, _, v = part.partition("=")
        if k == "t":
            t = v
        elif k == "v1" and v:
            sigs.append(v)
    if not t or not sigs:
        return False
    if abs(time.time() - int(t)) > 300:  # replay protection
        return False
    computed = hmac.new(
        secret.encode(), (t + "." + raw_body).encode(), hashlib.sha256
    ).hexdigest()
    return any(hmac.compare_digest(computed, s) for s in sigs)

Prüfen Sie die Signatur gegen den rohen Anfrageinhalt (die Bytes vor dem Auswerten des JSON) - ein erneutes Serialisieren ändert die Bytes und die Signatur passt nicht mehr. raw_body / rawBody sind genau die im POST-Inhalt empfangenen Bytes, vor dem Dekodieren des JSON.

Ein Rezept für Zapier und Make

  1. Legen Sie in Zapier einen Zap mit dem Auslöser Webhooks by Zapier - Catch Hook an (in Make: das Modul Custom Webhook). Kopieren Sie die erzeugte Adresse.
  2. Fügen Sie in der NavyFlame-Oberfläche (Konto - API - Webhooks) ein Abonnement hinzu: wählen Sie das Ereignis und fügen Sie die Adresse als Ziel ein. Das Signaturgeheimnis sehen Sie einmal, bewahren Sie es auf.
  3. Nutzen Sie die Schaltfläche Test senden in der Oberfläche, um zu bestätigen, dass Ihr Ablauf den Inhalt empfängt.
  4. (Empfohlen) Fügen Sie mit der obigen Funktion einen Schritt zur Signaturprüfung ein, bevor Sie den Daten vertrauen.

DSGVO

Die Inhalte der Webhooks tragen personenbezogene Daten der Käuferschaft. Wenn Sie ein Abonnement einrichten (die Zieladresse wählen, etwa Zapier, meist eine Übermittlung ausserhalb des EWR), handeln Sie als verantwortliche Stelle für diese Daten, und das Abonnement ist Ihre dokumentierte Weisung zur Verarbeitung. Die Löschung oder Anonymisierung von Käuferdaten in Systeme weiterzugeben, die über Schnittstelle und Webhooks gespeist werden, liegt bei Ihnen.

Anleitungen

Schnellstart (vom Schlüssel zum ersten Aufruf)

  1. Legen Sie in der Oberfläche (Konto - API) einen Schlüssel mit den nötigen Bereichen an. Den Schlüssel sehen Sie nur einmal, bewahren Sie ihn in einem sicheren Speicher auf.
  2. Bestätigen Sie die Verbindung: GET /me (braucht keinen Bereich). Es liefert Tarif, Limits und die Bereiche des Schlüssels.
  3. Machen Sie den ersten Aufruf gegen die gewünschte Ressource, etwa GET /orders?limit=25.

Abholender Abgleich (updatedSince, überlappendes Fenster und Entdopplung)

  1. Fragen Sie mit updatedSince = letzter_Abgleich - Überlappungsfenster ab (etwa 5 Minuten). Die Bedeutung ist einschliessend (>=), auf die Millisekunde genau.
  2. Blättern Sie über den Cursor, bis pagination.nextCursor gleich null ist.
  3. Entdoppeln Sie über die id - >= allein schützt nicht vor einem Datensatz, dessen Transaktion nach Ihrem Lesen bestätigt wurde (daher das überlappende Fenster).
  4. Merken Sie sich das höchste updatedAt der Seite als Startpunkt des nächsten Durchlaufs.
  5. Führen Sie nach einer Wiederherstellung des Kontos aus einer Sicherung einen vollständigen Neuabgleich durch - verlassen Sie sich nicht auf updatedSince (und legen Sie neue Schlüssel an).

Zapier und Make (ein Webhook in eine Aktion)

  1. Legen Sie in Zapier den Auslöser Webhooks by Zapier - Catch Hook an (in Make: Custom Webhook) und kopieren Sie die erzeugte Adresse.
  2. Fügen Sie in der Oberfläche (Konto - API - Webhooks) ein Abonnement hinzu: Ereignis wählen, Adresse als Ziel einfügen, das Geheimnis sichern (wird einmal gezeigt).
  3. Klicken Sie in der Oberfläche auf Test senden, um den Empfang des Inhalts zu bestätigen.
  4. Fügen Sie einen Schritt zur Signaturprüfung ein (siehe den Abschnitt Webhooks), bevor Sie den Daten vertrauen.
  5. Nutzen Sie für Rückrufe an die Schnittstelle das Modul HTTP / Custom Request mit dem Kopfteil Authorization: Bearer.

Schlüssel und Webhook-Geheimnis wechseln (Fenster von 24 Std.)

  • Schlüssel: ein Wechsel in der Oberfläche gibt einmalig ein neues Token aus; das alte gilt noch 24 Std. (ohne Ausfall) - tauschen Sie es in diesem Fenster in Ihrer Anbindung. Ein Widerruf wirkt sofort.
  • Webhook-Geheimnis: der Wechsel hat ein Überlappungsfenster - altes und neues Geheimnis signieren 24 Std. parallel. Der Signatur-Kopfteil kann mehrere Paare v1= tragen, sodass der Wechsel keine brechende Änderung ist, wenn Sie jedes passende annehmen.
  • Nach einer Wiederherstellung aus einer Sicherung werden die Schlüssel automatisch widerrufen - legen Sie neue an und gleichen Sie vollständig neu ab.

Mit Limits umgehen (Retry-After und wachsende Abstände)

  • Lesen Sie das Tariflimit aus GET /me ( rateLimitPerMin) oder GET /usage. Limits gelten je Konto, nicht je Schlüssel.
  • Jede Antwort trägt X-RateLimit-Limit, X-RateLimit-Remaining und X-RateLimit-Reset - steuern Sie Ihr Tempo laufend.
  • Beachten Sie bei 429 das Retry-After (Sekunden) und warten Sie exponentiell länger. Halten Sie die Gleichzeitigkeit unter dem Limit laufender Anfragen (20 parallele Anfragen je Konto).
  • Bei Enterprise ist das Minutenlimit abgeschaltet; der Schutz gegen Fluten je IP-Adresse und die Obergrenze der Gleichzeitigkeit gelten immer (Schutz der Infrastruktur, keine Tarifeigenschaft).

Versionierung und Änderungen

Die Version steht im Pfad (/api/public/v1). Ergänzende Änderungen (neue Felder, neue Endpunkte, neue Ereignistypen) brechen die Verträglichkeit nicht - Ihr Client muss unbekannte Felder übergehen. Brechende Änderungen kündigen wir vorher an: ein Eintrag im Änderungsverlauf, eine E-Mail an die Inhaberschaft aktiver Schlüssel sowie die Kopfteile Deprecation und Sunset.

Änderungsverlauf

Der Versionsverlauf von v1 (die Versionsnummer ist die jeweils nächste Ausbaustufe). Alle Änderungen sind ergänzend - wir haben keinen Endpunkt und kein Feld entfernt und die Bedeutung keines davon geändert. Aktuelle Fassung der OpenAPI-Spezifikation: v1.10.0.

FassungPhaseWas hinzukam (ergänzend)
v1.0GADer Kern der Schnittstelle: /me, Bestellungen (lesen, schreiben und Rechnungsstellung), Lager (lesen und Bestand ändern), Rechnungen (lesen), Sendungen (lesen). Webhooks: order.synced, invoice.issued, shipment.status_updated, catalog.updated. Seitenweise Abfrage über Cursor, Idempotenz, Fehler nach RFC 9457.
v1.1Phase ANur lesende Auswertungen: Berichte zu Verkauf, Artikeln und Vorgängen (samt CSV/XLSX-Export), AI-Ops, Überwachung, Verbrauch sowie Auswertungen und Statusverlauf der Bestellungen.
v1.2Phase BNur lesende personenbezogene Daten: Kundschaft, E-Mail-Vorlagen und -Protokolle, Benachrichtigungen und Einstellungen, Regeln für Warnungen, Nachverkaufsbearbeitung.
v1.3Phase CSchreiben im Katalog: Artikel (anlegen, lesen, ändern, löschen), Lager und Lagerorte, Reservierungen, Lagerdokumente, Bündel, Vorlagen (Beschreibungen und Artikel) sowie KI-Inhalte (kostenpflichtig).
v1.4Phase D1Schreiben der Versandeinrichtung: Regeln, Zonen mit Tarifen, Zustelloptionen, Ausnahmen je Artikel und der Kostenrechner.
v1.5Phase D2Lebenszyklus der Sendung und Transporteur: Anlegen (einzeln und in Mengen), Etikett kaufen (kostenpflichtig), Stornieren, Verfolgung, Übergabe an Allegro sowie unterstützende Abfragen beim Transporteur (Etiketten-PDF, Stellen, Dienste, Zeiten).
v1.6Phase E1Anbindungen entdecken (ohne Geheimnisse) sowie lokale Abfragen von Marktplatzangeboten und Kategoriezuordnungen.
v1.7Phase E2Live-Abfragen beim Marktplatz gegen Entgelt (Artikel, Kategorien, GPSR) sowie das Schreiben von Kategoriezuordnungen (und Abgleich des Zwischenspeichers).
v1.8Phase E3Veröffentlichen, Abgleichen, Abholen, Importieren und Preisliste je Kanal für echte Marktplatzangebote (kostenpflichtig).
v1.9Phase FSchreiben in Kommunikation und Nachverkauf: Benachrichtigungen, Warnungen, E-Mail (Versand kostenpflichtig), erneute Verarbeitung der Fehlerliste sowie Nachverkaufsbearbeitung und Rückzahlungen (der abgetrennte Bereich postsale:refunds:write).
v1.10WebhooksDas neue Ereignis order.status_changed nach einer bestätigten echten Statusänderung einer Bestellung, mit previousStatus und origin. Kein Ereignis bei einem Vorgang ohne Wirkung (no-op) und bei einem abgelehnten Wechsel.

Die Versionierung steht im Pfad: eine brechende Änderung käme nach /v2, wobei v1 daneben mindestens 6 Monate ab der Ankündigung weiterläuft (ein Eintrag im Änderungsverlauf, eine E-Mail an die Inhaberschaft aktiver Schlüssel sowie die Kopfteile Deprecation und Sunset).

Bewährte Vorgehensweisen

  • Prüfen Sie die Verbindung mit GET /me, bevor Sie die erste Anbindung bauen.
  • Fügen Sie Schreibvorgängen immer einen Idempotency-Key bei und wiederholen Sie vorübergehende Fehler mit wachsendem Abstand.
  • Führen Sie nach einer Wiederherstellung des Kontos aus einer Sicherung einen vollständigen Neuabgleich durch (verlassen Sie sich nicht auf updatedSince) und legen Sie neue Schlüssel an - die alten werden dabei ungültig.
  • Nutzen Sie für den abholenden Abgleich updatedSince mit überlappendem Fenster und entdoppeln Sie über die id.

Häufige Fragen

Melden Sie sich in der Oberfläche an, gehen Sie zu Konto - API und legen Sie einen Schlüssel mit den nötigen Bereichen an. Den Schlüssel sehen Sie nur einmal, bewahren Sie ihn also sicher auf. Machen Sie den ersten Versuch gegen GET /me, um die Verbindung zu bestätigen und Tarif und Limits zu sehen.

Ein Schlüssel dient eingehenden Aufrufen: Ihr System fragt NavyFlame nach Daten oder führt einen Vorgang aus. Ein Webhook ist eine ausgehende Benachrichtigung: NavyFlame schickt Ihnen ein Signal über ein Ereignis (etwa eine neue Bestellung), sobald es eintritt.

Nutzen Sie zum Empfangen von Webhooks das Modul Webhooks (Zapier) oder Custom Webhook (Make) und geben Sie die Adresse in der Oberfläche als Ziel des Abonnements an. Für Aufrufe der Schnittstelle nutzen Sie das Modul HTTP / Custom Request mit dem Kopfteil Authorization: Bearer. Die Prüfung der Signatur beschreibt der Abschnitt Webhooks.

Nicht, wenn Sie den Kopfteil Idempotency-Key nutzen. Eine Wiederholung mit demselben Schlüssel gibt dasselbe Ergebnis zurück, ohne doppelte Wirkung. Der Kopfteil ist beim Anlegen von Bestellungen und beim Auslösen der Rechnungsstellung erforderlich.

Die Schnittstelle gibt 403 mit dem Code plan_limit zurück, bis verlängert wird. Nach einer Wiederherstellung des Kontos aus einer Sicherung werden Schlüssel automatisch ungültig (legen Sie neue an), und wir empfehlen einen vollständigen Neuabgleich statt sich auf updatedSince zu verlassen.

Bereit, Ihr System anzubinden?

Legen Sie ein Konto an, erstellen Sie in der Oberfläche einen Schlüssel und starten Sie mit GET /me.

Konto anlegen

Diese Website verwendet Cookies

Wir verwenden Cookies, damit die Website funktioniert, um Zugriffe zu messen und Inhalte zu personalisieren. Mehr dazu in unserer Datenschutzerklärung.

Einstellungen verwalten