# Die JSON-API: Webseiten automatisieren

> 30 API-Aktionen für Seiten, Beiträge, Medien, Theme und Konfiguration: wie die CMF-API arbeitet, wo ihre Grenzen liegen und was du damit automatisierst.

Kanonische URL: https://cmf.brosemedien.de/news/json-api-automatisieren

---

# Die JSON-API: Webseiten automatisieren

30 API-Aktionen, Token im Header, JSON rein und raus. Das CMF als programmierbarer Baukasten.

Fast alles, was du im Admin mit Inhalten tust, geht auch per API: Seiten anlegen, Beiträge veröffentlichen, das Theme ändern, Medien hochladen – mit einem HTTP-Request und einem Token. Diese Website ist selbst der Beleg: Die News-Beiträge vom 15.09.2026 wurden komplett per API angelegt.

Nicht per API erreichbar sind die Verwaltungsaufgaben: Benutzer und Tokens, Formular-Einsendungen, das System-Update, der ZIP-Export und die Blog-Einstellungen (Präfix und Kategorien). Die bleiben im Admin.

## Was die API kann

### Inhalte

Seiten und Beiträge lesen, anlegen, ändern, löschen. Header und Footer als globale Bereiche.

**7 Aktionen** für Seiten (inklusive Export und Import), **5** für den Blog.

### Design

Theme-Werte wie Farben, Schriften und Abstände per `styles_update` – ein Teilobjekt genügt, die `theme.css` entsteht neu. Custom CSS lesen und ersetzen. 10 Schriftfamilien liegen bereit.

### Medien

Bilder und Dateien per `multipart/form-data` hochladen; sie landen unter `/media/JJJJ/MM/` mit Zufallsanhang im Namen. Vor dem Löschen zeigt `media_usage`, wo eine Datei eingebunden ist.

Eingebundene Medien sind gegen Löschen geschützt.

### System

`site_bundle` liefert Konfiguration, Theme, Header, Footer und Custom CSS in einem Request. `site_export` und `site_import` übertragen dasselbe plus alle Seiten – ohne Blog und ohne Medien.

Öffentlich, ohne Token: `search_index` und `version_check`.

## Lesen geht auch ohne Token

Wer nur lesen will, braucht keinen Zugang: Jede veröffentlichte Seite gibt es als Markdown, wenn du `.md` an die Adresse hängst – [/home.md](/home.md) für die Startseite, [dieser Beitrag als Markdown](/news/json-api-automatisieren.md). Die [llms.txt](/llms.txt) listet alle Seiten und Beiträge. Die API brauchst du, sobald du die Blöcke strukturiert bekommen oder etwas ändern willst.

## So funktioniert ein API-Call

### Lesen

```
GET /api.php?a=page&slug=kontakt
Authorization: Bearer cms_DEIN_TOKEN

→ Antwort:
{
  "ok": true,
  "data": {
    "page": { "id": "…", "slug": "kontakt", … },
    "content": {
      "meta": { "title": "Kontakt", … },
      "content": { "blocks": [ … ] }
    }
  }
}
```

Erfolg: `{"ok": true, "data": {…}}`. Fehler: `{"ok": false, "error": "…", "details": […]}` mit sprechendem Fehlercode – bei ungültigen Blöcken nennt `details` genau, welcher Block was falsch hat.

### Schreiben

```
POST /api.php?a=page_update&id=abc123
Authorization: Bearer cms_DEIN_TOKEN
Content-Type: application/json

{
  "content": {
    "meta": { "title": "Kontakt", "description": "…" },
    "content": { "blocks": [ … ] }
  }
}
```

**Wichtig:** `content` ersetzt das ganze Dokument, auch `meta`. Schick `description`, `image` und `robots` also immer mit. Am einfachsten nimmst du `data.content` aus dem GET, änderst es und schickst es als `{"content": …}` zurück.

Ohne `content` ändern `title`, `slug`, `status` und `nav` nur die Verwaltungsdaten. Prüfe die Antwort: `ok: true` allein heißt nicht, dass sich der Inhalt geändert hat.

## Was ersetzt, was zusammenführt

- `site_update` **ersetzt die site.json komplett** (Pflicht: `name` und `lang`). Also erst `GET ?a=site`, ändern, vollständig zurückschicken – sonst sind Felder wie `csp` oder `og_image` weg.
- `custom_css_update` und `partial_update` ersetzen Custom CSS bzw. Header oder Footer ebenfalls komplett.
- `styles_update` und das `nav`-Objekt werden dagegen zusammengeführt – einzelne Werte reichen.
- `page_create` blendet eine Seite ohne `nav`-Angabe standardmäßig ins Menü ein und macht einen schon vergebenen Slug eindeutig (etwa `-2`). Den endgültigen Slug liest du aus der Antwort.
- Sitemap, Feed, `llms.txt` und Suchindex entstehen bei jeder Seiten- oder Blog-Änderung automatisch neu. `sitemap_generate` brauchst du nur nach einem `site_update`, etwa wenn sich die `baseUrl` ändert.

## Maschinen als Content-Partner, n8n als Pipeline

Die API ist so gebaut, dass Maschinen sie direkt bedienen können. Die [README_MASCHINEN.md](/files/README_MASCHINEN.md) fasst Endpunkte, Blocktypen und Regeln kompakt zusammen – kurz genug als Kontext für Claude, ChatGPT oder ein anderes Modell. Die vollständige Referenz steht in der [API-Anleitung](/api-anleitung), erprobte Abläufe in der [Anleitung für Maschinen](/maschinen-anleitung).

### Maschinen als Content-Partner

Was ein KI-Assistent mit Token-Zugang tun kann:

- **Seiten erstellen** – Inhalt als Blöcke erzeugen und per `page_create` anlegen, zuerst als Entwurf
- **Inhalte verbessern** – Seite laden, Texte überarbeiten, vollständig zurückschreiben
- **Beiträge schreiben** – Titel, Kategorie, Bild, Beschreibung und Inhalt in einem Request
- **SEO prüfen** – Meta-Titel, Beschreibungen und Alt-Texte durchgehen und korrigieren
- **Design anpassen** – Farben, Schriften und Custom CSS ändern

**Tipp:** Je konkreter der Auftrag, desto besser – Zielgruppe, Tonfall und gewünschte Blocktypen angeben.

### Praxisbeispiel: n8n-Workflow

Ein typischer automatisierter Ablauf:

- **Auslöser** – Webhook, Zeitplan oder eingehende E-Mail
- **Kontext laden** – HTTP-Node liest `site_bundle` und `blog_posts` (dort stehen die gültigen Kategorien)
- **Modell erzeugt** – Claude oder GPT liefert den Inhalt als API-konformes JSON
- **API schreibt** – HTTP-Node sendet `page_create` oder `blog_create`
- **Benachrichtigen** – E-Mail oder Chat-Nachricht mit dem Link. Sitemap, Feed und `llms.txt` hat das CMF zu diesem Zeitpunkt schon aktualisiert.

**Für den HTTP-Node:** POST, Header `Authorization: Bearer …`, Body als JSON. Die Antwort des Modells vorher prüfen – gültiges JSON, genau eine h1 – statt sie ungesehen durchzureichen.

## Vier weitere Szenarien

### Automatische Beiträge

Ein Workflow beobachtet einen RSS-Feed, ein Postfach oder einen Zeitplan und macht daraus einen Beitrag – Bild hochladen, Kategorie setzen, veröffentlichen.

`media_upload` → `blog_create`

### Staging und Produktion

Konfiguration, Theme, Header, Footer, Custom CSS und Seiten auf einer Test-Installation vorbereiten und auf die echte übertragen. Beiträge und Medien gehören nicht dazu – dafür gibt es `blog_create` und `media_upload`, oder den ZIP-Export im Admin für die ganze Website.

`site_export` → `site_import`

### Qualitätssicherung

Ein Script liest regelmäßig alle Seiten und meldet fehlende Meta-Descriptions, zu lange Titel oder leere Alt-Texte bei Bildern mit Inhalt – als Liste für einen Menschen, nicht als stille Korrektur.

`pages` + `page`

### Mehrere Installationen

Wer mehrere CMF-Websites betreut, sieht per `version_check` den Versionsstand jeder Installation – ohne Token – und rollt Theme-Änderungen per `styles_update` auf alle aus. Das Update selbst spielst du im Admin ein.

`version_check` + `styles_update`

## Der bewährte API-Ablauf

Ob per Script, Assistent oder n8n – der Ablauf ist immer gleich:

### 1. Zustand lesen

`site_bundle` liefert Konfiguration, Theme, Header, Footer und Custom CSS auf einmal.

Danach `pages` oder `blog_posts` für die Übersicht, dann die Zielseite vollständig laden.

**Regel:** Immer erst lesen, dann ändern. Nie blind schreiben.

### 2. Inhalte ändern

Blöcke hinzufügen, ändern oder entfernen, Meta-Daten anpassen. Medien zuerst hochladen und den zurückgegebenen Pfad verwenden.

**Regel:** Block-IDs stabil halten, das vollständige Dokument mit `meta` zurückschreiben. Admin und API speichern seit Version 1.17 sicher nacheinander – wer aber mit einem alten Stand zurückschreibt, überschreibt, was zwischendurch im Admin gespeichert wurde. Deshalb kurz vor dem Schreiben frisch lesen.

### 3. Prüfen

Die Antwort enthält das gespeicherte Dokument – vergleiche es mit dem, was du schicken wolltest. Dann die Seite im Frontend oder als `.md` ansehen: Sind alle Blöcke da, stimmen die Links?

Bei vielen Änderungen Seite für Seite arbeiten, nicht alles auf einmal.

**Regel:** Fehlermeldungen auswerten – bei 422 steht in `details`, was falsch ist.

## Sicherheit und Authentifizierung

### Bearer-Token

Jeder Request außer `search_index` und `version_check` braucht den Header `Authorization: Bearer cms_…`. Den Token erzeugst du im Admin unter *Benutzer*: neuen Zugang anlegen, Häkchen „API-Zugang anlegen“ setzen. Er wird genau einmal angezeigt.

Auf dem Server liegt nur ein Hash. Ein API-Zugang hat volle Rechte – behandle den Token wie ein Admin-Passwort.

### Gute Praxis

- Token nie in öffentliche Repos oder geteilte Prompts
- Für jede Automatisierung einen eigenen Zugang anlegen
- Vor großen Änderungen sichern (ZIP-Export im Admin)
- Token erneuern: neuen Zugang anlegen, alten löschen
- Nur über HTTPS – der Token steht im Header

- [API-Referenz](/api-anleitung)
- [Anleitung für Maschinen](/maschinen-anleitung)
- [README_MASCHINEN.md](/files/README_MASCHINEN.md)
