1. Was ist die Kunden-API und warum existiert sie?

Das Server-Control-Panel bietet ab Werk ausschließlich eine administrative API. Diese besitzt einen globalen Master-Schlüssel mit unbeschränkten Root-Rechten über alle Server-Kunden und Konfigurationen.

Das Problem: Ein administrativer Master-Key kann Kunden aus Sicherheitsgründen niemals ausgehändigt werden, da damit der gesamte Server kompromittiert werden könnte.

Die Lösung: Dieses Kunden-API Gateway fungiert als sicherer Übersetzer und Schutzschild ("Tenant Shield"). Es ermöglicht Kunden, sich direkt mit ihren gewohnten Webspace-Zugangsdaten (Benutzername & Passwort) anzumelden, und filtert alle Aktionen serverseitig streng nach Mandant.

2. Architektur & Funktionsweise

Das Gateway arbeitet als hochperformanter, schlanker Micro-Proxy ohne schwere Frameworks:

  1. Anfrage empfangen: Der Kunde sendet eine Anfrage an /api/v1/....
  2. Login prüfen: Das Gateway authentifiziert den Kunden und ermittelt seine interne Benutzer-ID.
  3. Mandanten-Filter: Der serverseitige TenantGuard stellt sicher, dass der Kunde ausschließlich Ressourcen einsehen oder verändern kann, die ihm selbst gehören.
  4. Server-Befehl ausführen: Die Anfrage wird sicher an das Backend weitergeleitet und das Ergebnis als sauberes JSON zurückgegeben.

3. Mandantenschutz (Tenant Guard)

Der Mandantenschutz verhindert IDOR-Lücken (Insecure Direct Object Reference). Wenn ein Kunde versucht, eine Ressource eines anderen Benutzers anzufordern (z. B. /api/v1/domains/999), prüft das System vorab den Besitzer:

Garantierte Sicherheit: Jeder Kunde sieht ausnahmslos nur seine eigenen Domains, Mailboxen, Datenbanken, FTP-Accounts und Zertifikate. Fremde Ressourcen antworten mit 403 Forbidden oder 404 Not Found.

4. Authentifizierung

Methode A: HTTP Basic Auth (Empfohlen für Skripte & CLI)

Verwende deinen normalen Webspace-Benutzernamen und dein Passwort direkt in der Anfrage:

curl -u "dein_kunden_user:dein_passwort" https://api.unterwelt-hosting.de/api/v1/account

Methode B: Bearer Session-Token (Empfohlen für Web-Panels & SPAs)

Erstelle über den Login-Endpunkt ein Session-Token, um Passwörter nicht dauerhaft im Client speichern zu müssen:

POST /api/v1/auth/login
Content-Type: application/json

{
  "username": "dein_kunden_user",
  "password": "dein_passwort"
}

Verwende das zurückgegebene token in allen weiteren Requests:

curl -H "Authorization: Bearer kh_sess_xxxxxxxxxxxxxxxx" https://api.unterwelt-hosting.de/api/v1/domains

Methode C: Feste API-Keys

Falls für Cronjobs oder Bots feste Keys eingerichtet sind, können diese per Header übergeben werden:

curl -H "X-API-Key: cst_live_xxxx" https://api.unterwelt-hosting.de/api/v1/domains

5. Praxis-Workflows

Account-Informationen & Quotas

Speicherplatz, Traffic und Quotas abfragen:

curl -u "user:pass" https://api.unterwelt-hosting.de/api/v1/account/stats

Domains & Subdomains

GET Alle Domains abfragen:

curl -u "user:pass" https://api.unterwelt-hosting.de/api/v1/domains

POST Neue Subdomain anlegen:

curl -u "user:pass" -X POST https://api.unterwelt-hosting.de/api/v1/domains \
  -H "Content-Type: application/json" \
  -d '{"domain": "shop.meinedomain.de", "php_version": "8.3", "target_dir": "/www/shop"}'

Let's Encrypt Wildcard-Zertifikate (Certbot DNS-01)

Für Wildcard-Zertifikate (*.meinedomain.de) stellt die API einen automatisierten Challenge-Endpunkt bereit:

# 1. Challenge-Record setzen:
curl -u "user:pass" -X POST https://api.unterwelt-hosting.de/api/v1/acme/dns-challenge \
  -H "Content-Type: application/json" \
  -d '{"domain": "meinedomain.de", "token": "acme_challenge_token_von_certbot"}';

# 2. Challenge-Record nach Verifizierung aufräumen:
curl -u "user:pass" -X DELETE https://api.unterwelt-hosting.de/api/v1/acme/dns-challenge \
  -H "Content-Type: application/json" \
  -d '{"domain": "meinedomain.de"}';

E-Mail-Postfächer

POST Neues E-Mail-Postfach anlegen:

curl -u "user:pass" -X POST https://api.unterwelt-hosting.de/api/v1/mailboxes \
  -H "Content-Type: application/json" \
  -d '{"address": "support@meinedomain.de", "password": "SicheresPasswort2026!", "quota_mb": 1024}'

MySQL Datenbanken & Benutzer

# Datenbank anlegen:
curl -u "user:pass" -X POST https://api.unterwelt-hosting.de/api/v1/databases \
  -H "Content-Type: application/json" \
  -d '{"database_name": "app_db", "description": "Produktivdatenbank"}';

# Datenbank-Benutzer anlegen:
curl -u "user:pass" -X POST https://api.unterwelt-hosting.de/api/v1/database-users \
  -H "Content-Type: application/json" \
  -d '{"username": "app_user", "password": "GeheimesPasswort123!"}';

FTP-Zugänge

curl -u "user:pass" -X POST https://api.unterwelt-hosting.de/api/v1/ftp-users \
  -H "Content-Type: application/json" \
  -d '{"username": "ftp_deploy", "password": "SicheresPasswort123!", "directory": "/www/shop"}'

6. Code-Beispiele

PHP

<?php
$url = 'https://api.unterwelt-hosting.de/api/v1/domains';
$ch = curl_init($url);
curl_setopt_array($ch, [
CURLOPT_RETURNTRANSFER => true,
CURLOPT_USERPWD => 'mein_user:mein_passwort',
CURLOPT_HTTPHEADER => ['Accept: application/json'],
]);
$response = json_decode(curl_exec($ch), true);
curl_close($ch);
print_r($response['data']);

JavaScript (Fetch / Node.js)

const credentials = btoa('mein_user:mein_passwort');
fetch('https://api.unterwelt-hosting.de/api/v1/domains', {
  headers: {
'Authorization': `Basic ${credentials}`,
'Accept': 'application/json'
  }
})
.then(res => res.json())
.then(json => console.log('Domains:', json.data));

Python (requests)

import requests
from requests.auth import HTTPBasicAuth

res = requests.get(
'https://api.unterwelt-hosting.de/api/v1/domains',
auth=HTTPBasicAuth('mein_user', 'mein_passwort')
)
print(res.json()['data'])

7. Statuscodes & Fehlerbehandlung

CodeBedeutungErklärung
200 OKErfolgDaten erfolgreich abgerufen oder aktualisiert.
201 CreatedErstelltNeue Ressource (z. B. Domain, Postfach) angelegt.
400 Bad RequestFehlerhafte EingabePflichtfelder fehlen oder ungültige Parameter.
401 UnauthorizedNicht autorisiertBenutzername oder Passwort falsch.
403 ForbiddenZugriff verweigertMandantenschutz: Zugriff auf fremde Ressourcen abgewiesen.
404 Not FoundNicht gefundenRessource existiert nicht.
500 ErrorServerfehlerFehler bei der Kommunikation mit dem Backend.