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.
1. Einrichtung
- Gehen Sie im PassportLab-Dashboard zu Integrationen.
- Klicken Sie auf der Kachel Generic Webhook auf Webhook konfigurieren.
- Geben Sie der Integration eine Bezeichnung (z. B. SAP S/4HANA Produktion).
- Bei der Erstellung zeigt ein einmaliger Dialog die Webhook-URL und das Signaturgeheimnis. Kopieren Sie beides sofort — das Geheimnis wird nur einmal angezeigt.
- (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
| Ratenlimit | 60 Anfragen / Minute / Integration |
|---|---|
| Max. Datensätze pro Aufruf | 10 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 (pending → processing → complete / 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:
| Feld | Beispiel | Bedeutung |
|---|---|---|
source_path | $.MaterialDescription | JSONPath in Ihre ERP-Nutzlast. Sowohl Klammer- als auch Punktnotation werden unterstützt. |
target_field | productName | Gepunkteter Pfad in das DPP-<code>passportData</code>-Objekt. |
transform | trim, upper, number, iso_date, regex:<p>:<r> | Optionale Werttransformation. |
default | "DE" | Wird verwendet, wenn der Quellpfad fehlt. |
6. Fehlerantworten
| Status | Bedeutung | Was zu tun ist |
|---|---|---|
| 401 — X-PassportLab-Timestamp fehlt | Signatur-Header gesendet, kein Zeitstempel | Fügen Sie den Zeitstempel-Header hinzu. |
| 401 — Außerhalb der 5-Minuten-Toleranz | Zeitabweichung > 5 Min. | Synchronisieren Sie die Uhr Ihres ERP-Servers per NTP. |
| 401 — Signatur stimmt nicht überein | HMAC-Digest stimmt nicht überein | Prüfen Sie das Geheimnis sowie, ob Sie timestamp + "." + raw body signiert haben. |
| 400 — Body muss {"records": [...]} sein | Falsch geformte Hülle | Stellen Sie sicher, dass der JSON-Body das records-Array verwendet. |
| 403 — Nicht autorisiert für diese Integration | Bearer-Cookie einer anderen Organisation | Verwenden Sie stattdessen die HMAC-Signatur. |
| 404 — Integration nicht gefunden | Falsche integration_id in der URL | Prüfen Sie das Integrations-Dashboard. |
| 413 — Max. 10 000 Datensätze / Aufruf | Zu viele Datensätze | In mehrere Aufrufe aufteilen. |
| 429 — Ratenbegrenzung erreicht | > 60 Anfragen / Minute / Integration | Drosseln 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
| Symptom | Wahrscheinliche Ursache |
|---|---|
401 Signature mismatch jedes Mal | Ihre 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 fehl | Manche 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 Felder | Ihre 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 Minute | Sie 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.