{
  "anweisung": "gemeinsamki-produktfeed-anweisung/1",
  "titel": "Anweisung: Produktfeed für GemeinsamKI Suche erzeugen (Format gemeinsamki-produktfeed/1)",
  "fuer": "KI-Systeme (Sprachmodelle, Agenten, Shop-Plugins), die für einen Händler einen Produktfeed erzeugen. Menschen lesen die Beschreibung unter https://search.gemeinsamki.de/produktfeed.",
  "aufgabe": "Erzeuge aus den Produktdaten des Händlers (Shop-Export als CSV/XML/JSON, Tabelle, Liste oder Shop-Adresse) genau ein JSON-Objekt im Format gemeinsamki-produktfeed/1, das das JSON-Schema in json_schema erfüllt und alle Regeln einhält. GemeinsamKI Suche ruft den Feed ab und prüft ihn streng: Ein einziger Fehler – fehlendes Pflichtfeld, falscher Typ, unbekanntes Feld – und der ganze Feed wird nicht angezeigt.",
  "eingaben_vom_haendler": [
    "Produktdaten: je Artikel Kennung, Name, Produktseite, Bildadresse, Preis inkl. MwSt., Versandkosten nach Deutschland, Verfügbarkeit, Zustand.",
    "Für Ware nach Gewicht, Volumen, Länge oder Fläche: Menge mit Einheit oder den Grundpreis.",
    "Für Geräte mit EU-Energielabel (z. B. Waschmaschinen, Kühlschränke, Fernseher, Lampen, Smartphones, Reifen): Klasse, Skala und Adresse des Labels.",
    "Für rezeptfreie Arzneimittel und Biozidprodukte: die Art und bei Arzneimitteln die Adresse der Pflichtangaben.",
    "Händler: Firma mit Rechtsform, ladungsfähige Anschrift, Adresse des Impressums, ob die Umsatzsteuer enthalten ist oder Kleinunternehmerregelung (§ 19 UStG) gilt.",
    "Die Domain der bei GemeinsamKI Suche angemeldeten Website (alle Produktadressen und das Impressum liegen dort)."
  ],
  "vorgehen": [
    "1. Lies json_schema, felder und regeln vollständig.",
    "2. Ordne jedes Feld der Produktdaten einem Feld des Formats zu; nutze nur die Felder aus felder.",
    "3. Rechne Preise in Euro mit höchstens zwei Nachkommastellen um und schreibe sie als JSON-Zahl mit Punkt (19.99).",
    "4. Setze grundpreis, energielabel und pflichthinweis bei jedem Produkt: null, wenn es nicht zutrifft, sonst das Objekt.",
    "5. Berechne einen fehlenden Grundpreis nur aus einer angegebenen Menge: Preis ÷ Menge in kg, l, m, m² oder m³, auf Cent gerundet.",
    "6. Lass Produkte weg, die nicht in den Feed gehören (nicht_in_den_feed), und nenne sie dem Händler.",
    "7. Setze stand auf den Zeitpunkt, zu dem die Produktdaten gelten (RFC 3339 mit Zeitzone).",
    "8. Gehe die pruefliste_vor_der_ausgabe durch und korrigiere jeden Verstoß.",
    "9. Gib nur das JSON-Objekt aus (UTF-8, ohne Kommentar, ohne Markdown-Zaun), dazu getrennt die offenen Fragen an den Händler."
  ],
  "regeln": [
    "Genau ein JSON-Objekt; keine Felder außer den beschriebenen (auch nicht leer oder mit Unterstrich) – unbekannte Felder sind Fehler.",
    "Pflichtfelder immer angeben; freiwillige Felder ohne Wert weglassen, nicht als leeren Text oder null.",
    "grundpreis, energielabel und pflichthinweis sind Pflichtschlüssel: null oder Objekt, nie weglassen.",
    "Beträge als Zahl, nie als Text; Punkt als Dezimaltrenner; höchstens zwei Nachkommastellen; keine Währungszeichen.",
    "preis ist der Endpreis inkl. Umsatzsteuer; versandkosten gelten für genau diesen einen Artikel bei Lieferung nach Deutschland.",
    "Alle Adressen mit https://; url und anbieter.impressum_url auf der angemeldeten Website (oder einer Unterdomain, wenn eine ganze Domain angemeldet ist).",
    "Texte ohne HTML, ohne Steuerzeichen, in den angegebenen Längen; Titel ohne Werbefloskeln in Großbuchstaben.",
    "Jede id nur einmal im Feed; dieselbe Ware behält über alle Feeds hinweg dieselbe id.",
    "stand höchstens 24 Stunden alt und nicht in der Zukunft – der Feed muss mindestens so oft neu erzeugt werden.",
    "Keine Streichpreise, Rabatte, „statt“-Preise oder Prozentangaben – das Format kennt sie nicht.",
    "skala mit der besten Klasse zuerst (A-G, A-E, A+++-D); klasse muss in der Skala liegen.",
    "gtin nur mit gültiger Prüfziffer (8, 12, 13 oder 14 Ziffern), sonst weglassen.",
    "Höchstens 2000 Produkte und 20 MB je Feed."
  ],
  "nie_erfinden": [
    "Firma, Anschrift und Impressum des Händlers.",
    "Preise, Versandkosten und Verfügbarkeit – nur aus den Daten übernehmen.",
    "Grundpreis ohne angegebene Menge.",
    "Energieeffizienzklasse, Skala und Label-Adresse.",
    "Ob eine Ware Arzneimittel oder Biozidprodukt ist und die Adresse der Pflichtangaben.",
    "GTIN, Bildadressen und Produktadressen.",
    "Fehlt etwas davon: nachfragen. Ein Produkt mit fehlender Pflichtangabe nicht aufnehmen und dem Händler nennen."
  ],
  "nicht_in_den_feed": [
    "Tabakerzeugnisse, E-Zigaretten, Nachfüllbehälter und Nikotinprodukte (§§ 19, 20 TabakerzG).",
    "Verschreibungspflichtige Arzneimittel (§ 10 HWG).",
    "Waffen und Munition.",
    "Inhalte und Waren, die erst ab 18 Jahren zugänglich sein dürfen, und alles Rechtswidrige."
  ],
  "ausgabe": {
    "art": "genau ein JSON-Objekt",
    "bereitstellen": "unter einer festen https-Adresse (Shop, Server oder Feed-Dienstleister), die GemeinsamKI Suche abrufen kann",
    "content_type": "application/json",
    "dateiname": "produktfeed.json",
    "kodierung": "UTF-8"
  },
  "felder": [
    {
      "pfad": "format",
      "pflicht": "ja",
      "typ": "genau \"gemeinsamki-produktfeed/1\"",
      "werte": [
        "gemeinsamki-produktfeed/1"
      ],
      "bedeutung": "Kennung des Formats."
    },
    {
      "pfad": "stand",
      "pflicht": "ja",
      "typ": "Zeitpunkt nach RFC 3339 mit Zeitzone, höchstens 24 Stunden alt, nicht in der Zukunft",
      "bedeutung": "Zeitpunkt, zu dem Preise und Verfügbarkeit gelten, nach RFC 3339 mit Zeitzone (2026-10-22T14:05:00+02:00). Wird als „Stand“ am Angebot gezeigt.",
      "grund": "§ 5 UWG; BGH I ZR 123/08"
    },
    {
      "pfad": "waehrung",
      "pflicht": "ja",
      "typ": "genau \"EUR\"",
      "werte": [
        "EUR"
      ],
      "bedeutung": "Währung aller Beträge."
    },
    {
      "pfad": "lieferland",
      "pflicht": "ja",
      "typ": "genau \"DE\"",
      "werte": [
        "DE"
      ],
      "bedeutung": "Land, für das die Versandkosten gelten."
    },
    {
      "pfad": "anbieter",
      "pflicht": "ja",
      "typ": "Objekt",
      "bedeutung": "Der Händler."
    },
    {
      "pfad": "anbieter.name",
      "pflicht": "ja",
      "typ": "Text, 2–120 Zeichen, ohne HTML",
      "bedeutung": "Firma mit Rechtsform, wie im Impressum.",
      "grund": "§ 5b Abs. 1 Nr. 2 UWG"
    },
    {
      "pfad": "anbieter.anschrift",
      "pflicht": "ja",
      "typ": "Text, 10–200 Zeichen, ohne HTML",
      "bedeutung": "Ladungsfähige Anschrift (Straße, PLZ, Ort).",
      "grund": "§ 5b Abs. 1 Nr. 2 UWG"
    },
    {
      "pfad": "anbieter.impressum_url",
      "pflicht": "ja",
      "typ": "https-Adresse auf der angemeldeten Website",
      "bedeutung": "Adresse des Impressums auf der eigenen Website."
    },
    {
      "pfad": "anbieter.shopname",
      "pflicht": "nein",
      "typ": "Text, 2–60 Zeichen, ohne HTML",
      "bedeutung": "Name des Shops (sonst zeigt die Suche die Domain)."
    },
    {
      "pfad": "anbieter.umsatzsteuer",
      "pflicht": "ja",
      "typ": "einer der Werte \"enthalten\", \"kleinunternehmer\"",
      "werte": [
        "enthalten",
        "kleinunternehmer"
      ],
      "bedeutung": "enthalten (Preise inkl. MwSt.) oder kleinunternehmer (§ 19 UStG, keine Umsatzsteuer).",
      "grund": "§ 6 Abs. 1 Nr. 1 PAngV"
    },
    {
      "pfad": "produkte",
      "pflicht": "ja",
      "typ": "Liste mit 1 bis 2000 Objekten",
      "bedeutung": "Die Angebote."
    },
    {
      "pfad": "produkte[].id",
      "pflicht": "ja",
      "typ": "Text, 1–64 Zeichen, ohne HTML",
      "bedeutung": "Eindeutige Kennung des Angebots im Feed (z. B. Artikelnummer). Gleiche id = gleiches Angebot.",
      "grund": "Statistik, Bild und Klickziel bleiben stabil"
    },
    {
      "pfad": "produkte[].titel",
      "pflicht": "ja",
      "typ": "Text, 3–150 Zeichen, ohne HTML",
      "bedeutung": "Produktname, reiner Text ohne HTML."
    },
    {
      "pfad": "produkte[].url",
      "pflicht": "ja",
      "typ": "https-Adresse auf der angemeldeten Website",
      "bedeutung": "Adresse der Produktseite im Shop.",
      "grund": "Ziel des Klicks; nur eigene Angebote"
    },
    {
      "pfad": "produkte[].bild_url",
      "pflicht": "ja",
      "typ": "https-Adresse",
      "bedeutung": "Adresse eines Produktbildes (PNG, JPEG oder WebP bis 5 MB, mindestens 100 × 100 Pixel). Darf auf einem CDN liegen.",
      "grund": "Bild im Band; die Suche zeigt nur eine eigene Kopie"
    },
    {
      "pfad": "produkte[].preis",
      "pflicht": "ja",
      "typ": "Zahl (Euro, Punkt als Dezimaltrenner, höchstens 2 Nachkommastellen) von 0,01 bis 1.000.000",
      "bedeutung": "Gesamtpreis in Euro einschließlich Umsatzsteuer und aller sonstigen Preisbestandteile, höchstens zwei Nachkommastellen, als Zahl (19.99, nicht \"19,99\").",
      "grund": "§ 3 PAngV"
    },
    {
      "pfad": "produkte[].versandkosten",
      "pflicht": "ja",
      "typ": "Zahl (Euro, Punkt als Dezimaltrenner, höchstens 2 Nachkommastellen) von 0 bis 10.000",
      "bedeutung": "Versandkosten für diesen einen Artikel bei Lieferung nach Deutschland in Euro; 0 = versandkostenfrei.",
      "grund": "§ 6 Abs. 2 PAngV; BGH I ZR 140/07 und I ZR 16/08 (Froogle)"
    },
    {
      "pfad": "produkte[].verfuegbarkeit",
      "pflicht": "ja",
      "typ": "einer der Werte \"lieferbar\", \"vorbestellbar\", \"nicht_lieferbar\"",
      "werte": [
        "lieferbar",
        "vorbestellbar",
        "nicht_lieferbar"
      ],
      "bedeutung": "Ob die Ware lieferbar ist. nicht_lieferbar wird nicht angezeigt.",
      "grund": "§ 5 UWG, Anhang Nr. 5 (Lockangebote)"
    },
    {
      "pfad": "produkte[].zustand",
      "pflicht": "ja",
      "typ": "einer der Werte \"neu\", \"gebraucht\", \"generalueberholt\"",
      "werte": [
        "neu",
        "gebraucht",
        "generalueberholt"
      ],
      "bedeutung": "Zustand der Ware.",
      "grund": "§ 5 UWG"
    },
    {
      "pfad": "produkte[].grundpreis",
      "pflicht": "null_erlaubt",
      "typ": "null oder Objekt",
      "bedeutung": "null, wenn die Ware nicht nach Gewicht, Volumen, Länge oder Fläche verkauft wird; sonst Preis je 1 kg, 1 l, 1 m, 1 m² oder 1 m³.",
      "grund": "§§ 4, 5 PAngV"
    },
    {
      "pfad": "produkte[].grundpreis.preis",
      "pflicht": "ja",
      "typ": "Zahl (Euro, Punkt als Dezimaltrenner, höchstens 2 Nachkommastellen) von 0,01 bis 1.000.000",
      "bedeutung": "Grundpreis in Euro je Einheit."
    },
    {
      "pfad": "produkte[].grundpreis.einheit",
      "pflicht": "ja",
      "typ": "einer der Werte \"kg\", \"l\", \"m\", \"m2\", \"m3\"",
      "werte": [
        "kg",
        "l",
        "m",
        "m2",
        "m3"
      ],
      "bedeutung": "Mengeneinheit: kg, l, m, m2 (Quadratmeter), m3 (Kubikmeter)."
    },
    {
      "pfad": "produkte[].energielabel",
      "pflicht": "null_erlaubt",
      "typ": "null oder Objekt",
      "bedeutung": "null, wenn das Produkt kein EU-Energielabel trägt; sonst Klasse, Skala und Adresse des Labels.",
      "grund": "Art. 6 VO (EU) 2017/1369; VO (EU) 2023/1669; VO (EU) 2020/740"
    },
    {
      "pfad": "produkte[].energielabel.klasse",
      "pflicht": "ja",
      "typ": "einer der Werte \"A+++\", \"A++\", \"A+\", \"A\", \"B\", \"C\", \"D\", \"E\", \"F\", \"G\"",
      "werte": [
        "A+++",
        "A++",
        "A+",
        "A",
        "B",
        "C",
        "D",
        "E",
        "F",
        "G"
      ],
      "bedeutung": "Energieeffizienzklasse laut Label."
    },
    {
      "pfad": "produkte[].energielabel.skala",
      "pflicht": "ja",
      "typ": "Text, 3–9 Zeichen, ohne HTML",
      "bedeutung": "Spannweite der Skala, beste Klasse zuerst: A-G, A-E (Reifen) oder A+++-D."
    },
    {
      "pfad": "produkte[].energielabel.label_url",
      "pflicht": "ja",
      "typ": "https-Adresse",
      "bedeutung": "Adresse des vollständigen Labels (bei Reifen das Reifenlabel)."
    },
    {
      "pfad": "produkte[].energielabel.datenblatt_url",
      "pflicht": "nein",
      "typ": "https-Adresse",
      "bedeutung": "Adresse des Produktdatenblatts (z. B. EPREL)."
    },
    {
      "pfad": "produkte[].pflichthinweis",
      "pflicht": "null_erlaubt",
      "typ": "null oder Objekt",
      "bedeutung": "null, wenn die Ware weder Arzneimittel noch Biozidprodukt ist; sonst Art und – bei Arzneimitteln Pflicht – Adresse der Pflichtangaben.",
      "grund": "§ 4 HWG; Art. 72 VO (EU) 528/2012"
    },
    {
      "pfad": "produkte[].pflichthinweis.art",
      "pflicht": "ja",
      "typ": "einer der Werte \"arzneimittel\", \"biozid\"",
      "werte": [
        "arzneimittel",
        "biozid"
      ],
      "bedeutung": "arzneimittel (rezeptfrei) oder biozid."
    },
    {
      "pfad": "produkte[].pflichthinweis.url",
      "pflicht": "wenn art = arzneimittel",
      "typ": "https-Adresse",
      "bedeutung": "Adresse der Pflichtangaben bzw. Packungsbeilage."
    },
    {
      "pfad": "produkte[].marke",
      "pflicht": "nein",
      "typ": "Text, 1–70 Zeichen, ohne HTML",
      "bedeutung": "Marke oder Hersteller."
    },
    {
      "pfad": "produkte[].gtin",
      "pflicht": "nein",
      "typ": "Text, 8–14 Zeichen, ohne HTML",
      "bedeutung": "GTIN/EAN mit gültiger Prüfziffer (8, 12, 13 oder 14 Ziffern)."
    },
    {
      "pfad": "produkte[].beschreibung",
      "pflicht": "nein",
      "typ": "Text, 1–1000 Zeichen, ohne HTML",
      "bedeutung": "Kurze Beschreibung, reiner Text; wird durchsucht."
    },
    {
      "pfad": "produkte[].kategorie",
      "pflicht": "nein",
      "typ": "Text, 1–200 Zeichen, ohne HTML",
      "bedeutung": "Kategorie, gern als Pfad (Lebensmittel > Kaffee)."
    },
    {
      "pfad": "produkte[].lieferzeit",
      "pflicht": "nein",
      "typ": "Text, 1–60 Zeichen, ohne HTML",
      "bedeutung": "Lieferzeit, z. B. „1–3 Werktage“."
    },
    {
      "pfad": "produkte[].versand_hinweis",
      "pflicht": "nein",
      "typ": "Text, 1–80 Zeichen, ohne HTML",
      "bedeutung": "Hinweis zum Versand, z. B. „ab 50 € versandkostenfrei“."
    }
  ],
  "pruefliste_vor_der_ausgabe": [
    "Ist format genau \"gemeinsamki-produktfeed/1\", waehrung \"EUR\", lieferland \"DE\"?",
    "Ist stand ein RFC-3339-Zeitpunkt mit Zeitzone, höchstens 24 Stunden alt?",
    "Hat anbieter name, anschrift, impressum_url (eigene Website, https) und umsatzsteuer (enthalten | kleinunternehmer)?",
    "Hat jedes Produkt id, titel, url, bild_url, preis, versandkosten, verfuegbarkeit, zustand, grundpreis, energielabel, pflichthinweis?",
    "Sind alle Beträge Zahlen mit höchstens zwei Nachkommastellen und preis größer als 0?",
    "Liegen alle url auf der angemeldeten Website und beginnen alle Adressen mit https://?",
    "Hat jedes Arzneimittel einen pflichthinweis mit url?",
    "Kommt jede id nur einmal vor? Gibt es kein Feld außerhalb von felder?",
    "Enthält kein Text HTML? Ist kein Produkt aus nicht_in_den_feed dabei?"
  ],
  "einreichen": {
    "abruf": "etwa alle 60 Minuten; schneller über „Jetzt abrufen“ in der Konsole",
    "beschreibung": "https://search.gemeinsamki.de/produktfeed",
    "konsole": "https://search.gemeinsamki.de/konsole",
    "schritte": [
      "Website in der Konsole anmelden und den Besitz nachweisen.",
      "Konsole → Website → Produkte → „Feed hinterlegen“: https-Adresse eintragen und der Erklärung zustimmen.",
      "Die Suche ruft den Feed sofort ab und zeigt jeden Fehler mit Pfad; nach der Freigabe durch einen Administrator erscheinen die Angebote."
    ]
  },
  "prompt_vorlage": "Erzeuge aus meinen Produktdaten (angehängt) einen Produktfeed für GemeinsamKI Suche. Halte dich genau an die angehängte Anweisung gemeinsamki-produktfeed-anweisung/1 (https://search.gemeinsamki.de/produktfeed/anweisung.json): Felder, Regeln, JSON-Schema und Prüfliste. Erfinde nichts – fehlen Angaben wie Firma, Anschrift, Versandkosten, Grundpreis oder Energielabel, frag mich danach. Gib am Ende nur das fertige JSON-Objekt aus, ohne Kommentar und ohne Markdown.",
  "json_schema": {
    "$id": "https://search.gemeinsamki.de/produktfeed/schema.json",
    "$schema": "https://json-schema.org/draft/2020-12/schema",
    "additionalProperties": false,
    "description": "Produktfeed für GemeinsamKI Suche. Beschreibung: https://search.gemeinsamki.de/produktfeed. Ein Feed mit auch nur einem Fehler wird nicht angezeigt.",
    "properties": {
      "anbieter": {
        "additionalProperties": false,
        "description": "Der Händler.",
        "properties": {
          "anschrift": {
            "description": "Ladungsfähige Anschrift (Straße, PLZ, Ort). (§ 5b Abs. 1 Nr. 2 UWG)",
            "maxLength": 200,
            "minLength": 10,
            "pattern": "^(?![\\s\\S]*<\\s*/?\\s*[A-Za-z!])",
            "type": "string"
          },
          "impressum_url": {
            "description": "Adresse des Impressums auf der eigenen Website. Muss auf der bei GemeinsamKI Suche angemeldeten Website liegen.",
            "format": "uri",
            "maxLength": 2048,
            "minLength": 10,
            "pattern": "^https://",
            "type": "string"
          },
          "name": {
            "description": "Firma mit Rechtsform, wie im Impressum. (§ 5b Abs. 1 Nr. 2 UWG)",
            "maxLength": 120,
            "minLength": 2,
            "pattern": "^(?![\\s\\S]*<\\s*/?\\s*[A-Za-z!])",
            "type": "string"
          },
          "shopname": {
            "description": "Name des Shops (sonst zeigt die Suche die Domain).",
            "maxLength": 60,
            "minLength": 2,
            "pattern": "^(?![\\s\\S]*<\\s*/?\\s*[A-Za-z!])",
            "type": "string"
          },
          "umsatzsteuer": {
            "description": "enthalten (Preise inkl. MwSt.) oder kleinunternehmer (§ 19 UStG, keine Umsatzsteuer). (§ 6 Abs. 1 Nr. 1 PAngV)",
            "enum": [
              "enthalten",
              "kleinunternehmer"
            ],
            "type": "string"
          }
        },
        "required": [
          "name",
          "anschrift",
          "impressum_url",
          "umsatzsteuer"
        ],
        "type": "object"
      },
      "format": {
        "const": "gemeinsamki-produktfeed/1",
        "description": "Kennung des Formats."
      },
      "lieferland": {
        "const": "DE",
        "description": "Land, für das die Versandkosten gelten."
      },
      "produkte": {
        "description": "Die Angebote. Jede id nur einmal.",
        "items": {
          "additionalProperties": false,
          "properties": {
            "beschreibung": {
              "description": "Kurze Beschreibung, reiner Text; wird durchsucht.",
              "maxLength": 1000,
              "minLength": 1,
              "pattern": "^(?![\\s\\S]*<\\s*/?\\s*[A-Za-z!])",
              "type": "string"
            },
            "bild_url": {
              "description": "Adresse eines Produktbildes (PNG, JPEG oder WebP bis 5 MB, mindestens 100 × 100 Pixel). Darf auf einem CDN liegen. (Bild im Band; die Suche zeigt nur eine eigene Kopie)",
              "format": "uri",
              "maxLength": 2048,
              "minLength": 10,
              "pattern": "^https://",
              "type": "string"
            },
            "energielabel": {
              "additionalProperties": false,
              "description": "null, wenn das Produkt kein EU-Energielabel trägt; sonst Klasse, Skala und Adresse des Labels. (Art. 6 VO (EU) 2017/1369; VO (EU) 2023/1669; VO (EU) 2020/740)",
              "properties": {
                "datenblatt_url": {
                  "description": "Adresse des Produktdatenblatts (z. B. EPREL).",
                  "format": "uri",
                  "maxLength": 2048,
                  "minLength": 10,
                  "pattern": "^https://",
                  "type": "string"
                },
                "klasse": {
                  "description": "Energieeffizienzklasse laut Label.",
                  "enum": [
                    "A+++",
                    "A++",
                    "A+",
                    "A",
                    "B",
                    "C",
                    "D",
                    "E",
                    "F",
                    "G"
                  ],
                  "type": "string"
                },
                "label_url": {
                  "description": "Adresse des vollständigen Labels (bei Reifen das Reifenlabel).",
                  "format": "uri",
                  "maxLength": 2048,
                  "minLength": 10,
                  "pattern": "^https://",
                  "type": "string"
                },
                "skala": {
                  "description": "Spannweite der Skala, beste Klasse zuerst: A-G, A-E (Reifen) oder A+++-D.",
                  "maxLength": 9,
                  "minLength": 3,
                  "pattern": "^(A\\+{0,3}|[B-G])-(A\\+{0,3}|[B-G])$",
                  "type": "string"
                }
              },
              "required": [
                "klasse",
                "skala",
                "label_url"
              ],
              "type": [
                "object",
                "null"
              ]
            },
            "grundpreis": {
              "additionalProperties": false,
              "description": "null, wenn die Ware nicht nach Gewicht, Volumen, Länge oder Fläche verkauft wird; sonst Preis je 1 kg, 1 l, 1 m, 1 m² oder 1 m³. (§§ 4, 5 PAngV)",
              "properties": {
                "einheit": {
                  "description": "Mengeneinheit: kg, l, m, m2 (Quadratmeter), m3 (Kubikmeter).",
                  "enum": [
                    "kg",
                    "l",
                    "m",
                    "m2",
                    "m3"
                  ],
                  "type": "string"
                },
                "preis": {
                  "description": "Grundpreis in Euro je Einheit. Höchstens zwei Nachkommastellen.",
                  "maximum": 1000000,
                  "minimum": 0.01,
                  "type": "number"
                }
              },
              "required": [
                "preis",
                "einheit"
              ],
              "type": [
                "object",
                "null"
              ]
            },
            "gtin": {
              "description": "GTIN/EAN mit gültiger Prüfziffer (8, 12, 13 oder 14 Ziffern).",
              "maxLength": 14,
              "minLength": 8,
              "pattern": "^([0-9]{8}|[0-9]{12,14})$",
              "type": "string"
            },
            "id": {
              "description": "Eindeutige Kennung des Angebots im Feed (z. B. Artikelnummer). Gleiche id = gleiches Angebot. (Statistik, Bild und Klickziel bleiben stabil)",
              "maxLength": 64,
              "minLength": 1,
              "pattern": "^[A-Za-z0-9][A-Za-z0-9._:/-]{0,63}$",
              "type": "string"
            },
            "kategorie": {
              "description": "Kategorie, gern als Pfad (Lebensmittel > Kaffee).",
              "maxLength": 200,
              "minLength": 1,
              "pattern": "^(?![\\s\\S]*<\\s*/?\\s*[A-Za-z!])",
              "type": "string"
            },
            "lieferzeit": {
              "description": "Lieferzeit, z. B. „1–3 Werktage“.",
              "maxLength": 60,
              "minLength": 1,
              "pattern": "^(?![\\s\\S]*<\\s*/?\\s*[A-Za-z!])",
              "type": "string"
            },
            "marke": {
              "description": "Marke oder Hersteller.",
              "maxLength": 70,
              "minLength": 1,
              "pattern": "^(?![\\s\\S]*<\\s*/?\\s*[A-Za-z!])",
              "type": "string"
            },
            "pflichthinweis": {
              "additionalProperties": false,
              "description": "null, wenn die Ware weder Arzneimittel noch Biozidprodukt ist; sonst Art und – bei Arzneimitteln Pflicht – Adresse der Pflichtangaben. (§ 4 HWG; Art. 72 VO (EU) 528/2012)",
              "if": {
                "properties": {
                  "art": {
                    "const": "arzneimittel"
                  }
                },
                "type": "object"
              },
              "properties": {
                "art": {
                  "description": "arzneimittel (rezeptfrei) oder biozid.",
                  "enum": [
                    "arzneimittel",
                    "biozid"
                  ],
                  "type": "string"
                },
                "url": {
                  "description": "Adresse der Pflichtangaben bzw. Packungsbeilage.",
                  "format": "uri",
                  "maxLength": 2048,
                  "minLength": 10,
                  "pattern": "^https://",
                  "type": "string"
                }
              },
              "required": [
                "art"
              ],
              "then": {
                "required": [
                  "url"
                ]
              },
              "type": [
                "object",
                "null"
              ]
            },
            "preis": {
              "description": "Gesamtpreis in Euro einschließlich Umsatzsteuer und aller sonstigen Preisbestandteile, höchstens zwei Nachkommastellen, als Zahl (19.99, nicht \"19,99\"). (§ 3 PAngV) Höchstens zwei Nachkommastellen.",
              "maximum": 1000000,
              "minimum": 0.01,
              "type": "number"
            },
            "titel": {
              "description": "Produktname, reiner Text ohne HTML.",
              "maxLength": 150,
              "minLength": 3,
              "pattern": "^(?![\\s\\S]*<\\s*/?\\s*[A-Za-z!])",
              "type": "string"
            },
            "url": {
              "description": "Adresse der Produktseite im Shop. (Ziel des Klicks; nur eigene Angebote) Muss auf der bei GemeinsamKI Suche angemeldeten Website liegen.",
              "format": "uri",
              "maxLength": 2048,
              "minLength": 10,
              "pattern": "^https://",
              "type": "string"
            },
            "verfuegbarkeit": {
              "description": "Ob die Ware lieferbar ist. nicht_lieferbar wird nicht angezeigt. (§ 5 UWG, Anhang Nr. 5 (Lockangebote))",
              "enum": [
                "lieferbar",
                "vorbestellbar",
                "nicht_lieferbar"
              ],
              "type": "string"
            },
            "versand_hinweis": {
              "description": "Hinweis zum Versand, z. B. „ab 50 € versandkostenfrei“.",
              "maxLength": 80,
              "minLength": 1,
              "pattern": "^(?![\\s\\S]*<\\s*/?\\s*[A-Za-z!])",
              "type": "string"
            },
            "versandkosten": {
              "description": "Versandkosten für diesen einen Artikel bei Lieferung nach Deutschland in Euro; 0 = versandkostenfrei. (§ 6 Abs. 2 PAngV; BGH I ZR 140/07 und I ZR 16/08 (Froogle)) Höchstens zwei Nachkommastellen.",
              "maximum": 10000,
              "minimum": 0,
              "type": "number"
            },
            "zustand": {
              "description": "Zustand der Ware. (§ 5 UWG)",
              "enum": [
                "neu",
                "gebraucht",
                "generalueberholt"
              ],
              "type": "string"
            }
          },
          "required": [
            "id",
            "titel",
            "url",
            "bild_url",
            "preis",
            "versandkosten",
            "verfuegbarkeit",
            "zustand",
            "grundpreis",
            "energielabel",
            "pflichthinweis"
          ],
          "type": "object"
        },
        "maxItems": 2000,
        "minItems": 1,
        "type": "array"
      },
      "stand": {
        "description": "Zeitpunkt, zu dem Preise und Verfügbarkeit gelten, nach RFC 3339 mit Zeitzone (2026-10-22T14:05:00+02:00). Wird als „Stand“ am Angebot gezeigt. (§ 5 UWG; BGH I ZR 123/08) Höchstens 24 Stunden alt.",
        "format": "date-time",
        "type": "string"
      },
      "waehrung": {
        "const": "EUR",
        "description": "Währung aller Beträge."
      }
    },
    "required": [
      "format",
      "stand",
      "waehrung",
      "lieferland",
      "anbieter",
      "produkte"
    ],
    "title": "GemeinsamKI Produktfeed (gemeinsamki-produktfeed/1)",
    "type": "object"
  },
  "beispiel": {
    "format": "gemeinsamki-produktfeed/1",
    "stand": "2026-10-22T14:05:00+02:00",
    "waehrung": "EUR",
    "lieferland": "DE",
    "anbieter": {
      "name": "Muster Handels GmbH",
      "anschrift": "Musterstraße 1, 12345 Musterstadt",
      "impressum_url": "https://www.mustershop.de/impressum",
      "shopname": "Mustershop",
      "umsatzsteuer": "enthalten"
    },
    "produkte": [
      {
        "id": "KAF-1001",
        "titel": "Espresso Bohnen Bio, 1 kg",
        "url": "https://www.mustershop.de/p/espresso-bio-1kg",
        "bild_url": "https://cdn.mustershop.de/bilder/kaf-1001.jpg",
        "preis": 18.90,
        "versandkosten": 4.95,
        "verfuegbarkeit": "lieferbar",
        "zustand": "neu",
        "grundpreis": {
          "preis": 18.90,
          "einheit": "kg"
        },
        "energielabel": null,
        "pflichthinweis": null,
        "marke": "Musterrösterei",
        "gtin": "4006381333931",
        "beschreibung": "Ganze Bohnen aus ökologischem Anbau, schonend geröstet.",
        "kategorie": "Lebensmittel > Kaffee",
        "lieferzeit": "1–3 Werktage",
        "versand_hinweis": "ab 50 € versandkostenfrei"
      },
      {
        "id": "WM-2002",
        "titel": "Waschmaschine 8 kg, 1400 U/min",
        "url": "https://www.mustershop.de/p/waschmaschine-8kg",
        "bild_url": "https://cdn.mustershop.de/bilder/wm-2002.jpg",
        "preis": 549.00,
        "versandkosten": 0,
        "verfuegbarkeit": "vorbestellbar",
        "zustand": "neu",
        "grundpreis": null,
        "energielabel": {
          "klasse": "A",
          "skala": "A-G",
          "label_url": "https://www.mustershop.de/label/wm-2002.pdf",
          "datenblatt_url": "https://eprel.ec.europa.eu/qr/123456"
        },
        "pflichthinweis": null
      }
    ]
  }
}
