PassportLabEntwicklerWebhook-Integration

Produktdaten per Webhook in PassportLab übertragen

Ein signierter HTTP-Endpunkt zum Streamen von Produkten aus jedem ERP-, PIM- oder PLM-System. Kein PassportLab-Benutzer-Login erforderlich — Ihr ERP authentifiziert jede Anfrage mit einer HMAC-SHA256-Signatur und einem aktuellen Zeitstempel.

HMAC-SHA256 signiertReplay-geschützt (±5 Min.)Asynchrone ARQ-WarteschlangeFeldzuordnungs-Engine

1. Einrichtung

  1. Gehen Sie im PassportLab-Dashboard zu Integrationen.
  2. Klicken Sie auf der Kachel Generic Webhook auf Webhook konfigurieren.
  3. Geben Sie der Integration eine Bezeichnung (z. B. SAP S/4HANA Produktion).
  4. Bei der Erstellung zeigt ein einmaliger Dialog die Webhook-URL und das Signaturgeheimnis. Kopieren Sie beides sofort — das Geheimnis wird nur einmal angezeigt.
  5. (Optional, aber empfohlen.) Öffnen Sie Zuordnungsregeln auf der Integrationskarte und ordnen Sie die Feldnamen Ihres ERP den DPP-Passdatenfeldern zu. Die integrierte Test-Schaltfläche zeigt die normalisierte Ausgabe anhand einer Beispiel-Nutzlast.

2. Anfrageformat

Methode & Header

POST {webhookUrl}
Content-Type: application/json
X-PassportLab-Timestamp: <unix epoch seconds>
X-PassportLab-Signature: sha256=<hex digest>

Body

{
  "records": [
    { "name": "Widget Pro", "barcode": "01234567890123", ... },
    { "name": "Widget Lite", "barcode": "01234567890116", ... }
  ]
}

Jedes Element in records ist ein frei formbares Objekt — Ihre Zuordnungsregeln wandeln es in einen DPP-Pass um. Sind keine Regeln konfiguriert, müssen die Datensätze bereits der DPP-passportData-Struktur entsprechen.

Limits

Ratenlimit60 Anfragen / Minute / Integration
Max. Datensätze pro Aufruf10 000
Zeitstempel-Toleranz±5 Minuten zur Serverzeit

3. Signierung

Wir verwenden das Signaturschema im Stripe-Stil: Zeitstempel + Punkt + Body, HMAC-SHA256, Hex-Digest, vorangestellt mit sha256=.

signing_base = <timestamp> + "." + <raw request body bytes>
signature    = "sha256=" + HMAC-SHA256(secret, signing_base).hexdigest()

Die Einbeziehung des Zeitstempels in die signierte Nutzlast ist ein Replay-Schutz: Selbst wenn eine gültige Anfrage durchsickert, kann sie außerhalb des 5-Minuten-Fensters nicht erneut gesendet werden.

import hashlib, hmac, json, time, requests

INTEGRATION_ID = "REPLACE_ME"
SECRET         = "REPLACE_ME"  # from your credential vault
BASE_URL       = "https://api.passportlab.io"

records = [{"name": "Widget Pro", "barcode": "01234567890123"}]
body    = json.dumps({"records": records}).encode("utf-8")
ts      = str(int(time.time()))
sig     = "sha256=" + hmac.new(
    SECRET.encode(), f"{ts}.".encode() + body, hashlib.sha256
).hexdigest()

res = requests.post(
    f"{BASE_URL}/api/v1/integrations/{INTEGRATION_ID}/webhook-ingest",
    data=body,
    headers={
        "Content-Type": "application/json",
        "X-PassportLab-Timestamp": ts,
        "X-PassportLab-Signature": sig,
    },
    timeout=30,
)
res.raise_for_status()
print(res.json())  # → {"jobId": "...", "totalRecords": 1, "enqueued": true}

4. Antwort & Abfrage

Eine erfolgreiche Anfrage liefert 202 Accepted:

{
  "jobId": "f4c1f2c8-7a51-4e3b-8c12-9bb9d8f00111",
  "totalRecords": 1,
  "enqueued": true
}
  • enqueued: true — der Job wurde an den ARQ-Worker übergeben.
  • enqueued: false — Redis ist nicht erreichbar; der Job läuft als Fallback inline. Funktional identisch, bei großen Batches jedoch langsamer.

Ergebnisse abfragen

GET {baseUrl}/api/v1/jobs/{jobId}

Liefert status (pendingprocessingcomplete / partial / failed), Zähler pro Datensatz sowie bei Abschluss ein results-Array.

5. Feldzuordnung

Wenn die Nutzlaststruktur Ihres ERP vom DPP-Schema abweicht (was fast immer der Fall ist), definieren Sie Zuordnungsregeln im Dashboard. Jede Regel besteht aus vier Feldern:

FeldBeispielBedeutung
source_path$.MaterialDescriptionJSONPath in Ihre ERP-Nutzlast. Sowohl Klammer- als auch Punktnotation werden unterstützt.
target_fieldproductNameGepunkteter Pfad in das DPP-<code>passportData</code>-Objekt.
transformtrim, upper, number, iso_date, regex:<p>:<r>Optionale Werttransformation.
default"DE"Wird verwendet, wenn der Quellpfad fehlt.

6. Fehlerantworten

StatusBedeutungWas zu tun ist
401 — X-PassportLab-Timestamp fehltSignatur-Header gesendet, kein ZeitstempelFügen Sie den Zeitstempel-Header hinzu.
401 — Außerhalb der 5-Minuten-ToleranzZeitabweichung > 5 Min.Synchronisieren Sie die Uhr Ihres ERP-Servers per NTP.
401 — Signatur stimmt nicht übereinHMAC-Digest stimmt nicht übereinPrüfen Sie das Geheimnis sowie, ob Sie timestamp + "." + raw body signiert haben.
400 — Body muss {"records": [...]} seinFalsch geformte HülleStellen Sie sicher, dass der JSON-Body das records-Array verwendet.
403 — Nicht autorisiert für diese IntegrationBearer-Cookie einer anderen OrganisationVerwenden Sie stattdessen die HMAC-Signatur.
404 — Integration nicht gefundenFalsche integration_id in der URLPrüfen Sie das Integrations-Dashboard.
413 — Max. 10 000 Datensätze / AufrufZu viele DatensätzeIn mehrere Aufrufe aufteilen.
429 — Ratenbegrenzung erreicht> 60 Anfragen / Minute / IntegrationDrosseln oder seltener aufrufen.

7. Betriebshinweise

Idempotenz

PassportLab verwendet den DPP-Code (abgeleitet aus GTIN + Seriennummer) als eindeutige Kennung. Das erneute Senden eines Datensatzes mit derselben GTIN+Seriennummer wird übersprungen, nicht dupliziert — die Antwort markiert ihn als skipped mit dem Grund "DPP code 'DPP-…' already exists". Bei vorübergehenden Fehlern gefahrlos wiederholbar.

Wiederholungen

Bei 502 / 503 / 504 oder Netzwerk-Timeouts mit exponentiellem Backoff erneut versuchen (1s, 2s, 4s, 8s, gedeckelt bei 30s). In der Regel reichen bis zu 3 Wiederholungen. Nicht bei 4xx-Antworten wiederholen — die Anfrage schlägt erneut fehl.

Batching

  • Kleine ERPs (< 1 000 SKUs): den vollständigen Katalog nächtlich in einem Aufruf senden.
  • Größere ERPs: nur das Delta senden (seit der letzten Synchronisierung geänderte Zeilen), in Gruppen von bis zu 1 000 Datensätzen pro Anfrage.

8. Fehlerbehebung

SymptomWahrscheinliche Ursache
401 Signature mismatch jedes MalIhre Signaturbasis stimmt vermutlich nicht mit f"{ts}." + raw_body überein. Geben Sie beides aus und vergleichen Sie die Bytes.
Funktioniert mit curl, schlägt im Code fehlManche HTTP-Clients serialisieren JSON vor dem Senden neu und verändern dabei Leerraum. Signieren Sie immer die exakten Bytes, die auf die Leitung gehen — berechnen Sie den Digest nach JSON.stringify.
Datensätze kommen an, aber die resultierenden DPPs haben leere FelderIhre Zuordnungsregeln decken diese Felder nicht ab. Öffnen Sie den Feldzuordnungs-Editor, fügen Sie ein Beispiel ein, klicken Sie auf Test und prüfen Sie die normalisierte Ausgabe.
429 einmal pro MinuteSie senden einen Datensatz pro HTTP-Aufruf. Fassen Sie sie in einem einzigen POST mit records: [...] zusammen.

Bereit, Ihren ersten ERP-Datensatz zu senden?

Starten Sie ein kostenloses PassportLab-Konto, konfigurieren Sie einen generischen Webhook, und in unter 10 Minuten fließen Daten.