mirror of
https://github.com/complexcaresolutions/cms.c2sgmbh.git
synced 2026-03-18 01:34:11 +00:00
Tests: - Update frontend.e2e.spec.ts with locale testing - Add search.e2e.spec.ts for search functionality - Add i18n.int.spec.ts for localization tests - Add search.int.spec.ts for search integration - Update playwright.config.ts Documentation: - Add CLAUDE.md with project instructions - Add docs/ directory with detailed documentation - Add scripts/ for utility scripts 🤖 Generated with [Claude Code](https://claude.com/claude-code) Co-Authored-By: Claude <noreply@anthropic.com>
550 lines
11 KiB
Markdown
550 lines
11 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 die Universal Features.
|
|
|
|
**Base URL:** `https://pl.c2sgmbh.de/api`
|
|
|
|
---
|
|
|
|
## Authentifizierung
|
|
|
|
### Login
|
|
|
|
```bash
|
|
curl -X POST "https://pl.c2sgmbh.de/api/users/login" \
|
|
-H "Content-Type: application/json" \
|
|
-d '{
|
|
"email": "admin@example.com",
|
|
"password": "your-password"
|
|
}'
|
|
```
|
|
|
|
**Response:**
|
|
```json
|
|
{
|
|
"message": "Auth Passed",
|
|
"user": { ... },
|
|
"token": "eyJhbGciOiJIUzI1NiIs..."
|
|
}
|
|
```
|
|
|
|
### Token verwenden
|
|
|
|
```bash
|
|
curl "https://pl.c2sgmbh.de/api/posts" \
|
|
-H "Authorization: JWT eyJhbGciOiJIUzI1NiIs..."
|
|
```
|
|
|
|
---
|
|
|
|
## Posts API
|
|
|
|
### Alle Posts abrufen
|
|
|
|
```bash
|
|
# Alle Posts
|
|
curl "https://pl.c2sgmbh.de/api/posts"
|
|
|
|
# Nur Blog-Artikel
|
|
curl "https://pl.c2sgmbh.de/api/posts?where[type][equals]=blog"
|
|
|
|
# Nur News
|
|
curl "https://pl.c2sgmbh.de/api/posts?where[type][equals]=news"
|
|
|
|
# Nur veröffentlichte Posts
|
|
curl "https://pl.c2sgmbh.de/api/posts?where[status][equals]=published"
|
|
|
|
# Nur hervorgehobene Posts
|
|
curl "https://pl.c2sgmbh.de/api/posts?where[isFeatured][equals]=true"
|
|
|
|
# Mit Sortierung (neueste zuerst)
|
|
curl "https://pl.c2sgmbh.de/api/posts?sort=-publishedAt"
|
|
|
|
# Limitiert auf 10 Einträge
|
|
curl "https://pl.c2sgmbh.de/api/posts?limit=10"
|
|
|
|
# Pagination (Seite 2)
|
|
curl "https://pl.c2sgmbh.de/api/posts?limit=10&page=2"
|
|
```
|
|
|
|
### Einzelnen Post abrufen
|
|
|
|
```bash
|
|
# Nach ID
|
|
curl "https://pl.c2sgmbh.de/api/posts/1"
|
|
|
|
# Nach Slug (über Query)
|
|
curl "https://pl.c2sgmbh.de/api/posts?where[slug][equals]=mein-erster-artikel"
|
|
```
|
|
|
|
### Post erstellen (Auth erforderlich)
|
|
|
|
```bash
|
|
curl -X POST "https://pl.c2sgmbh.de/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.c2sgmbh.de/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.c2sgmbh.de/api/posts/1" \
|
|
-H "Authorization: JWT your-token"
|
|
```
|
|
|
|
---
|
|
|
|
## Testimonials API
|
|
|
|
### Alle Testimonials abrufen
|
|
|
|
```bash
|
|
# Alle Testimonials
|
|
curl "https://pl.c2sgmbh.de/api/testimonials"
|
|
|
|
# Nur aktive Testimonials
|
|
curl "https://pl.c2sgmbh.de/api/testimonials?where[isActive][equals]=true"
|
|
|
|
# Sortiert nach Bewertung (beste zuerst)
|
|
curl "https://pl.c2sgmbh.de/api/testimonials?sort=-rating"
|
|
|
|
# Sortiert nach eigener Reihenfolge
|
|
curl "https://pl.c2sgmbh.de/api/testimonials?sort=order"
|
|
```
|
|
|
|
### Testimonial erstellen (Auth erforderlich)
|
|
|
|
```bash
|
|
curl -X POST "https://pl.c2sgmbh.de/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.c2sgmbh.de/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.c2sgmbh.de/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.c2sgmbh.de/api/newsletter-subscribers" \
|
|
-H "Authorization: JWT your-token"
|
|
|
|
# Nur bestätigte Subscribers
|
|
curl "https://pl.c2sgmbh.de/api/newsletter-subscribers?where[status][equals]=confirmed" \
|
|
-H "Authorization: JWT your-token"
|
|
|
|
# Nach E-Mail suchen
|
|
curl "https://pl.c2sgmbh.de/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.c2sgmbh.de/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.c2sgmbh.de/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.c2sgmbh.de/api/pages"
|
|
|
|
# Seite nach Slug
|
|
curl "https://pl.c2sgmbh.de/api/pages?where[slug][equals]=startseite"
|
|
|
|
# Nur veröffentlichte Seiten
|
|
curl "https://pl.c2sgmbh.de/api/pages?where[status][equals]=published"
|
|
```
|
|
|
|
### 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"
|
|
}
|
|
]
|
|
}]
|
|
}
|
|
```
|
|
|
|
---
|
|
|
|
## 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
|
|
```
|
|
|
|
---
|
|
|
|
## 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": "You are not allowed to perform this action."
|
|
}
|
|
]
|
|
}
|
|
```
|
|
|
|
### 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.c2sgmbh.de/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.c2sgmbh.de/api/posts?where[tenant][equals]=1"
|
|
```
|
|
|
|
---
|
|
|
|
## Beispiel: Frontend-Integration
|
|
|
|
### Next.js Beispiel
|
|
|
|
```typescript
|
|
// lib/api.ts
|
|
const API_BASE = 'https://pl.c2sgmbh.de/api'
|
|
const TENANT_ID = 1
|
|
|
|
export async function getPosts(type?: string, limit = 10) {
|
|
const params = new URLSearchParams({
|
|
'where[tenant][equals]': String(TENANT_ID),
|
|
'where[status][equals]': 'published',
|
|
limit: String(limit),
|
|
sort: '-publishedAt',
|
|
depth: '1',
|
|
})
|
|
|
|
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 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
|
|
|
|
Aktuell gibt es kein Rate Limiting. Für Production-Umgebungen sollte ein Reverse Proxy (z.B. Caddy, nginx) mit Rate Limiting konfiguriert werden.
|
|
|
|
---
|
|
|
|
## Weitere Ressourcen
|
|
|
|
- **Admin Panel:** https://pl.c2sgmbh.de/admin
|
|
- **Payload CMS Docs:** https://payloadcms.com/docs
|
|
- **GraphQL Playground:** https://pl.c2sgmbh.de/api/graphql (wenn aktiviert)
|