diff --git a/dnsapi/dns_sdns.sh b/dnsapi/dns_sdns.sh
new file mode 100644
index 00000000..581d3a3d
--- /dev/null
+++ b/dnsapi/dns_sdns.sh
@@ -0,0 +1,128 @@
+#!/usr/bin/env sh
+
+# s-dns is the Domain Name Registration System of Kyberio GmbH, former Hostway Deutschland GmbH
+
+# Steps to order a * certificate:
+# First log in into the domain robot, enable the dynamic DNS password for your zone and click save.
+
+# Copy the password and set the SDNS_ZONE_KEY variable with
+# export SDNS_ZONE_KEY=your_zone_key
+
+#
+# ./acme.sh --issue -d '*.www.domain.com' --dns dns_sdns --server letsencrypt --dnssleep 240
+
+SDNS_API_URL="https://robot.s-dns.de:8488/"
+
+
+######## Public functions #####################
+
+# Adds a txt record with the specified value. Does not remove an existing record
+# Usage: dns_sdns_add _acme-challenge.www.domain.com "XKrxpRBosdIKFzxW_CT3KLZNf6q0HG9i01zxXp5CPBs"
+dns_sdns_add() {
+ fulldomain=$1
+ txtvalue=$2
+ _debug2 "dns_sdns_add() entered"
+ SDNS_ZONE_KEY="${SDNS_ZONE_KEY:-$(_readaccountconf_mutable SDNS_ZONE_KEY)}"
+ if [ -z "$SDNS_ZONE_KEY" ]; then
+ SDNS_ZONE_KEY=""
+ _err "You didn't specify your zone key yet. (export SDNS_ZONE_KEY=yourkey)"
+ return 1
+ fi
+ _saveaccountconf_mutable SDNS_ZONE_KEY "$SDNS_ZONE_KEY"
+ _debug "First detect the root zone"
+ if ! _get_root "$fulldomain"; then
+ _err "invalid domain"
+ return 1
+ fi
+ _debug _sub_domain "$_sub_domain"
+ _debug _domain "$_domain"
+ _payload="
+
+
+
+
+"
+ _debug2 "$_payload"
+ response=$(_post "$_payload" "$SDNS_API_URL")
+ _debug2 "$response"
+ if _contains "$response" "status=\"OK\""; then
+ _debug "The TXT record has been added."
+ return 0
+ else
+ _err "The attempt to add the TXT record has failed."
+ return 1
+ fi
+}
+
+# Removes a txt record with the specified value. This function does not remove resource records with the same name but a different values.
+# Usage: dns_sdns_rm _acme-challenge.www.domain.com "XKrxpRBosdIKFzxW_CT3KLZNf6q0HG9i01zxXp5CPBs"
+dns_sdns_rm() {
+ fulldomain=$1
+ txtvalue=$2
+ _debug2 "dns_sdns_rm() entered"
+ SDNS_ZONE_KEY="${SDNS_ZONE_KEY:-$(_readaccountconf_mutable SDNS_ZONE_KEY)}"
+ if [ -z "$SDNS_ZONE_KEY" ]; then
+ SDNS_ZONE_KEY=""
+ _err "You didn't specify your zone key yet. (export SDNS_ZONE_KEY=yourkey)"
+ return 1
+ fi
+ _saveaccountconf_mutable SDNS_ZONE_KEY "$SDNS_ZONE_KEY"
+ _debug "First detect the root zone"
+ if ! _get_root "$fulldomain"; then
+ _err "invalid domain"
+ return 1
+ fi
+ _debug _sub_domain "$_sub_domain"
+ _debug _domain "$_domain"
+ _payload="
+
+
+
+
+"
+ _debug "$_payload"
+ response=$(_post "$_payload" "$SDNS_API_URL")
+ _debug "$response"
+ if _contains "$response" "status=\"OK\""; then
+ _debug "The TXT record has been deleted."
+ return 0
+ else
+ _err "The attempt to delete the TXT record has failed."
+ return 1
+ fi
+}
+
+#################### Private functions below ##################################
+#_acme-challenge.www.domain.com
+
+#returns
+# _sub_domain=_acme-challenge.www
+# _domain=domain.com
+_get_root() {
+ fulldomain=$1
+ _debug2 "_get_root() entered"
+ SDNS_ZONE_KEY="${SDNS_ZONE_KEY:-$(_readaccountconf_mutable SDNS_ZONE_KEY)}"
+ if [ -z "$SDNS_ZONE_KEY" ]; then
+ SDNS_ZONE_KEY=""
+ _err "You didn't specify your zone key yet. (export SDNS_ZONE_KEY=yourkey)"
+ return 1
+ fi
+ _saveaccountconf_mutable SDNS_ZONE_KEY "$SDNS_ZONE_KEY"
+ _payload="
+
+ $fulldomain
+"
+ _debug2 "$_payload"
+ response=$(_post "$_payload" "$SDNS_API_URL")
+ _debug2 "$response"
+ if _contains "$response" "status=\"found\""; then
+ _debug "root domain is found"
+
+ _domain=$(printf "%s\n" "$response" | _egrep_o "(.*)" | cut -d ">" -f 2 | cut -d "<" -f 1)
+ _sub_domain=$(printf "%s\n" "$response" | _egrep_o "(.*)" | cut -d ">" -f 2 | cut -d "<" -f 1)
+
+ _debug _domain "$_domain"
+ _debug _sub_domain "$_sub_domain"
+ return 0
+ fi
+}