Skip to content

REST-Schnittstelle

ZPO spricht JSON über eine REST-Schnittstelle unter dem Basis-Pfad /api/v1. Die Web-Oberfläche selbst läuft über dieselbe API — was die Oberfläche kann, kann auch ein Skript.

  • Anfragen und Antworten sind JSON (Content-Type: application/json).
  • Fehler kommen als {"error": "…"} mit dem passenden HTTP-Status: 401 ohne gültige Anmeldung, 403 bei fehlender Berechtigung, 404 bei unbekanntem Endpunkt.
  • Die Zugriffskontrolle ist rollenbasiert: Jede geschützte Route fordert eine Berechtigung, die über die Rollen des Benutzers aufgelöst wird.
  • Unbekannte Pfade unter /api/v1 enden in einem JSON-404 — nicht in der Oberfläche.

Zwei Wege, beide über Header:

Authorization: Bearer <jwt> — Benutzer-Sitzung aus dem Login
X-API-Key: <schlüssel> — API-Schlüssel für Skripte und Dienste

Login: POST /api/v1/auth/login mit username und password liefert token und das Benutzerprofil. Das Token signiert ZPO mit dem jwt_secret aus der Konfiguration; die Lebensdauer steuert access_token_ttl_minutes (siehe Konfiguration). Ist für den Benutzer Zwei-Faktor aktiv, antwortet der Login ohne code mit 200, totp_required: true und einer challenge. Die geht zusammen mit dem sechsstelligen Code aus der Authenticator-App (oder einem Einmalcode) an POST /api/v1/auth/login/totp ({"challenge": …, "code": …}) und liefert dort Token und Profil. Eine Challenge gilt fünf Minuten, lässt fünf Codes zu und ist nach der Anmeldung verbraucht. Skripte können den Code stattdessen auch gleich beim Login im Feld code mitschicken.

API-Schlüssel werden unter apikeys angelegt und tragen einen Scope: read (nur lesende Methoden — ein schreibender Aufruf endet in 403) oder readwrite (Vorgabe) — oder mcp: Ein solcher Schlüssel gilt nur an der MCP-Schnittstelle, an der REST-API nicht. Der Schlüssel wird einmalig beim Anlegen angezeigt und lässt sich später nur noch widerrufen. Requests mit X-API-Key (an /mcp auch als Bearer zpo_…) unterliegen einer Begrenzung pro Schlüssel und Minute (api_key_rate_limit_per_minute); die Begrenzung greift vor der Schlüsselprüfung und drosselt damit auch Brute-Force mit ungültigen Schlüsseln.

MethodePfadZweck
POST/api/v1/auth/loginAnmelden, Token und Profil holen (bei 2FA: Challenge)
POST/api/v1/auth/login/totpZweiter Schritt: Challenge und Code gegen Token und Profil
GET/api/v1/auth/meProfil des angemeldeten Benutzers
GET/api/v1/accountEigenes Konto lesen
PUT/api/v1/accountEigenes Profil ändern
PUT/api/v1/account/passwordEigenes Passwort ändern
POST/api/v1/account/2fa/startZwei-Faktor (TOTP) einrichten beginnen
POST/api/v1/account/2fa/confirmTOTP-Einrichtung bestätigen
POST/api/v1/account/2fa/disableTOTP abschalten
POST/api/v1/account/2fa/recovery-codesEinmalcodes neu erzeugen
GET/api/v1/usersBenutzer auflisten
GET/api/v1/users/:idEinzelnen Benutzer lesen
POST/api/v1/usersBenutzer anlegen
PUT/api/v1/users/:id/rolesRollen eines Benutzers setzen
DELETE/api/v1/users/:idBenutzer löschen
GET/api/v1/rolesRollen auflisten
GET/api/v1/apikeysAPI-Schlüssel auflisten
POST/api/v1/apikeysAPI-Schlüssel anlegen (Schlüssel einmalig in der Antwort)
DELETE/api/v1/apikeys/:idAPI-Schlüssel widerrufen
MethodePfadZweck
GET/api/v1/sitesStandorte auflisten
GET/api/v1/sites/:idEinzelnen Standort lesen
POST/api/v1/sitesStandort anlegen
PUT/api/v1/sites/:idStandort ändern
DELETE/api/v1/sites/:idStandort löschen
POST/api/v1/sites/:id/failbackManuell zurückschwenken (Failback)

Proxy-Knoten (HAProxy) und DNS-Knoten (MikroTik RouterOS, AdGuard Home). Der Verbindungstest schreibt den Zustand fort und zählt als schreibender Zugriff.

Bei einem Proxy-Knoten mit https://-Verwaltungs-Adresse trägt das Feld tls_fingerprint den SHA-256-Fingerabdruck des Zertifikats (das Setup-Skript gibt ihn aus). Ohne Fingerabdruck prüft ZPO gegen die CAs des Systems. Mit http:// ist das Feld nicht erlaubt.

MethodePfadZweck
GET/api/v1/proxy-nodesProxy-Knoten auflisten
POST/api/v1/proxy-nodesProxy-Knoten eintragen
PUT/api/v1/proxy-nodes/:idProxy-Knoten ändern
DELETE/api/v1/proxy-nodes/:idProxy-Knoten löschen
POST/api/v1/proxy-nodes/:id/testVerbindungstest ausführen
POST/api/v1/proxy-nodes/:id/disabledKnoten deaktivieren bzw. aktivieren ({"disabled": true})
POST/api/v1/proxy-nodes/:id/maintenanceKnoten in Wartung nehmen bzw. zurückholen
POST/api/v1/proxy-nodes/:id/cleanupVerwaiste Objekte auf dem Knoten entfernen
GET/api/v1/dns-nodesDNS-Knoten auflisten
POST/api/v1/dns-nodesDNS-Knoten eintragen
PUT/api/v1/dns-nodes/:idDNS-Knoten ändern
DELETE/api/v1/dns-nodes/:idDNS-Knoten löschen
POST/api/v1/dns-nodes/:id/testVerbindungstest ausführen
POST/api/v1/dns-nodes/:id/cleanupVerwaiste Einträge auf dem Resolver entfernen
GET/api/v1/dns-recordsEinträge auf den Resolvern, live gelesen
MethodePfadZweck
GET/api/v1/hostsVeröffentlichte Dienste auflisten
GET/api/v1/hosts/:idEinzelnen Dienst lesen
POST/api/v1/hostsDienst veröffentlichen
PUT/api/v1/hosts/:idDienst ändern
DELETE/api/v1/hosts/:idDienst zurückziehen
POST/api/v1/hosts/:id/maintenanceWartungsmodus ein-/ausschalten ({"active": true})
GET/api/v1/poolsBackend-Pools auflisten
GET/api/v1/pools/:idEinzelnen Pool lesen
POST/api/v1/poolsPool anlegen
PUT/api/v1/pools/:idPool ändern
DELETE/api/v1/pools/:idPool löschen
MethodePfadZweck
GET/api/v1/syncOffene Aufträge, Fehlschläge und Abweichungen
GET/api/v1/sync/summaryAuftragslage als Zusammenfassung
POST/api/v1/sync/:id/retryFehlgeschlagenen Auftrag erneut anstoßen
GET/api/v1/eventsEreignisse auflisten (Failover, Zertifikate, Drift)
POST/api/v1/events/:id/confirmEreignis bestätigen
MethodePfadZweck
GET/api/v1/certificatesZertifikate auflisten
GET/api/v1/certificates/:idEinzelnes Zertifikat lesen
POST/api/v1/certificatesZertifikat anlegen
PUT/api/v1/certificates/:idZertifikat ändern
DELETE/api/v1/certificates/:idZertifikat löschen
POST/api/v1/certificates/:id/orderZertifikat bei der CA bestellen
POST/api/v1/certificates/:id/renewErneuerung sofort anstoßen
POST/api/v1/certificates/:id/exportHerunterladen: {"format": "fullchain"} — fullchain, cert, chain, der, p7b; mit Schreibrecht auch key, bundle, pfx, pfx-legacy (diese beiden mit password)
POST/api/v1/certificates/uploadFremdzertifikat hochladen
GET/api/v1/acme-accountsACME-Konten auflisten
POST/api/v1/acme-accountsACME-Konto anlegen
PUT/api/v1/acme-accounts/:idACME-Konto ändern
DELETE/api/v1/acme-accounts/:idACME-Konto löschen
GET/api/v1/dns-providersDNS-01-Provider-Zugänge auflisten
GET/api/v1/dns-providers/catalogKatalog der gepflegten Provider-Masken
POST/api/v1/dns-providersProvider-Zugang anlegen
POST/api/v1/dns-providers/testZugang testen: {"id", "provider", "values", "domain"} — legt _acme-challenge.<domain> an und entfernt ihn wieder
PUT/api/v1/dns-providers/:idProvider-Zugang ändern
DELETE/api/v1/dns-providers/:idProvider-Zugang löschen

IP-Gruppen sind die CIDR-Listen, die Dienste binden können; die Rate-Limits selbst sind Felder am Dienst (/api/v1/hosts), siehe Betrieb.

MethodePfadZweck
GET/api/v1/ip-groupsIP-Gruppen auflisten
GET/api/v1/ip-groups/:idEinzelne IP-Gruppe lesen
POST/api/v1/ip-groupsIP-Gruppe anlegen
PUT/api/v1/ip-groups/:idIP-Gruppe ändern
DELETE/api/v1/ip-groups/:idIP-Gruppe löschen (abgelehnt, solange gebunden)

trusted: true macht die Netze einer Gruppe vertrauenswürdig: CrowdSec prüft sie nie, und ZPO hebt Sperren gegen sie auf.

MethodePfadZweck
GET/api/v1/crowdsecJe Standort LAPI und Proxys mit ihrem Zustand, Gesamtzustand der LAPI (health) und angebundene Systeme (clients), dazu der Abgleich (Matrix, zuletzt übertragen)
POST/api/v1/crowdsec/lapisLAPI eines Standorts eintragen: {"site_id", "url", "tls_fingerprint", "key", "machine"} — tls_fingerprint nur bei https, SHA-256 mit oder ohne Doppelpunkte
PUT/api/v1/crowdsec/lapis/:idLAPI ändern (leerer Schlüssel bzw. leeres Passwort: bisheriges behalten; leerer Fingerabdruck: keiner)
DELETE/api/v1/crowdsec/lapis/:idLAPI austragen
GET/api/v1/crowdsec/lapis/:id/allowlistsAllowlists aus CrowdSec selbst (cscli allowlists), nur lesend — braucht den Maschinen-Zugang
GET/api/v1/crowdsec/bansAktive Entscheidungen je Standort samt Stand des Abgleichs; type ist ban oder captcha (Stufe 1)
GET/api/v1/crowdsec/history?value=<adresse>Verlauf einer Adresse oder eines Netzes: die Vorfälle, die ZPO für die Sperrstufen zählt (at, scenario, site, escalated — führte zur Sperre), neueste zuerst, höchstens 100
POST/api/v1/crowdsec/bans/liftSperre aufheben: {"lapi_id", "scope", "value", "everywhere"} — braucht den Maschinen-Zugang der LAPI
GET/api/v1/crowdsec/policyDie zwei Sperrstufen: captcha_off, cookie_minutes, max_number, escalate_after, window_hours, ban_hours, ban_max_hours, direct_ban (Szenarien je Zeile), dazu captcha_stage_hours (Dauer der Stufe 1, nur lesend)
PUT/api/v1/crowdsec/policySperrstufen ändern; 0 heißt Vorgabe
GET/api/v1/statsStatistik: ?period=24h|7d|30d&site=&node=&host= — Kennzahlen, Verlauf, Dienste, Ranglisten der Alarme. totals.active_bans zählt die echten Sperren, totals.active_captchas die Adressen, die nur die Prüfseite bekommen

Der Schutz eines Dienstes sind Felder am Dienst (/api/v1/hosts): waf_level (patches, strict, off), bot_challenge, traps, captcha_off, login_preset (proxmox, wordpress, gitlab, odoo, custom oder leer), login_paths, login_max_attempts, error_rate_limit, max_connections.

MethodePfadZweck
GET/api/v1/auditAudit-Log lesen (Filter: entity, entity_id)
GET/api/v1/audit/:idEinzelnen Eintrag mit Vorher/Nachher lesen
POST/api/v1/audit/:id/rollbackDienst auf den Vorher-Stand zurückrollen
MethodePfadZweck
GET/api/v1/backupEinstellungen der Sicherung lesen
PUT/api/v1/backupEinstellungen speichern
GET/api/v1/backup/filesSicherungen im Pfad-Ziel auflisten
POST/api/v1/backup/nowSicherung sofort auslösen
POST/api/v1/backup/restoreSicherungsdatei einspielen (ZPO startet danach neu)
MethodePfadZweck
GET/api/v1/settings/alertsAlarm-Einstellungen lesen (ohne Geheimnisse)
PUT/api/v1/settings/alertsAlarm-Einstellungen speichern
POST/api/v1/settings/alerts/test/:channelProbe über smtp oder webhook, mit den Werten der Maske (Body wie beim Speichern)
GET/api/v1/settings/generalAllgemeine Einstellungen lesen (Sitzungsdauer samt Vorgabe)
PUT/api/v1/settings/general{"session_seconds": 28800} — 0 heißt Vorgabe aus der config.json
GET/api/v1/settings/exportKonfigurations-Export ohne Geheimnisse
MethodePfadZweck
GET/api/v1/healthHealth-Check, öffentlich — {"status": "ok"}
GET/api/v1/system/infoVersion, Build und Uptime
GET/metricsPrometheus-Kennzahlen, außerhalb der API; optional per metrics_token geschützt

Die Kennzahlen hinter /metrics stehen unter Betrieb.