KeyHelp-REST-API nutzen: Kunden, Domains und Postfächer per Skript anlegen
So richten Sie die REST-API von KeyHelp ein: API-Schlüssel mit IP-Sperre, sichere Optionen, ein Anlegeskript für Kunde, Domain, Postfach und Datenbank sowie alle Fehlerantworten, jeder Aufruf in einer VM getestet.
Geprüft am 01.10.2026 · für KeyHelp 26.1.1
Mit KI erstellt – redaktionelle Prüfung ausstehend
WerbelinksMit * markierte Links sind Werbelinks: Bei einem Kauf erhalten wir eine Provision, der Preis bleibt gleich. Als Amazon-Partner verdiene ich an qualifizierten Verkäufen. Mehr dazu

Wer mehr als eine Handvoll Kunden auf einem KeyHelp-Server betreut, legt Konten, Domains, Postfächer und Datenbanken irgendwann nicht mehr von Hand an. KeyHelp bringt dafür eine REST-API mit, die genau diese Objekte anlegt, ändert, sperrt und löscht. Typische Einsätze in Agenturen und kleinen Hosting-Betrieben sind ein Anlegeskript für Neukunden, die Anbindung an eine Rechnungs- oder Ticketsoftware und regelmäßige Auswertungen über Speicher und Traffic. Diese Anleitung setzt einen Server voraus, den Sie wie in unserer Anleitung KeyHelp installieren und absichern eingerichtet haben. Sie zeigt den Weg vom ersten API-Schlüssel bis zum fertigen Anlegeskript und dokumentiert, welche Antworten die API in Fehlerfällen liefert. Jeder Aufruf stammt aus der offiziellen OpenAPI-Spezifikation (API-Version 2.15) und wurde von uns auf KeyHelp 26.1.1 ausgeführt.
Voraussetzungen
- KeyHelp mit API-Version 2: Wir haben KeyHelp 26.1.1 (Build 3698) auf Debian 12 getestet, die API meldet dort Version 2.15. Die API ist in der kostenlosen Ausgabe enthalten, eine Pro-Lizenz ist nicht nötig.
- Admin-Zugang zum Panel, um API und Schlüssel einzurichten.
- Ein Rechner für die Skripte mit fester IP-Adresse,
curlundjq(apt install curl jq). Im Test lief das Skript direkt auf dem Server und griff über 127.0.0.1 zu. - Ein gültiges Zertifikat für den Hostnamen des Panels. Mit dem selbst signierten Zertifikat einer frischen Installation bricht curl ab (siehe „Typische Fehler“). Wie Sie das Zertifikat setzen, steht in unserer Anleitung zu SSL-Zertifikaten in KeyHelp.
- Ein aktuelles Backup, bevor Sie Skripte gegen einen Produktivserver laufen lassen.
DELETElöscht ohne Rückfrage.
Schritt 1: API aktivieren und Optionen setzen
Öffnen Sie im Admin-Bereich „Konfiguration“ → „API“. Die Seite zeigt die API-Version, Links zur „REST API Referenz“ sowie die Spezifikation als JSON und YAML (/api/openapi.json auf Ihrem Server). Ab Werk steht „API-Zugriff:“ auf „Deaktiviert“, ein Klick auf den Schalter stellt ihn auf „Aktiviert“.
Prüfen Sie danach die Schaltfläche „Optionen“. Dort gibt es drei Schalter:
- „Ressourcenbegrenzungen von Benutzerkonten ignorieren“: war im Test eingeschaltet. Die API legt dann Domains und Postfächer auch an, wenn das Kundenkonto seine Grenzen überschreitet.
- „Passwort-Richtlinie bei Verwendung der API anwenden“: war ausgeschaltet. Laut Panel ist dann „die Anwendung, die die API verwendet, für die Bereitstellung sicherer Passwörter verantwortlich“. Schalten Sie diese Option ein.
- „Passwort-Hashes verwenden“: aktiviert das Feld
password_hash, mit dem sich gespeicherte Hashes lesen und schreiben lassen. Nur für Migrationen sinnvoll, sonst ausgeschaltet lassen.
Verifizieren: Bei abgeschalteter API antwortet der Server mit 403, nach dem Einschalten mit 200. Im Test:
API is disabled.
[HTTP 403]
Schritt 2: API-Schlüssel anlegen und einschränken
Klicken Sie auf „API-Schlüssel hinzufügen“. Das Formular hat nur zwei Felder: „Name“ und „IP-Adressen“. Tragen Sie einen sprechenden Namen ein, etwa „automatisierung“, und die IP-Adresse oder den Bereich, von dem das Skript zugreift. KeyHelp weist selbst darauf hin, dass ein Schlüssel nur mit IP-Beschränkung als sicher gelten sollte.
Nach dem Speichern erscheint der Schlüssel genau einmal im Klartext: „Der API-Schlüssel wurde erstellt, bitte bewahren Sie ihn an einem sicheren Ort auf.“ KeyHelp speichert nur einen Hash und ein Präfix aus acht Zeichen, an dem Sie mehrere Schlüssel in der Liste unterscheiden. Ein verlorener Schlüssel lässt sich nicht wiederherstellen, nur neu anlegen. Legen Sie ihn auf dem Skript-Rechner in einer Datei ab, die nur root lesen darf:
install -m 600 /dev/null /root/.keyhelp-api-key
nano /root/.keyhelp-api-key # Schlüssel einfügen, speichern
Verifizieren: Der Endpunkt /ping eignet sich als Verbindungstest:
curl -s -H "X-API-Key: $(cat /root/.keyhelp-api-key)" https://kh.example.com/api/v2/ping
{
"response": "pong"
}
In der Schlüsselliste steht danach unter „Letzter Zugriff“ der Zeitpunkt des Aufrufs.
Schritt 3: Server und Hosting-Pläne abfragen
Bevor Sie etwas anlegen, lohnt ein Blick auf den Server. GET /server liefert Version, Betriebssystem, Auslastung und offene Updates. Bemerkenswert: Im Test meldete das Feld end_of_life für Debian 12 den Wert true, ein Hinweis auf das anstehende Upgrade.
K=$(cat /root/.keyhelp-api-key)
curl -s -H "X-API-Key: $K" https://kh.example.com/api/v2/server | jq .meta
curl -s -H "X-API-Key: $K" https://kh.example.com/api/v2/hosting-plans | jq -r '.[] | "\(.id) \(.name)"'
Die Hosting-Pläne sind die Konto-Vorlagen aus dem Panel. Sie sind wichtig, weil POST /clients Ressourcen und Rechte nicht direkt annimmt: Laut Spezifikation sind resource_limits und permissions dort nur lesbar, gesetzt werden sie über id_hosting_plan. Fehlt der Plan, nimmt KeyHelp die Standard-Vorlage.
Verifizieren: Im Test lieferte der Server:
"panel_version": "26.1.1",
"api_version": "2.15",
"keyhelp_pro": false
1 Unlimited
Schritt 4: Kunde, Domain, Postfach und Datenbank anlegen
Das folgende Skript legt einen kompletten Neukunden an. Jeder Aufruf gibt bei Erfolg HTTP 201 und die neue ID zurück, die der nächste Aufruf als id_user braucht. Lassen Sie das Passwort weg, erzeugt KeyHelp eines und gibt es einmalig in der Antwort zurück. Das Skript speichert diese Antworten mit Rechten 600.
#!/bin/bash
# Neuen Kunden mit Domain, Postfach und Datenbank über die KeyHelp-API anlegen
# Aufruf: ./neukunde.sh BENUTZERNAME DOMAIN
set -euo pipefail
API="https://kh.example.com/api/v2"
KEY=$(cat /root/.keyhelp-api-key)
USER_NAME=$1; DOMAIN=$2
api() { # api METHODE PFAD [JSON]
curl -sS --fail-with-body -H "X-API-Key: $KEY" -H "Content-Type: application/json" \
-X "$1" ${3:+-d "$3"} "$API/$2"
}
PLAN=$(api GET "hosting-plans/name/Unlimited" | jq -r .id)
CID=$(api POST clients "{\"username\":\"$USER_NAME\",\"email\":\"admin@$DOMAIN\",\"id_hosting_plan\":$PLAN,\"language\":\"de\",\"send_login_credentials\":false}" | jq -r .id)
DID=$(api POST domains "{\"id_user\":$CID,\"domain\":\"$DOMAIN\",\"create_www_subdomain\":true}" | jq -r .id)
api POST emails "{\"id_user\":$CID,\"email\":\"info@$DOMAIN\",\"max_size\":\"1G\"}" > "/root/$USER_NAME-postfach.json"
api POST databases "{\"id_user\":$CID,\"description\":\"Website\"}" > "/root/$USER_NAME-datenbank.json"
chmod 600 /root/$USER_NAME-*.json
echo "Kunde $CID, Domain $DID angelegt, Zugangsdaten in /root/$USER_NAME-*.json"
Einige Felder im Detail: send_login_credentials verhindert, dass KeyHelp die Zugangsdaten per Mail verschickt. Ohne create_system_domain: false legt KeyHelp zusätzlich eine Systemdomain nach dem Schema benutzer.hostname an. Größen wie max_size nehmen die Kurzformen K, M, G und T an. Ohne database_name vergibt KeyHelp Namen nach dem Muster benutzer_db1.
Verifizieren: Der Lauf dauerte im Test unter einer Sekunde. Eine Minute später, nach dem KeyHelp-Cronjob, zeigte GET /clients/name/shopkunde/resources alle Objekte mit Status 1 (okay), und die Website antwortete:
Kunde 4, Domain 7 angelegt, Zugangsdaten in /root/shopkunde-*.json
{"d":[["shopkunde.kh.example.com",1],["shop.example",1],["www.shop.example",1]],
"e":[["info@shop.example",1]],"db":["shopkunde_db1"]}
curl -H "Host: shop.example" http://127.0.0.1/ -> 200
Direkt nach dem Anlegen meldet eine Domain Status 4 (config_update). Warten Sie auf Status 1, bevor Sie Dateien hochladen.
Schritt 5: Bestehende Objekte ändern, sperren und löschen
Für Änderungen nehmen Sie PUT mit nur den Feldern, die sich ändern sollen. Statt der ID funktioniert bei den meisten Objekten auch der Name, etwa /emails/name/info@shop.example.
# Alias und Weiterleitung setzen, Kopie im Postfach behalten
curl -s -X PUT -H "X-API-Key: $K" -H "Content-Type: application/json" \
-d '{"aliases":["kontakt@shop.example"],"forwardings":["extern@example.net"],"store_forwarded_emails":true}' \
https://kh.example.com/api/v2/emails/name/info@shop.example
# Kunden sperren und wieder freigeben
curl -s -X PUT -H "X-API-Key: $K" -H "Content-Type: application/json" \
-d '{"is_suspended":true}' https://kh.example.com/api/v2/clients/name/shopkunde
# Einmal-Login-URL für den Kundenbereich (laut Spezifikation 60 Minuten gültig)
curl -s -H "X-API-Key: $K" https://kh.example.com/api/v2/login/name/shopkunde
# Kunden mit allen Domains, Postfächern und Datenbanken löschen
curl -s -X DELETE -H "X-API-Key: $K" https://kh.example.com/api/v2/clients/name/shopkunde
Verifizieren: Im Test kam eine Mail an den Alias im Postfach an. Ein gesperrter Kunde lieferte nach etwa einer Minute statt der Website eine Umleitung, und die Postfach-Anmeldung schlug fehl:
HTTP/1.1 302 Found
Location: https://kh.example.com/index.php?page=domain_disabled
passdb: info@apikunde.example auth failed
Nach DELETE (Antwort 204) waren Systembenutzer, Home-Verzeichnis, Datenbanken, Maildir und Apache-Konfiguration entfernt, ein erneutes GET lieferte 404.
Schritt 6: Fehler im Skript sauber behandeln
Die API antwortet bei Fehlern mit JSON aus code und message. Das Skript aus Schritt 4 bricht dank --fail-with-body und set -e beim ersten Fehler ab und zeigt die Meldung. Diese Antworten haben wir im Test ausgelöst:
| Auslöser | Status | Meldung |
|---|---|---|
| kein Schlüssel | 401 | API key is missing. |
| falscher Schlüssel oder fremde IP | 401 | API key is invalid / You are not allowed to access the API due to IP restrictions. |
| Benutzername vergeben | 400 | The username 'apikunde' is already in use. |
| Domain vergeben | 400 | The domain name 'apikunde.example' is already in use. |
| ungültiges JSON | 400 | Invalid request body. |
id_user fehlt | 400 | Invalid user ID. |
| schwaches Passwort, Richtlinie an | 400 | Password does not match required complexity. |
| unbekannte ID | 404 | The specified resource was not found. |
| falsche Methode | 405 | HTTP method not allowed. Use one of the following alternative HTTP methods instead: GET |
Accept-Header text/csv | 406 | Invalid value for HTTP header 'Accept'. … |
Die Spezifikation nennt einen weiteren Fall: Lädt KeyHelp gerade den Webserver neu, kann eine Anfrage mit 500 oder 503 scheitern. Ein Skript sollte diese Anfragen nach einigen Sekunden wiederholen, etwa mit curl --retry 3 --retry-delay 5. Einen solchen Fehler haben wir im Test nicht ausgelöst.
Verifizieren: Ein zweiter Lauf des Anlegeskripts mit demselben Kunden bricht sofort ab:
curl: (22) The requested URL returned error: 400
rc=22
Typische Fehler
curl: (60) SSL certificate problem: self-signed certificate
Im Test lief das Panel noch mit dem selbst signierten Zertifikat der Installation. Setzen Sie für den Hostnamen ein gültiges Zertifikat. curl -k schaltet die Prüfung ab und ist nur im Testnetz vertretbar, weil der Schlüssel sonst an einen Mittelsmann gehen kann.
Neuer Kunde hat nur 1 MiB Speicher
Ohne id_hosting_plan nutzt KeyHelp die Standard-Vorlage. Im Test bekam ein so angelegter Kunde 1 MiB Speicher und null Domains. Die Domain legte die API trotzdem an, weil „Ressourcenbegrenzungen ignorieren“ aktiv war. Rechte wie permissions per PUT /clients zu setzen, ignoriert die API ohne Fehlermeldung: Antwort 200, Wert unverändert. Ändern Sie stattdessen den Plan.
Passwort „123“ wird angenommen
Ab Werk prüft die API keine Passwortstärke. Aktivieren Sie die Option aus Schritt 1 oder lassen Sie KeyHelp die Passwörter erzeugen.
401 trotz richtigem Schlüssel
Die Meldung unterscheidet nicht zwischen falschem Schlüssel und falscher Quell-IP. Prüfen Sie zuerst, mit welcher Adresse Ihr Skript beim Server ankommt.
Häufige Fragen
Brauche ich KeyHelp Pro für die API?
Nein. Unser Testserver lief mit „KeyHelp Standard“ und "keyhelp_pro": false, alle hier gezeigten Endpunkte funktionierten.
Kann ich statt JSON auch XML oder YAML bekommen?
Ja, über den Header Accept: application/xml oder Accept: text/yaml. Im Test antwortete /ping mit response: pong in YAML.
Was kann die API noch?
Die Spezifikation 2.15 enthält auch Endpunkte für Administratoren, DNS-Zonen, Zertifikate, FTP-Benutzer, geplante Aufgaben, Verzeichnisschutz, Backup-Vorgänge und seit KeyHelp 26.1 für von Fail2Ban gesperrte IP-Adressen. Getestet haben wir davon GET /dns/{id} und GET /fail2ban/banned-ips.
Wie sichere ich die Daten vor einem Massenlauf?
Mit einem Backup, das Sie auch zurückspielen können. Wie das in KeyHelp geht, zeigt unsere Anleitung zu KeyHelp-Backups mit getestetem Restore.
Testumfang
Wir haben die API auf KeyHelp 26.1.1 unter Debian 12 in einer virtuellen Maschine eingerichtet und Kunden, Domains, Postfächer und Datenbanken angelegt, geändert, gesperrt und gelöscht, jeweils mit Prüfung im System. Auffällig war, dass die API ab Werk schwache Passwörter annimmt. Nicht getestet wurden Zertifikate, DNS-Änderungen, Backup-Endpunkte und Server mit hoher Last. Testen Sie Skripte zuerst mit einem Wegwerf-Kunden.
Fazit
Die KeyHelp-API ist schlicht aufgebaut und gut dokumentiert: ein Schlüssel im Header, JSON rein, ID raus. Für ein Anlegeskript reichen vier Aufrufe. Die Arbeit liegt in den Details: Hosting-Plan statt Einzelrechten, Passwort-Richtlinie einschalten, Schlüssel auf eine IP beschränken und Fehler im Skript auswerten statt zu ignorieren. Wer bereits andere Server per Schnittstelle steuert, findet ein ähnliches Vorgehen in unserer Anleitung zur netcup SCP REST API.
Weiterführende Anleitungen und Quellen
- KeyHelp installieren und absichern: das kostenlose Hosting-Panel für eigene Server
- KeyHelp: SSL-Zertifikate einrichten und überwachen
- KeyHelp RESTful API, offizielle Referenz (Spezifikation auch unter
/api/openapi.jsonauf Ihrem Server) - Keyweb: KeyHelp 26.1 mit neuem Fail2Ban-Endpunkt


