Ablauf
Der Label Compliance Check verbindet die DPP-Labels-Website mit einem n8n-Workflow. Das Frontend laedt ein Etikett-Bild hoch, der PHP-Server leitet es an n8n weiter, und das Frontend pollt, bis n8n die Ergebnisse zurueck-POSTet.
Frontend PHP-Server n8n-Workflow
│ │ │
│── POST /api/label-check/submit ─────────────────────────────►│
│ (file + label_type) │ │
│◄── 202 { job_id } ─────────│ │
│ │ │
│── GET /status?job_id=… │ │
│ (Polling alle 5 Sek.) │ │
│◄── { status: "pending" } │ │
│ │ n8n verarbeitet… │
│ │◄── POST /callback │
│ │ + X-Callback-Secret │
│── GET /status (naechster Poll) │
│◄── { status: "complete", result: { … } } │
│ │ │
│ → Teaser-Dashboard │ │
POST /api/label-check/submit
Frontend-Endpunkt: Bild hochladen und Analyse starten.
| Feld |
Status |
Hinweis |
Beispiel |
file |
Pflicht |
Etikett-Bild (JPG, PNG, WEBP · max. 5 MB) |
(binaere Bilddaten) |
label_type |
Pflicht |
wein | bier | kosmetik | lebensmittel | kerzen | elektronik |
"kosmetik" |
Erfolgsantwort 202 Accepted
{
"job_id": "a1b2c3d4e5f6a7b8c9d0e1f2a3b4c5d6",
"status": "pending"
}
Fehlerantworten
| HTTP |
Ausloeser |
Beispiel |
400 |
Datei fehlt, zu gross, falsches Format, ungueltiger Etikettentyp |
{"error": "Ungültiges Dateiformat. Erlaubt: JPG, PNG, WEBP."} |
405 |
Nur POST erlaubt |
{"error": "Method not allowed"} |
503 |
LABEL_CHECK_WEBHOOK_URL nicht konfiguriert oder n8n nicht erreichbar |
{"error": "Analyse-Service derzeit nicht erreichbar."} |
POST /api/label-check/callback (n8n → PHP)
n8n ruft diesen Endpunkt auf, sobald die Analyse abgeschlossen ist. Wenn LABEL_CHECK_CALLBACK_SECRET konfiguriert ist, muss der Request den passenden Header X-Callback-Secret enthalten.
Header
| Feld |
Status |
Hinweis |
Beispiel |
Content-Type |
Pflicht |
application/json |
"application/json" |
X-Callback-Secret |
Optional |
Pflicht, sobald LABEL_CHECK_CALLBACK_SECRET in .env gesetzt ist |
"mein-geheimnis-xyz" |
🔒 Sicherheitshinweis
Der X-Callback-Secret-Header verhindert, dass Dritte gefaelschte Ergebnisse an den Callback senden. Fuer produktiven Betrieb sollte derselbe Wert in .env und im n8n-HTTP-Node konfiguriert sein.
Body — Ergebnis-JSON
{
"job_id": "a1b2c3d4e5f6a7b8c9d0e1f2a3b4c5d6",
"status": "complete",
"label_type": "wein",
"overall_score": 72,
"categories": [
{
"name": "Pflichtangaben",
"status": "pass",
"teaser": "Alle gesetzlichen Mindestangaben vorhanden."
},
{
"name": "EU-Lebensmittelrecht",
"status": "warn",
"teaser": "1 Angabe unvollstaendig oder fehlend."
},
{
"name": "DPP-Bereitschaft",
"status": "fail",
"teaser": "Kein QR-Code / Digital Link erkannt."
},
{
"name": "Sprachkonformitaet",
"status": "pass",
"teaser": "Sprachliche Anforderungen erfuellt."
}
],
"findings": [
{
"id": "f1",
"severity": "warn",
"title": "Naehrwertkennzeichnung unvollstaendig",
"teaser_text": "Ballaststoffe und Salz fehlen in der Tabelle.",
"full_text": "Gemaess EU 1169/2011 Art. 30 Abs. 1 muessen folgende Naehrwerte …"
},
{
"id": "f2",
"severity": "fail",
"title": "Kein GS1 Digital Link erkannt",
"teaser_text": "Kein QR-Code oder Digital-Link-URI auf dem Etikett gefunden.",
"full_text": "Die EU-ESPR-Verordnung (Entwurf) sieht ab 2027 …"
}
]
}
Datenvertrag im Detail
Root-Felder
| Feld |
Status |
Hinweis |
Beispiel |
job_id |
Pflicht |
Die 32-Zeichen Hex-ID aus Submit |
"a1b2c3d4…" |
status |
Pflicht |
"complete" oder "error" |
"complete" |
label_type |
Echo |
Echo des Etikettentyps |
"wein" |
overall_score |
Pflicht |
0–100 Compliance-Score |
72 |
categories |
Pflicht |
Array von Kategorie-Bewertungen |
(Array) |
findings |
Pflicht |
Array von Einzelbefunden |
(Array) |
categories[*]
| Feld |
Status |
Hinweis |
Beispiel |
name |
Pflicht |
Name der Kategorie (Freitext) |
"Pflichtangaben" |
status |
Pflicht |
pass | warn | fail |
"warn" |
teaser |
Pflicht |
Einzeilige Zusammenfassung |
"1 Angabe fehlt." |
Status-Werte (Ampel-System)
✅
pass — Konform
⚠️
warn — Pruefbedarf
🔴
fail — Nicht konform
findings[*]
| Feld |
Status |
Hinweis |
Beispiel |
id |
Pflicht |
Eindeutige Befund-ID |
"f1" |
severity |
Pflicht |
pass | warn | fail |
"warn" |
title |
Pflicht |
Befund-Titel |
"Naehrwertkennzeichnung unvollstaendig" |
teaser_text |
Pflicht |
Kurztext — im Teaser-Dashboard sichtbar |
"Ballaststoffe und Salz fehlen." |
full_text |
Pflicht |
Volltext — nur im E-Mail-Report |
"Gemaess EU 1169/2011 Art. 30 …" |
💡 Teaser vs. Volltext
Das Frontend zeigt nur teaser_text der ersten 2 Befunde an. Alle weiteren Befunde (inkl. full_text) werden erst im per E-Mail versandten Vollbericht sichtbar. Dies dient als Lead-Magnet.
GET /api/label-check/status
Das Frontend pollt diesen Endpunkt alle 5 Sekunden, um den aktuellen Status abzufragen.
| Feld |
Status |
Hinweis |
Beispiel |
job_id |
Pflicht |
32-Hex-ID als Query-Parameter |
"?job_id=a1b2c3d4…" |
Antwort (ausstehend)
{
"job_id": "a1b2c3d4…",
"status": "pending",
"submitted_at": "2026-07-08T10:00:00+02:00",
"label_type": "wein"
}
Antwort (abgeschlossen)
Gibt das komplette Job-Objekt inkl. result zurueck. Das Feld visitor_email wird aus Datenschutzgruenden entfernt.
POST /api/label-check/claim
Besucher gibt seine E-Mail-Adresse ein, um den vollstaendigen Compliance-Bericht zu erhalten.
| Feld |
Status |
Hinweis |
Beispiel |
job_id |
Pflicht |
32-Hex-ID |
"a1b2c3d4…" |
email |
Pflicht |
Gueltige E-Mail-Adresse |
"info@example.de" |
consent |
Pflicht |
Muss "1" sein (DSGVO-Einwilligung) |
"1" |
_token |
Pflicht |
CSRF-Token aus der aktuellen Session |
"abc123…" |
Umgebungsvariablen (.env)
| Variable |
Beschreibung |
Beispiel |
LABEL_CHECK_WEBHOOK_URL |
Webhook-URL des n8n-Label-Check-Workflows |
https://your-n8n.com/webhook/label-check |
LABEL_CHECK_API_KEY |
Optionaler API-Key zur Authentifizierung beim n8n-Webhook (X-Api-Key Header) |
dpp-lc-key-abc123 |
LABEL_CHECK_CALLBACK_SECRET |
Optionaler geheimer Schluessel fuer n8n-Callbacks; empfohlen fuer produktiven Betrieb |
random-secret-string |
# .env
LABEL_CHECK_WEBHOOK_URL=https://your-n8n.com/webhook/label-check
LABEL_CHECK_API_KEY=dpp-lc-key-abc123
LABEL_CHECK_CALLBACK_SECRET=generate-a-random-secret-here
Job-Dateistruktur
Jeder Analyse-Job wird als JSON gespeichert unter:
content/label-compliance-check/{job_id}.json
Lebenszyklus
| Phase |
Aktion |
Status |
Ausloeser |
| 1. Erstellt |
Job-Datei angelegt |
status: "pending" |
POST /api/label-check/submit |
| 2. Aktualisiert |
Ergebnis eingetragen |
status: "complete" |
POST /api/label-check/callback (n8n) |
| 3. Beansprucht |
E-Mail gespeichert |
email_claimed: true |
POST /api/label-check/claim |
Fehlerbehandlung
| Situation |
n8n-Aktion |
Frontend-Verhalten |
| Analyse erfolgreich |
POST callback mit "status": "complete" |
Teaser-Dashboard wird angezeigt |
| Analyse fehlgeschlagen |
POST callback mit "status": "error" |
Fehlermeldung im Loading-Panel |
| Bild nicht lesbar |
POST callback mit "status": "error" |
Fehlermeldung + Neuversuch-Option |
| Timeout (kein Callback) |
n8n antwortet nicht innerhalb 6 Min. |
Timeout-Meldung; wenn E-Mail angegeben, spaetere Benachrichtigung |