mirror of
https://github.com/complexcaresolutions/cms.c2sgmbh.git
synced 2026-03-17 20:54:11 +00:00
Add comprehensive YouTube feature documentation covering 9 collections, 12 custom API endpoints, 3 cron jobs, admin views, services, hooks, and access control across CLAUDE.md, CLAUDE_REFERENCE.md, and API_ANLEITUNG.md. Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
1514 lines
40 KiB
Markdown
1514 lines
40 KiB
Markdown
# 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
|
|
|
|
```bash
|
|
curl -X POST "https://pl.porwoll.tech/api/users/login" \
|
|
-H "Content-Type: application/json" \
|
|
-d '{
|
|
"email": "admin@example.com",
|
|
"password": "your-password"
|
|
}'
|
|
```
|
|
|
|
**Response:**
|
|
```json
|
|
{
|
|
"message": "Auth Passed",
|
|
"user": {
|
|
"id": 1,
|
|
"email": "admin@example.com",
|
|
"isSuperAdmin": true,
|
|
"tenants": [...]
|
|
},
|
|
"token": "eyJhbGciOiJIUzI1NiIs..."
|
|
}
|
|
```
|
|
|
|
### Token verwenden
|
|
|
|
```bash
|
|
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.
|
|
|
|
```bash
|
|
# 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
|
|
|
|
```bash
|
|
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)
|
|
|
|
```bash
|
|
curl "https://pl.porwoll.tech/api/tenants" \
|
|
-H "Authorization: JWT your-token"
|
|
```
|
|
|
|
### Tenant erstellen (Auth + SuperAdmin erforderlich)
|
|
|
|
```bash
|
|
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
|
|
|
|
```bash
|
|
# 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
|
|
|
|
```bash
|
|
# 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)
|
|
|
|
```bash
|
|
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)
|
|
|
|
```bash
|
|
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)
|
|
|
|
```bash
|
|
curl -X DELETE "https://pl.porwoll.tech/api/posts/1" \
|
|
-H "Authorization: JWT your-token"
|
|
```
|
|
|
|
---
|
|
|
|
## Testimonials API
|
|
|
|
### Alle Testimonials abrufen
|
|
|
|
```bash
|
|
# 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)
|
|
|
|
```bash
|
|
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)
|
|
|
|
```bash
|
|
# 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):**
|
|
```json
|
|
{
|
|
"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)
|
|
|
|
```bash
|
|
# 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)
|
|
|
|
```bash
|
|
# Ü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
|
|
|
|
```bash
|
|
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
|
|
|
|
```bash
|
|
# 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:
|
|
|
|
```json
|
|
{
|
|
"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.
|
|
|
|
```bash
|
|
# Für Frontend Cookie-Banner
|
|
curl "https://pl.porwoll.tech/api/cookie-configurations?where[tenant][equals]=1"
|
|
```
|
|
|
|
**Response:**
|
|
```json
|
|
{
|
|
"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.
|
|
|
|
```bash
|
|
# 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:**
|
|
```json
|
|
{
|
|
"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.
|
|
|
|
```bash
|
|
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:**
|
|
```json
|
|
{
|
|
"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-Key` Header
|
|
- 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).
|
|
|
|
```bash
|
|
curl "https://pl.porwoll.tech/api/privacy-policy-settings?where[tenant][equals]=1"
|
|
```
|
|
|
|
**Response:**
|
|
```json
|
|
{
|
|
"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)
|
|
|
|
```bash
|
|
# 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)
|
|
|
|
```bash
|
|
# Aufsteigend
|
|
?sort=fieldName
|
|
|
|
# Absteigend
|
|
?sort=-fieldName
|
|
|
|
# Mehrere Felder
|
|
?sort=-publishedAt,title
|
|
```
|
|
|
|
### Pagination
|
|
|
|
```bash
|
|
# Limit
|
|
?limit=10
|
|
|
|
# Seite
|
|
?page=2
|
|
|
|
# Beide kombiniert
|
|
?limit=10&page=2
|
|
```
|
|
|
|
### Depth (Relations laden)
|
|
|
|
```bash
|
|
# Keine Relations laden
|
|
?depth=0
|
|
|
|
# Eine Ebene
|
|
?depth=1
|
|
|
|
# Zwei Ebenen
|
|
?depth=2
|
|
```
|
|
|
|
### Locale (Mehrsprachigkeit)
|
|
|
|
```bash
|
|
# 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
|
|
|
|
```json
|
|
{
|
|
"errors": [
|
|
{
|
|
"message": "Du hast keine Berechtigung, diese Aktion auszuführen."
|
|
}
|
|
]
|
|
}
|
|
```
|
|
|
|
### Validierungsfehler
|
|
|
|
```json
|
|
{
|
|
"errors": [
|
|
{
|
|
"message": "The following field is invalid: email",
|
|
"field": "email"
|
|
}
|
|
]
|
|
}
|
|
```
|
|
|
|
---
|
|
|
|
## Multi-Tenant Hinweise
|
|
|
|
### Tenant-ID ermitteln
|
|
|
|
1. **Admin Panel:** Unter "Settings → Tenants" die ID ablesen
|
|
2. **API:**
|
|
```bash
|
|
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:
|
|
```bash
|
|
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
|
|
|
|
```typescript
|
|
// 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
|
|
|
|
```tsx
|
|
// 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
|
|
|
|
```json
|
|
{
|
|
"error": "Too many requests",
|
|
"retryAfter": 60
|
|
}
|
|
```
|
|
|
|
**HTTP Status:** 429 Too Many Requests
|
|
|
|
**Headers:**
|
|
- `X-RateLimit-Limit`: Maximale Requests
|
|
- `X-RateLimit-Remaining`: Verbleibende Requests
|
|
- `X-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 |
|
|
| YT Tasks | `yt-tasks` | Nein | Aufgaben mit Zuweisung |
|
|
| YT Batches | `yt-batches` | Nein | Produktions-Batches |
|
|
| YT Checklist Templates | `yt-checklist-templates` | Nein | Checklisten-Vorlagen |
|
|
| YT Monthly Goals | `yt-monthly-goals` | Nein | Monatsziele pro Kanal |
|
|
| YT Script Templates | `yt-script-templates` | Nein | Skript-Vorlagen |
|
|
| 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)
|
|
|
|
```bash
|
|
# 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)
|
|
|
|
```bash
|
|
# 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
|
|
|
|
```bash
|
|
# 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
|
|
|
|
```bash
|
|
# 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
|
|
|
|
```bash
|
|
# 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)
|
|
|
|
```bash
|
|
# 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 |
|
|
|
|
### YT Tasks API (Auth erforderlich)
|
|
|
|
```bash
|
|
# Alle Tasks
|
|
curl "https://pl.porwoll.tech/api/yt-tasks" \
|
|
-H "Authorization: JWT your-token"
|
|
|
|
# Tasks eines Videos
|
|
curl "https://pl.porwoll.tech/api/yt-tasks?where[video][equals]=1" \
|
|
-H "Authorization: JWT your-token"
|
|
|
|
# Offene Tasks nach Priorität
|
|
curl "https://pl.porwoll.tech/api/yt-tasks?where[status][not_equals]=done&sort=priority" \
|
|
-H "Authorization: JWT your-token"
|
|
```
|
|
|
|
**Felder:**
|
|
|
|
| Feld | Typ | Beschreibung |
|
|
|------|-----|--------------|
|
|
| `title` | string | Aufgabentitel (lokalisiert) |
|
|
| `description` | textarea | Beschreibung (lokalisiert) |
|
|
| `video` | relation | Zugehöriges Video |
|
|
| `channel` | relation | Kanal (auto-populiert) |
|
|
| `taskType` | select | script_write, script_review, shoot_prep, shoot, edit, graphics, thumbnail, review, upload, track, comments, other |
|
|
| `status` | select | todo, in_progress, blocked, waiting_review, done, cancelled |
|
|
| `priority` | select | urgent, high, normal, low |
|
|
| `assignedTo` | relation | Zugewiesener User |
|
|
| `dueDate` | date | Fälligkeitsdatum |
|
|
| `completedAt` | date | Abschlussdatum (auto) |
|
|
| `completedBy` | relation | Abgeschlossen von (auto) |
|
|
|
|
### YT Batches API (Auth erforderlich)
|
|
|
|
```bash
|
|
# Alle Batches
|
|
curl "https://pl.porwoll.tech/api/yt-batches" \
|
|
-H "Authorization: JWT your-token"
|
|
|
|
# Batches eines Kanals
|
|
curl "https://pl.porwoll.tech/api/yt-batches?where[channel][equals]=1" \
|
|
-H "Authorization: JWT your-token"
|
|
```
|
|
|
|
**Felder:**
|
|
|
|
| Feld | Typ | Beschreibung |
|
|
|------|-----|--------------|
|
|
| `name` | string | Batch-Name |
|
|
| `channel` | relation | YouTube-Kanal |
|
|
| `status` | select | planning, production, published |
|
|
| `productionPeriodStart` | date | Produktionsbeginn |
|
|
| `productionPeriodEnd` | date | Produktionsende |
|
|
| `targets.shortsTarget` | number | Shorts-Ziel |
|
|
| `targets.longformsTarget` | number | Longform-Ziel |
|
|
| `progress.percentage` | number | Fortschritt in % |
|
|
|
|
### YT Checklist Templates API (Auth erforderlich)
|
|
|
|
```bash
|
|
# Alle Templates
|
|
curl "https://pl.porwoll.tech/api/yt-checklist-templates" \
|
|
-H "Authorization: JWT your-token"
|
|
|
|
# Nach Typ filtern
|
|
curl "https://pl.porwoll.tech/api/yt-checklist-templates?where[type][equals]=upload" \
|
|
-H "Authorization: JWT your-token"
|
|
```
|
|
|
|
**Felder:**
|
|
|
|
| Feld | Typ | Beschreibung |
|
|
|------|-----|--------------|
|
|
| `name` | string | Template-Name (lokalisiert) |
|
|
| `channel` | relation | Kanal-spezifisch (optional) |
|
|
| `type` | select | upload, production, review, post_publish |
|
|
| `format` | select | all, short, longform |
|
|
| `items` | array | Checklisten-Items (order, task, category, isRequired) |
|
|
| `isDefault` | boolean | Auto-Zuordnung bei neuen Videos |
|
|
|
|
### YT Monthly Goals API (Auth erforderlich)
|
|
|
|
```bash
|
|
# Monatsziele eines Kanals
|
|
curl "https://pl.porwoll.tech/api/yt-monthly-goals?where[channel][equals]=1" \
|
|
-H "Authorization: JWT your-token"
|
|
```
|
|
|
|
**Felder:**
|
|
|
|
| Feld | Typ | Beschreibung |
|
|
|------|-----|--------------|
|
|
| `channel` | relation | YouTube-Kanal |
|
|
| `month` | date | Zielmonat |
|
|
| `contentGoals` | group | longformsTarget/Current, shortsTarget/Current |
|
|
| `audienceGoals` | group | subscribersTarget/Current, viewsTarget/Current |
|
|
| `engagementGoals` | group | avgCtrTarget/Current, avgRetentionTarget/Current |
|
|
| `businessGoals` | group | newsletterSignupsTarget/Current, affiliateRevenueTarget/Current |
|
|
|
|
### YT Script Templates API (Auth erforderlich)
|
|
|
|
```bash
|
|
# Vorlagen eines Kanals
|
|
curl "https://pl.porwoll.tech/api/yt-script-templates?where[channel][equals]=1" \
|
|
-H "Authorization: JWT your-token"
|
|
```
|
|
|
|
**Felder:**
|
|
|
|
| Feld | Typ | Beschreibung |
|
|
|------|-----|--------------|
|
|
| `name` | string | Vorlagenname (lokalisiert) |
|
|
| `channel` | relation | YouTube-Kanal |
|
|
| `series` | string | Serienname |
|
|
| `format` | select | short (45-60s), longform (8-16 Min) |
|
|
| `description` | textarea | Beschreibung (lokalisiert) |
|
|
|
|
---
|
|
|
|
## YouTube Custom API Endpoints
|
|
|
|
### OAuth & Authentifizierung
|
|
|
|
```bash
|
|
# OAuth-Flow starten
|
|
curl "https://pl.porwoll.tech/api/youtube/auth?socialAccountId=1" \
|
|
-H "Authorization: JWT your-token"
|
|
# → Redirect zu Google OAuth
|
|
|
|
# Token erneuern
|
|
curl -X POST "https://pl.porwoll.tech/api/youtube/refresh-token" \
|
|
-H "Authorization: JWT your-token" \
|
|
-H "Content-Type: application/json" \
|
|
-d '{"socialAccountId": 1}'
|
|
```
|
|
|
|
### Dashboard & Analytics
|
|
|
|
```bash
|
|
# Dashboard-Übersicht (Pipeline, Freigaben, Aufgaben)
|
|
curl "https://pl.porwoll.tech/api/youtube/dashboard" \
|
|
-H "Authorization: JWT your-token"
|
|
|
|
# Analytics (Tabs: performance, pipeline, goals, community, comparison, trends, roi)
|
|
curl "https://pl.porwoll.tech/api/youtube/analytics?tab=performance&channel=all&period=30d" \
|
|
-H "Authorization: JWT your-token"
|
|
|
|
# Video-Vergleich
|
|
curl "https://pl.porwoll.tech/api/youtube/analytics?tab=comparison&videoIds=1,2,3&metric=views" \
|
|
-H "Authorization: JWT your-token"
|
|
```
|
|
|
|
### Content Calendar
|
|
|
|
```bash
|
|
# Kalender-Events abrufen (FullCalendar-kompatibel)
|
|
curl "https://pl.porwoll.tech/api/youtube/calendar?start=2026-02-01&end=2026-02-28&channelId=all" \
|
|
-H "Authorization: JWT your-token"
|
|
|
|
# Content per Drag-&-Drop umplanen
|
|
curl -X PATCH "https://pl.porwoll.tech/api/youtube/calendar" \
|
|
-H "Authorization: JWT your-token" \
|
|
-H "Content-Type: application/json" \
|
|
-d '{"contentId": 1, "newDate": "2026-02-20T10:00:00Z"}'
|
|
```
|
|
|
|
### Tasks & Kapazität
|
|
|
|
```bash
|
|
# Eigene offene Tasks
|
|
curl "https://pl.porwoll.tech/api/youtube/my-tasks" \
|
|
-H "Authorization: JWT your-token"
|
|
|
|
# Task als erledigt markieren
|
|
curl -X POST "https://pl.porwoll.tech/api/youtube/complete-task/5" \
|
|
-H "Authorization: JWT your-token"
|
|
|
|
# Team-Kapazität
|
|
curl "https://pl.porwoll.tech/api/youtube/capacity" \
|
|
-H "Authorization: JWT your-token"
|
|
```
|
|
|
|
### Upload & Thumbnails
|
|
|
|
```bash
|
|
# Video-Upload-Job erstellen (BullMQ)
|
|
curl -X POST "https://pl.porwoll.tech/api/youtube/upload" \
|
|
-H "Authorization: JWT your-token" \
|
|
-H "Content-Type: application/json" \
|
|
-d '{"contentId": 1}'
|
|
|
|
# Upload-Status abfragen
|
|
curl "https://pl.porwoll.tech/api/youtube/upload?jobId=abc123" \
|
|
-H "Authorization: JWT your-token"
|
|
|
|
# Bulk-Thumbnail-Download (Super-Admin)
|
|
curl -X POST "https://pl.porwoll.tech/api/youtube/thumbnails/bulk?dryRun=true" \
|
|
-H "Authorization: JWT your-token"
|
|
```
|
|
|
|
### YouTube Cron Jobs
|
|
|
|
```bash
|
|
# YouTube-Kommentar-Sync (alle 15 Min)
|
|
curl "https://pl.porwoll.tech/api/cron/youtube-sync" \
|
|
-H "Authorization: Bearer $CRON_SECRET"
|
|
|
|
# Kanal-Statistiken (täglich 04:00 UTC)
|
|
curl "https://pl.porwoll.tech/api/cron/youtube-channel-sync" \
|
|
-H "Authorization: Bearer $CRON_SECRET"
|
|
|
|
# Video-Performance-Metriken (alle 6 Stunden)
|
|
curl "https://pl.porwoll.tech/api/cron/youtube-metrics-sync" \
|
|
-H "Authorization: Bearer $CRON_SECRET"
|
|
|
|
# Status-Check (HEAD → 200 idle, 423 running)
|
|
curl -I "https://pl.porwoll.tech/api/cron/youtube-channel-sync" \
|
|
-H "Authorization: Bearer $CRON_SECRET"
|
|
```
|
|
|
|
### Community Interactions API (Auth erforderlich)
|
|
|
|
```bash
|
|
# 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
|
|
|
|
```bash
|
|
# 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)
|
|
|
|
```bash
|
|
# 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*
|