xCloud DNS API
Überblick
Mit der REST-API von xCloud DNS verwaltest du Zonen, Records, Domains und Kontakte aus Skripten, CI-Pipelines oder eigenen Werkzeugen, so wie im DNS-Bereich der Web-App. Diese Dokumentation umfasst folgende Bereiche:
- Zonen und Records: Zonen anlegen, Records aller Typen verwalten, DynDNS, DNSSEC, delegierte Subdomains, Import und Export von Zonendateien
- Domains und Kontakte: Verfügbarkeit prüfen, Domains registrieren und transferieren, Nameserver und Kontakte ändern, Auto-Renew, Transfer-Lock, Auth-Code sowie Kontakte (Handles) verwalten
- Webhooks: Ereignisse, die xCloud an deine eigene URL schickt
- Preise: die öffentliche Preisliste für Domains
Die API verwendet JSON für Anfragen und Antworten und die üblichen HTTP-Methoden: GET
liest, POST legt an oder löst Aktionen aus, PATCH ändert und DELETE löscht.
Basis-URL
Alle Pfade in dieser Dokumentation beziehen sich auf folgende Basis-URL:
https://app.xcloud.eu/api/dns/v1
Die Zonenliste erreichst du zum Beispiel unter https://app.xcloud.eu/api/dns/v1/zones.
Authentifizierung
Die API authentifiziert Anfragen über API-Token. Einen Token erstellst du in der
Web-App im Reiter API-Token des DNS-Bereichs (siehe API-Token). Token
beginnen mit xcdns_ und werden nur beim Erstellen ein einziges Mal angezeigt. Bewahre
sie sicher auf, z. B. in einem Passwortmanager oder im Secret-Speicher deines CI-Systems.
Jeder Token gehört zu dem Projekt, in dem du ihn erstellt hast. Er wirkt nur auf die Zonen, Records, Domains und Kontakte dieses Projekts; die Pfade enthalten das Projekt deshalb nicht.
Schick den Token bei jeder Anfrage im Header Authorization mit:
export XCLOUD_DNS_TOKEN='xcdns_...'
curl https://app.xcloud.eu/api/dns/v1/zones \
-H "Authorization: Bearer $XCLOUD_DNS_TOKEN"
API-Token und Benachrichtigungen verwaltest du ausschließlich in der
Web-App. Ein API-Token hat darauf keinen Zugriff; solche Anfragen werden mit 403
abgelehnt.
Rechte
Jeder Token hat für drei Bereiche eine Zugriffsstufe: Kein Zugriff, Lesen oder Schreiben.
| Bereich | Umfasst |
|---|---|
| Records | Zonen, Records und delegierte Subdomains (/zones, /records) |
| Domains | Domains (/domains) |
| Kontakte | Kontakte (/handles) |
Schreiben schließt Lesen ein. Mit Lesen darf ein Token GET-Anfragen und die
Verfügbarkeitsprüfung für Domains (POST /domains/check) nutzen; alle anderen Anfragen
erfordern Schreiben.
Weitere Einschränkungen, die du pro Token festlegen kannst:
- Zonen: Ein auf ausgewählte Zonen beschränkter Token sieht nur diese Zonen und ihre
Records. Listen enthalten nur die erlaubten Zonen; Anfragen zu anderen Zonen werden mit
403abgelehnt. Ohne Einschränkung gilt der Token für alle Zonen, auch künftige. - IP-Allowlist: Ein Token mit IP-Allowlist wird nur von den eingetragenen IP-Adressen
oder CIDR-Bereichen aus akzeptiert; Anfragen von anderen Adressen werden mit
401abgelehnt. - Gültigkeit: Ein abgelaufener oder widerrufener Token wird wie ein fehlender oder
unbekannter Token mit
401abgelehnt.
Anfragen
- Schick Anfrage-Bodys als JSON mit dem Header
Content-Type: application/json. - Die meisten Anfrage-Bodys verpacken ihre Attribute in einem Objekt, das nach der
Ressource benannt ist, z. B.
{"zone": {...}},{"record": {...}},{"domain": {...}}oder{"handle": {...}}. - Ressourcen werden über ihre
id(einen UUID-String) angesprochen, nicht über ihren Namen. Wie du die ID zu einem Namen findest, steht unter Listen.
Antworten
Erfolgreiche Antworten haben den Status 200 und liefern ihren Inhalt in data:
{
"data": {
"id": "0b7c4f0e-2a51-4c4e-9a7f-5d3c1e8b9f10",
"name": "example.com",
"...": "..."
}
}
Zeitangaben sind im Format ISO 8601. Vollständige Beispielantworten findest du bei den einzelnen Ressourcen.
DELETE-Anfragen, die etwas löschen, liefern 200 ohne Inhalt. Das gilt für Zonen,
Records, Subdomains und Kontakte, ebenso für POST /zones/{zone_id}/records/bulk_destroy.
DELETE-Anfragen, die eine Funktion ausschalten oder eine Domain kündigen, liefern
dagegen die geänderte Ressource in data:
DELETE /domains/{id}undDELETE /domains/{id}/auto_renew(Domain kündigen)DELETE /domains/{id}/transfer_lock(Transfer-Lock entfernen)DELETE /zones/{id}/dnssec(DNSSEC ausschalten)DELETE /records/{id}/dyndns(DynDNS ausschalten)
DELETE /domains/bulk_auto_renew liefert wie alle Sammelaktionen für Domains die
Domains in data und abgelehnte Domains in errors (siehe
Sammelaktionen).
Listen
Listen liefern ein Array in data und sind immer vollständig: Es gibt keine
Seitenaufteilung und, abgesehen vom Parameter zone_id bei GET /records, keine Filter.
Um die ID einer Zone oder Domain anhand ihres Namens zu finden, lädst du die Liste und
suchst auf deiner Seite nach dem Namen, z. B. mit jq:
curl -s https://app.xcloud.eu/api/dns/v1/zones \
-H "Authorization: Bearer $XCLOUD_DNS_TOKEN" |
jq -r '.data[] | select(.name == "example.com") | .id'
Asynchrone Vorgänge
Manche Vorgänge laufen im Hintergrund. Die Antwort beschreibt dann den Zustand direkt nach der Anfrage; frag die Ressource später erneut ab, um das Ergebnis zu sehen:
- Zonen starten im Zustand
pendingund werdenactive, sobald sie auf den Nameservern eingerichtet sind. - Domain-Registrierungen, -Transfers und -Änderungen bearbeitet die Registry. Der
stateder Domain zeigt den Fortschritt (ordering,transfer_pending,update_pending, dannregisteredoderfailed). - DNSSEC-Signierung, Delegierungsprüfung und der Zonentransfer sekundärer Zonen werden in eine Warteschlange gestellt.
Record-Änderungen sind nach spätestens 60 Sekunden auf allen Nameservern aktiv.
Fehler
Fehler kommen mit einem HTTP-Statuscode und einem error-Objekt zurück:
| Status | Bedeutung |
|---|---|
400 |
Ein Pflichtparameter fehlt, oder eine Liste (z. B. von IDs) ist leer oder zu lang |
401 |
Kein gültiger Token, oder die Absenderadresse fehlt in der IP-Allowlist des Tokens |
402 |
Eine bestätigte Zahlungsmethode ist erforderlich |
403 |
Dem Token fehlt das nötige Recht oder die Zone, oder die Aktion ist nicht erlaubt |
404 |
Die Ressource existiert nicht oder gehört nicht zum Projekt des Tokens |
422 |
Die Anfrage ist ungültig, z. B. ein Validierungsfehler oder ein unzulässiger Zustand |
Ist DNS im Projekt des Tokens gesperrt, werden alle Anfragen mit 404 beantwortet.
Validierungsfehler (422) führen jedes Problem mit dem betroffenen Feld in name auf:
{
"error": {
"status": "422",
"errors": [
{ "name": "content", "message": "is not a valid IPv4 address" }
]
}
}
Allgemeine Fehler enthalten stattdessen eine message:
{
"error": {
"status": "403",
"message": "Forbidden"
}
}
Webhooks
xCloud kann deine eigene URL aufrufen, wenn sich bei deinen Domains und Zonen etwas
ereignet. Die Webhook-URL und die Ereignisse, für die xCloud sie aufruft, legst du in der
Web-App im Reiter Benachrichtigungen fest (siehe Benachrichtigungen).
Die URL muss mit https:// beginnen.
Für jedes Ereignis schickt xCloud eine POST-Anfrage mit dem Header
Content-Type: application/json und folgendem Body:
{
"event": "transfer_update",
"occurred_at": "2026-10-20T09:14:02+02:00",
"data": {
"domain": "example.com",
"status": "completed",
"detail": ""
}
}
event: Name des Ereignisses, siehe untenoccurred_at: Zeitpunkt des Ereignissesdata: Angaben zum Ereignis; welche Felder es enthält, hängt vom Ereignis ab
Ereignisse
In Klammern steht jeweils der Name des Ereignisses in der Web-App.
expiry(Domain läuft ab): Eine Domain, deren Auto-Renew ausgeschaltet ist, wird innerhalb der eingestellten Vorwarnzeit freigegeben. Das Ereignis kommt einmal pro Laufzeit. Felder:domain,expires_on(Datum der Freigabe).operation_failed(Verlängerung fehlgeschlagen): Die Bestellung einer Domain ist fehlgeschlagen. Felder:domain,operation(registration),detail(Fehlermeldung).delegation_broken(Delegierung gestört): Die Delegierungsprüfung einer Zone war bisher in Ordnung und findet jetzt andere Nameserver. Felder:zone,observed(die bei der Registry gefundenen Nameserver, durch Komma getrennt).transfer_update(Transfer-Status): Ein Transfer zu xCloud ist abgeschlossen (status:completed) oder ließ sich nicht starten (status:failed, Grund indetail). Felder:domain,status,detail.zone_changed(Zone geändert): Records einer Zone wurden angelegt, geändert, gelöscht oder importiert, in der Web-App oder per API. Felder:zone.dnssec_update(DNSSEC-Schlüssel läuft ab): xCloud hat die DS-Records einer über xCloud registrierten Domain bei der Registry veröffentlicht. Felder:zone,status(ds_published).
Signatur
Webhooks sind nicht signiert: Die Anfrage enthält weder eine Signatur noch Zugangsdaten. Verwende deshalb eine schwer zu erratende URL und behandle den Inhalt als Hinweis. Den verbindlichen Stand fragst du bei Bedarf über die API ab.
Preise
GET /prices liefert die Preise für Domains je Endung (TLD). Der Endpunkt ist
öffentlich und braucht keinen Token:
curl https://app.xcloud.eu/api/dns/v1/prices
Die Antwort enthält in data einen Eintrag pro Endung:
| Attribut | Beschreibung |
|---|---|
tld |
Endung ohne Punkt, z. B. de |
registration_fee |
Preis für die Registrierung |
transfer_fee |
Preis für den Transfer zu xCloud |
annual_fee |
Jährlicher Preis |
restore_fee |
Preis für die Wiederherstellung einer gelöschten Domain |
Die Preise kommen als Strings mit sechs Nachkommastellen oder als null, wenn für die
Endung kein Preis hinterlegt ist.