{"openapi":"3.1.0","info":{"title":"SliceQuote Public API","version":"1.0.0","description":"Öffentlich erreichbare Endpunkte des SliceQuote-Widgets und des\nCheckout-Flows. Diese Endpunkte werden von eingebetteten Widgets\nauf Shop-Websites und von Shop-Integrationen (ERP, eigene Tools)\naufgerufen.\n\n## Authentifizierung\n- **Öffentlich:** Widget-/Public-Endpunkte benötigen keine\n  Authentifizierung; der Shop-Kontext wird über `shopId` (Query oder\n  Pfad) aufgelöst.\n- **Session-Cookie (`cookieAuth`):** Admin-/Super-Admin-Routen (hier\n  nicht dokumentiert, Stufe 2) nutzen die next-auth-Session.\n- **API-Key (`apiKeyAuth`):** Die `/api/v1/*`-Endpunkte erwarten einen\n  shop-scoped Key: `Authorization: Bearer sq_live_…` (Verwaltung unter\n  Admin → API-Keys, Premium-Feature). Scopes je Endpunkt siehe unten.\n\n## Agent-Zugriff\nDie Homepage `/` unterstützt `Accept: text/markdown` und `Vary: Accept`.\n`/index.md` liefert denselben Markdown-Inhalt; `/llms.txt` verlinkt Produkt und Dokumentation.\n`GET /api` entdeckt die API; unbekannte API-Pfade liefern strukturierte JSON-404.\n\n## Fehlerformat\nAPI-Zugangsfehler, unbekannte API-Pfade und Shop-Konfigurationsfehler verwenden\n`application/problem+json` nach RFC 9457 mit `code`, `message`, `resolution`\nund dem bisherigen `error`-Feld. Andere Routen behalten ihre dokumentierten Fehlerformate.\nValidierungsfehler folgen einheitlich dem Format\n`400 { error: string, details: ZodIssue[] }` (siehe `zodErrorResponse`).\nPlan-Limits werden mit `403 { code: \"PLAN_LIMIT_REACHED\", ... }`\nsignalisiert (Issue #92).\n\n## Rate-Limits\n- `POST /api/upload`: 20 Uploads pro IP / 15 Minuten\n- `POST /api/quotes`: 5 Anfragen pro IP / Stunde\nÜberschreitung → `429` mit `Retry-After`-Header."},"servers":[{"url":"/","description":"Aktuelle Instanz"}],"tags":[{"name":"Public","description":"Öffentliche Shop-/Widget-Konfiguration"},{"name":"Widget","description":"Upload- und Bestell-Flow des Widgets"},{"name":"API v1","description":"Shop-scoped REST-API (API-Key-Auth)"},{"name":"Admin","description":"Shop-Admin-Routen (Session-Auth via Cookie)"}],"components":{"securitySchemes":{"cookieAuth":{"type":"apiKey","in":"cookie","name":"next-auth.session-token","description":"next-auth-Session-Cookie (Admin-/Super-Admin-Routen)."},"apiKeyAuth":{"type":"http","scheme":"bearer","description":"Shop-scoped API-Key (`sq_live_…`), verwaltet unter Admin → API-Keys."}},"schemas":{"ProblemDetails":{"type":"object","description":"RFC 9457 Problem Details mit rückwärtskompatiblem error und Lösungshinweis.","required":["type","title","status","detail","error","code","message","resolution","links"],"properties":{"type":{"type":"string","const":"about:blank"},"title":{"type":"string"},"status":{"type":"integer","minimum":400,"maximum":599},"detail":{"type":"string"},"instance":{"type":"string","format":"uri-reference"},"error":{"type":"string"},"code":{"type":"string"},"message":{"type":"string"},"resolution":{"type":"string","description":"Konkreter nächster Schritt für den Aufrufer."},"links":{"type":"object","properties":{"documentation":{"type":"string","const":"/api-docs"},"specification":{"type":"string","const":"/api/openapi.json"}}}}},"Error":{"type":"object","properties":{"error":{"type":"string","description":"Menschenlesbare Fehlermeldung."},"details":{"type":"array","description":"Rohes Zod-Fehlerarray bei Validierungsfehlern (400).","items":{"type":"object","properties":{"path":{"type":"array","items":{"type":"string"}},"message":{"type":"string"}}}}},"required":["error"]},"PlanLimitError":{"type":"object","properties":{"code":{"type":"string","enum":["PLAN_LIMIT_REACHED"]},"error":{"type":"string"},"resource":{"type":"string","example":"materials"}},"required":["code"]},"CustomerData":{"type":"object","properties":{"name":{"type":"string"},"company":{"type":"string"},"email":{"type":"string","format":"email"},"phone":{"type":"string"},"notes":{"type":"string"},"billingAddress":{"type":"string"},"shippingAddress":{"type":"string"}},"required":["name","email"]},"CreateOrderRequest":{"type":"object","description":"Spiegelt `CreateOrderSchema` in `app/api/orders/route.ts`.","properties":{"printJobId":{"type":"string"},"paymentProviderId":{"type":"string"},"shippingMethodName":{"type":"string","maxLength":200,"description":"Name einer aktiven Versandart des Shops (users.shippingMethods). Der Preis wird serverseitig übernommen und fließt in totalAmount ein."},"locale":{"type":"string","maxLength":10,"description":"Kundensprache für die transaktionalen Mails dieser Bestellung (de/en/fr/es/it/nl/pl; wird serverseitig normalisiert, Fallback de)."},"customerData":{"$ref":"#/components/schemas/CustomerData"}},"required":["printJobId","paymentProviderId","customerData"]},"ShopConfig":{"type":"object","description":"Öffentliche Widget-Konfiguration eines Shops (Felder je nach Setup).","additionalProperties":true},"CheckoutRequest":{"type":"object","required":["orderId"],"properties":{"orderId":{"type":"string","minLength":1,"maxLength":100,"pattern":"^[A-Za-z0-9_-]+$"}}},"BatchCheckoutRequest":{"type":"object","required":["orderIds"],"properties":{"orderIds":{"type":"array","uniqueItems":true,"minItems":1,"maxItems":20,"description":"Das JSON-serialisierte Array darf maximal 500 Zeichen haben (Anbieter-Metadatenlimit). Alle IDs müssen existieren und zum selben Shop gehören.","items":{"type":"string","minLength":1,"maxLength":100,"pattern":"^[A-Za-z0-9_-]+$"}}}},"CheckoutError":{"type":"object","required":["error","code","canRetry","requestId"],"properties":{"error":{"type":"string","description":"Öffentlicher Fallbacktext; keine internen Anbieterdetails."},"code":{"type":"string","enum":["INVALID_REQUEST","ORDER_NOT_FOUND","MIXED_SHOPS","PAYMENT_NOT_CONFIGURED","ALREADY_PAID","PAYMENT_PROCESSING","ORDER_NOT_PAYABLE","CHECKOUT_CONFLICT","PAYMENT_STATUS_UNAVAILABLE","PAYMENT_UNAVAILABLE","PAYMENT_REVIEW_REQUIRED","CHECKOUT_FAILED"]},"canRetry":{"type":"boolean","description":"Manuelle Wiederholung sinnvoll; keinen neuen Bestellvorgang starten."},"requestId":{"type":"string","format":"uuid"}}},"SaveQuoteRequest":{"type":"object","description":"Spiegelt das Body-Schema in `app/api/quotes/route.ts`.","properties":{"shopId":{"type":"string"},"email":{"type":"string","format":"email"},"locale":{"type":"string","maxLength":10,"description":"Widget-Sprache des Kunden für die Angebots-Mails (de/en/fr/es/it/nl/pl; serverseitig normalisiert, Fallback de)."},"consentGiven":{"type":"boolean","description":"Muss `true` sein (DSGVO-Einwilligung)."},"jobIds":{"type":"array","items":{"type":"string"},"minItems":1,"maxItems":50,"description":"IDs der konfigurierten Print-Jobs des Angebots."}},"required":["shopId","email","consentGiven","jobIds"]},"ManualQuoteRequest":{"type":"object","description":"Spiegelt das Body-Schema in `app/api/quote-requests/route.ts`.","properties":{"shopId":{"type":"string"},"email":{"type":"string","format":"email"},"name":{"type":"string","maxLength":100},"phone":{"type":"string","maxLength":50},"message":{"type":"string","maxLength":2000,"description":"Freitext des Kunden (z. B. Stückzahl, Budget, Sonderwunsch)."},"locale":{"type":"string","maxLength":10,"description":"Widget-Sprache des Kunden für die Angebots-Mails (de/en/fr/es/it/nl/pl; serverseitig normalisiert, Fallback de)."},"consentGiven":{"type":"boolean","description":"Muss `true` sein (Einwilligung zur Kontaktaufnahme)."},"jobIds":{"type":"array","items":{"type":"string"},"minItems":1,"maxItems":50,"description":"IDs der konfigurierten Print-Jobs der Anfrage."}},"required":["shopId","email","consentGiven","jobIds"]},"UploadError":{"type":"object","description":"Upload-Fehler: code wird im Widget übersetzt; error bleibt als menschenlesbarer Fallback erhalten. Keine internen Fehlermeldungen.","properties":{"error":{"type":"string"},"code":{"type":"string","enum":["MISSING_SHOP","SHOP_NOT_FOUND","INVALID_REQUEST","MISSING_FILE","EMPTY_FILE","FILE_TOO_LARGE","UNSUPPORTED_FORMAT","FORMAT_NOT_AVAILABLE","INVALID_MODEL","RATE_LIMITED","SHOP_UNAVAILABLE","STORAGE_UNAVAILABLE","UPLOAD_FAILED"]},"canRetry":{"type":"boolean","description":"Ein späterer neuer Versuch ist sinnvoll; kein automatischer POST-Retry."},"requestId":{"type":"string","format":"uuid","description":"Serverseitige Referenz zum zugehörigen Fehlerprotokoll; auch im X-Request-ID-Header."},"messageParams":{"type":"object","description":"Parameter zur Übersetzung: maxMB, formats oder format.","additionalProperties":{"anyOf":[{"type":"string"},{"type":"number"}]}}},"required":["error","code","canRetry","requestId"]},"UploadResult":{"type":"object","description":"Analyseergebnis des hochgeladenen 3D-Modells (Auszug).","additionalProperties":true},"PrintJobConfigurationRequest":{"type":"object","description":"Widget-Konfigurationsfelder aus PATCH in app/api/print-jobs/[id]/route.ts. Alle Felder sind optional. Preise werden serverseitig berechnet; unitPrice und totalPrice werden ignoriert.","properties":{"materialId":{"type":["string","null"],"description":"Aktives Material des Shops; ungültige/fremde IDs werden ignoriert."},"materialColorId":{"type":["string","null"],"description":"Materialfarbe des Shops; ungültige/fremde IDs werden ignoriert."},"printerId":{"type":["string","null"],"description":"Aktiver Drucker des Shops; ungültige IDs werden durch die automatische Druckerauswahl ersetzt, soweit möglich."},"infillPercent":{"type":"integer","minimum":5,"maximum":100},"layerHeight":{"type":"number","minimum":0.05,"maximum":1,"description":"Schichthöhe in mm."},"rushOrder":{"type":"boolean"},"quantity":{"type":"integer","minimum":1,"maximum":10000},"scaleFactor":{"type":"number","minimum":0.01,"maximum":1000,"description":"Gleichmäßiger Faktor gegenüber der Originalgeometrie. Das resultierende bekannte Volumen muss zwischen 0,01 und 100000 cm³ liegen."},"volume":{"type":"number","minimum":0.01,"maximum":100000,"description":"Volumen in cm³; nur übernommen, wenn noch kein positives serverseitiges Volumen gespeichert ist."},"surfaceArea":{"type":"number","minimum":0.01,"description":"Oberfläche in cm²; nur übernommen, wenn noch kein positiver serverseitiger Wert gespeichert ist."},"printTime":{"type":["number","null"],"minimum":0},"filamentWeight":{"type":["number","null"],"minimum":0},"boundingBoxX":{"type":["number","null"],"minimum":0,"description":"Modellmaß in mm."},"boundingBoxY":{"type":["number","null"],"minimum":0,"description":"Modellmaß in mm."},"boundingBoxZ":{"type":["number","null"],"minimum":0,"description":"Modellmaß in mm."},"layerCount":{"type":["integer","null"],"minimum":0}}},"PrintJobUpdateError":{"type":"object","properties":{"error":{"type":"string","description":"Menschenlesbarer Fallback ohne interne Fehlerdetails."},"code":{"type":"string","enum":["INVALID_CONFIGURATION","JOB_NOT_FOUND","CONFIGURATION_FORBIDDEN","CONFIGURATION_EXPIRED","CONFIGURATION_CONFLICT","PRICE_CALCULATION_FAILED","CONFIGURATION_UPDATE_FAILED"]},"canRetry":{"type":"boolean","description":"true bei CONFIGURATION_CONFLICT, PRICE_CALCULATION_FAILED und CONFIGURATION_UPDATE_FAILED; sonst false."},"requestId":{"type":"string","format":"uuid","description":"Referenz zum Fehlerprotokoll und X-Request-ID-Header."}},"required":["error","code","canRetry","requestId"]},"PrintJobUpdateResult":{"type":"object","properties":{"success":{"type":"boolean","const":true},"printJob":{"type":"object","description":"Gespeicherter Print-Job inklusive Konfiguration und neu berechnetem Preis (Auszug).","properties":{"id":{"type":"string"},"totalCost":{"type":["number","string","null"],"description":"Gesamtpreis; null, wenn Angaben für die Preisberechnung fehlen. Dezimalwerte können als String serialisiert werden."},"updatedAt":{"type":"string","format":"date-time"}},"additionalProperties":true}},"required":["success","printJob"]},"Order":{"type":"object","description":"Bestellung (v1-API, auf den Shop des Keys beschränkt).","properties":{"id":{"type":"string"},"orderNumber":{"type":"string"},"customerName":{"type":"string"},"customerEmail":{"type":"string","format":"email"},"quantity":{"type":"integer"},"totalAmount":{"type":"number"},"paymentStatus":{"type":"string"},"orderStatus":{"type":"string","enum":["PENDING_PAYMENT","PAID","PROCESSING","PRINTED","SHIPPED","DELIVERED","CANCELLED","REFUNDED"]},"trackingNumber":{"type":["string","null"]},"fileName":{"type":["string","null"]},"fileFormat":{"type":["string","null"]},"createdAt":{"type":"string","format":"date-time"}}},"Material":{"type":"object","description":"Material inkl. Farben (v1-API).","properties":{"id":{"type":"string"},"name":{"type":"string"},"description":{"type":["string","null"]},"density":{"type":"number"},"colors":{"type":"array","items":{"type":"object","properties":{"id":{"type":"string"},"colorName":{"type":"string"},"colorHex":{"type":["string","null"]},"pricePerKg":{"type":"number"}}}}}},"Printer":{"type":"object","description":"Druckerprofil (v1-API).","properties":{"id":{"type":"string"},"name":{"type":"string"},"buildVolumeX":{"type":"number"},"buildVolumeY":{"type":"number"},"buildVolumeZ":{"type":"number"},"nozzleDiameter":{"type":"number"},"maxPrintSpeed":{"type":"number"},"layerHeights":{"type":"array","items":{"type":"number"}},"powerConsumption":{"type":"number"},"hourlyRate":{"type":"number"},"setupTime":{"type":"number"}}},"ProviderListing":{"type":"object","description":"Ergebnis des „Anbieter finden\"-Portals. Spiegelt `getEligibleProviders` in `app/lib/network-providers.ts`.","properties":{"volume":{"type":"number","description":"Modellvolumen in cm³."},"dimensions":{"type":"object","properties":{"x":{"type":"number"},"y":{"type":"number"},"z":{"type":"number"}},"description":"Bauraum-Maße in mm."},"providers":{"type":"array","items":{"type":"object","properties":{"shopId":{"type":"string"},"name":{"type":"string"},"city":{"type":["string","null"]},"country":{"type":["string","null"]},"currency":{"type":"string","description":"ISO-4217-Währung, in der der Preis angegeben ist."},"processingDays":{"type":"integer"},"completedOrders":{"type":"integer"},"avgReactionHours":{"type":["number","null"],"description":"Ø Reaktionszeit auf Angebotsanfragen in Stunden."},"price":{"type":"number","description":"„ab\"-Richtpreis inkl. Plattformgebühr."},"fits":{"type":"boolean","description":"Passt das Modell in mindestens einen Bauraum?"},"score":{"type":"number","description":"Empfehlungs-Score (höher = besser)."}}}}}}}},"paths":{"/api/stripe/create-checkout-session":{"post":{"tags":["Widget"],"summary":"Zahlung starten oder fortsetzen","description":"Öffentlicher Bestelllink-Flow. Wiederholungen verwenden dieselbe serverseitige Reservierung und denselben Idempotency-Key. Bereits bezahlte/verarbeitete Bestellungen und überlappende Zahlungsversuche werden abgelehnt. Nur eine beim Anbieter bestätigte abgelaufene Sitzung erlaubt einen neuen Versuch. Ungeklärte Reservierungen nach 23 Stunden erfordern manuelle Prüfung. Keine Kundendaten aus dem Fehlertext auswerten; code lokal übersetzen.","security":[],"requestBody":{"required":true,"content":{"application/json":{"schema":{"$ref":"#/components/schemas/CheckoutRequest"}}}},"responses":{"200":{"description":"Bestehende oder neu angelegte Bezahlseite","headers":{"X-Request-ID":{"schema":{"type":"string","format":"uuid"},"description":"Serverseitige Referenz; bei Fehlern identisch mit requestId im JSON-Body."}},"content":{"application/json":{"schema":{"type":"object","required":["sessionId","url"],"properties":{"sessionId":{"type":"string"},"url":{"type":"string","format":"uri"}}}}}},"400":{"description":"Ungültige Anfrage oder gemischte Shops","headers":{"X-Request-ID":{"schema":{"type":"string","format":"uuid"},"description":"Serverseitige Referenz; bei Fehlern identisch mit requestId im JSON-Body."}},"content":{"application/json":{"schema":{"$ref":"#/components/schemas/CheckoutError"}}}},"404":{"description":"Mindestens eine Bestellung fehlt","headers":{"X-Request-ID":{"schema":{"type":"string","format":"uuid"},"description":"Serverseitige Referenz; bei Fehlern identisch mit requestId im JSON-Body."}},"content":{"application/json":{"schema":{"$ref":"#/components/schemas/CheckoutError"}}}},"409":{"description":"Bereits bezahlt, in Verarbeitung, nicht zahlbar oder Konflikt/Prüfung erforderlich","headers":{"X-Request-ID":{"schema":{"type":"string","format":"uuid"},"description":"Serverseitige Referenz; bei Fehlern identisch mit requestId im JSON-Body."}},"content":{"application/json":{"schema":{"$ref":"#/components/schemas/CheckoutError"}}}},"500":{"description":"Interner Fehler; Reservierung bleibt für Wiederholung erhalten","headers":{"X-Request-ID":{"schema":{"type":"string","format":"uuid"},"description":"Serverseitige Referenz; bei Fehlern identisch mit requestId im JSON-Body."}},"content":{"application/json":{"schema":{"$ref":"#/components/schemas/CheckoutError"}}}},"503":{"description":"Anbieter/Status nicht verfügbar oder Konfigurationsfehler; canRetry beachten","headers":{"X-Request-ID":{"schema":{"type":"string","format":"uuid"},"description":"Serverseitige Referenz; bei Fehlern identisch mit requestId im JSON-Body."},"Retry-After":{"schema":{"type":"integer"},"description":"10 Sekunden bei wiederholbaren 503-Fehlern."}},"content":{"application/json":{"schema":{"$ref":"#/components/schemas/CheckoutError"}}}}}}},"/api/stripe/create-batch-checkout-session":{"post":{"tags":["Widget"],"summary":"Sammelzahlung starten oder fortsetzen","description":"Öffentlicher Bestelllink-Flow. Wiederholungen verwenden dieselbe serverseitige Reservierung und denselben Idempotency-Key. Bereits bezahlte/verarbeitete Bestellungen und überlappende Zahlungsversuche werden abgelehnt. Nur eine beim Anbieter bestätigte abgelaufene Sitzung erlaubt einen neuen Versuch. Ungeklärte Reservierungen nach 23 Stunden erfordern manuelle Prüfung. Keine Kundendaten aus dem Fehlertext auswerten; code lokal übersetzen.","security":[],"requestBody":{"required":true,"content":{"application/json":{"schema":{"$ref":"#/components/schemas/BatchCheckoutRequest"}}}},"responses":{"200":{"description":"Bestehende oder neu angelegte Bezahlseite","headers":{"X-Request-ID":{"schema":{"type":"string","format":"uuid"},"description":"Serverseitige Referenz; bei Fehlern identisch mit requestId im JSON-Body."}},"content":{"application/json":{"schema":{"type":"object","required":["sessionId","url"],"properties":{"sessionId":{"type":"string"},"url":{"type":"string","format":"uri"}}}}}},"400":{"description":"Ungültige Anfrage oder gemischte Shops","headers":{"X-Request-ID":{"schema":{"type":"string","format":"uuid"},"description":"Serverseitige Referenz; bei Fehlern identisch mit requestId im JSON-Body."}},"content":{"application/json":{"schema":{"$ref":"#/components/schemas/CheckoutError"}}}},"404":{"description":"Mindestens eine Bestellung fehlt","headers":{"X-Request-ID":{"schema":{"type":"string","format":"uuid"},"description":"Serverseitige Referenz; bei Fehlern identisch mit requestId im JSON-Body."}},"content":{"application/json":{"schema":{"$ref":"#/components/schemas/CheckoutError"}}}},"409":{"description":"Bereits bezahlt, in Verarbeitung, nicht zahlbar oder Konflikt/Prüfung erforderlich","headers":{"X-Request-ID":{"schema":{"type":"string","format":"uuid"},"description":"Serverseitige Referenz; bei Fehlern identisch mit requestId im JSON-Body."}},"content":{"application/json":{"schema":{"$ref":"#/components/schemas/CheckoutError"}}}},"500":{"description":"Interner Fehler; Reservierung bleibt für Wiederholung erhalten","headers":{"X-Request-ID":{"schema":{"type":"string","format":"uuid"},"description":"Serverseitige Referenz; bei Fehlern identisch mit requestId im JSON-Body."}},"content":{"application/json":{"schema":{"$ref":"#/components/schemas/CheckoutError"}}}},"503":{"description":"Anbieter/Status nicht verfügbar oder Konfigurationsfehler; canRetry beachten","headers":{"X-Request-ID":{"schema":{"type":"string","format":"uuid"},"description":"Serverseitige Referenz; bei Fehlern identisch mit requestId im JSON-Body."},"Retry-After":{"schema":{"type":"integer"},"description":"10 Sekunden bei wiederholbaren 503-Fehlern."}},"content":{"application/json":{"schema":{"$ref":"#/components/schemas/CheckoutError"}}}}}}},"/api":{"get":{"tags":["Public"],"summary":"API-Dokumentation und Agent-Ressourcen entdecken","description":"Öffentliche Links auf die Spezifikation und Dokumentation. Unbekannte API-Pfade liefern HTTP 404 als RFC-9457-JSON mit ENDPOINT_NOT_FOUND und Lösungshinweis. Geschützte API-Pfade behalten ihre vorgelagerte Auth-Prüfung.","responses":{"200":{"description":"API-Verzeichnis","content":{"application/json":{"schema":{"type":"object","required":["name","description","documentation","specification","agents"],"properties":{"name":{"type":"string"},"description":{"type":"string"},"documentation":{"type":"string","const":"/api-docs"},"specification":{"type":"string","const":"/api/openapi.json"},"agents":{"type":"string","const":"/llms.txt"}}}}}}}}},"/index.md":{"get":{"tags":["Public"],"summary":"Öffentliche Homepage als Markdown","description":"Englische Produktdefinition und öffentliche Links. Auch GET / mit Accept: text/markdown liefert diesen Inhalt; HTML bleibt die Standarddarstellung. Qualitätsgewichte werden ausgewertet, RSC-Anfragen behalten das Router-Protokoll. GET und HEAD werden unterstützt.","responses":{"200":{"description":"Markdown-Homepage","headers":{"Vary":{"schema":{"type":"string"},"description":"Enthält Accept bei Aushandlung über die Homepage."}},"content":{"text/markdown":{"schema":{"type":"string"}}}}}}},"/llms.txt":{"get":{"tags":["Public"],"summary":"Produkt- und Dokumentationsindex für Agents","description":"Markdown nach llmstxt.org: H1, Blockquote, Einführung und H2-Abschnitte mit Links. GET und HEAD werden unterstützt.","responses":{"200":{"description":"Agent-Index","content":{"text/plain":{"schema":{"type":"string"}}}}}}},"/api/snippet/{shopId}/data":{"get":{"tags":["Public"],"summary":"Shop-Daten für das Widget","parameters":[{"name":"shopId","in":"path","required":true,"schema":{"type":"string"}}],"responses":{"200":{"description":"Aktive Shop-Konfiguration","content":{"application/json":{"schema":{"type":"object","additionalProperties":true}}}},"404":{"description":"Shop nicht gefunden oder inaktiv","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}},"application/problem+json":{"schema":{"$ref":"#/components/schemas/ProblemDetails"}}}},"500":{"description":"Shop-Konfiguration vorübergehend nicht verfügbar","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}},"application/problem+json":{"schema":{"$ref":"#/components/schemas/ProblemDetails"}}}}}}},"/api/public/shop/{shopId}/config":{"get":{"tags":["Public"],"summary":"Öffentliche Widget-Konfiguration eines Shops","parameters":[{"name":"shopId","in":"path","required":true,"schema":{"type":"string"},"description":"Öffentliche Shop-ID."}],"responses":{"200":{"description":"Konfiguration gefunden","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ShopConfig"}}}},"404":{"description":"Shop nicht gefunden","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}},"application/problem+json":{"schema":{"$ref":"#/components/schemas/ProblemDetails"}}}},"500":{"description":"Shop-Konfiguration nicht verfügbar","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}},"application/problem+json":{"schema":{"$ref":"#/components/schemas/ProblemDetails"}}}}}}},"/api/public/tracking-config":{"get":{"tags":["Public"],"summary":"Öffentliche Tracking-/Analytics-Konfiguration","responses":{"200":{"description":"Tracking-Konfiguration","content":{"application/json":{"schema":{"type":"object","additionalProperties":true}}}}}}},"/api/upload":{"post":{"tags":["Widget"],"summary":"3D-Datei hochladen und analysieren","description":"Nimmt eine 3D-Modelldatei (STL, OBJ, 3MF, AMF sowie die CAD-Formate STEP/IGES) entgegen, prüft Format/Größe plan-abhängig und legt einen Print-Job an. STEP/IGES werden serverseitig zu einem Mesh tesselliert; exotische Formate (3MF, AMF, STEP, IGES) erfordern einen Premium-/Enterprise-Plan. Beschädigte, leere oder nicht endliche Geometrie wird vor dem Speichern abgewiesen. Fehler enthalten einen stabilen code, Übersetzungsparameter und eine serverseitige requestId. Speicher- und Dienstfehler sind von ungültigen Dateien unterscheidbar. Rate-Limit: 20/IP/15 min.","parameters":[{"name":"shopId","in":"query","required":true,"schema":{"type":"string"},"description":"Shop-Kontext; bestimmt Plan-Limits (Format, Upload-Größe)."}],"requestBody":{"required":true,"content":{"multipart/form-data":{"schema":{"type":"object","properties":{"file":{"type":"string","format":"binary","description":"3D-Modelldatei."}},"required":["file"]}}}},"responses":{"201":{"description":"Datei analysiert und Print-Job angelegt","headers":{"X-Request-ID":{"schema":{"type":"string","format":"uuid"}}},"content":{"application/json":{"schema":{"$ref":"#/components/schemas/UploadResult"}}}},"400":{"description":"Fehlende Datei/shopId, beschädigtes Multipart, ungültiges Modell/Format oder zu große Datei","content":{"application/json":{"schema":{"$ref":"#/components/schemas/UploadError"}}}},"403":{"description":"Der Shop nimmt wegen der Umsatzstaffelsperre keine Uploads an","content":{"application/json":{"schema":{"$ref":"#/components/schemas/UploadError"}}}},"404":{"description":"Shop nicht gefunden oder Demo-Shop nicht aktiv","content":{"application/json":{"schema":{"$ref":"#/components/schemas/UploadError"}}}},"429":{"description":"Rate-Limit überschritten","headers":{"Retry-After":{"schema":{"type":"integer"},"description":"Sekunden bis zum nächsten Versuch."}},"content":{"application/json":{"schema":{"$ref":"#/components/schemas/UploadError"}}}},"500":{"description":"Interner Fehler beim Speichern des Print-Jobs; requestId für Diagnose verwenden","content":{"application/json":{"schema":{"$ref":"#/components/schemas/UploadError"}}}},"503":{"description":"Shop-Auflösung, Dateispeicher oder CAD-Konverter vorübergehend nicht verfügbar","content":{"application/json":{"schema":{"$ref":"#/components/schemas/UploadError"}}}}}}},"/api/print-jobs/{id}":{"patch":{"tags":["Widget"],"summary":"Print-Job konfigurieren und Preis neu berechnen","description":"Anonymes Widget: passende shopId, Status CONFIGURED/SUBMITTED, höchstens 24 Stunden alt und noch keine Bestellung oder Shopify-Draft-Order. Alternativ ist eine Admin-Session erlaubt; Shop-Admins dürfen nur eigene Jobs ändern. Konfiguration und berechnete Kosten werden gemeinsam gespeichert. Ein Berechnungsfehler lässt die bisherige Konfiguration und ihren Preis unverändert (503). Fehlen Preisgrundlagen, wird die Konfiguration erfolgreich gespeichert und der Preis auf null gesetzt. Wird der Job während der Verarbeitung parallel geändert, schlägt das Speichern mit CONFIGURATION_CONFLICT (409) fehl.","security":[{},{"cookieAuth":[]}],"parameters":[{"name":"id","in":"path","required":true,"schema":{"type":"string"},"description":"ID des hochgeladenen Print-Jobs."},{"name":"shopId","in":"query","required":false,"schema":{"type":"string"},"description":"Öffentliche Shop-ID; für anonymen Widget-Zugriff erforderlich, bei einer Admin-Session optional."}],"requestBody":{"required":true,"content":{"application/json":{"schema":{"$ref":"#/components/schemas/PrintJobConfigurationRequest"}}}},"responses":{"200":{"description":"Konfiguration gespeichert; berechneter Preis oder null bei unvollständigen Preisgrundlagen","headers":{"X-Request-ID":{"schema":{"type":"string","format":"uuid"},"description":"Serverseitige Referenz; bei Fehlern identisch mit requestId im JSON-Body."}},"content":{"application/json":{"schema":{"$ref":"#/components/schemas/PrintJobUpdateResult"}}}},"400":{"description":"INVALID_CONFIGURATION: ungültiges JSON, Feldtyp oder Zahlenbereich; canRetry=false","headers":{"X-Request-ID":{"schema":{"type":"string","format":"uuid"},"description":"Serverseitige Referenz; bei Fehlern identisch mit requestId im JSON-Body."}},"content":{"application/json":{"schema":{"$ref":"#/components/schemas/PrintJobUpdateError"}}}},"403":{"description":"CONFIGURATION_FORBIDDEN: Shop-Kontext/Status/Bestellung verbietet die Änderung; CONFIGURATION_EXPIRED: älter als 24 Stunden; canRetry=false","headers":{"X-Request-ID":{"schema":{"type":"string","format":"uuid"},"description":"Serverseitige Referenz; bei Fehlern identisch mit requestId im JSON-Body."}},"content":{"application/json":{"schema":{"$ref":"#/components/schemas/PrintJobUpdateError"}}}},"404":{"description":"JOB_NOT_FOUND: Job fehlt oder gehört nicht zum authentifizierten Shop-Admin; canRetry=false","headers":{"X-Request-ID":{"schema":{"type":"string","format":"uuid"},"description":"Serverseitige Referenz; bei Fehlern identisch mit requestId im JSON-Body."}},"content":{"application/json":{"schema":{"$ref":"#/components/schemas/PrintJobUpdateError"}}}},"409":{"description":"CONFIGURATION_CONFLICT: parallele Änderung; nichts aus dieser Anfrage gespeichert, canRetry=true","headers":{"X-Request-ID":{"schema":{"type":"string","format":"uuid"},"description":"Serverseitige Referenz; bei Fehlern identisch mit requestId im JSON-Body."}},"content":{"application/json":{"schema":{"$ref":"#/components/schemas/PrintJobUpdateError"}}}},"503":{"description":"PRICE_CALCULATION_FAILED: Berechnung fehlgeschlagen, gespeicherte Konfiguration und Preis unverändert; CONFIGURATION_UPDATE_FAILED: Speichern/Verarbeitung fehlgeschlagen; canRetry=true","headers":{"X-Request-ID":{"schema":{"type":"string","format":"uuid"},"description":"Serverseitige Referenz; bei Fehlern identisch mit requestId im JSON-Body."}},"content":{"application/json":{"schema":{"$ref":"#/components/schemas/PrintJobUpdateError"}}}}}}},"/api/orders":{"post":{"tags":["Widget"],"summary":"Bestellung anlegen","description":"Erzeugt aus einem konfigurierten Print-Job und Kundendaten eine Bestellung.","requestBody":{"required":true,"content":{"application/json":{"schema":{"$ref":"#/components/schemas/CreateOrderRequest"}}}},"responses":{"200":{"description":"Bestellung erstellt","content":{"application/json":{"schema":{"type":"object","additionalProperties":true}}}},"400":{"description":"Validierungsfehler","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}}}}},"/api/quotes":{"post":{"tags":["Widget"],"summary":"Angebot per E-Mail speichern (Lead-Capture)","description":"Speichert die konfigurierte Kalkulation und sendet dem Endkunden einen Wiedereinstiegs-Link per E-Mail. Preis/Snapshot werden serverseitig aus den Print-Jobs des Shops ermittelt (Client-Preis wird ignoriert). Rate-Limit: 5/IP/h.","requestBody":{"required":true,"content":{"application/json":{"schema":{"$ref":"#/components/schemas/SaveQuoteRequest"}}}},"responses":{"201":{"description":"Angebot gespeichert, E-Mail wird versendet","content":{"application/json":{"schema":{"type":"object","properties":{"success":{"type":"boolean"}}}}}},"400":{"description":"Validierungsfehler, fehlende Einwilligung oder keine gültige Konfiguration","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"403":{"description":"Feature für den Shop nicht verfügbar oder deaktiviert (Premium-Gate `save_quote`)","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"404":{"description":"Shop nicht gefunden","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"429":{"description":"Rate-Limit überschritten","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}}}}},"/api/quote-requests":{"post":{"tags":["Widget"],"summary":"Manuelles Angebot anfordern (Lead-Capture)","description":"Legt eine manuelle Angebotsanfrage für den Shop an und benachrichtigt den Betreiber per E-Mail. Konfiguration und kalkulierter Preis werden serverseitig aus den Print-Jobs des Shops ermittelt (Client-Preis wird ignoriert). Premium-Feature: Für Shops ohne `manual_quote`-Gate oder mit deaktiviertem Feature antwortet die Route mit 403. Rate-Limit: 5/IP/h.","requestBody":{"required":true,"content":{"application/json":{"schema":{"$ref":"#/components/schemas/ManualQuoteRequest"}}}},"responses":{"201":{"description":"Anfrage angelegt, Shop wird benachrichtigt","content":{"application/json":{"schema":{"type":"object","properties":{"success":{"type":"boolean"}}}}}},"400":{"description":"Validierungsfehler, fehlende Einwilligung oder keine gültige Konfiguration","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"403":{"description":"Feature für den Shop nicht verfügbar oder deaktiviert","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"404":{"description":"Shop nicht gefunden","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"429":{"description":"Rate-Limit überschritten","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}}}}},"/api/quote-requests/{token}/accept":{"post":{"tags":["Widget"],"summary":"Manuelles Angebot annehmen","description":"Nimmt das vom Shop erstellte individuelle Angebot an. Der Angebotspreis wird proportional auf die Print-Jobs der Konfiguration übertragen, sodass die Bestellung über den normalen Checkout mit dem manuellen Preis läuft. Der Token stammt aus der Angebots-E-Mail. Rate-Limit: 10/IP/h.","parameters":[{"name":"token","in":"path","required":true,"schema":{"type":"string"},"description":"Angebots-Token aus der E-Mail an den Kunden."}],"responses":{"200":{"description":"Angebot angenommen – Checkout-URL für die Bestellung","content":{"application/json":{"schema":{"type":"object","properties":{"checkoutUrl":{"type":"string"}}}}}},"404":{"description":"Angebot nicht gefunden","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"409":{"description":"Kein annehmbares Angebot vorhanden oder Konfiguration nicht mehr verfügbar","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"429":{"description":"Rate-Limit überschritten","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}}}}},"/api/network/providers":{"post":{"tags":["Public"],"summary":"Anbieter für eine Datei ermitteln („Anbieter finden\"-Portal)","description":"Nimmt eine 3D-Modelldatei (STL, OBJ, 3MF, AMF, STEP, IGES) entgegen, analysiert sie serverseitig (nichts wird persistiert) und liefert die gerankte Liste gelisteter Premium-/Enterprise-Shops mit „ab\"-Richtpreis, Ort und Lieferzeit. Der Endpunkt ist nur aktiv, wenn das Portal global scharfgeschaltet ist (sonst 404). Siehe `app/api/network/providers/route.ts`. Rate-Limit: 20/IP/15 min.","requestBody":{"required":true,"content":{"multipart/form-data":{"schema":{"type":"object","properties":{"file":{"type":"string","format":"binary","description":"3D-Modelldatei."}},"required":["file"]}}}},"responses":{"200":{"description":"Gerankte Anbieterliste","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ProviderListing"}}}},"400":{"description":"Keine/ungültige Datei, nicht unterstütztes Format oder nicht analysierbar","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"404":{"description":"Portal nicht scharfgeschaltet","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"429":{"description":"Rate-Limit überschritten","headers":{"Retry-After":{"schema":{"type":"integer"},"description":"Sekunden bis zum nächsten Versuch."}},"content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}}}}},"/api/shopify/widget-config":{"get":{"tags":["Public"],"summary":"Shopify-App: Widget-Konfiguration für den Theme-App-Block","description":"Löst eine verknüpfte Shopify-Domain in die öffentliche SliceQuote-`shopId` auf (Issue #183). Wird vom App-Block im Storefront aufgerufen (CORS offen); liefert nur die shopId, die auch im Embed-Snippet steht. Siehe `app/api/shopify/widget-config/route.ts`.","parameters":[{"name":"shop","in":"query","required":true,"schema":{"type":"string"},"description":"Shopify-Domain, z. B. mein-shop.myshopify.com"}],"responses":{"200":{"description":"Shop ist verknüpft","content":{"application/json":{"schema":{"type":"object","properties":{"linked":{"type":"boolean"},"shopId":{"type":"string"}},"required":["linked","shopId"]}}}},"400":{"description":"Ungültige Shop-Domain"},"404":{"description":"Shop nicht verknüpft oder App deinstalliert"}}}},"/api/shopify/webhooks":{"post":{"tags":["Public"],"summary":"Shopify-App: Webhook-Empfänger (app/uninstalled + GDPR)","description":"Nur für Shopify bestimmt: verifiziert den `X-Shopify-Hmac-Sha256`-Header über den rohen Body und verarbeitet `app/uninstalled` sowie die GDPR-Pflicht-Topics. Siehe `app/api/shopify/webhooks/route.ts`.","responses":{"200":{"description":"Webhook quittiert"},"401":{"description":"HMAC-Prüfung fehlgeschlagen"},"503":{"description":"Shopify-App nicht konfiguriert"}}}},"/api/network/status":{"get":{"tags":["Public"],"summary":"Status des „Anbieter finden\"-Portals","description":"Gibt zurück, ob das Portal global scharfgeschaltet ist. Siehe `app/api/network/status/route.ts`.","responses":{"200":{"description":"Portalstatus","content":{"application/json":{"schema":{"type":"object","properties":{"enabled":{"type":"boolean"}},"required":["enabled"]}}}}}}},"/api/v1/orders":{"get":{"tags":["API v1"],"summary":"Bestellungen des Shops auflisten","description":"Gibt die Bestellungen des zum API-Key gehörenden Shops zurück. Erfordert Scope `orders:read`. Rate-Limit: 120/Key/Minute.","security":[{"apiKeyAuth":[]}],"parameters":[{"name":"limit","in":"query","required":false,"schema":{"type":"integer","minimum":1,"maximum":100,"default":50},"description":"Maximale Anzahl (1–100, Default 50)."},{"name":"status","in":"query","required":false,"schema":{"type":"string","enum":["PENDING_PAYMENT","PAID","PROCESSING","PRINTED","SHIPPED","DELIVERED","CANCELLED","REFUNDED"]},"description":"Optionaler Filter nach Bestellstatus."}],"responses":{"200":{"description":"Liste der Bestellungen","content":{"application/json":{"schema":{"type":"object","properties":{"data":{"type":"array","items":{"$ref":"#/components/schemas/Order"}},"count":{"type":"integer"}}}}}},"400":{"description":"Ungültiger status-Filter","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"401":{"description":"Fehlender/ungültiger API-Key","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"403":{"description":"Fehlender Scope oder Plan ohne API-Zugriff","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"429":{"description":"Rate-Limit überschritten","headers":{"Retry-After":{"schema":{"type":"integer"}}},"content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}}}}},"/api/v1/orders/{id}":{"patch":{"tags":["API v1"],"summary":"Bestellstatus/Tracking aktualisieren","description":"Setzt Bestellstatus und/oder Tracking-Nummer. Erfordert Scope `orders:write`. Nur Fulfillment-Status (PROCESSING, PRINTED, SHIPPED, DELIVERED); CANCELLED/REFUNDED sind ausgeschlossen (finanzielle Nebenwirkungen → Admin-UI).","security":[{"apiKeyAuth":[]}],"parameters":[{"name":"id","in":"path","required":true,"schema":{"type":"string"}}],"requestBody":{"required":true,"content":{"application/json":{"schema":{"type":"object","properties":{"orderStatus":{"type":"string","enum":["PROCESSING","PRINTED","SHIPPED","DELIVERED"]},"trackingNumber":{"type":["string","null"]}}}}}},"responses":{"200":{"description":"Aktualisierte Bestellung","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Order"}}}},"400":{"description":"Validierungsfehler (z. B. unzulässiger Status)","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"401":{"description":"Fehlender/ungültiger API-Key","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}},"application/problem+json":{"schema":{"$ref":"#/components/schemas/ProblemDetails"}}}},"403":{"description":"Fehlender Scope oder Plan ohne API-Zugriff","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}},"application/problem+json":{"schema":{"$ref":"#/components/schemas/ProblemDetails"}}}},"404":{"description":"Bestellung nicht gefunden","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}}}}},"/api/v1/materials":{"get":{"tags":["API v1"],"summary":"Materialien des Shops auflisten","description":"Aktive Materialien inkl. Farben. Erfordert Scope `materials:read`.","security":[{"apiKeyAuth":[]}],"responses":{"200":{"description":"Liste der Materialien","content":{"application/json":{"schema":{"type":"object","properties":{"data":{"type":"array","items":{"$ref":"#/components/schemas/Material"}},"count":{"type":"integer"}}}}}},"401":{"description":"Fehlender/ungültiger API-Key","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}},"application/problem+json":{"schema":{"$ref":"#/components/schemas/ProblemDetails"}}}},"403":{"description":"Fehlender Scope oder Plan ohne API-Zugriff","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}},"application/problem+json":{"schema":{"$ref":"#/components/schemas/ProblemDetails"}}}}}}},"/api/v1/printers":{"get":{"tags":["API v1"],"summary":"Druckerprofile des Shops auflisten","description":"Aktive Druckerprofile. Erfordert Scope `printers:read`.","security":[{"apiKeyAuth":[]}],"responses":{"200":{"description":"Liste der Druckerprofile","content":{"application/json":{"schema":{"type":"object","properties":{"data":{"type":"array","items":{"$ref":"#/components/schemas/Printer"}},"count":{"type":"integer"}}}}}},"401":{"description":"Fehlender/ungültiger API-Key","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}},"application/problem+json":{"schema":{"$ref":"#/components/schemas/ProblemDetails"}}}},"403":{"description":"Fehlender Scope oder Plan ohne API-Zugriff","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}},"application/problem+json":{"schema":{"$ref":"#/components/schemas/ProblemDetails"}}}}}}},"/api/admin/errors":{"get":{"tags":["Admin"],"summary":"Fehler des eigenen Shops aus den letzten 30 Tagen","security":[{"cookieAuth":[]}],"description":"Enthält nur Codes, übersetzbare Parameter und Referenzen, keine Stack-Traces oder Anbieterdetails. Shop-Zuordnung kommt aus der Session. Zusammenfassung und häufige Fehler gelten für den gesamten 30-Tage-Zeitraum.","parameters":[{"name":"page","in":"query","schema":{"type":"integer","minimum":1,"maximum":100000,"default":1},"description":"25 Einträge pro Seite"},{"name":"source","in":"query","schema":{"type":"string","enum":["upload","pricing","payment"]}},{"name":"severity","in":"query","schema":{"type":"string","enum":["WARNING","ERROR","CRITICAL"]}},{"name":"state","in":"query","schema":{"type":"string","enum":["open","reported","resolved"]}},{"name":"requestId","in":"query","schema":{"type":"string","format":"uuid"}},{"name":"summaryOnly","in":"query","schema":{"type":"boolean","default":false}}],"responses":{"200":{"description":"OK","content":{"application/json":{"schema":{"type":"object","additionalProperties":true}}}},"400":{"description":"Ungültiger Filter, Aktion oder fehlender JSON-Content-Type","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}},"application/problem+json":{"schema":{"$ref":"#/components/schemas/ProblemDetails"}}}},"401":{"description":"Admin-Session/Systemberechtigung erforderlich","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}},"application/problem+json":{"schema":{"$ref":"#/components/schemas/ProblemDetails"}}}},"500":{"description":"Fehlerübersicht nicht verfügbar","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}},"application/problem+json":{"schema":{"$ref":"#/components/schemas/ProblemDetails"}}}}}},"post":{"tags":["Admin"],"summary":"Eigenen Fehler an den Plattform-Support melden","security":[{"cookieAuth":[]}],"description":"Die Meldung wird dauerhaft im Super-Admin-Dashboard sichtbar. Wiederholungen erhalten den ersten Meldezeitpunkt. Nur Fehler des eigenen Shops sind zulässig.","requestBody":{"required":true,"content":{"application/json":{"schema":{"type":"object","required":["id","action"],"properties":{"id":{"type":"string","minLength":1,"maxLength":100},"action":{"type":"string","enum":["report"]}}}}}},"responses":{"200":{"description":"OK","content":{"application/json":{"schema":{"type":"object","additionalProperties":true}}}},"400":{"description":"Ungültiger Filter, Aktion oder fehlender JSON-Content-Type","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}},"application/problem+json":{"schema":{"$ref":"#/components/schemas/ProblemDetails"}}}},"401":{"description":"Admin-Session/Systemberechtigung erforderlich","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}},"application/problem+json":{"schema":{"$ref":"#/components/schemas/ProblemDetails"}}}},"403":{"description":"Privilegierte Aktion über Shop-API abgelehnt","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}},"application/problem+json":{"schema":{"$ref":"#/components/schemas/ProblemDetails"}}}},"404":{"description":"Fehler nicht gefunden oder gehört nicht zum eigenen Shop","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}},"application/problem+json":{"schema":{"$ref":"#/components/schemas/ProblemDetails"}}}},"500":{"description":"Fehlerübersicht nicht verfügbar","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}},"application/problem+json":{"schema":{"$ref":"#/components/schemas/ProblemDetails"}}}}}}},"/api/admin/api-key":{"get":{"tags":["Admin"],"summary":"API-Key-Status","security":[{"cookieAuth":[]}],"responses":{"200":{"description":"OK","content":{"application/json":{"schema":{"type":"object","additionalProperties":true}}}},"401":{"description":"Nicht authentifiziert","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}},"application/problem+json":{"schema":{"$ref":"#/components/schemas/ProblemDetails"}}}}}},"post":{"tags":["Admin"],"summary":"Shop-API-Key erzeugen (Legacy-Einzelkey)","security":[{"cookieAuth":[]}],"requestBody":{"content":{"application/json":{"schema":{"type":"object","additionalProperties":true}}}},"responses":{"200":{"description":"OK","content":{"application/json":{"schema":{"type":"object","additionalProperties":true}}}},"400":{"description":"Validierungsfehler","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}},"application/problem+json":{"schema":{"$ref":"#/components/schemas/ProblemDetails"}}}},"401":{"description":"Nicht authentifiziert","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}},"application/problem+json":{"schema":{"$ref":"#/components/schemas/ProblemDetails"}}}}}},"delete":{"tags":["Admin"],"summary":"Shop-API-Key widerrufen","security":[{"cookieAuth":[]}],"requestBody":{"content":{"application/json":{"schema":{"type":"object","additionalProperties":true}}}},"responses":{"200":{"description":"OK","content":{"application/json":{"schema":{"type":"object","additionalProperties":true}}}},"400":{"description":"Validierungsfehler","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}},"application/problem+json":{"schema":{"$ref":"#/components/schemas/ProblemDetails"}}}},"401":{"description":"Nicht authentifiziert","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}},"application/problem+json":{"schema":{"$ref":"#/components/schemas/ProblemDetails"}}}}}}},"/api/admin/api-keys":{"get":{"tags":["Admin"],"summary":"API-Keys auflisten","security":[{"cookieAuth":[]}],"responses":{"200":{"description":"OK","content":{"application/json":{"schema":{"type":"object","additionalProperties":true}}}},"401":{"description":"Nicht authentifiziert","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}},"application/problem+json":{"schema":{"$ref":"#/components/schemas/ProblemDetails"}}}}}},"post":{"tags":["Admin"],"summary":"API-Key erstellen","security":[{"cookieAuth":[]}],"requestBody":{"content":{"application/json":{"schema":{"type":"object","additionalProperties":true}}}},"responses":{"200":{"description":"OK","content":{"application/json":{"schema":{"type":"object","additionalProperties":true}}}},"400":{"description":"Validierungsfehler","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}},"application/problem+json":{"schema":{"$ref":"#/components/schemas/ProblemDetails"}}}},"401":{"description":"Nicht authentifiziert","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}},"application/problem+json":{"schema":{"$ref":"#/components/schemas/ProblemDetails"}}}}}}},"/api/admin/api-keys/{id}":{"delete":{"tags":["Admin"],"summary":"API-Key widerrufen","security":[{"cookieAuth":[]}],"parameters":[{"name":"id","in":"path","required":true,"schema":{"type":"string"}}],"requestBody":{"content":{"application/json":{"schema":{"type":"object","additionalProperties":true}}}},"responses":{"200":{"description":"OK","content":{"application/json":{"schema":{"type":"object","additionalProperties":true}}}},"400":{"description":"Validierungsfehler","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}},"application/problem+json":{"schema":{"$ref":"#/components/schemas/ProblemDetails"}}}},"401":{"description":"Nicht authentifiziert","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}},"application/problem+json":{"schema":{"$ref":"#/components/schemas/ProblemDetails"}}}},"404":{"description":"Nicht gefunden","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}},"application/problem+json":{"schema":{"$ref":"#/components/schemas/ProblemDetails"}}}}}}},"/api/admin/email-config":{"get":{"tags":["Admin"],"summary":"SMTP-Konfiguration lesen","security":[{"cookieAuth":[]}],"responses":{"200":{"description":"OK","content":{"application/json":{"schema":{"type":"object","additionalProperties":true}}}},"401":{"description":"Nicht authentifiziert","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}},"application/problem+json":{"schema":{"$ref":"#/components/schemas/ProblemDetails"}}}}}},"post":{"tags":["Admin"],"summary":"SMTP-Konfiguration speichern","security":[{"cookieAuth":[]}],"requestBody":{"content":{"application/json":{"schema":{"type":"object","additionalProperties":true}}}},"responses":{"200":{"description":"OK","content":{"application/json":{"schema":{"type":"object","additionalProperties":true}}}},"400":{"description":"Validierungsfehler","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}},"application/problem+json":{"schema":{"$ref":"#/components/schemas/ProblemDetails"}}}},"401":{"description":"Nicht authentifiziert","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}},"application/problem+json":{"schema":{"$ref":"#/components/schemas/ProblemDetails"}}}}}},"delete":{"tags":["Admin"],"summary":"SMTP-Konfiguration löschen","security":[{"cookieAuth":[]}],"requestBody":{"content":{"application/json":{"schema":{"type":"object","additionalProperties":true}}}},"responses":{"200":{"description":"OK","content":{"application/json":{"schema":{"type":"object","additionalProperties":true}}}},"400":{"description":"Validierungsfehler","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}},"application/problem+json":{"schema":{"$ref":"#/components/schemas/ProblemDetails"}}}},"401":{"description":"Nicht authentifiziert","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}},"application/problem+json":{"schema":{"$ref":"#/components/schemas/ProblemDetails"}}}}}}},"/api/admin/email-config/test":{"post":{"tags":["Admin"],"summary":"SMTP-Testmail senden","security":[{"cookieAuth":[]}],"requestBody":{"content":{"application/json":{"schema":{"type":"object","additionalProperties":true}}}},"responses":{"200":{"description":"OK","content":{"application/json":{"schema":{"type":"object","additionalProperties":true}}}},"400":{"description":"Validierungsfehler","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}},"application/problem+json":{"schema":{"$ref":"#/components/schemas/ProblemDetails"}}}},"401":{"description":"Nicht authentifiziert","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}},"application/problem+json":{"schema":{"$ref":"#/components/schemas/ProblemDetails"}}}}}}},"/api/admin/email-logs":{"get":{"tags":["Admin"],"summary":"E-Mail-Versand-Logs","security":[{"cookieAuth":[]}],"responses":{"200":{"description":"OK","content":{"application/json":{"schema":{"type":"object","additionalProperties":true}}}},"401":{"description":"Nicht authentifiziert","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}},"application/problem+json":{"schema":{"$ref":"#/components/schemas/ProblemDetails"}}}}}}},"/api/admin/smtp-config":{"get":{"tags":["Admin"],"summary":"Eigene SMTP-Konfiguration lesen (Passwort maskiert)","security":[{"cookieAuth":[]}],"responses":{"200":{"description":"OK","content":{"application/json":{"schema":{"type":"object","additionalProperties":true}}}},"401":{"description":"Nicht authentifiziert","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}},"application/problem+json":{"schema":{"$ref":"#/components/schemas/ProblemDetails"}}}}}},"put":{"tags":["Admin"],"summary":"Eigene SMTP-Konfiguration speichern","security":[{"cookieAuth":[]}],"requestBody":{"content":{"application/json":{"schema":{"type":"object","additionalProperties":true}}}},"responses":{"200":{"description":"OK","content":{"application/json":{"schema":{"type":"object","additionalProperties":true}}}},"400":{"description":"Validierungsfehler","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}},"application/problem+json":{"schema":{"$ref":"#/components/schemas/ProblemDetails"}}}},"401":{"description":"Nicht authentifiziert","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}},"application/problem+json":{"schema":{"$ref":"#/components/schemas/ProblemDetails"}}}}}},"delete":{"tags":["Admin"],"summary":"Eigene SMTP-Konfiguration entfernen","security":[{"cookieAuth":[]}],"requestBody":{"content":{"application/json":{"schema":{"type":"object","additionalProperties":true}}}},"responses":{"200":{"description":"OK","content":{"application/json":{"schema":{"type":"object","additionalProperties":true}}}},"400":{"description":"Validierungsfehler","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}},"application/problem+json":{"schema":{"$ref":"#/components/schemas/ProblemDetails"}}}},"401":{"description":"Nicht authentifiziert","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}},"application/problem+json":{"schema":{"$ref":"#/components/schemas/ProblemDetails"}}}}}}},"/api/admin/smtp-config/test":{"post":{"tags":["Admin"],"summary":"SMTP-Verbindung testen","security":[{"cookieAuth":[]}],"requestBody":{"content":{"application/json":{"schema":{"type":"object","additionalProperties":true}}}},"responses":{"200":{"description":"OK","content":{"application/json":{"schema":{"type":"object","additionalProperties":true}}}},"400":{"description":"Validierungsfehler","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}},"application/problem+json":{"schema":{"$ref":"#/components/schemas/ProblemDetails"}}}},"401":{"description":"Nicht authentifiziert","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}},"application/problem+json":{"schema":{"$ref":"#/components/schemas/ProblemDetails"}}}}}}},"/api/admin/email-templates":{"get":{"tags":["Admin"],"summary":"E-Mail-Vorlagen auflisten","security":[{"cookieAuth":[]}],"responses":{"200":{"description":"OK","content":{"application/json":{"schema":{"type":"object","additionalProperties":true}}}},"401":{"description":"Nicht authentifiziert","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}},"application/problem+json":{"schema":{"$ref":"#/components/schemas/ProblemDetails"}}}}}}},"/api/admin/email-templates/{templateKey}":{"get":{"tags":["Admin"],"summary":"E-Mail-Vorlage lesen","security":[{"cookieAuth":[]}],"parameters":[{"name":"templateKey","in":"path","required":true,"schema":{"type":"string"}}],"responses":{"200":{"description":"OK","content":{"application/json":{"schema":{"type":"object","additionalProperties":true}}}},"401":{"description":"Nicht authentifiziert","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}},"application/problem+json":{"schema":{"$ref":"#/components/schemas/ProblemDetails"}}}},"404":{"description":"Nicht gefunden","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}},"application/problem+json":{"schema":{"$ref":"#/components/schemas/ProblemDetails"}}}}}},"put":{"tags":["Admin"],"summary":"E-Mail-Vorlage speichern","security":[{"cookieAuth":[]}],"parameters":[{"name":"templateKey","in":"path","required":true,"schema":{"type":"string"}}],"requestBody":{"content":{"application/json":{"schema":{"type":"object","additionalProperties":true}}}},"responses":{"200":{"description":"OK","content":{"application/json":{"schema":{"type":"object","additionalProperties":true}}}},"400":{"description":"Validierungsfehler","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}},"application/problem+json":{"schema":{"$ref":"#/components/schemas/ProblemDetails"}}}},"401":{"description":"Nicht authentifiziert","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}},"application/problem+json":{"schema":{"$ref":"#/components/schemas/ProblemDetails"}}}},"404":{"description":"Nicht gefunden","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}},"application/problem+json":{"schema":{"$ref":"#/components/schemas/ProblemDetails"}}}}}}},"/api/admin/email-templates-custom":{"get":{"tags":["Admin"],"summary":"White-Label-Templates: überschreibbare Vorlagen + eigene Overrides","security":[{"cookieAuth":[]}],"responses":{"200":{"description":"OK","content":{"application/json":{"schema":{"type":"object","additionalProperties":true}}}},"401":{"description":"Nicht authentifiziert","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}},"application/problem+json":{"schema":{"$ref":"#/components/schemas/ProblemDetails"}}}}}}},"/api/admin/email-templates-custom/{templateKey}":{"put":{"tags":["Admin"],"summary":"Shop-Template-Override speichern","security":[{"cookieAuth":[]}],"parameters":[{"name":"templateKey","in":"path","required":true,"schema":{"type":"string"}}],"requestBody":{"content":{"application/json":{"schema":{"type":"object","additionalProperties":true}}}},"responses":{"200":{"description":"OK","content":{"application/json":{"schema":{"type":"object","additionalProperties":true}}}},"400":{"description":"Validierungsfehler","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}},"application/problem+json":{"schema":{"$ref":"#/components/schemas/ProblemDetails"}}}},"401":{"description":"Nicht authentifiziert","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}},"application/problem+json":{"schema":{"$ref":"#/components/schemas/ProblemDetails"}}}},"404":{"description":"Nicht gefunden","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}},"application/problem+json":{"schema":{"$ref":"#/components/schemas/ProblemDetails"}}}}}},"delete":{"tags":["Admin"],"summary":"Shop-Template-Override zurücksetzen","security":[{"cookieAuth":[]}],"parameters":[{"name":"templateKey","in":"path","required":true,"schema":{"type":"string"}}],"requestBody":{"content":{"application/json":{"schema":{"type":"object","additionalProperties":true}}}},"responses":{"200":{"description":"OK","content":{"application/json":{"schema":{"type":"object","additionalProperties":true}}}},"400":{"description":"Validierungsfehler","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}},"application/problem+json":{"schema":{"$ref":"#/components/schemas/ProblemDetails"}}}},"401":{"description":"Nicht authentifiziert","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}},"application/problem+json":{"schema":{"$ref":"#/components/schemas/ProblemDetails"}}}},"404":{"description":"Nicht gefunden","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}},"application/problem+json":{"schema":{"$ref":"#/components/schemas/ProblemDetails"}}}}}}},"/api/admin/employees":{"get":{"tags":["Admin"],"summary":"Mitarbeiter auflisten","security":[{"cookieAuth":[]}],"responses":{"200":{"description":"OK","content":{"application/json":{"schema":{"type":"object","additionalProperties":true}}}},"401":{"description":"Nicht authentifiziert","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}},"application/problem+json":{"schema":{"$ref":"#/components/schemas/ProblemDetails"}}}}}},"post":{"tags":["Admin"],"summary":"Mitarbeiter anlegen","security":[{"cookieAuth":[]}],"requestBody":{"content":{"application/json":{"schema":{"type":"object","additionalProperties":true}}}},"responses":{"200":{"description":"OK","content":{"application/json":{"schema":{"type":"object","additionalProperties":true}}}},"400":{"description":"Validierungsfehler","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}},"application/problem+json":{"schema":{"$ref":"#/components/schemas/ProblemDetails"}}}},"401":{"description":"Nicht authentifiziert","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}},"application/problem+json":{"schema":{"$ref":"#/components/schemas/ProblemDetails"}}}}}}},"/api/admin/invoices/export":{"get":{"tags":["Admin"],"summary":"Kundenrechnungen eines Zeitraums als ZIP exportieren (PDF je Bestellung + CSV inkl. Umsatzbeteiligung)","security":[{"cookieAuth":[]}],"responses":{"200":{"description":"OK","content":{"application/json":{"schema":{"type":"object","additionalProperties":true}}}},"401":{"description":"Nicht authentifiziert","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}},"application/problem+json":{"schema":{"$ref":"#/components/schemas/ProblemDetails"}}}}}}},"/api/admin/employees/{id}":{"get":{"tags":["Admin"],"summary":"Mitarbeiter lesen","security":[{"cookieAuth":[]}],"parameters":[{"name":"id","in":"path","required":true,"schema":{"type":"string"}}],"responses":{"200":{"description":"OK","content":{"application/json":{"schema":{"type":"object","additionalProperties":true}}}},"401":{"description":"Nicht authentifiziert","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}},"application/problem+json":{"schema":{"$ref":"#/components/schemas/ProblemDetails"}}}},"404":{"description":"Nicht gefunden","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}},"application/problem+json":{"schema":{"$ref":"#/components/schemas/ProblemDetails"}}}}}},"patch":{"tags":["Admin"],"summary":"Mitarbeiter ändern","security":[{"cookieAuth":[]}],"parameters":[{"name":"id","in":"path","required":true,"schema":{"type":"string"}}],"requestBody":{"content":{"application/json":{"schema":{"type":"object","additionalProperties":true}}}},"responses":{"200":{"description":"OK","content":{"application/json":{"schema":{"type":"object","additionalProperties":true}}}},"400":{"description":"Validierungsfehler","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}},"application/problem+json":{"schema":{"$ref":"#/components/schemas/ProblemDetails"}}}},"401":{"description":"Nicht authentifiziert","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}},"application/problem+json":{"schema":{"$ref":"#/components/schemas/ProblemDetails"}}}},"404":{"description":"Nicht gefunden","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}},"application/problem+json":{"schema":{"$ref":"#/components/schemas/ProblemDetails"}}}}}},"delete":{"tags":["Admin"],"summary":"Mitarbeiter entfernen","security":[{"cookieAuth":[]}],"parameters":[{"name":"id","in":"path","required":true,"schema":{"type":"string"}}],"requestBody":{"content":{"application/json":{"schema":{"type":"object","additionalProperties":true}}}},"responses":{"200":{"description":"OK","content":{"application/json":{"schema":{"type":"object","additionalProperties":true}}}},"400":{"description":"Validierungsfehler","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}},"application/problem+json":{"schema":{"$ref":"#/components/schemas/ProblemDetails"}}}},"401":{"description":"Nicht authentifiziert","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}},"application/problem+json":{"schema":{"$ref":"#/components/schemas/ProblemDetails"}}}},"404":{"description":"Nicht gefunden","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}},"application/problem+json":{"schema":{"$ref":"#/components/schemas/ProblemDetails"}}}}}}},"/api/admin/employees/{id}/invite":{"post":{"tags":["Admin"],"summary":"Einladung (erneut) senden – Mail mit Signup-Link (Issue #249)","security":[{"cookieAuth":[]}],"parameters":[{"name":"id","in":"path","required":true,"schema":{"type":"string"}}],"requestBody":{"content":{"application/json":{"schema":{"type":"object","additionalProperties":true}}}},"responses":{"200":{"description":"OK","content":{"application/json":{"schema":{"type":"object","additionalProperties":true}}}},"400":{"description":"Validierungsfehler","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}},"application/problem+json":{"schema":{"$ref":"#/components/schemas/ProblemDetails"}}}},"401":{"description":"Nicht authentifiziert","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}},"application/problem+json":{"schema":{"$ref":"#/components/schemas/ProblemDetails"}}}},"404":{"description":"Nicht gefunden","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}},"application/problem+json":{"schema":{"$ref":"#/components/schemas/ProblemDetails"}}}}}}},"/api/admin/employees/{id}/permissions":{"patch":{"tags":["Admin"],"summary":"Berechtigungen ändern","security":[{"cookieAuth":[]}],"parameters":[{"name":"id","in":"path","required":true,"schema":{"type":"string"}}],"requestBody":{"content":{"application/json":{"schema":{"type":"object","additionalProperties":true}}}},"responses":{"200":{"description":"OK","content":{"application/json":{"schema":{"type":"object","additionalProperties":true}}}},"400":{"description":"Validierungsfehler","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}},"application/problem+json":{"schema":{"$ref":"#/components/schemas/ProblemDetails"}}}},"401":{"description":"Nicht authentifiziert","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}},"application/problem+json":{"schema":{"$ref":"#/components/schemas/ProblemDetails"}}}},"404":{"description":"Nicht gefunden","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}},"application/problem+json":{"schema":{"$ref":"#/components/schemas/ProblemDetails"}}}}}}},"/api/admin/employees/{id}/status":{"patch":{"tags":["Admin"],"summary":"Aktiv-Status ändern","security":[{"cookieAuth":[]}],"parameters":[{"name":"id","in":"path","required":true,"schema":{"type":"string"}}],"requestBody":{"content":{"application/json":{"schema":{"type":"object","additionalProperties":true}}}},"responses":{"200":{"description":"OK","content":{"application/json":{"schema":{"type":"object","additionalProperties":true}}}},"400":{"description":"Validierungsfehler","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}},"application/problem+json":{"schema":{"$ref":"#/components/schemas/ProblemDetails"}}}},"401":{"description":"Nicht authentifiziert","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}},"application/problem+json":{"schema":{"$ref":"#/components/schemas/ProblemDetails"}}}},"404":{"description":"Nicht gefunden","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}},"application/problem+json":{"schema":{"$ref":"#/components/schemas/ProblemDetails"}}}}}}},"/api/admin/print-jobs":{"get":{"tags":["Admin"],"summary":"Print-Jobs auflisten","security":[{"cookieAuth":[]}],"responses":{"200":{"description":"OK","content":{"application/json":{"schema":{"type":"object","additionalProperties":true}}}},"401":{"description":"Nicht authentifiziert","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}},"application/problem+json":{"schema":{"$ref":"#/components/schemas/ProblemDetails"}}}}}}},"/api/admin/print-jobs/cleanup":{"post":{"tags":["Admin"],"summary":"Verwaiste Print-Jobs aufräumen","security":[{"cookieAuth":[]}],"requestBody":{"content":{"application/json":{"schema":{"type":"object","additionalProperties":true}}}},"responses":{"200":{"description":"OK","content":{"application/json":{"schema":{"type":"object","additionalProperties":true}}}},"400":{"description":"Validierungsfehler","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}},"application/problem+json":{"schema":{"$ref":"#/components/schemas/ProblemDetails"}}}},"401":{"description":"Nicht authentifiziert","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}},"application/problem+json":{"schema":{"$ref":"#/components/schemas/ProblemDetails"}}}}}}},"/api/admin/quote-requests":{"get":{"tags":["Admin"],"summary":"Angebotsanfragen auflisten","security":[{"cookieAuth":[]}],"responses":{"200":{"description":"OK","content":{"application/json":{"schema":{"type":"object","additionalProperties":true}}}},"401":{"description":"Nicht authentifiziert","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}},"application/problem+json":{"schema":{"$ref":"#/components/schemas/ProblemDetails"}}}}}}},"/api/admin/quote-requests/{id}":{"patch":{"tags":["Admin"],"summary":"Angebotsanfrage-Status ändern","security":[{"cookieAuth":[]}],"parameters":[{"name":"id","in":"path","required":true,"schema":{"type":"string"}}],"requestBody":{"content":{"application/json":{"schema":{"type":"object","additionalProperties":true}}}},"responses":{"200":{"description":"OK","content":{"application/json":{"schema":{"type":"object","additionalProperties":true}}}},"400":{"description":"Validierungsfehler","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}},"application/problem+json":{"schema":{"$ref":"#/components/schemas/ProblemDetails"}}}},"401":{"description":"Nicht authentifiziert","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}},"application/problem+json":{"schema":{"$ref":"#/components/schemas/ProblemDetails"}}}},"404":{"description":"Nicht gefunden","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}},"application/problem+json":{"schema":{"$ref":"#/components/schemas/ProblemDetails"}}}}}}},"/api/admin/quote-requests/{id}/quote":{"post":{"tags":["Admin"],"summary":"Manuelles Angebot senden","security":[{"cookieAuth":[]}],"parameters":[{"name":"id","in":"path","required":true,"schema":{"type":"string"}}],"requestBody":{"content":{"application/json":{"schema":{"type":"object","additionalProperties":true}}}},"responses":{"200":{"description":"OK","content":{"application/json":{"schema":{"type":"object","additionalProperties":true}}}},"400":{"description":"Validierungsfehler","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}},"application/problem+json":{"schema":{"$ref":"#/components/schemas/ProblemDetails"}}}},"401":{"description":"Nicht authentifiziert","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}},"application/problem+json":{"schema":{"$ref":"#/components/schemas/ProblemDetails"}}}},"404":{"description":"Nicht gefunden","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}},"application/problem+json":{"schema":{"$ref":"#/components/schemas/ProblemDetails"}}}}}}},"/api/admin/quotes":{"get":{"tags":["Admin"],"summary":"Gespeicherte Angebote auflisten","security":[{"cookieAuth":[]}],"responses":{"200":{"description":"OK","content":{"application/json":{"schema":{"type":"object","additionalProperties":true}}}},"401":{"description":"Nicht authentifiziert","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}},"application/problem+json":{"schema":{"$ref":"#/components/schemas/ProblemDetails"}}}}}}},"/api/admin/setup-checklist":{"get":{"tags":["Admin"],"summary":"Onboarding-Checkliste","security":[{"cookieAuth":[]}],"responses":{"200":{"description":"OK","content":{"application/json":{"schema":{"type":"object","additionalProperties":true}}}},"401":{"description":"Nicht authentifiziert","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}},"application/problem+json":{"schema":{"$ref":"#/components/schemas/ProblemDetails"}}}}}}},"/api/admin/snippet":{"get":{"tags":["Admin"],"summary":"Widget-Embed-Snippet","security":[{"cookieAuth":[]}],"responses":{"200":{"description":"OK","content":{"application/json":{"schema":{"type":"object","additionalProperties":true}}}},"401":{"description":"Nicht authentifiziert","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}},"application/problem+json":{"schema":{"$ref":"#/components/schemas/ProblemDetails"}}}}}}},"/api/admin/snippet-config":{"get":{"tags":["Admin"],"summary":"Widget-Konfiguration lesen","security":[{"cookieAuth":[]}],"responses":{"200":{"description":"OK","content":{"application/json":{"schema":{"type":"object","additionalProperties":true}}}},"401":{"description":"Nicht authentifiziert","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}},"application/problem+json":{"schema":{"$ref":"#/components/schemas/ProblemDetails"}}}}}},"put":{"tags":["Admin"],"summary":"Widget-Konfiguration speichern","security":[{"cookieAuth":[]}],"requestBody":{"content":{"application/json":{"schema":{"type":"object","additionalProperties":true}}}},"responses":{"200":{"description":"OK","content":{"application/json":{"schema":{"type":"object","additionalProperties":true}}}},"400":{"description":"Validierungsfehler","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}},"application/problem+json":{"schema":{"$ref":"#/components/schemas/ProblemDetails"}}}},"401":{"description":"Nicht authentifiziert","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}},"application/problem+json":{"schema":{"$ref":"#/components/schemas/ProblemDetails"}}}}}}},"/api/admin/stats":{"get":{"tags":["Admin"],"summary":"Shop-Statistiken","security":[{"cookieAuth":[]}],"responses":{"200":{"description":"OK","content":{"application/json":{"schema":{"type":"object","additionalProperties":true}}}},"401":{"description":"Nicht authentifiziert","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}},"application/problem+json":{"schema":{"$ref":"#/components/schemas/ProblemDetails"}}}}}}},"/api/admin/webhooks":{"get":{"tags":["Admin"],"summary":"Webhooks auflisten (inkl. verfügbarer Ereignis-Typen)","security":[{"cookieAuth":[]}],"responses":{"200":{"description":"OK","content":{"application/json":{"schema":{"type":"object","additionalProperties":true}}}},"401":{"description":"Nicht authentifiziert","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}},"application/problem+json":{"schema":{"$ref":"#/components/schemas/ProblemDetails"}}}}}},"post":{"tags":["Admin"],"summary":"Webhook erstellen – Secret wird nur einmalig im Klartext zurückgegeben; Zustellungen sind per HMAC-SHA256 im Header X-SliceQuote-Signature signiert","security":[{"cookieAuth":[]}],"requestBody":{"content":{"application/json":{"schema":{"type":"object","additionalProperties":true}}}},"responses":{"200":{"description":"OK","content":{"application/json":{"schema":{"type":"object","additionalProperties":true}}}},"400":{"description":"Validierungsfehler","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}},"application/problem+json":{"schema":{"$ref":"#/components/schemas/ProblemDetails"}}}},"401":{"description":"Nicht authentifiziert","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}},"application/problem+json":{"schema":{"$ref":"#/components/schemas/ProblemDetails"}}}}}}},"/api/admin/webhooks/{id}":{"put":{"tags":["Admin"],"summary":"Webhook ändern (URL/Ereignisse/aktiv)","security":[{"cookieAuth":[]}],"parameters":[{"name":"id","in":"path","required":true,"schema":{"type":"string"}}],"requestBody":{"content":{"application/json":{"schema":{"type":"object","additionalProperties":true}}}},"responses":{"200":{"description":"OK","content":{"application/json":{"schema":{"type":"object","additionalProperties":true}}}},"400":{"description":"Validierungsfehler","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}},"application/problem+json":{"schema":{"$ref":"#/components/schemas/ProblemDetails"}}}},"401":{"description":"Nicht authentifiziert","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}},"application/problem+json":{"schema":{"$ref":"#/components/schemas/ProblemDetails"}}}},"404":{"description":"Nicht gefunden","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}},"application/problem+json":{"schema":{"$ref":"#/components/schemas/ProblemDetails"}}}}}},"delete":{"tags":["Admin"],"summary":"Webhook löschen","security":[{"cookieAuth":[]}],"parameters":[{"name":"id","in":"path","required":true,"schema":{"type":"string"}}],"requestBody":{"content":{"application/json":{"schema":{"type":"object","additionalProperties":true}}}},"responses":{"200":{"description":"OK","content":{"application/json":{"schema":{"type":"object","additionalProperties":true}}}},"400":{"description":"Validierungsfehler","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}},"application/problem+json":{"schema":{"$ref":"#/components/schemas/ProblemDetails"}}}},"401":{"description":"Nicht authentifiziert","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}},"application/problem+json":{"schema":{"$ref":"#/components/schemas/ProblemDetails"}}}},"404":{"description":"Nicht gefunden","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}},"application/problem+json":{"schema":{"$ref":"#/components/schemas/ProblemDetails"}}}}}}},"/api/admin/webhooks/{id}/test":{"post":{"tags":["Admin"],"summary":"Signierten Test-Ping senden","security":[{"cookieAuth":[]}],"parameters":[{"name":"id","in":"path","required":true,"schema":{"type":"string"}}],"requestBody":{"content":{"application/json":{"schema":{"type":"object","additionalProperties":true}}}},"responses":{"200":{"description":"OK","content":{"application/json":{"schema":{"type":"object","additionalProperties":true}}}},"400":{"description":"Validierungsfehler","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}},"application/problem+json":{"schema":{"$ref":"#/components/schemas/ProblemDetails"}}}},"401":{"description":"Nicht authentifiziert","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}},"application/problem+json":{"schema":{"$ref":"#/components/schemas/ProblemDetails"}}}},"404":{"description":"Nicht gefunden","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}},"application/problem+json":{"schema":{"$ref":"#/components/schemas/ProblemDetails"}}}}}}},"/api/admin/webhooks/{id}/deliveries":{"get":{"tags":["Admin"],"summary":"Zustell-Log (letzte 25 Versuche)","security":[{"cookieAuth":[]}],"parameters":[{"name":"id","in":"path","required":true,"schema":{"type":"string"}}],"responses":{"200":{"description":"OK","content":{"application/json":{"schema":{"type":"object","additionalProperties":true}}}},"401":{"description":"Nicht authentifiziert","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}},"application/problem+json":{"schema":{"$ref":"#/components/schemas/ProblemDetails"}}}},"404":{"description":"Nicht gefunden","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}},"application/problem+json":{"schema":{"$ref":"#/components/schemas/ProblemDetails"}}}}}}}}}