Die Schnittstelle zwischen Client und Manage-Server. Wer den mitgelieferten Client
verwendet, braucht dieses Dokument nicht – es ist für eigene Clients, für Debugging
und für die Fehlersuche mit curl gedacht.
Basis-URL: <MANAGE_SERVER_URL>/api/v1/
Jede Anfrage trägt zwei Header:
X-Manage-Instance: meinprojekt-prod
X-Manage-Token: e4032c4dc51e9100…
Der Server speichert nur den SHA-256-Hash des Tokens und vergleicht in konstanter Zeit. Es gibt keine Sitzung, kein Cookie und kein gemeinsames Passwort.
Fehlerantworten:
| Status | Bedeutung |
|---|---|
401 |
Header fehlen, Instanz unbekannt oder Token falsch – bewusst nicht unterscheidbar |
403 |
Instanz existiert, ist aber deaktiviert |
405 |
Falsche HTTP-Methode |
429 |
Zu viele fehlgeschlagene Authentifizierungen von dieser IP |
Fehlgeschlagene Anmeldungen sind pro IP begrenzt, damit Instanz-Kennungen nicht durchprobiert werden können. Eine erfolgreiche Anmeldung setzt den Zähler zurück.
Alle Fehlerantworten haben denselben Aufbau:
{
"success": false,
"error": "Authentifizierung fehlgeschlagen."
}
Liefert das Release, das die Instanz installieren soll.
curl -s https://manage.example.org/api/v1/manifest.php \
-H "X-Manage-Instance: meinprojekt-prod" \
-H "X-Manage-Token: $TOKEN"
{
"success": true,
"latest": "v1.3.0",
"version": "v1.3.0",
"package_url": "https://manage.example.org/api/v1/package.php?version=v1.3.0",
"sha256": "70f17aae44a9afdd948de1767daa61f936bbecb52096753757791e230a22f024",
"size": 2199,
"published_at": "2026-08-20T09:20:43+00:00"
}
404, wenn kein gültiges Release veröffentlicht ist.
package_url wird aus der Serverkonfiguration (MANAGE_PUBLIC_URL) gebildet, nicht
aus dem Host-Header der Anfrage. Ein gefälschter Header kann einen Client daher
nicht auf einen fremden Server umlenken.
Liefert das Release-ZIP.
curl -s -o release.zip \
"https://manage.example.org/api/v1/package.php?version=v1.3.0" \
-H "X-Manage-Instance: meinprojekt-prod" \
-H "X-Manage-Token: $TOKEN"
Antwort: application/zip mit Content-Length und
Cache-Control: private, no-store. Bei Erfolg kein JSON.
400 bei ungültigem Versionsformat, 404, wenn das Release nicht existiert.
Der Client vergleicht Größe und SHA-256 mit dem Manifest und löscht die Datei bei Abweichung. Ein eigener Client muss das ebenso tun – ohne diese Prüfung wird beliebiger Code ausgerollt.
Nimmt ein Backup-Archiv entgegen. multipart/form-data:
| Feld | Pflicht | Bedeutung |
|---|---|---|
backup |
ja | die ZIP-Datei |
filename |
nein | backup-YYYYmmdd-HHMMSS[-N].zip; ohne Angabe vergibt der Server einen Namen |
sha256 |
nein | Prüfsumme; wird serverseitig neu berechnet und verglichen |
meta |
nein | JSON mit trigger, file_count, source_bytes, app_version |
curl -s https://manage.example.org/api/v1/backup.php \
-H "X-Manage-Instance: meinprojekt-prod" \
-H "X-Manage-Token: $TOKEN" \
-F "filename=backup-20260820-092104.zip" \
-F "sha256=824f3f80…" \
-F 'meta={"trigger":"cron","file_count":3}' \
-F "backup=@backup-20260820-092104.zip"
{
"success": true,
"instance": "meinprojekt-prod",
"filename": "backup-20260820-092104.zip",
"size": 427,
"sha256": "824f3f80…",
"retention": 30,
"s3": { "enabled": false, "uploaded": false, "pending": 0 }
}
Der Server prüft in dieser Reihenfolge: Upload-Fehlercode, is_uploaded_file,
Größenlimit, ZIP-Signatur, Dateinamensmuster, Prüfsumme nach dem Speichern. Weicht
die Prüfsumme ab, wird die Datei wieder gelöscht und 400 gemeldet.
Ein vorhandener Dateiname wird nie überschrieben: Der Server hängt -2, -3 an.
Fehler beim S3-Archivieren lassen den Upload nicht fehlschlagen – die lokale Kopie ist gespeichert und wird später nachgezogen.
Statusmeldung. application/json:
{
"version": "v1.3.0",
"php_version": "8.3.6",
"disk_free": 12884901888,
"pending_migrations": 0,
"last_backup_at": "2026-08-20T09:21:04+00:00"
}
{
"success": true,
"instance": "meinprojekt-prod",
"latest": "v1.3.0",
"update_available": false,
"server_time": "2026-08-20T09:23:11+00:00"
}
Alle Felder der Anfrage sind optional; fehlende Felder lassen den bisherigen Wert
auf dem Server unverändert. Die Antwort ersetzt für einfache Überwachung einen
eigenen Aufruf von manifest.php.
Jede erfolgreich authentifizierte Anfrage aktualisiert last_seen_at und die
letzte IP der Instanz. Die Übersicht im Manage-Server bleibt dadurch aktuell, auch
wenn nur Backups laufen und nie ein Heartbeat gesendet wird.