diff --git a/README.md b/README.md
index 9e64e61..eb12291 100644
--- a/README.md
+++ b/README.md
@@ -340,6 +340,7 @@ You don't have to do anything manually!
1. Yandex PDD API (https://pdd.yandex.ru)
1. Hurricane Electric DNS service (https://dns.he.net)
1. UnoEuro API (https://www.unoeuro.com/)
+1. INWX (https://www.inwx.de/)
And:
diff --git a/dnsapi/README.md b/dnsapi/README.md
index 8a486ae..c16e759 100644
--- a/dnsapi/README.md
+++ b/dnsapi/README.md
@@ -618,6 +618,23 @@ acme.sh --issue --dns dns_unoeuro -d example.com -d www.example.com
The `UNO_Key` and `UNO_User` will be saved in `~/.acme.sh/account.conf` and will be reused when needed.
+## 33. Use INWX
+
+[INWX](https://www.inwx.de/) offers an [xmlrpc api](https://www.inwx.de/de/help/apidoc) with your standard login credentials, set them like so:
+
+```
+export INWX_User="yourusername"
+export INWX_Password="password"
+```
+
+Then you can issue your certificates with:
+
+```
+acme.sh --issue --dns dns_inwx -d example.com -d www.example.com
+```
+
+The `INWX_User` and `INWX_Password` settings will be saved in `~/.acme.sh/account.conf` and will be reused when needed.
+
# Use custom API
If your API is not supported yet, you can write your own DNS API.
diff --git a/dnsapi/dns_inwx.sh b/dnsapi/dns_inwx.sh
new file mode 100755
index 0000000..74440bd
--- /dev/null
+++ b/dnsapi/dns_inwx.sh
@@ -0,0 +1,355 @@
+#!/usr/bin/env sh
+
+#
+#INWX_User="username"
+#
+#INWX_Password="password"
+
+INWX_Api="https://api.domrobot.com/xmlrpc/"
+
+######## Public functions #####################
+
+#Usage: add _acme-challenge.www.domain.com "XKrxpRBosdIKFzxW_CT3KLZNf6q0HG9i01zxXp5CPBs"
+dns_inwx_add() {
+ fulldomain=$1
+ txtvalue=$2
+
+ INWX_User="${INWX_User:-$(_readaccountconf_mutable INWX_User)}"
+ INWX_Password="${INWX_Password:-$(_readaccountconf_mutable INWX_Password)}"
+ if [ -z "$INWX_User" ] || [ -z "$INWX_Password" ]; then
+ INWX_User=""
+ INWX_Password=""
+ _err "You don't specify inwx user and password yet."
+ _err "Please create you key and try again."
+ return 1
+ fi
+
+ #save the api key and email to the account conf file.
+ _saveaccountconf_mutable INWX_User "$INWX_User"
+ _saveaccountconf_mutable INWX_Password "$INWX_Password"
+
+ _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"
+ _debug "Getting txt records"
+
+ xml_content=$(printf '
+
+ nameserver.info
+
+
+
+
+
+ domain
+
+ %s
+
+
+
+ type
+
+ TXT
+
+
+
+ name
+
+ %s
+
+
+
+
+
+
+ ' "$_domain" "$_sub_domain")
+ response="$(_post "$xml_content" "$INWX_Api" "" "POST")"
+
+ if ! printf "%s" "$response" | grep "Command completed successfully" >/dev/null; then
+ _err "Error could net get txt records"
+ return 1
+ fi
+
+ if ! printf "%s" "$response" | grep "count" >/dev/null; then
+ _info "Adding record"
+ _inwx_add_record "$_domain" "$_sub_domain" "$txtvalue"
+ else
+ _record_id=$(printf '%s' "$response" | _egrep_o '.*(record){1}(.*)([0-9]+){1}' | _egrep_o 'id<\/name>[0-9]+' | _egrep_o '[0-9]+')
+ _info "Updating record"
+ _inwx_update_record "$_record_id" "$txtvalue"
+ fi
+
+}
+
+#fulldomain txtvalue
+dns_inwx_rm() {
+
+ fulldomain=$1
+ txtvalue=$2
+
+ INWX_User="${INWX_User:-$(_readaccountconf_mutable INWX_User)}"
+ INWX_Password="${INWX_Password:-$(_readaccountconf_mutable INWX_Password)}"
+ if [ -z "$INWX_User" ] || [ -z "$INWX_Password" ]; then
+ INWX_User=""
+ INWX_Password=""
+ _err "You don't specify inwx user and password yet."
+ _err "Please create you key and try again."
+ return 1
+ fi
+
+ #save the api key and email to the account conf file.
+ _saveaccountconf_mutable INWX_User "$INWX_User"
+ _saveaccountconf_mutable INWX_Password "$INWX_Password"
+
+ _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"
+
+ _debug "Getting txt records"
+
+ xml_content=$(printf '
+
+ nameserver.info
+
+
+
+
+
+ domain
+
+ %s
+
+
+
+ type
+
+ TXT
+
+
+
+ name
+
+ %s
+
+
+
+
+
+
+ ' "$_domain" "$_sub_domain")
+ response="$(_post "$xml_content" "$INWX_Api" "" "POST")"
+
+ if ! printf "%s" "$response" | grep "Command completed successfully" >/dev/null; then
+ _err "Error could not get txt records"
+ return 1
+ fi
+
+ if ! printf "%s" "$response" | grep "count" >/dev/null; then
+ _info "Do not need to delete record"
+ else
+ _record_id=$(printf '%s' "$response" | _egrep_o '.*(record){1}(.*)([0-9]+){1}' | _egrep_o 'id<\/name>[0-9]+' | _egrep_o '[0-9]+')
+ _info "Deleting record"
+ _inwx_delete_record "$_record_id"
+ fi
+
+}
+
+#################### Private functions below ##################################
+
+_inwx_login() {
+
+ xml_content=$(printf '
+
+ account.login
+
+
+
+
+
+ user
+
+ %s
+
+
+
+ pass
+
+ %s
+
+
+
+
+
+
+ ' $INWX_User $INWX_Password)
+
+ response="$(_post "$xml_content" "$INWX_Api" "" "POST")"
+
+ printf "Cookie: %s" "$(grep "domrobot=" "$HTTP_HEADER" | grep "^Set-Cookie:" | _tail_n 1 | _egrep_o 'domrobot=[^;]*;' | tr -d ';')"
+
+}
+
+_get_root() {
+ domain=$1
+ _debug "get root"
+
+ domain=$1
+ i=2
+ p=1
+
+ _H1=$(_inwx_login)
+ export _H1
+ xml_content='
+
+ nameserver.list
+ '
+
+ response="$(_post "$xml_content" "$INWX_Api" "" "POST")"
+ while true; do
+ h=$(printf "%s" "$domain" | cut -d . -f $i-100)
+ _debug h "$h"
+ if [ -z "$h" ]; then
+ #not valid
+ return 1
+ fi
+
+ if _contains "$response" "$h"; then
+ _sub_domain=$(printf "%s" "$domain" | cut -d . -f 1-$p)
+ _domain="$h"
+ return 0
+ fi
+ p=$i
+ i=$(_math "$i" + 1)
+ done
+ return 1
+
+}
+
+_inwx_delete_record() {
+ record_id=$1
+ xml_content=$(printf '
+
+ nameserver.deleteRecord
+
+
+
+
+
+ id
+
+ %s
+
+
+
+
+
+
+ ' "$record_id")
+
+ response="$(_post "$xml_content" "$INWX_Api" "" "POST")"
+
+ if ! printf "%s" "$response" | grep "Command completed successfully" >/dev/null; then
+ _err "Error"
+ return 1
+ fi
+ return 0
+
+}
+
+_inwx_update_record() {
+ record_id=$1
+ txtval=$2
+ xml_content=$(printf '
+
+ nameserver.updateRecord
+
+
+
+
+
+ content
+
+ %s
+
+
+
+ id
+
+ %s
+
+
+
+
+
+
+ ' "$txtval" "$record_id")
+
+ response="$(_post "$xml_content" "$INWX_Api" "" "POST")"
+
+ if ! printf "%s" "$response" | grep "Command completed successfully" >/dev/null; then
+ _err "Error"
+ return 1
+ fi
+ return 0
+
+}
+
+_inwx_add_record() {
+
+ domain=$1
+ sub_domain=$2
+ txtval=$3
+
+ xml_content=$(printf '
+
+ nameserver.createRecord
+
+
+
+
+
+ domain
+
+ %s
+
+
+
+ type
+
+ TXT
+
+
+
+ content
+
+ %s
+
+
+
+ name
+
+ %s
+
+
+
+
+
+
+ ' "$domain" "$txtval" "$sub_domain")
+
+ response="$(_post "$xml_content" "$INWX_Api" "" "POST")"
+
+ if ! printf "%s" "$response" | grep "Command completed successfully" >/dev/null; then
+ _err "Error"
+ return 1
+ fi
+ return 0
+}