DNS-API-Referenz

Skriptgesteuerter Zugriff für Let's Encrypt DNS-01, certbot, acme.sh, eigene Automatisierung.

Typischer Anwendungsfall: Wildcard-Zertifikate per Let's Encrypt automatisiert ausstellen, ohne dass dein Host vom Internet erreichbar sein muss. Wir validieren die Domain über einen TXT-Record (DNS-01) in deiner Zone bei uns.

1. Authentifizierung

Alle Endpunkte erwarten einen API-Token. Token werden im Kundenportal → Profil → API-Token erstellt.

  • Token-Format: hm_<16 Zeichen>_<32 Zeichen>
  • Wichtig: Das geheime Token wird nur einmal angezeigt — direkt nach der Erstellung.
  • Verwende für jedes Skript / jeden Host einen separaten Token (granularer Widerruf).

Beide Header-Varianten sind gleichwertig:

curl
# Variante A — eigener Header
curl -H "X-API-Token: hm_xxx_yyy" http://127.0.0.1:8899/api/v1/dns/records?name=test.example.com

# Variante B — Standard-Bearer
curl -H "Authorization: Bearer hm_xxx_yyy" http://127.0.0.1:8899/api/v1/dns/records?name=test.example.com

Scopes

ScopeBedeutung
dns:readDNS-Records lesen
dns:writeAnlegen, Ändern, Löschen (TXT, A, AAAA, CNAME, MX, SRV, CAA, TLSA, SSHFP)

Für certbot / acme.sh: dns:write reicht.

2. Endpunkte

Basis-URL: http://127.0.0.1:8899/api

2.1 — ACME DNS-01-Challenge anlegen

POST /api/v1/dns/acme-challenge
curl -X POST "http://127.0.0.1:8899/api/v1/dns/acme-challenge" \
  -H "X-API-Token: hm_xxx_yyy" \
  -H "Content-Type: application/json" \
  -d '{
    "domain": "irc.example.com",
    "value":  "AbCdEf...",
    "ttl":    60
  }'

Legt automatisch _acme-challenge.irc.example.com TXT "AbCdEf..." an.

Response 200
{
  "success": true,
  "name":    "_acme-challenge.irc.example.com",
  "value":   "AbCdEf...",
  "zone":    "example.com",
  "ttl":     60
}

2.2 — ACME DNS-01-Challenge löschen (Cleanup)

DELETE /api/v1/dns/acme-challenge
curl -X DELETE "http://127.0.0.1:8899/api/v1/dns/acme-challenge" \
  -H "X-API-Token: hm_xxx_yyy" \
  -H "Content-Type: application/json" \
  -d '{
    "domain": "irc.example.com",
    "value":  "AbCdEf..."
  }'

Ohne value: gesamtes rrset wird gelöscht. Bei paralleler Issuance immer den konkreten value mitgeben.

2.3 — Generisches DNS-Record-Management

Funktioniert für TXT, A, AAAA, CNAME, MX, SRV, CAA, TLSA, SSHFP:

POST /api/v1/dns/records
curl -X POST "http://127.0.0.1:8899/api/v1/dns/records" \
  -H "X-API-Token: hm_xxx_yyy" \
  -H "Content-Type: application/json" \
  -d '{
    "name":    "_acme-challenge.irc.example.com",
    "type":    "TXT",
    "content": "AbCdEf...",
    "ttl":     60
  }'
GET /api/v1/dns/records
curl "http://127.0.0.1:8899/api/v1/dns/records?name=_acme-challenge.irc.example.com&type=TXT" \
  -H "X-API-Token: hm_xxx_yyy"
DELETE /api/v1/dns/records
curl -X DELETE "http://127.0.0.1:8899/api/v1/dns/records" \
  -H "X-API-Token: hm_xxx_yyy" \
  -H "Content-Type: application/json" \
  -d '{
    "name":    "_acme-challenge.irc.example.com",
    "type":    "TXT",
    "content": "AbCdEf..."
  }'

2.4 — TLSA / DANE automatisiert aktualisieren

Ideal, um nach einem Zertifikats-/Schlüsselwechsel (z.B. Mailserver) den TLSA-Record automatisch zu setzen. Format des content: <usage> <selector> <matching-type> <hash> — z.B. 3 1 1 <SHA256-SPKI-Hash>.

POST /api/v1/dns/records — TLSA
curl -X POST "http://127.0.0.1:8899/api/v1/dns/records" \
  -H "X-API-Token: hm_xxx_yyy" \
  -H "Content-Type: application/json" \
  -d '{
    "name":    "_25._tcp.mail.example.com",
    "type":    "TLSA",
    "content": "3 1 1 <SHA256-SPKI-Hash>",
    "ttl":     3600
  }'

Anhängen (Standard): Der neue Hash wird an den bestehenden rrset angehängt — so kannst du beim Rollover nach DANE-Best-Practice alten und neuen Hash gleichzeitig veröffentlichen. Gleicher Inhalt wird dedupliziert (idempotent, retry-sicher).

Ersetzen: Mit "replace": true im Body wird der komplette TLSA-rrset dieses Namens durch genau diesen einen Record ersetzt — praktisch für einen einfachen „alt gegen neu"-Tausch.

TLSA — einfacher Swap (replace)
curl -X POST "http://127.0.0.1:8899/api/v1/dns/records" \
  -H "X-API-Token: hm_xxx_yyy" \
  -H "Content-Type: application/json" \
  -d '{
    "name":    "_25._tcp.mail.example.com",
    "type":    "TLSA",
    "content": "3 1 1 <NEUER-Hash>",
    "replace": true
  }'
TLSA — alten Hash gezielt entfernen
curl -X DELETE "http://127.0.0.1:8899/api/v1/dns/records" \
  -H "X-API-Token: hm_xxx_yyy" \
  -H "Content-Type: application/json" \
  -d '{
    "name":    "_25._tcp.mail.example.com",
    "type":    "TLSA",
    "content": "3 1 1 <ALTER-Hash>"
  }'

3. Vollständiges certbot-Beispiel

Zwei Hook-Skripte:

auth-hook.sh

auth-hook.sh
#!/usr/bin/env bash
curl -fs -X POST "http://127.0.0.1:8899/api/v1/dns/acme-challenge" \
  -H "X-API-Token: $HM_TOKEN" \
  -H "Content-Type: application/json" \
  -d "{\"domain\":\"$CERTBOT_DOMAIN\",\"value\":\"$CERTBOT_VALIDATION\",\"ttl\":60}"
# DNS-Propagation abwarten
sleep 30

cleanup-hook.sh

cleanup-hook.sh
#!/usr/bin/env bash
curl -fs -X DELETE "http://127.0.0.1:8899/api/v1/dns/acme-challenge" \
  -H "X-API-Token: $HM_TOKEN" \
  -H "Content-Type: application/json" \
  -d "{\"domain\":\"$CERTBOT_DOMAIN\",\"value\":\"$CERTBOT_VALIDATION\"}"

Zertifikat anfordern:

certbot
chmod +x auth-hook.sh cleanup-hook.sh
HM_TOKEN=hm_xxx_yyy certbot certonly \
  --manual --preferred-challenges dns \
  --manual-auth-hook ./auth-hook.sh \
  --manual-cleanup-hook ./cleanup-hook.sh \
  -d irc.example.com -d '*.irc.example.com'

4. acme.sh-Beispiel (empfohlen)

acme.sh ist deutlich schlanker und bringt einen eingebauten Renew-Cron mit. Custom-DNS-Hook einrichten:

acme.sh-Hook
# acme.sh installieren
curl https://get.acme.sh | sh -s email=du@as.gmbh

# Custom-Hook anlegen
mkdir -p ~/.acme.sh/dnsapi
cat > ~/.acme.sh/dnsapi/dns_hostmaster.sh <<'EOF'
dns_hostmaster_add() {
  curl -fs -X POST "http://127.0.0.1:8899/api/v1/dns/acme-challenge" \
    -H "X-API-Token: $HM_TOKEN" -H "Content-Type: application/json" \
    -d "{\"domain\":\"${1#_acme-challenge.}\",\"value\":\"$2\",\"ttl\":60}"
}
dns_hostmaster_rm() {
  curl -fs -X DELETE "http://127.0.0.1:8899/api/v1/dns/acme-challenge" \
    -H "X-API-Token: $HM_TOKEN" -H "Content-Type: application/json" \
    -d "{\"domain\":\"${1#_acme-challenge.}\",\"value\":\"$2\"}"
}
EOF

# Zertifikat holen
export HM_TOKEN=hm_xxx_yyy
~/.acme.sh/acme.sh --issue --dns dns_hostmaster \
  -d deine-domain.de -d '*.deine-domain.de'

5. Fehler-Codes

StatusBedeutung
401Token fehlt, ist widerrufen oder abgelaufen
403Token hat nicht den nötigen Scope (z.B. dns:write fehlt)
404Zone nicht gefunden bzw. nicht im Eigentum des Token-Inhabers
502PowerDNS-Backend hat einen Fehler zurückgegeben

6. Sicherheits-Hinweise

  • Behandle den Token wie ein Passwort. Niemals in öffentliche Repos commiten. Verwende Umgebungsvariablen oder Secret-Manager.
  • Nutze separate Tokens für unterschiedliche Hosts oder Skripte — beim Widerruf eines kompromittierten Tokens bleiben die anderen aktiv.
  • Beschränke den Scope auf das Minimum (dns:read reicht für Monitoring/Backups).
  • Last-Used-Tracking: Jeder API-Call aktualisiert last_used_at. Im API-Token-Panel kannst du tote Token erkennen und löschen.

Bereit anzufangen?

Erstelle deinen ersten API-Token im Kundenportal.

Cookie-Einstellungen

Wir verwenden Cookies für Grundfunktionen sowie optional für Komfort, Statistik und Marketing.

Sie können Ihre Auswahl anpassen. Sie können Ihre Einwilligung jederzeit hier ändern.