diff --git a/dnsapi/dns_subreg.sh b/dnsapi/dns_subreg.sh
new file mode 100644
index 00000000..944a51ff
--- /dev/null
+++ b/dnsapi/dns_subreg.sh
@@ -0,0 +1,219 @@
+#!/usr/bin/env sh
+# shellcheck disable=SC2034
+dns_subreg_info='Subreg.cz
+Site: subreg.cz
+Docs: github.com/acmesh-official/acme.sh/wiki/dnsapi2#dns_subreg
+Options:
+ SUBREG_API_USERNAME API username
+ SUBREG_API_PASSWORD API password
+Author: Tomas Pavlic <@tomaspavli>
+'
+
+# Subreg SOAP API
+# https://subreg.cz/manual/
+
+SUBREG_API_URL="https://soap.subreg.cz/cmd.php"
+
+######## Public functions #####################
+
+# Usage: dns_subreg_add _acme-challenge.www.domain.com "XKrxpRBosdIKFzxW_CT3KLZNf6q0HG9i01zxXp5CPBs"
+dns_subreg_add() {
+ fulldomain=$1
+ txtvalue=$2
+
+ SUBREG_API_USERNAME="${SUBREG_API_USERNAME:-$(_readaccountconf_mutable SUBREG_API_USERNAME)}"
+ SUBREG_API_PASSWORD="${SUBREG_API_PASSWORD:-$(_readaccountconf_mutable SUBREG_API_PASSWORD)}"
+ if [ -z "$SUBREG_API_USERNAME" ] || [ -z "$SUBREG_API_PASSWORD" ]; then
+ _err "SUBREG_API_USERNAME and SUBREG_API_PASSWORD are not set."
+ return 1
+ fi
+
+ _saveaccountconf_mutable SUBREG_API_USERNAME "$SUBREG_API_USERNAME"
+ _saveaccountconf_mutable SUBREG_API_PASSWORD "$SUBREG_API_PASSWORD"
+
+ if ! _subreg_login; then
+ return 1
+ fi
+
+ if ! _get_root "$fulldomain"; then
+ _err "Cannot determine root domain for: $fulldomain"
+ return 1
+ fi
+
+ _debug _sub_domain "$_sub_domain"
+ _debug _domain "$_domain"
+
+ _subreg_soap "Add_DNS_Record" "$_domain$_sub_domainTXT$txtvalue0120"
+ if _subreg_ok; then
+ _record_id="$(_subreg_map_get record_id)"
+ _savedomainconf "SUBREG_RECORD_ID" "$_record_id"
+ return 0
+ fi
+ _err "Failed to add TXT record."
+ _err "$response"
+ return 1
+}
+
+# Usage: dns_subreg_rm _acme-challenge.www.domain.com "XKrxpRBosdIKFzxW_CT3KLZNf6q0HG9i01zxXp5CPBs"
+dns_subreg_rm() {
+ fulldomain=$1
+ txtvalue=$2
+
+ SUBREG_API_USERNAME="${SUBREG_API_USERNAME:-$(_readaccountconf_mutable SUBREG_API_USERNAME)}"
+ SUBREG_API_PASSWORD="${SUBREG_API_PASSWORD:-$(_readaccountconf_mutable SUBREG_API_PASSWORD)}"
+ if [ -z "$SUBREG_API_USERNAME" ] || [ -z "$SUBREG_API_PASSWORD" ]; then
+ _err "SUBREG_API_USERNAME and SUBREG_API_PASSWORD are not set."
+ return 1
+ fi
+
+ if ! _subreg_login; then
+ return 1
+ fi
+
+ if ! _get_root "$fulldomain"; then
+ _err "Cannot determine root domain for: $fulldomain"
+ return 1
+ fi
+
+ _debug _sub_domain "$_sub_domain"
+ _debug _domain "$_domain"
+
+ _record_id="$(_readdomainconf "SUBREG_RECORD_ID")"
+ if [ -z "$_record_id" ]; then
+ _err "Could not find saved record ID for $fulldomain"
+ return 1
+ fi
+ _cleardomainconf "SUBREG_RECORD_ID"
+
+ _debug "Deleting record ID: $_record_id"
+ _subreg_soap "Delete_DNS_Record" "$_domain$_record_id"
+ if _subreg_ok; then
+ return 0
+ fi
+ _err "Failed to delete TXT record."
+ _err "$response"
+ return 1
+}
+
+#################### Private functions #####################
+
+# Check if the current $response contains a successful status in the ns2:Map format:
+# - statusok
+_subreg_ok() {
+ [ "$(_subreg_map_get status)" = "ok" ]
+}
+
+# Extract the value for a given key from the ns2:Map response.
+# Usage: _subreg_map_get keyname
+# Reads from $response
+_subreg_map_get() {
+ _key="$1"
+ echo "$response" | tr -d '\n\r' | \
+ _egrep_o ">${_key}]*>[^<]*" | \
+ sed 's/.*]*>//;s/<\/value>//'
+}
+
+# Login and store session token in _subreg_ssid
+_subreg_login() {
+ _debug "Logging in to Subreg API as $SUBREG_API_USERNAME"
+ _subreg_soap_noauth "Login" "$SUBREG_API_USERNAME$SUBREG_API_PASSWORD"
+ if ! _subreg_ok; then
+ _err "Subreg login failed."
+ _err "$response"
+ return 1
+ fi
+ _subreg_ssid="$(_subreg_map_get ssid)"
+ if [ -z "$_subreg_ssid" ]; then
+ _err "Subreg login: could not extract session token (ssid)."
+ return 1
+ fi
+ _debug "_subreg_ssid" "$_subreg_ssid"
+ return 0
+}
+
+# _get_root _acme-challenge.www.domain.com
+# returns _sub_domain and _domain
+_get_root() {
+ domain=$1
+ i=1
+ p=1
+
+ while true; do
+ h=$(printf "%s" "$domain" | cut -d . -f "$i"-100)
+ if [ -z "$h" ]; then
+ return 1
+ fi
+
+ _subreg_soap "Get_DNS_Zone" "$h"
+
+ if _subreg_ok; then
+ _sub_domain=$(printf "%s" "$domain" | cut -d . -f 1-"$p")
+ _domain="$h"
+ return 0
+ fi
+
+ p=$i
+ i=$(_math "$i" + 1)
+ done
+ _err "Unable to retrieve DNS zone matching domain: $domain"
+ return 1
+}
+
+# Send a SOAP request without authentication (used for Login)
+# _subreg_soap_noauth command inner_xml
+_subreg_soap_noauth() {
+ _cmd="$1"
+ _inner="$2"
+
+ _soap_body="
+
+
+
+
+ ${_inner}
+
+
+
+"
+
+ export _H1="Content-Type: text/xml"
+ export _H2="SOAPAction: http://soap.subreg.cz/soap#${_cmd}"
+ response="$(_post "$_soap_body" "$SUBREG_API_URL" "" "POST" "text/xml")"
+ _debug2 "response" "$response"
+}
+
+# Send an authenticated SOAP request (requires _subreg_ssid to be set)
+# _subreg_soap command inner_xml
+_subreg_soap() {
+ _cmd="$1"
+ _inner="$2"
+
+ _soap_body="
+
+
+
+
+ ${_subreg_ssid}
+ ${_inner}
+
+
+
+"
+
+ export _H1="Content-Type: text/xml"
+ export _H2="SOAPAction: http://soap.subreg.cz/soap#${_cmd}"
+ response="$(_post "$_soap_body" "$SUBREG_API_URL" "" "POST" "text/xml")"
+ _debug2 "response" "$response"
+}