- Add API documentation (API_ANLEITUNG.md) - Add architecture docs (UNIVERSAL_FEATURES.md, Analytics.md) - Add guides (FRONTEND.md, SEO_ERWEITERUNG.md, styleguide.md) - Add Planungs-KI prompt template (ANLEITUNG-PLANUNGS-KI-FRONTEND.md) - Add BlogWoman frontend development prompt with: - Tenant-ID 9 configuration - Design system based on styleguide - BlogWoman-specific blocks (Favorites, Series, VideoEmbed) - API patterns with tenant isolation - SEO and Analytics integration Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
33 KiB
API-Anleitung - Payload CMS
Übersicht
Das Payload CMS stellt eine REST-API und eine GraphQL-API bereit. Diese Anleitung beschreibt die Nutzung der REST-API für alle Collections.
Base URL: https://pl.porwoll.tech/api
Authentifizierung
Login
curl -X POST "https://pl.porwoll.tech/api/users/login" \
-H "Content-Type: application/json" \
-d '{
"email": "admin@example.com",
"password": "your-password"
}'
Response:
{
"message": "Auth Passed",
"user": {
"id": 1,
"email": "admin@example.com",
"isSuperAdmin": true,
"tenants": [...]
},
"token": "eyJhbGciOiJIUzI1NiIs..."
}
Token verwenden
curl "https://pl.porwoll.tech/api/posts" \
-H "Authorization: JWT eyJhbGciOiJIUzI1NiIs..."
Mehrsprachigkeit (Localization)
Das CMS unterstützt Deutsch (de) und Englisch (en). Lokalisierte Felder können über den locale Parameter abgerufen werden.
# Deutsche Inhalte (Standard)
curl "https://pl.porwoll.tech/api/posts?locale=de"
# Englische Inhalte
curl "https://pl.porwoll.tech/api/posts?locale=en"
# Alle Sprachen gleichzeitig
curl "https://pl.porwoll.tech/api/posts?locale=all"
Users API
Aktuellen User abrufen
curl "https://pl.porwoll.tech/api/users/me" \
-H "Authorization: JWT your-token"
User-Felder
| Feld | Typ | Beschreibung |
|---|---|---|
email |
string | E-Mail-Adresse (eindeutig) |
isSuperAdmin |
boolean | Super Admin hat Zugriff auf alle Tenants |
tenants |
array | Zugewiesene Tenants |
Tenants API
Alle Tenants abrufen (Auth + SuperAdmin erforderlich)
curl "https://pl.porwoll.tech/api/tenants" \
-H "Authorization: JWT your-token"
Tenant erstellen (Auth + SuperAdmin erforderlich)
curl -X POST "https://pl.porwoll.tech/api/tenants" \
-H "Authorization: JWT your-token" \
-H "Content-Type: application/json" \
-d '{
"name": "Meine Firma GmbH",
"slug": "meine-firma",
"domains": [
{ "domain": "meine-firma.de" },
{ "domain": "www.meine-firma.de" }
]
}'
Tenant-Felder
| Feld | Typ | Beschreibung |
|---|---|---|
name |
string | Anzeigename des Tenants |
slug |
string | URL-freundlicher Identifier (eindeutig) |
domains |
array | Zugeordnete Domains |
Posts API
Alle Posts abrufen
# Alle Posts
curl "https://pl.porwoll.tech/api/posts"
# Nur Blog-Artikel
curl "https://pl.porwoll.tech/api/posts?where[type][equals]=blog"
# Nur News
curl "https://pl.porwoll.tech/api/posts?where[type][equals]=news"
# Nur veröffentlichte Posts
curl "https://pl.porwoll.tech/api/posts?where[status][equals]=published"
# Nur hervorgehobene Posts
curl "https://pl.porwoll.tech/api/posts?where[isFeatured][equals]=true"
# Mit Sortierung (neueste zuerst)
curl "https://pl.porwoll.tech/api/posts?sort=-publishedAt"
# Limitiert auf 10 Einträge
curl "https://pl.porwoll.tech/api/posts?limit=10"
# Pagination (Seite 2)
curl "https://pl.porwoll.tech/api/posts?limit=10&page=2"
# Mit Locale
curl "https://pl.porwoll.tech/api/posts?locale=de"
Einzelnen Post abrufen
# Nach ID
curl "https://pl.porwoll.tech/api/posts/1"
# Nach Slug (über Query)
curl "https://pl.porwoll.tech/api/posts?where[slug][equals]=mein-erster-artikel"
Post erstellen (Auth erforderlich)
curl -X POST "https://pl.porwoll.tech/api/posts" \
-H "Authorization: JWT your-token" \
-H "Content-Type: application/json" \
-d '{
"tenant": 1,
"title": "Mein neuer Artikel",
"slug": "mein-neuer-artikel",
"type": "blog",
"isFeatured": false,
"excerpt": "Eine kurze Zusammenfassung des Artikels...",
"content": {
"root": {
"type": "root",
"children": [
{
"type": "paragraph",
"children": [{ "text": "Der Artikelinhalt..." }]
}
]
}
},
"status": "draft"
}'
Post aktualisieren (Auth erforderlich)
curl -X PATCH "https://pl.porwoll.tech/api/posts/1" \
-H "Authorization: JWT your-token" \
-H "Content-Type: application/json" \
-d '{
"status": "published",
"publishedAt": "2025-11-30T12:00:00.000Z"
}'
Post löschen (Auth erforderlich)
curl -X DELETE "https://pl.porwoll.tech/api/posts/1" \
-H "Authorization: JWT your-token"
Testimonials API
Alle Testimonials abrufen
# Alle Testimonials
curl "https://pl.porwoll.tech/api/testimonials"
# Nur aktive Testimonials
curl "https://pl.porwoll.tech/api/testimonials?where[isActive][equals]=true"
# Sortiert nach Bewertung (beste zuerst)
curl "https://pl.porwoll.tech/api/testimonials?sort=-rating"
# Sortiert nach eigener Reihenfolge
curl "https://pl.porwoll.tech/api/testimonials?sort=order"
Testimonial erstellen (Auth erforderlich)
curl -X POST "https://pl.porwoll.tech/api/testimonials" \
-H "Authorization: JWT your-token" \
-H "Content-Type: application/json" \
-d '{
"tenant": 1,
"quote": "Hervorragender Service! Ich bin sehr zufrieden.",
"author": "Max Mustermann",
"role": "Geschäftsführer",
"company": "Musterfirma GmbH",
"rating": 5,
"source": "Google Reviews",
"isActive": true,
"order": 1
}'
Newsletter Subscribers API
Newsletter-Anmeldung (Öffentlich)
# Einfache Anmeldung
curl -X POST "https://pl.porwoll.tech/api/newsletter-subscribers" \
-H "Content-Type: application/json" \
-d '{
"tenant": 1,
"email": "kunde@example.com",
"source": "website-footer"
}'
# Mit Namen und Interessen
curl -X POST "https://pl.porwoll.tech/api/newsletter-subscribers" \
-H "Content-Type: application/json" \
-d '{
"tenant": 1,
"email": "kunde@example.com",
"firstName": "Max",
"lastName": "Mustermann",
"interests": ["blog", "products"],
"source": "blog-sidebar"
}'
Response (Erfolg):
{
"doc": {
"id": 1,
"tenant": 1,
"email": "kunde@example.com",
"status": "pending",
"confirmationToken": "uuid-token-here",
"subscribedAt": "2025-11-30T14:23:41.012Z"
},
"message": "Newsletter Subscriber successfully created."
}
Subscribers abrufen (Auth erforderlich)
# Alle Subscribers
curl "https://pl.porwoll.tech/api/newsletter-subscribers" \
-H "Authorization: JWT your-token"
# Nur bestätigte Subscribers
curl "https://pl.porwoll.tech/api/newsletter-subscribers?where[status][equals]=confirmed" \
-H "Authorization: JWT your-token"
# Nach E-Mail suchen
curl "https://pl.porwoll.tech/api/newsletter-subscribers?where[email][equals]=kunde@example.com" \
-H "Authorization: JWT your-token"
Subscriber bestätigen (Double Opt-In)
# Über Token bestätigen
curl -X PATCH "https://pl.porwoll.tech/api/newsletter-subscribers/1" \
-H "Authorization: JWT your-token" \
-H "Content-Type: application/json" \
-d '{
"status": "confirmed"
}'
Subscriber abmelden
curl -X PATCH "https://pl.porwoll.tech/api/newsletter-subscribers/1" \
-H "Authorization: JWT your-token" \
-H "Content-Type: application/json" \
-d '{
"status": "unsubscribed"
}'
Pages API
Seiten abrufen
# Alle Seiten
curl "https://pl.porwoll.tech/api/pages"
# Seite nach Slug
curl "https://pl.porwoll.tech/api/pages?where[slug][equals]=startseite"
# Nur veröffentlichte Seiten
curl "https://pl.porwoll.tech/api/pages?where[status][equals]=published"
# Mit Locale
curl "https://pl.porwoll.tech/api/pages?locale=de&depth=2"
Seite mit Blocks
Die Blocks werden im layout-Array zurückgegeben:
{
"docs": [{
"id": 1,
"title": "Startseite",
"slug": "startseite",
"layout": [
{
"blockType": "hero-block",
"title": "Willkommen",
"subtitle": "..."
},
{
"blockType": "posts-list-block",
"title": "Aktuelle News",
"postType": "news",
"limit": 3
},
{
"blockType": "testimonials-block",
"title": "Das sagen unsere Kunden",
"layout": "slider"
}
]
}]
}
Consent Management APIs
Cookie-Konfiguration abrufen (Öffentlich, Tenant-isoliert)
Die Cookie-Konfiguration wird automatisch nach Domain gefiltert.
# Für Frontend Cookie-Banner
curl "https://pl.porwoll.tech/api/cookie-configurations?where[tenant][equals]=1"
Response:
{
"docs": [{
"id": 1,
"tenant": 1,
"title": "Cookie-Einstellungen",
"revision": 1,
"enabledCategories": ["necessary", "analytics"],
"translations": {
"de": {
"bannerTitle": "Wir respektieren Ihre Privatsphäre",
"bannerDescription": "Diese Website verwendet Cookies...",
"acceptAllButton": "Alle akzeptieren",
"acceptNecessaryButton": "Nur notwendige",
"settingsButton": "Einstellungen",
"saveButton": "Auswahl speichern",
"privacyPolicyUrl": "/datenschutz",
"categoryLabels": {
"necessary": { "title": "Notwendig", "description": "..." },
"functional": { "title": "Funktional", "description": "..." },
"analytics": { "title": "Statistik", "description": "..." },
"marketing": { "title": "Marketing", "description": "..." }
}
}
},
"styling": {
"position": "bottom",
"theme": "dark"
}
}]
}
Cookie-Inventory abrufen (Öffentlich, Tenant-isoliert)
Dokumentation aller verwendeten Cookies für die Datenschutzerklärung.
# Alle Cookies eines Tenants
curl "https://pl.porwoll.tech/api/cookie-inventory?where[tenant][equals]=1"
# Nur aktive Cookies
curl "https://pl.porwoll.tech/api/cookie-inventory?where[tenant][equals]=1&where[isActive][equals]=true"
# Nach Kategorie filtern
curl "https://pl.porwoll.tech/api/cookie-inventory?where[tenant][equals]=1&where[category][equals]=analytics"
Response:
{
"docs": [{
"id": 1,
"tenant": 1,
"name": "_ga",
"provider": "Google LLC",
"category": "analytics",
"duration": "2 Jahre",
"description": "Wird verwendet, um Benutzer zu unterscheiden.",
"isActive": true
}]
}
Cookie-Inventory Felder
| Feld | Typ | Beschreibung |
|---|---|---|
name |
string | Technischer Cookie-Name (z.B. "_ga") |
provider |
string | Anbieter (z.B. "Google LLC") |
category |
enum | necessary, functional, analytics, marketing |
duration |
string | Speicherdauer (z.B. "2 Jahre") |
description |
string | Beschreibung für Endnutzer |
isActive |
boolean | Cookie aktiv? |
Consent-Log erstellen (API-Key erforderlich)
Consent-Logs sind ein WORM (Write-Once-Read-Many) Audit-Trail für DSGVO-Nachweise.
curl -X POST "https://pl.porwoll.tech/api/consent-logs" \
-H "Content-Type: application/json" \
-H "X-API-Key: your-consent-api-key" \
-d '{
"tenant": 1,
"clientRef": "uuid-from-cookie",
"categories": {
"necessary": true,
"functional": false,
"analytics": true,
"marketing": false
},
"revision": 1,
"userAgent": "Mozilla/5.0..."
}'
Response:
{
"doc": {
"id": 1,
"consentId": "550e8400-e29b-41d4-a716-446655440000",
"tenant": 1,
"clientRef": "uuid-from-cookie",
"categories": { "necessary": true, "analytics": true, ... },
"revision": 1,
"anonymizedIp": "a1b2c3d4e5f6...",
"expiresAt": "2028-12-02T00:00:00.000Z",
"createdAt": "2025-12-02T10:00:00.000Z"
}
}
Wichtig:
- CREATE: Nur mit gültigem
X-API-KeyHeader - READ: Nur authentifizierte Admin-User
- UPDATE: Nicht erlaubt (WORM-Prinzip)
- DELETE: Nicht erlaubt (nur via Retention-Job)
Consent-Log Felder
| Feld | Typ | Beschreibung |
|---|---|---|
consentId |
string | Server-generierte UUID (read-only) |
clientRef |
string | Client-Cookie-Referenz für Traceability |
tenant |
relation | Zugehöriger Tenant |
categories |
json | Akzeptierte Kategorien |
revision |
number | Konfigurationsversion zum Zeitpunkt der Zustimmung |
userAgent |
string | Browser-Information |
anonymizedIp |
string | HMAC-Hash der IP (täglich rotierend) |
expiresAt |
date | Automatische Löschung nach 3 Jahren |
Privacy Policy Settings abrufen (Öffentlich, Tenant-isoliert)
Konfiguration für die Datenschutzerklärungs-Seite (z.B. Alfright Integration).
curl "https://pl.porwoll.tech/api/privacy-policy-settings?where[tenant][equals]=1"
Response:
{
"docs": [{
"id": 1,
"tenant": 1,
"title": "Datenschutzerklärung",
"provider": "alfright",
"alfright": {
"tenantId": "alfright_schutzteam",
"apiKey": "9f315103c43245bcb0806dd56c2be757",
"language": "de-de",
"iframeHeight": 4000
},
"styling": {
"headerColor": "#ca8a04",
"backgroundColor": "#111827",
...
},
"showCookieTable": true,
"cookieTableTitle": "Übersicht der verwendeten Cookies"
}]
}
Query-Parameter
Filterung (where)
# Equals
?where[field][equals]=value
# Not equals
?where[field][not_equals]=value
# Greater than
?where[field][greater_than]=10
# Less than
?where[field][less_than]=100
# Contains (Text)
?where[field][contains]=suchtext
# In (Array)
?where[field][in]=value1,value2
# AND-Verknüpfung
?where[and][0][field1][equals]=value1&where[and][1][field2][equals]=value2
# OR-Verknüpfung
?where[or][0][field1][equals]=value1&where[or][1][field2][equals]=value2
Sortierung (sort)
# Aufsteigend
?sort=fieldName
# Absteigend
?sort=-fieldName
# Mehrere Felder
?sort=-publishedAt,title
Pagination
# Limit
?limit=10
# Seite
?page=2
# Beide kombiniert
?limit=10&page=2
Depth (Relations laden)
# Keine Relations laden
?depth=0
# Eine Ebene
?depth=1
# Zwei Ebenen
?depth=2
Locale (Mehrsprachigkeit)
# Deutsch (Standard)
?locale=de
# Englisch
?locale=en
# Alle Sprachen
?locale=all
Fehlerbehandlung
Häufige Fehlercodes
| Code | Bedeutung |
|---|---|
| 200 | Erfolg |
| 201 | Erstellt |
| 400 | Ungültige Anfrage |
| 401 | Nicht authentifiziert |
| 403 | Nicht autorisiert |
| 404 | Nicht gefunden |
| 500 | Server-Fehler |
Fehler-Response
{
"errors": [
{
"message": "Du hast keine Berechtigung, diese Aktion auszuführen."
}
]
}
Validierungsfehler
{
"errors": [
{
"message": "The following field is invalid: email",
"field": "email"
}
]
}
Multi-Tenant Hinweise
Tenant-ID ermitteln
- Admin Panel: Unter "Settings → Tenants" die ID ablesen
- API:
curl "https://pl.porwoll.tech/api/tenants" \
-H "Authorization: JWT your-token"
Domain-basierter Zugriff
Wenn ein Frontend über eine Tenant-Domain (z.B. porwoll.de) zugreift, wird der Tenant automatisch erkannt und nur dessen Daten zurückgegeben.
Manueller Tenant-Filter
Für direkte API-Zugriffe:
curl "https://pl.porwoll.tech/api/posts?where[tenant][equals]=1"
Super Admin
User mit isSuperAdmin: true haben Zugriff auf alle Tenants und können neue Tenants erstellen/bearbeiten.
Beispiel: Frontend-Integration
Next.js Beispiel
// lib/api.ts
const API_BASE = 'https://pl.porwoll.tech/api'
const TENANT_ID = 1
export async function getPosts(type?: string, limit = 10, locale = 'de') {
const params = new URLSearchParams({
'where[tenant][equals]': String(TENANT_ID),
'where[status][equals]': 'published',
limit: String(limit),
sort: '-publishedAt',
depth: '1',
locale,
})
if (type && type !== 'all') {
params.append('where[type][equals]', type)
}
const res = await fetch(`${API_BASE}/posts?${params}`)
return res.json()
}
export async function getTestimonials(limit = 6) {
const params = new URLSearchParams({
'where[tenant][equals]': String(TENANT_ID),
'where[isActive][equals]': 'true',
limit: String(limit),
sort: 'order',
depth: '1',
})
const res = await fetch(`${API_BASE}/testimonials?${params}`)
return res.json()
}
export async function getCookieConfig() {
const params = new URLSearchParams({
'where[tenant][equals]': String(TENANT_ID),
})
const res = await fetch(`${API_BASE}/cookie-configurations?${params}`)
const data = await res.json()
return data.docs[0] || null
}
export async function getCookieInventory() {
const params = new URLSearchParams({
'where[tenant][equals]': String(TENANT_ID),
'where[isActive][equals]': 'true',
sort: 'category',
})
const res = await fetch(`${API_BASE}/cookie-inventory?${params}`)
return res.json()
}
export async function logConsent(
categories: Record<string, boolean>,
revision: number,
clientRef: string,
apiKey: string
) {
const res = await fetch(`${API_BASE}/consent-logs`, {
method: 'POST',
headers: {
'Content-Type': 'application/json',
'X-API-Key': apiKey,
},
body: JSON.stringify({
tenant: TENANT_ID,
clientRef,
categories,
revision,
userAgent: navigator.userAgent,
}),
})
return res.json()
}
export async function subscribeNewsletter(email: string, source: string) {
const res = await fetch(`${API_BASE}/newsletter-subscribers`, {
method: 'POST',
headers: { 'Content-Type': 'application/json' },
body: JSON.stringify({
tenant: TENANT_ID,
email,
source,
}),
})
return res.json()
}
React Component
// components/NewsletterForm.tsx
import { useState } from 'react'
import { subscribeNewsletter } from '@/lib/api'
export function NewsletterForm() {
const [email, setEmail] = useState('')
const [status, setStatus] = useState<'idle' | 'loading' | 'success' | 'error'>('idle')
const handleSubmit = async (e: React.FormEvent) => {
e.preventDefault()
setStatus('loading')
try {
const result = await subscribeNewsletter(email, 'website-footer')
if (result.doc) {
setStatus('success')
setEmail('')
} else {
setStatus('error')
}
} catch {
setStatus('error')
}
}
return (
<form onSubmit={handleSubmit}>
<input
type="email"
value={email}
onChange={(e) => setEmail(e.target.value)}
placeholder="Ihre E-Mail-Adresse"
required
/>
<button type="submit" disabled={status === 'loading'}>
{status === 'loading' ? 'Wird gesendet...' : 'Anmelden'}
</button>
{status === 'success' && <p>Vielen Dank! Bitte bestätigen Sie Ihre E-Mail.</p>}
{status === 'error' && <p>Es ist ein Fehler aufgetreten.</p>}
</form>
)
}
Rate Limiting
Das System verwendet einen zentralen Rate-Limiter mit Redis-Backend (Fallback auf In-Memory).
Vordefinierte Limits
| Limiter | Limit | Fenster | Verwendung |
|---|---|---|---|
publicApiLimiter |
60 Requests | 1 Minute | Öffentliche API-Endpunkte |
authLimiter |
5 Requests | 15 Minuten | Login-Versuche |
emailLimiter |
10 Requests | 1 Minute | E-Mail-Versand |
searchLimiter |
30 Requests | 1 Minute | Suche & Posts-API |
formLimiter |
5 Requests | 10 Minuten | Formular-Submissions, Newsletter |
Response bei Rate-Limit
{
"error": "Too many requests",
"retryAfter": 60
}
HTTP Status: 429 Too Many Requests
Headers:
X-RateLimit-Limit: Maximale RequestsX-RateLimit-Remaining: Verbleibende RequestsX-RateLimit-Reset: Reset-Zeitpunkt (Unix Timestamp)Retry-After: Sekunden bis zum Reset
Alle Collections Übersicht
Core Collections
| Collection | Slug | Öffentlich | Beschreibung |
|---|---|---|---|
| Users | users |
Nein | Benutzer-Verwaltung |
| Tenants | tenants |
Nein | Mandanten |
| Media | media |
Ja | Bilder und Dateien (11 responsive Sizes) |
| Pages | pages |
Ja | Seiten mit Blocks |
Content Collections
| Collection | Slug | Öffentlich | Beschreibung |
|---|---|---|---|
| Posts | posts |
Ja | Blog, News, Presse, Ankündigungen |
| Categories | categories |
Ja | Kategorien für Posts |
| Tags | tags |
Ja | Tags für Posts |
| Authors | authors |
Ja | Autoren für Posts |
| Testimonials | testimonials |
Ja | Kundenbewertungen |
| FAQs | faqs |
Ja | Häufig gestellte Fragen |
| Social Links | social-links |
Ja | Social Media Links |
Team & Services
| Collection | Slug | Öffentlich | Beschreibung |
|---|---|---|---|
| Team | team |
Ja | Team-Mitglieder |
| Service Categories | service-categories |
Ja | Kategorien für Leistungen |
| Services | services |
Ja | Leistungen/Dienstleistungen |
| Jobs | jobs |
Ja | Stellenangebote |
Portfolio & Media
| Collection | Slug | Öffentlich | Beschreibung |
|---|---|---|---|
| Portfolios | portfolios |
Ja | Portfolio-Galerien |
| Portfolio Categories | portfolio-categories |
Ja | Kategorien für Portfolios |
| Videos | videos |
Ja | Video-Bibliothek (YouTube/Vimeo/Upload) |
| Video Categories | video-categories |
Ja | Kategorien für Videos |
Products (E-Commerce)
| Collection | Slug | Öffentlich | Beschreibung |
|---|---|---|---|
| Products | products |
Ja | Produkte |
| Product Categories | product-categories |
Ja | Produkt-Kategorien |
Feature Collections
| Collection | Slug | Öffentlich | Beschreibung |
|---|---|---|---|
| Locations | locations |
Ja | Standorte/Filialen |
| Partners | partners |
Ja | Partner/Kunden (Logos) |
| Downloads | downloads |
Ja | Download-Dateien |
| Events | events |
Ja | Veranstaltungen |
| Timelines | timelines |
Ja | Chronologische Events |
| Workflows | workflows |
Ja | Prozess-Darstellungen |
BlogWoman Collections
| Collection | Slug | Öffentlich | Beschreibung |
|---|---|---|---|
| Favorites | favorites |
Ja | Affiliate-Produkte mit Kategorien/Badges |
| Series | series |
Ja | YouTube-Serien mit Branding |
Community Management (YouTube/Meta)
| Collection | Slug | Öffentlich | Beschreibung |
|---|---|---|---|
| YouTube Channels | youtube-channels |
Nein | Multi-Kanal-Verwaltung |
| YouTube Content | youtube-content |
Nein | Videos + Shorts mit Statistiken |
| YT Series | yt-series |
Nein | Serien mit Branding (Logo, Farben) |
| YT Notifications | yt-notifications |
Nein | Handlungsbedarf-System |
| Social Platforms | social-platforms |
Nein | Plattform-Konfiguration |
| Social Accounts | social-accounts |
Nein | OAuth-Verbindungen |
| Community Interactions | community-interactions |
Nein | Kommentare/Nachrichten aller Plattformen |
Formulare & Newsletter
| Collection | Slug | Öffentlich | Beschreibung |
|---|---|---|---|
| Forms | forms |
Nein | Formular-Builder (Plugin) |
| Form Submissions | form-submissions |
Nein | Formular-Einsendungen mit CRM-Workflow |
| Newsletter Subscribers | newsletter-subscribers |
Create: Ja | Newsletter mit Double Opt-In |
Consent & Privacy (DSGVO)
| Collection | Slug | Öffentlich | Beschreibung |
|---|---|---|---|
| Cookie Configurations | cookie-configurations |
Ja (Tenant-isoliert) | Cookie-Banner Konfiguration |
| Cookie Inventory | cookie-inventory |
Ja (Tenant-isoliert) | Cookie-Dokumentation |
| Consent Logs | consent-logs |
Nein (API-Key) | WORM Audit-Trail |
| Privacy Policy Settings | privacy-policy-settings |
Ja (Tenant-isoliert) | Datenschutz-Konfiguration |
Tenant-spezifische Collections
| Collection | Slug | Tenant | Beschreibung |
|---|---|---|---|
| Bookings | bookings |
porwoll.de | Fotografie-Buchungen |
| Certifications | certifications |
C2S | Zertifizierungen |
| Projects | projects |
gunshin.de | Game-Development-Projekte |
System Collections
| Collection | Slug | Öffentlich | Beschreibung |
|---|---|---|---|
| Site Settings | site-settings |
Ja (Tenant-isoliert) | Website-Einstellungen |
| Navigations | navigations |
Ja (Tenant-isoliert) | Navigationsmenüs |
| Email Logs | email-logs |
Nein | E-Mail-Protokollierung |
| Audit Logs | audit-logs |
Nein | Security Audit Trail |
| Redirects | redirects |
Nein | URL-Weiterleitungen (Plugin) |
BlogWoman APIs (NEU)
Favorites API (Affiliate-Produkte)
# Alle Favorites eines Tenants
curl "https://pl.porwoll.tech/api/favorites?where[tenant][equals]=1"
# Nach Kategorie filtern
curl "https://pl.porwoll.tech/api/favorites?where[tenant][equals]=1&where[category][equals]=fashion"
# Nach Badge filtern
curl "https://pl.porwoll.tech/api/favorites?where[tenant][equals]=1&where[badge][equals]=bestseller"
# Nach Preisbereich filtern
curl "https://pl.porwoll.tech/api/favorites?where[tenant][equals]=1&where[priceRange][equals]=mid"
Felder:
| Feld | Typ | Beschreibung |
|---|---|---|
title |
string | Produktname |
slug |
string | URL-Pfad |
description |
richtext | Beschreibung |
image |
relation | Produktbild |
affiliateUrl |
string | Affiliate-Link |
price |
string | Preis (Freitext) |
category |
select | fashion, beauty, travel, tech, home |
badge |
select | investment-piece, daily-driver, grfi-approved, new, bestseller |
priceRange |
select | budget, mid, premium, luxury |
isActive |
boolean | Sichtbarkeit |
Series API (YouTube-Serien)
# Alle Serien eines Tenants
curl "https://pl.porwoll.tech/api/series?where[tenant][equals]=1"
# Nur aktive Serien
curl "https://pl.porwoll.tech/api/series?where[tenant][equals]=1&where[isActive][equals]=true"
# Einzelne Serie nach Slug
curl "https://pl.porwoll.tech/api/series?where[tenant][equals]=1&where[slug][equals]=grfi"
Felder:
| Feld | Typ | Beschreibung |
|---|---|---|
title |
string | Serienname (lokalisiert) |
slug |
string | URL-Pfad |
description |
richtext | Beschreibung (lokalisiert) |
logo |
relation | Serien-Logo |
coverImage |
relation | Cover-Bild |
brandColor |
string | Hex-Farbcode |
youtubePlaylistId |
string | YouTube Playlist ID |
isActive |
boolean | Sichtbarkeit |
Community Management APIs (YouTube/Meta)
YouTube Channels API
# Alle Kanäle
curl "https://pl.porwoll.tech/api/youtube-channels" \
-H "Authorization: JWT your-token"
# Einzelner Kanal
curl "https://pl.porwoll.tech/api/youtube-channels/1" \
-H "Authorization: JWT your-token"
Felder:
| Feld | Typ | Beschreibung |
|---|---|---|
channelId |
string | YouTube Channel ID |
title |
string | Kanalname |
handle |
string | @handle |
thumbnailUrl |
string | Profilbild-URL |
subscriberCount |
number | Abonnenten |
videoCount |
number | Anzahl Videos |
isActive |
boolean | Sync aktiv |
YouTube Content API
# Alle Videos eines Kanals
curl "https://pl.porwoll.tech/api/youtube-content?where[channel][equals]=1" \
-H "Authorization: JWT your-token"
# Nur Videos (keine Shorts)
curl "https://pl.porwoll.tech/api/youtube-content?where[contentType][equals]=video" \
-H "Authorization: JWT your-token"
# Videos einer Serie
curl "https://pl.porwoll.tech/api/youtube-content?where[series][equals]=1" \
-H "Authorization: JWT your-token"
# Nach Veröffentlichungsdatum sortiert
curl "https://pl.porwoll.tech/api/youtube-content?sort=-publishedAt&limit=10" \
-H "Authorization: JWT your-token"
Felder:
| Feld | Typ | Beschreibung |
|---|---|---|
videoId |
string | YouTube Video ID |
title |
string | Video-Titel |
description |
text | Beschreibung |
thumbnailUrl |
string | Thumbnail-URL |
publishedAt |
date | Veröffentlichungsdatum |
contentType |
select | video, short |
channel |
relation | YouTube-Kanal |
series |
relation | YT-Serie |
viewCount |
number | Aufrufe |
likeCount |
number | Likes |
commentCount |
number | Kommentare |
YT Series API
# Alle Serien eines Kanals
curl "https://pl.porwoll.tech/api/yt-series?where[channel][equals]=1" \
-H "Authorization: JWT your-token"
# Nur aktive Serien
curl "https://pl.porwoll.tech/api/yt-series?where[isActive][equals]=true" \
-H "Authorization: JWT your-token"
Felder:
| Feld | Typ | Beschreibung |
|---|---|---|
name |
string | Serienname (lokalisiert) |
slug |
string | URL-Pfad |
description |
textarea | Beschreibung (lokalisiert) |
channel |
relation | YouTube-Kanal |
logo |
relation | Serien-Logo |
coverImage |
relation | Cover-Bild |
brandColor |
string | Primärfarbe (Hex) |
accentColor |
string | Akzentfarbe (Hex) |
youtubePlaylistId |
string | Playlist ID |
format |
select | short, longform, mixed |
isActive |
boolean | Sichtbarkeit |
YT Notifications API (Auth erforderlich)
# Alle Benachrichtigungen
curl "https://pl.porwoll.tech/api/yt-notifications" \
-H "Authorization: JWT your-token"
# Nur ungelesene
curl "https://pl.porwoll.tech/api/yt-notifications?where[status][equals]=unread" \
-H "Authorization: JWT your-token"
# Nach Priorität
curl "https://pl.porwoll.tech/api/yt-notifications?where[priority][equals]=high" \
-H "Authorization: JWT your-token"
Felder:
| Feld | Typ | Beschreibung |
|---|---|---|
type |
select | comment, mention, milestone, alert |
priority |
select | low, medium, high, urgent |
status |
select | unread, read, actioned, dismissed |
title |
string | Benachrichtigungstitel |
message |
text | Details |
channel |
relation | Betroffener Kanal |
content |
relation | Betroffenes Video |
Community Interactions API (Auth erforderlich)
# Alle Interaktionen
curl "https://pl.porwoll.tech/api/community-interactions" \
-H "Authorization: JWT your-token"
# Nach Plattform filtern
curl "https://pl.porwoll.tech/api/community-interactions?where[platform][equals]=1" \
-H "Authorization: JWT your-token"
# Nur Kommentare
curl "https://pl.porwoll.tech/api/community-interactions?where[type][equals]=comment" \
-H "Authorization: JWT your-token"
# Nach Status
curl "https://pl.porwoll.tech/api/community-interactions?where[status][equals]=pending" \
-H "Authorization: JWT your-token"
# Nach Sentiment (AI-Analyse)
curl "https://pl.porwoll.tech/api/community-interactions?where[analysis.sentiment][equals]=negative" \
-H "Authorization: JWT your-token"
Felder:
| Feld | Typ | Beschreibung |
|---|---|---|
platform |
relation | Social Platform |
socialAccount |
relation | Social Account |
type |
select | comment, reply, dm, mention |
externalId |
string | Plattform-ID |
author.name |
string | Autor-Name |
author.handle |
string | Autor-Handle |
message |
text | Nachrichteninhalt |
publishedAt |
date | Veröffentlichungsdatum |
status |
select | pending, read, in-progress, done, archived |
priority |
select | low, normal, high |
analysis.sentiment |
select | positive, neutral, negative |
analysis.language |
string | Erkannte Sprache |
Social Platforms API
# Alle Plattformen
curl "https://pl.porwoll.tech/api/social-platforms" \
-H "Authorization: JWT your-token"
Felder:
| Feld | Typ | Beschreibung |
|---|---|---|
name |
string | Plattformname |
slug |
string | youtube, facebook, instagram |
icon |
string | Emoji |
color |
string | Brand Color (Hex) |
apiConfig.apiType |
select | youtube_v3, facebook_graph, instagram_graph |
apiConfig.authType |
select | oauth2, api_key, bearer |
isActive |
boolean | Plattform aktiv |
Social Accounts API (Auth erforderlich)
# Alle verbundenen Accounts
curl "https://pl.porwoll.tech/api/social-accounts" \
-H "Authorization: JWT your-token"
# Nach Plattform filtern
curl "https://pl.porwoll.tech/api/social-accounts?where[platform][equals]=1" \
-H "Authorization: JWT your-token"
Felder:
| Feld | Typ | Beschreibung |
|---|---|---|
platform |
relation | Social Platform |
displayName |
string | Anzeigename |
accountHandle |
string | @handle |
externalId |
string | Plattform-Account-ID |
credentials.accessToken |
string | OAuth Token (verschlüsselt) |
credentials.tokenExpiresAt |
date | Token-Ablauf |
stats.lastSyncedAt |
date | Letzter Sync |
isActive |
boolean | Sync aktiv |
Weitere Ressourcen
- Admin Panel: https://pl.porwoll.tech/admin
- API-Dokumentation (Swagger): https://pl.porwoll.tech/api/docs
- OpenAPI JSON: https://pl.porwoll.tech/api/openapi.json
- Payload CMS Docs: https://payloadcms.com/docs
- GraphQL Playground: https://pl.porwoll.tech/api/graphql (wenn aktiviert)
Letzte Aktualisierung: 17.01.2026