Die API nutzen
Diese API gehört zur Konsole für die Cluster, die ich für dich betreibe. Deine eigene Landschaft
hat kein Portal; dort sprichst du mit kubectl oder dem CLI mit
dem Garden. Alles, was die Konsole tut, tut sie über dieselbe REST-API: Cluster erstellen,
Node-Pools verwalten, kubeconfigs ausstellen, die Abrechnung lesen. Diese Seite ist die
Orientierung: die Form der API und die Konventionen, die über alle Endpunkte hinweg gelten. Die
API-Referenz (derzeit auf Englisch) dokumentiert dann jeden Endpunkt vollständig,
generiert aus dem Live-Schema.
Basis-URL und Versionierung
Abschnitt betitelt „Basis-URL und Versionierung“Die API liegt unter dem Konsolen-Host, und die stabile Oberfläche ist mit dem Präfix /v1/
versioniert:
https://console.paasbox.com/api/v1/Anfragen und Antworten sind JSON über HTTPS. Eine neue Hauptversion würde zu /v2/ wechseln,
statt zu verändern, was /v1/ tut.
Authentifizierung
Abschnitt betitelt „Authentifizierung“Zwei Wege hinein, je nachdem, wer aufruft:
- Sitzung: Die Konsole authentifiziert dich über eine Browser-Sitzung. Das ist der interaktive Weg; du tust nichts Besonderes.
- API-Key: für Skripte, CI und alles Nicht-Interaktive. Erstelle in der Konsole einen Key
(siehe Teams & API-Keys) und sende ihn im
Authorization-Header.
Keys sehen aus wie pbx_live_…, werden bei der Erstellung einmalig angezeigt, gehören einem
Team-Mitglied und lassen sich jederzeit widerrufen. Sende ihn bei jeder Anfrage mit:
curl -s -H "Authorization: Token $PAASBOX_API_KEY" \ https://console.paasbox.com/api/v1/teams/<team>/clusters/Behalte den Key als das dauerhafte Geheimnis und nutze ihn, um pro Lauf eine frische kubeconfig zu holen, statt langlebige Cluster-Zugangsdaten zu speichern.
Alles hat einen Team-Scope
Abschnitt betitelt „Alles hat einen Team-Scope“Ressourcen gehören einem Team, nicht einer Person, deshalb tragen die Pfade, die Ressourcen besitzen, den Team-Slug:
/api/v1/teams/{team_slug}/clusters//api/v1/teams/{team_slug}/clusters/{cluster}/node-pools/Dein Key handelt in den Teams, in denen sein Besitzer Mitglied ist. Die Seite Teams & API-Keys behandelt Rollen und was ein Key darf; das Aktivitätsprotokoll führt jede per Key ausgelöste Änderung auf eine Person zurück.
Pagination
Abschnitt betitelt „Pagination“Listen-Endpunkte sind zu je 100 Einträgen paginiert. Fordere eine Seite mit ?page= an:
curl -s -H "Authorization: Token $PAASBOX_API_KEY" \ "https://console.paasbox.com/api/v1/teams/<team>/clusters/?page=2"Die Antwort verpackt die Einträge in eine kleine Hülle: count ist die Gesamtzahl, next und
previous sind Seiten-URLs (oder null an den Enden), und results enthält die Einträge:
{ "count": 137, "next": "https://console.paasbox.com/api/v1/teams/acme/clusters/?page=3", "previous": "https://console.paasbox.com/api/v1/teams/acme/clusters/?page=1", "results": [ /* … */ ]}Statuscodes und Fehler
Abschnitt betitelt „Statuscodes und Fehler“Es gelten die üblichen HTTP-Semantiken. Die, denen du begegnen wirst:
| Code | Bedeutung |
|---|---|
200 / 201 / 204 | Erfolg: gelesen, erstellt oder gelöscht (ohne Body). |
202 | Angenommen: Die Arbeit läuft asynchron (z. B. ein startender Cluster); frag die Ressource für den Status ab. |
401 / 403 | Nicht authentifiziert / nicht erlaubt. Prüfe den Key und die Rolle des Aufrufers im Team. |
402 | Ein Abrechnungs- oder Ausgabenlimit blockiert die Aktion. Kläre es in der Konsole und versuche es erneut. |
404 | Keine solche Ressource, oder sie liegt außerhalb der Teams, die dein Key erreicht. |
409 | Konflikt mit dem aktuellen Zustand (z. B. ein Name ist bereits vergeben). |
412 / 422 | Die Anfrage wurde verstanden, aber abgelehnt: Eine Vorbedingung schlug fehl, oder ein Feld war ungültig. |
Fehlerantworten tragen einen JSON-Body, der beschreibt, was schiefging; der Statuscode entscheidet, wie zu reagieren ist.
Zwei Flächen neben /api/v1/
Abschnitt betitelt „Zwei Flächen neben /api/v1/“Die paasbox-CLI, der kostenlose Weg, auf dem du die Landschaft selbst betreibst, spricht mit zwei kleineren Flächen, die den Konventionen oben nicht folgen. Beide sind hier von Hand dokumentiert: es sind einfache Endpunkte außerhalb des Frameworks, aus dem das Schema generiert wird, sie tauchen also nicht in der API-Referenz auf.
Anmelden aus der CLI
Abschnitt betitelt „Anmelden aus der CLI“Drei Endpunkte unter /api/cli/ auf dem Konsolen-Host implementieren den
OAuth-2.0-Device-Authorization-Grant (RFC 8628) –
denselben Ablauf, den gh auth login und docker login nutzen. Ein API-Key kommt hier nicht vor, denn der Sinn der
Sache ist, dass der Aufrufer noch keinen hat; die Bremsen sind der Ablauf nach zehn Minuten, ein
Ratenlimit pro Adresse und die Tatsache, dass nichts passiert, bis ein angemeldeter Mensch den Code
bestätigt. Die Fehler-Bodies sind die von RFC 8628, nicht die Formen oben, und jeder darf ein
error_description mitführen, das ein Client ignorieren kann.
POST /api/cli/device/start – eine Anmeldung eröffnen. Ohne Authentifizierung.
{ "scope": "dns", "client": "paasbox-cli/0.1.0" }{ "device_code": "…43 URL-sichere Zeichen…", "user_code": "FTQK-2X7M", "verification_uri": "https://console.paasbox.com/device", "verification_uri_complete": "https://console.paasbox.com/device?code=FTQK-2X7M", "expires_in": 600, "interval": 5}400 trägt invalid_scope oder invalid_request; 429 trägt slow_down, wenn von einer Adresse
zu viele Anmeldungen starten.
POST /api/cli/device/token – im Takt von interval abgefragt, bis der Mensch entschieden hat.
Ohne Authentifizierung; der Device-Code ist das Zugangsdatum.
{ "device_code": "…" }Solange es wartet, 400 mit einem von authorization_pending, slow_down, expired_token,
access_denied oder invalid_grant (ein unbekannter oder bereits verbrauchter Device-Code); 429
mit slow_down bei zu vielen Abfragen von einer Adresse. Wer schneller als interval abfragt,
bekommt slow_down und schiebt die Sperre um ein weiteres Intervall nach hinten – ein Client,
der das ignoriert, bekommt es also weiterhin.
Einmal, und nur einmal, antwortet die Abfrage mit 200 und der Bewilligung:
{ "token": "…", "team": "Acme GmbH", "label": "acme", "endpoint": "https://dns.paasbox.com/v1", "zone": "paasbox.app", "base": "paasbox.app", "scopes": ["dns"]}Jede spätere Abfrage mit demselben Device-Code bekommt invalid_grant. Der Token entsteht beim
Abholen, nicht beim Bestätigen, liegt dazwischen also nirgends. endpoint, zone und base kommen
aus der Konfiguration des antwortenden Portals statt aus einer festen Zeichenkette – lies sie aus
der Antwort, statt sie fest zu verdrahten.
GET /api/cli/whoami – was ein gespeicherter Token ist, für paasbox auth status. Schick den
Token als Bearer-Zugangsdatum:
curl -s -H "Authorization: Bearer $DNS_TOKEN" \ https://console.paasbox.com/api/cli/whoami{ "team": "Acme GmbH", "label": "acme", "scopes": ["dns"], "created": "2026-09-07T10:12:31+00:00", "endpoint": "https://dns.paasbox.com/v1", "zone": "paasbox.app", "base": "paasbox.app"}401 mit invalid_token heißt, der Token ist unbekannt oder wurde widerrufen – die CLI liest das
als „abgemeldet“, nicht als vorübergehende Störung.
Die API für gehostete Namen
Abschnitt betitelt „Die API für gehostete Namen“Die kostenlosen gehosteten Namen unter <team>.paasbox.app werden über
eine Hetzner-Cloud-kompatible Zone- und rrset-API auf einem eigenen Host geschrieben:
https://dns.paasbox.com/v1Sie bildet den Ausschnitt der Hetzner-Cloud-API nach, den Gardeners DNS-Extension, der Aufbau und
die hcloud-CLI tatsächlich aufrufen, Anfrage für Anfrage, und ergänzt das eine, was Hetzner nicht
kann: einen Bearer-Token mit Team-Scope. Ein unveränderter Client funktioniert also dagegen –
richte ihn auf den Endpunkt und gib ihm den Team-Token statt eines Hetzner-Tokens:
export HCLOUD_ENDPOINT=https://dns.paasbox.com/v1export HCLOUD_TOKEN=$DNS_TOKENhcloud zone rrset set-records --record 203.0.113.7 paasbox.app api.garden.acme A| Endpunkt | Was er tut |
|---|---|
GET /v1/zones | Liste, gefiltert per ?name=; liefert die eine Zone, die dein Token sieht |
GET /v1/zones/{zone} | per Id oder per Name |
GET /v1/zones/{zone}/rrsets | nur die Record-Sets deines Teams |
POST /v1/zones/{zone}/rrsets | anlegen |
GET / DELETE /v1/zones/{zone}/rrsets/{name}/{type} | eines lesen oder entfernen |
POST …/rrsets/{name}/{type}/actions/{action} | set_records, add_records, remove_records, change_ttl |
GET /v1/actions?id= und GET /v1/actions/{id} | Actions abfragen, so wie Hetzners Go-Client es tut |
Request- und Response-Bodies sind unverändert die von Hetzner, bis hin zur meta.pagination-Hülle
und der Form {"error": {"code": …, "message": …}}. Verweigert die Gegenstelle etwas, werden ihre
Antwort und ihr Statuscode wörtlich durchgereicht.
Anders ist, was der Token darf:
- Schreiben ist auf den eigenen Namen deines Teams und alles darunter erlaubt. Der Zonen-Apex,
die Namen jedes anderen Teams und alle unsere werden mit
403 forbiddenabgelehnt. - Lesen ist gefiltert. Eine Liste zeigt nur die Record-Sets deines Teams; jeder andere Name
antwortet
404 not_foundstatt403, damit sich die Zone durch diese Tür nicht aufzählen lässt. - Typen sind auf
A,AAAA,CNAMEundTXTbegrenzt.NSwird überall verweigert. - Actions sind auf Zonen-Actions gefiltert, die fortlaufenden Action-Ids eines Hetzner-Projekts verraten also nichts anderes.
- Kontingente (Stand: 2026-09-07): 200 Records und fünf aktive Tokens pro Team.
401 unauthorizedohne Bearer-Token,502 upstream_unavailable, wenn Hetzner nicht erreichbar ist.
Jeder Schreibvorgang wird festgehalten – Team, Token, Name, Typ, Aktion, Zeit und der Status, den die Gegenstelle geliefert hat – auch die verweigerten.
Die vollständige Referenz
Abschnitt betitelt „Die vollständige Referenz“Die API-Referenz listet jeden Endpunkt, Parameter, Request-Body und jede Antwortform auf. Sie wird aus dem Schema des laufenden Dienstes generiert und folgt so der API, wie sie ausgeliefert wird. Die beiden CLI-Flächen oben liegen außerhalb dieses Schemas und sind deshalb auf dieser Seite dokumentiert.