Die REST API ist für Pipelines, Skripte und alles, was kein Agent ist. Wenn Sie stattdessen ein Modell einbinden, verwenden Sie den MCP-Server – er stellt dieselben Operationen als Tools über dasselbe Berechtigungsmodell bereit.
Basis-URL
fastsite wird selbst gehostet, daher ist die Basis-URL Ihr eigener Engine-Host. Alles befindet sich unter einem einzigen Ursprung: das Dashboard, die API, der MCP-Endpunkt und eingehende Webhooks.
https://your-host/api/v1 Authentifizierung
Jede Anfrage enthält einen API-Schlüssel in einem Header. Auf dieser Oberfläche gibt es weder ein Bearer-Token noch eine Sitzung – Bearer-Auth gehört zu MCP.
X-API-Key: fs_<key_id>_<secret> Ein Schlüssel ist eine 44-stellige Zeichenkette: das literale Präfix fs_, eine 8-stellige öffentliche ID, ein Unterstrich und ein 32-stelliges Secret. Das Secret wird im Ruhezustand mit argon2id gehasht und genau einmal angezeigt, nämlich bei der Erstellung des Schlüssels.
php bin/fastsite key:create you@example.com \
--name="Deploy pipeline" \
--scopes=content:write,media:write,publish \
--sites=blog Verwenden Sie --sites=*, um jede Site zuzulassen. Schlüssel können auch über das Dashboard verwaltet und jederzeit rotiert oder widerrufen werden – ein widerrufener Schlüssel hört sofort auf zu funktionieren, anstatt bis zum Ende eines Cache-Fensters zu warten.
Jeder Fehler sieht gleich aus
Ein fehlender Header, ein fehlerhaft formatierter Schlüssel, ein unbekannter Schlüssel, ein falsches Secret, ein widerrufener Schlüssel und ein deaktivierter Benutzer geben alle dieselbe 401-Antwort mit derselben Meldung zurück. Das ist beabsichtigt – es bedeutet, dass die Existenz eines Schlüssels nicht durch Ausprobieren ermittelt werden kann.
Der Antwort-Envelope
Jede JSON-Antwort hat dieselbe Form, sodass ein Client anhand eines einzigen Felds verzweigen kann.
{ "success": true, "data": { … } }
{ "success": false, "error": { "message": "…" } } Listen-Endpunkte fügen neben data einen pagination-Block hinzu, und data ist ein einfaches Array statt eines Objekts:
{
"success": true,
"data": [ … ],
"pagination": { "total": 42, "page": 1, "per_page": 20, "total_pages": 3 }
} Zwei Endpunkte weichen bewusst vom Envelope ab, da eine Umhüllung keinen Nutzen hätte: Das Lesen einer Shell-Datei gibt die rohen Bytes als text/plain zurück, und das Löschen einer Datei gibt 204 ohne Body zurück.
Einen Beitrag erstellen und veröffentlichen
curl -X POST https://your-host/api/v1/sites/blog/content \
-H "X-API-Key: $FASTSITE_KEY" \
-H "Content-Type: application/json" \
-H "Idempotency-Key: 2f1c9a7e-…" \
-d '{
"type": "post",
"title": "Hello, world",
"body_html": "<p>Shipped in a single call.</p>",
"status": "published"
}' Das Schreiben von Inhalten veröffentlicht diese nicht. Beide Vorgänge sind bewusst getrennt – eine Pipeline kann so viel erstellen, überarbeiten und korrigieren wie nötig, ohne dass davon etwas bei den Besuchern ankommt. Wenn der Inhalt fertig ist, veröffentlichen Sie die Site:
curl -X POST https://your-host/api/v1/sites/blog/publish \
-H "X-API-Key: $FASTSITE_KEY"
# → { "success": true, "data": { "job": "0f3c…" } } Dies gibt 202 mit einer Job-ID zurück; der Build wird in der Warteschlange ausgeführt. Fragen Sie den Status mit GET /api/v1/jobs/0f3c… ab.
title ist das einzige Pflichtfeld beim Erstellen. type ist standardmäßig post, status ist standardmäßig draft, und der Slug wird aus dem Titel abgeleitet, wenn Sie keinen angeben. Ist dieser Slug bereits vergeben, hängt die Engine einen Zähler an und gibt den tatsächlich verwendeten Slug zurück – lesen Sie ihn immer zurück, anstatt ihn anzunehmen.
Endpunkte
Inhalte
| Methode | Pfad | Scope |
|---|---|---|
| GET | /sites/{site}/content | content:read |
| POST | /sites/{site}/content | content:write |
| GET | /sites/{site}/content/{id} | content:read |
| PATCH | /sites/{site}/content/{id} | content:write |
| DELETE | /sites/{site}/content/{id} | content:write |
| GET | /sites/{site}/content/trash | content:read |
| POST | /sites/{site}/content/{id}/restore | content:write |
| DELETE | /sites/{site}/content/{id}/purge | content:write |
| POST | /sites/{site}/content/{id}/fact-check | content:read |
Das Löschen ist ein Soft Delete – das Element wird in den Papierkorb verschoben und kann wiederhergestellt werden. purge ist der unwiderrufliche Vorgang.
Medien
| Methode | Pfad | Scope |
|---|---|---|
| GET | /sites/{site}/media | media:read |
| POST | /sites/{site}/media | media:write |
| DELETE | /sites/{site}/media/{id} | media:write |
| POST | /sites/{site}/media/{id}/restore | media:write |
| DELETE | /sites/{site}/media/{id}/purge | media:write |
Der Upload akzeptiert entweder ein Multipart-Formular mit einem Feld namens file oder JSON mit einer url zum Abrufen. Nicht beides – wenn eine Datei vorhanden ist, wird die URL ignoriert.
curl -X POST https://your-host/api/v1/sites/blog/media \
-H "X-API-Key: $FASTSITE_KEY" \
-F file=@hero.jpg \
-F alt="Sunrise over the harbour" Alt-Text ist für Bilder Pflicht, es sei denn, Sie übergeben explizit decorative=true. Das ist keine stilistische Präferenz – ein fehlender Alt-Text lässt das Build-Audit fehlschlagen, daher lehnt die API ihn bereits beim Eingang ab, anstatt ihn später eine Veröffentlichung scheitern zu lassen. URL-Importe sind gegen SSRF abgesichert: Private Adressbereiche werden abgelehnt, Weiterleitungen werden erneut validiert und der Download ist bytemäßig begrenzt.
Filtern Sie die Bibliothek mit ?kind=image,video,file. Bilder und Videos durchlaufen die Varianten-Pipeline; alles andere wird als herunterladbare Datei gespeichert.
Shell
| Methode | Pfad | Scope |
|---|---|---|
| GET | /sites/{site}/shell/files | shell:read |
| GET | /sites/{site}/shell/file/{path} | shell:read |
| PUT | /sites/{site}/shell/file/{path} | shell:write |
| DELETE | /sites/{site}/shell/file/{path} | shell:write |
| POST | /sites/{site}/shell/snapshot | shell:write |
| POST | /sites/{site}/shell/restore/{rev} | shell:write |
Der Body ist die Datei, kein JSON. Es gibt kein Wrapper-Objekt und keinen Feldnamen – Sie senden die Bytes und erhalten die Bytes zurück.
curl -X PUT https://your-host/api/v1/sites/blog/shell/file/templates/base.html.twig \
-H "X-API-Key: $FASTSITE_KEY" \
--data-binary @base.html.twig Der Pfad darf Schrägstriche enthalten. Schreibvorgänge sind auf das Shell-Verzeichnis beschränkt, auf 5 MB begrenzt und auf eine Erweiterungs-Zulassungsliste eingeschränkt (twig, css, js, json, woff2, svg und die üblichen Bildformate). Im Gegensatz zu Inhalten löst ein Shell-Schreibvorgang tatsächlich einen Rebuild aus – das Design hat sich geändert, daher muss auch die Ausgabe aktualisiert werden. Ein Burst von Bearbeitungen wird zu einem einzigen Build zusammengefasst, anstatt einen Build pro Datei auszulösen.
Erstellen Sie vor einer riskanten Änderung einen Snapshot. Bei der Wiederherstellung wird zunächst ein Snapshot erstellt, sodass eine Wiederherstellung selbst rückgängig gemacht werden kann.
Komponenten, Weiterleitungen, Skripte
| Methode | Pfad | Scope |
|---|---|---|
| PUT | /sites/{site}/components/{handle} | components:write |
| GET · POST | /sites/{site}/redirects | sites:read · sites:write |
| DELETE | /sites/{site}/redirects/{id} | sites:write |
| GET · POST | /sites/{site}/scripts | sites:read · sites:write |
| DELETE | /sites/{site}/scripts/{id} | sites:write |
Eine Komponente ist {type: "html"|"react", source_code, css?, variables_schema?}. React wird beim Upload kompiliert, sodass eine fehlerhafte Komponente zu einem 422 auf Ihre Anfrage führt statt später zu einer fehlerhaften Seite.
Sprachen, Veröffentlichung, Sites
| Methode | Pfad | Scope |
|---|---|---|
| POST | /sites/{site}/languages | translations:manage |
| DELETE | /sites/{site}/languages/{locale} | translations:manage |
| POST | /sites/{site}/publish | publish |
| GET | /jobs/{uuid} | jobs:read |
| GET | /sites | sites:read |
| POST | /sites | admin |
| PATCH | /sites/{site} | sites:write |
| GET · POST | /sites/{site}/webhooks | sites:read · sites:write |
| GET | /sites/{site}/webhooks/{id}/deliveries | sites:read |
| DELETE | /sites/{site}/webhooks/{id} | sites:write |
| GET | /authoring-guide | sites:read |
| GET | /sites/{site}/authoring-guide | sites:read |
Holen Sie zuerst den Authoring-Guide
GET /api/v1/authoring-guide gibt die maschinenlesbaren Regeln für Body-HTML, Bildeinbettung und den Shell-Vertrag zurück. Übergeben Sie eine Site, um deren Locales und die Einbettungssyntax einzuschließen. Das ist der Unterschied zwischen Inhalten, die gebaut werden, und Inhalten, die das Audit ablehnt.
Scopes
Schlüssel und OAuth-Grants teilen sich ein gemeinsames Scope-Vokabular, sodass ein Endpunkt und ein Tool den Zugriff identisch durchsetzen.
| Scope | Gewährt |
|---|---|
sites:read | Sites und deren Einstellungen einsehen |
sites:write | Site-Einstellungen, Weiterleitungen, Skripte und Webhooks ändern |
content:read | Beiträge und Seiten lesen |
content:write | Beiträge und Seiten erstellen und bearbeiten |
media:read | Medienbibliothek anzeigen |
media:write | Bilder, Videos und Dateien hochladen |
components:write | Komponenten erstellen und aktualisieren |
shell:read | Templates und Theme lesen |
shell:write | Templates und Theme bearbeiten |
translations:manage | Locales und Übersetzungen verwalten |
publish | Bauen und veröffentlichen |
jobs:read | Build- und Job-Status lesen |
backup:read · backup:run · backup:restore | Backup-Operationen |
admin | Alles |
Nur admin impliziert etwas anderes. Es gibt keine Lese-/Schreib-Hierarchie – content:write gewährt kein content:read, also fordern Sie beides an, wenn Sie beides benötigen. Schlüssel sind außerdem auf eine Site-Liste beschränkt, und eine Anfrage für eine Site außerhalb dieser Liste wird abgelehnt, bevor sie einen Handler erreicht.
Idempotenz
Senden Sie bei jedem POST einen Idempotency-Key-Header, und die Engine speichert das Ergebnis dazu.
- Derselbe Schlüssel mit derselben Methode, demselben Pfad und demselben Body gibt die gespeicherte Antwort wieder, mit
Idempotency-Replayed: truedarin. - Derselbe Schlüssel mit einem anderen Body führt zu einem
422– so stellen Sie fest, dass Ihre Wiederholungslogik den Payload verändert hat. - Ein Wiederholungsversuch, der eintrifft, während der erste noch läuft, erhält
409und einRetry-After. - Wenn der Handler einen Fehler wirft oder die Antwort ein
5xxoder429ist, wird der Schlüssel freigegeben, damit ein echter Wiederholungsversuch erfolgreich sein kann.
Andere Methoden ignorieren den Header vollständig.
Rate-Limits
Zwei Festfenster-Limits, beide pro Minute: 60 Anfragen pro IP und 120 pro API-Schlüssel. Das Überschreiten eines der Limits gibt 429 mit einem Retry-After zurück. Das IP-Bucket ist dasjenige, auf das Sie in der Regel zuerst stoßen, da ein einzelner Client eine einzige Adresse ist.
JSON-Request-Bodies sind auf 4 MiB begrenzt. Uploads sind von dieser Prüfung ausgenommen und stattdessen durch die typspezifischen Mediengrenzen beschränkt.
Statuscodes
| Code | Bedeutung |
|---|---|
| 200 · 201 · 202 · 204 | Erfolg. 202 bedeutet in der Warteschlange – Job abfragen. |
| 401 | Fehlender, fehlerhaft formatierter, unbekannter oder widerrufener Schlüssel. |
| 403 | Gültiger Schlüssel, aber Scope oder Site ist nicht erlaubt. |
| 404 | Route, Site oder Datensatz nicht vorhanden. |
| 409 | Duplikat oder eine idempotente Anfrage noch in Bearbeitung. |
| 413 | Body überschreitet das Limit. |
| 422 | Validierung fehlgeschlagen – lesen Sie error.message. |
| 429 | Rate-Limit überschritten. |
Wissenswerte Details vor dem Entwickeln
- Zeitstempel sind streng.
scheduled_atundpublished_atmüssen im FormatYYYY-MM-DDTHH:MM:SSZangegeben werden – UTC, großesT, abschließendesZ. Offsets wie+02:00werden abgelehnt statt konvertiert. - Status-Werte sind
draft,scheduled,publishedundarchived. Für die Planung istscheduled_aterforderlich, und der Scheduler veröffentlicht den Inhalt zum vorgesehenen Zeitpunkt für Sie. - Paginierung erfolgt über
?page=und?per_page=, standardmäßig 20 und maximal 100. - Body-HTML wird auf jedem Pfad bereinigt. Inline-Styles werden entfernt, Skripte und iframes werden gelöscht, und das Ergebnis wird mit einem
warnings-Array zurückgegeben. Inhaltsprobleme lassen Ihre Anfrage nie fehlschlagen – sie werden gemeldet, normalisiert und veröffentlicht. - Einiges ist nicht über REST verfügbar. Backups, Teams und API-Schlüsselverwaltung sind CLI- und Dashboard-Operationen; Backups und Wiederherstellungen sind auch über MCP verfügbar.
Weiter: der MCP-Server für agentengesteuerte Veröffentlichung oder Webhooks zum Einspeisen von Inhalten aus einem vorgelagerten System.