Repository: go-acme/lego
Pull request #1890 (2023-04-12 05:32:04)

Add Brandit.com as DNS provider
Adds support for the [Brandit](https://brandit.com/) DNS provider.

Fixes #1876


The company I work for is a customer of Brandit and are willing to set aside resources to maintain this provider


Output of command, example.com was replaced with example.<domain>.com and parts are masked

```console
$ ./lego -m XXXXX@XXXXX.com --dns brandit -d "*.example.XXXXX.com" -d example.XXXXX.com -s https://acme-staging-v02.api.letsencrypt.org/directory run
2023/04/11 09:39:05 No key found for account XXXXX@XXXXX.com. Generating a P256 key.
2023/04/11 09:39:05 Saved key to /Users/XXXXX/XXXXX/lego/dist/.lego/accounts/acme-staging-v02.api.letsencrypt.org/XXXXX@XXXXX.com/keys/XXXXX@XXXXX.com.key
2023/04/11 09:39:06 Please review the TOS at https://letsencrypt.org/documents/LE-SA-v1.3-September-21-2022.pdf
Do you accept the TOS? Y/n
Y
2023/04/11 09:39:08 [INFO] acme: Registering account for XXXXX@XXXXX.com
!!!! HEADS UP !!!!

Your account credentials have been saved in your Let's Encrypt
configuration directory at "/Users/XXXXX/XXXXX/lego/dist/.lego/accounts".

You should make a secure backup of this folder now. This
configuration directory will also contain certificates and
private keys obtained from Let's Encrypt so making regular
backups of this folder is ideal.
2023/04/11 09:39:08 [INFO] [*.example.XXXXX.com, example.XXXXX.com] acme: Obtaining bundled SAN certificate
2023/04/11 09:39:09 [INFO] [*.example.XXXXX.com] AuthURL: https://acme-staging-v02.api.letsencrypt.org/acme/authz-v3/6078251564
2023/04/11 09:39:09 [INFO] [example.XXXXX.com] AuthURL: https://acme-staging-v02.api.letsencrypt.org/acme/authz-v3/6078251574
2023/04/11 09:39:09 [INFO] [*.example.XXXXX.com] acme: use dns-01 solver
2023/04/11 09:39:09 [INFO] [example.XXXXX.com] acme: Could not find solver for: tls-alpn-01
2023/04/11 09:39:09 [INFO] [example.XXXXX.com] acme: Could not find solver for: http-01
2023/04/11 09:39:09 [INFO] [example.XXXXX.com] acme: use dns-01 solver
2023/04/11 09:39:09 [INFO] [*.example.XXXXX.com] acme: Preparing to solve DNS-01
2023/04/11 09:39:20 [INFO] [*.example.XXXXX.com] acme: Trying to solve DNS-01
2023/04/11 09:39:20 [INFO] [*.example.XXXXX.com] acme: Checking DNS record propagation using [10.145.42.15:53 10.45.0.11:53 10.45.0.12:53]
2023/04/11 09:39:22 [INFO] Wait for propagation [timeout: 30m0s, interval: 2s]
2023/04/11 09:42:58 [INFO] [*.example.XXXXX.com] acme: Waiting for DNS record propagation.
.
.
.
2023/04/11 09:44:21 [INFO] [*.example.XXXXX.com] acme: Waiting for DNS record propagation.
2023/04/11 09:44:27 [INFO] [*.example.XXXXX.com] The server validated our request
2023/04/11 09:44:27 [INFO] [*.example.XXXXX.com] acme: Cleaning DNS-01 challenge
2023/04/11 09:44:36 [INFO] sequence: wait for 0s
2023/04/11 09:44:36 [INFO] [example.XXXXX.com] acme: Preparing to solve DNS-01
2023/04/11 09:44:50 [INFO] [example.XXXXX.com] acme: Trying to solve DNS-01
2023/04/11 09:44:50 [INFO] [example.XXXXX.com] acme: Checking DNS record propagation using [10.145.42.15:53 10.45.0.11:53 10.45.0.12:53]
2023/04/11 09:44:52 [INFO] Wait for propagation [timeout: 30m0s, interval: 2s]
2023/04/11 09:44:53 [INFO] [example.XXXXX.com] acme: Waiting for DNS record propagation.
.
.
.
2023/04/11 09:46:23 [INFO] [example.XXXXX.com] acme: Waiting for DNS record propagation.
2023/04/11 09:46:29 [INFO] [example.XXXXX.com] The server validated our request
2023/04/11 09:46:29 [INFO] [example.XXXXX.com] acme: Cleaning DNS-01 challenge
2023/04/11 09:46:39 [INFO] [*.example.XXXXX.com, example.XXXXX.com] acme: Validations succeeded; requesting certificates
2023/04/11 09:46:40 [INFO] Wait for certificate [timeout: 30s, interval: 500ms]
2023/04/11 09:46:41 [INFO] [*.example.XXXXX.com] Server responded with a certificate.
```

ldez: there is still this one https://github.com/go-acme/lego/pull/1890#discussion_r1165105495
Andrei-Predoiu: Question, The default timeout is usually not enough. Should i do anything about that like leave a message or set a different default?
ldez: You can set the best default for the provider.
Andrei-Predoiu: I think this is everything.
ldez: can you also give me the "new" output of the following command:
```
./lego -m your@email.com --dns YOUR_PROVIDER_NAME -d *.example.com -d example.com -s https://acme-staging-v02.api.letsencrypt.org/directory run
```
Andrei-Predoiu: > ./lego -m xxxx@xxxxx.com --dns brandit -d "*.example.xxxxx.com" -d example.xxxxx.com -s https://acme-staging-v02.api.letsencrypt.org/directory run

```
lego -m asdd@xxxxxxx.com.com --dns brandit -d "*.example.xxxxxxx.com" -d example.xxxxxxx.com -s https://acme-staging-v02.api.letsencrypt.org/directory run
2023/04/13 18:29:51 Please review the TOS at https://letsencrypt.org/documents/LE-SA-v1.3-September-21-2022.pdf
Do you accept the TOS? Y/n
Y
2023/04/13 18:29:53 [INFO] acme: Registering account for  xxxx@xxxxx.com
!!!! HEADS UP !!!!

Your account credentials have been saved in your Let's Encrypt
configuration directory at "/mnt/e/dev/src/github.com/xxxxxxx/lego/.lego/accounts".

You should make a secure backup of this folder now. This
configuration directory will also contain certificates and
private keys obtained from Let's Encrypt so making regular
backups of this folder is ideal.
2023/04/13 18:29:53 [INFO] [*.example.xxxxxxx.com, example.xxxxxxx.com] acme: Obtaining bundled SAN certificate
2023/04/13 18:29:54 [INFO] [*.example.xxxxxxx.com] AuthURL: https://acme-staging-v02.api.letsencrypt.org/acme/authz-v3/6106562984
2023/04/13 18:29:54 [INFO] [example.xxxxxxx.com] AuthURL: https://acme-staging-v02.api.letsencrypt.org/acme/authz-v3/6106562994
2023/04/13 18:29:54 [INFO] [*.example.xxxxxxx.com] acme: use dns-01 solver
2023/04/13 18:29:54 [INFO] [example.xxxxxxx.com] acme: Could not find solver for: tls-alpn-01
2023/04/13 18:29:54 [INFO] [example.xxxxxxx.com] acme: Could not find solver for: http-01
2023/04/13 18:29:54 [INFO] [example.xxxxxxx.com] acme: use dns-01 solver
2023/04/13 18:29:54 [INFO] [*.example.xxxxxxx.com] acme: Preparing to solve DNS-01
2023/04/13 18:30:23 [INFO] [example.xxxxxxx.com] acme: Preparing to solve DNS-01
2023/04/13 18:30:34 [INFO] [*.example.xxxxxxx.com] acme: Trying to solve DNS-01
2023/04/13 18:30:34 [INFO] [*.example.xxxxxxx.com] acme: Checking DNS record propagation using [172.25.96.1:53]
2023/04/13 18:30:36 [INFO] Wait for propagation [timeout: 30m0s, interval: 2s]
2023/04/13 18:30:36 [INFO] [*.example.xxxxxxx.com] acme: Waiting for DNS record propagation.
2023/04/13 18:30:38 [INFO] [*.example.xxxxxxx.com] acme: Waiting for DNS record propagation.
2023/04/13 18:30:41 [INFO] [*.example.xxxxxxx.com] acme: Waiting for DNS record propagation.
2023/04/13 18:30:43 [INFO] [*.example.xxxxxxx.com] acme: Waiting for DNS record propagation.
2023/04/13 18:30:45 [INFO] [*.example.xxxxxxx.com] acme: Waiting for DNS record propagation.
2023/04/13 18:30:47 [INFO] [*.example.xxxxxxx.com] acme: Waiting for DNS record propagation.
2023/04/13 18:30:50 [INFO] [*.example.xxxxxxx.com] acme: Waiting for DNS record propagation.
2023/04/13 18:30:52 [INFO] [*.example.xxxxxxx.com] acme: Waiting for DNS record propagation.
2023/04/13 18:30:54 [INFO] [*.example.xxxxxxx.com] acme: Waiting for DNS record propagation.
2023/04/13 18:30:56 [INFO] [*.example.xxxxxxx.com] acme: Waiting for DNS record propagation.
2023/04/13 18:30:59 [INFO] [*.example.xxxxxxx.com] acme: Waiting for DNS record propagation.
2023/04/13 18:31:01 [INFO] [*.example.xxxxxxx.com] acme: Waiting for DNS record propagation.
2023/04/13 18:31:03 [INFO] [*.example.xxxxxxx.com] acme: Waiting for DNS record propagation.
2023/04/13 18:31:05 [INFO] [*.example.xxxxxxx.com] acme: Waiting for DNS record propagation.
2023/04/13 18:31:08 [INFO] [*.example.xxxxxxx.com] acme: Waiting for DNS record propagation.
2023/04/13 18:31:10 [INFO] [*.example.xxxxxxx.com] acme: Waiting for DNS record propagation.
2023/04/13 18:31:12 [INFO] [*.example.xxxxxxx.com] acme: Waiting for DNS record propagation.
2023/04/13 18:31:14 [INFO] [*.example.xxxxxxx.com] acme: Waiting for DNS record propagation.
2023/04/13 18:31:17 [INFO] [*.example.xxxxxxx.com] acme: Waiting for DNS record propagation.
2023/04/13 18:31:19 [INFO] [*.example.xxxxxxx.com] acme: Waiting for DNS record propagation.
2023/04/13 18:31:21 [INFO] [*.example.xxxxxxx.com] acme: Waiting for DNS record propagation.
2023/04/13 18:31:23 [INFO] [*.example.xxxxxxx.com] acme: Waiting for DNS record propagation.
2023/04/13 18:31:25 [INFO] [*.example.xxxxxxx.com] acme: Waiting for DNS record propagation.
2023/04/13 18:31:28 [INFO] [*.example.xxxxxxx.com] acme: Waiting for DNS record propagation.
2023/04/13 18:31:30 [INFO] [*.example.xxxxxxx.com] acme: Waiting for DNS record propagation.
2023/04/13 18:31:32 [INFO] [*.example.xxxxxxx.com] acme: Waiting for DNS record propagation.
2023/04/13 18:31:34 [INFO] [*.example.xxxxxxx.com] acme: Waiting for DNS record propagation.
2023/04/13 18:31:37 [INFO] [*.example.xxxxxxx.com] acme: Waiting for DNS record propagation.
2023/04/13 18:31:39 [INFO] [*.example.xxxxxxx.com] acme: Waiting for DNS record propagation.
2023/04/13 18:31:41 [INFO] [*.example.xxxxxxx.com] acme: Waiting for DNS record propagation.
2023/04/13 18:31:43 [INFO] [*.example.xxxxxxx.com] acme: Waiting for DNS record propagation.
2023/04/13 18:31:46 [INFO] [*.example.xxxxxxx.com] acme: Waiting for DNS record propagation.
2023/04/13 18:31:48 [INFO] [*.example.xxxxxxx.com] acme: Waiting for DNS record propagation.
2023/04/13 18:31:50 [INFO] [*.example.xxxxxxx.com] acme: Waiting for DNS record propagation.
2023/04/13 18:31:52 [INFO] [*.example.xxxxxxx.com] acme: Waiting for DNS record propagation.
2023/04/13 18:31:55 [INFO] [*.example.xxxxxxx.com] acme: Waiting for DNS record propagation.
2023/04/13 18:31:57 [INFO] [*.example.xxxxxxx.com] acme: Waiting for DNS record propagation.
2023/04/13 18:31:59 [INFO] [*.example.xxxxxxx.com] acme: Waiting for DNS record propagation.
2023/04/13 18:32:01 [INFO] [*.example.xxxxxxx.com] acme: Waiting for DNS record propagation.
2023/04/13 18:32:04 [INFO] [*.example.xxxxxxx.com] acme: Waiting for DNS record propagation.
2023/04/13 18:32:06 [INFO] [*.example.xxxxxxx.com] acme: Waiting for DNS record propagation.
2023/04/13 18:32:08 [INFO] [*.example.xxxxxxx.com] acme: Waiting for DNS record propagation.
2023/04/13 18:32:10 [INFO] [*.example.xxxxxxx.com] acme: Waiting for DNS record propagation.
2023/04/13 18:32:12 [INFO] [*.example.xxxxxxx.com] acme: Waiting for DNS record propagation.
2023/04/13 18:32:15 [INFO] [*.example.xxxxxxx.com] acme: Waiting for DNS record propagation.
2023/04/13 18:32:17 [INFO] [*.example.xxxxxxx.com] acme: Waiting for DNS record propagation.
2023/04/13 18:32:19 [INFO] [*.example.xxxxxxx.com] acme: Waiting for DNS record propagation.
2023/04/13 18:32:21 [INFO] [*.example.xxxxxxx.com] acme: Waiting for DNS record propagation.
2023/04/13 18:32:24 [INFO] [*.example.xxxxxxx.com] acme: Waiting for DNS record propagation.
2023/04/13 18:32:26 [INFO] [*.example.xxxxxxx.com] acme: Waiting for DNS record propagation.
2023/04/13 18:32:28 [INFO] [*.example.xxxxxxx.com] acme: Waiting for DNS record propagation.
2023/04/13 18:32:30 [INFO] [*.example.xxxxxxx.com] acme: Waiting for DNS record propagation.
2023/04/13 18:32:33 [INFO] [*.example.xxxxxxx.com] acme: Waiting for DNS record propagation.
2023/04/13 18:32:35 [INFO] [*.example.xxxxxxx.com] acme: Waiting for DNS record propagation.
2023/04/13 18:32:37 [INFO] [*.example.xxxxxxx.com] acme: Waiting for DNS record propagation.
2023/04/13 18:32:39 [INFO] [*.example.xxxxxxx.com] acme: Waiting for DNS record propagation.
2023/04/13 18:32:42 [INFO] [*.example.xxxxxxx.com] acme: Waiting for DNS record propagation.
2023/04/13 18:32:44 [INFO] [*.example.xxxxxxx.com] acme: Waiting for DNS record propagation.
2023/04/13 18:32:46 [INFO] [*.example.xxxxxxx.com] acme: Waiting for DNS record propagation.
2023/04/13 18:32:48 [INFO] [*.example.xxxxxxx.com] acme: Waiting for DNS record propagation.
2023/04/13 18:32:51 [INFO] [*.example.xxxxxxx.com] acme: Waiting for DNS record propagation.
2023/04/13 18:32:53 [INFO] [*.example.xxxxxxx.com] acme: Waiting for DNS record propagation.
2023/04/13 18:32:55 [INFO] [*.example.xxxxxxx.com] acme: Waiting for DNS record propagation.
2023/04/13 18:32:57 [INFO] [*.example.xxxxxxx.com] acme: Waiting for DNS record propagation.
2023/04/13 18:33:00 [INFO] [*.example.xxxxxxx.com] acme: Waiting for DNS record propagation.
2023/04/13 18:33:02 [INFO] [*.example.xxxxxxx.com] acme: Waiting for DNS record propagation.
2023/04/13 18:33:04 [INFO] [*.example.xxxxxxx.com] acme: Waiting for DNS record propagation.
2023/04/13 18:33:06 [INFO] [*.example.xxxxxxx.com] acme: Waiting for DNS record propagation.
2023/04/13 18:33:09 [INFO] [*.example.xxxxxxx.com] acme: Waiting for DNS record propagation.
2023/04/13 18:33:11 [INFO] [*.example.xxxxxxx.com] acme: Waiting for DNS record propagation.
2023/04/13 18:33:13 [INFO] [*.example.xxxxxxx.com] acme: Waiting for DNS record propagation.
2023/04/13 18:33:15 [INFO] [*.example.xxxxxxx.com] acme: Waiting for DNS record propagation.
2023/04/13 18:33:17 [INFO] [*.example.xxxxxxx.com] acme: Waiting for DNS record propagation.
2023/04/13 18:33:20 [INFO] [*.example.xxxxxxx.com] acme: Waiting for DNS record propagation.
2023/04/13 18:33:22 [INFO] [*.example.xxxxxxx.com] acme: Waiting for DNS record propagation.
2023/04/13 18:33:24 [INFO] [*.example.xxxxxxx.com] acme: Waiting for DNS record propagation.
2023/04/13 18:33:26 [INFO] [*.example.xxxxxxx.com] acme: Waiting for DNS record propagation.
2023/04/13 18:33:29 [INFO] [*.example.xxxxxxx.com] acme: Waiting for DNS record propagation.
2023/04/13 18:33:31 [INFO] [*.example.xxxxxxx.com] acme: Waiting for DNS record propagation.
2023/04/13 18:33:33 [INFO] [*.example.xxxxxxx.com] acme: Waiting for DNS record propagation.
2023/04/13 18:33:35 [INFO] [*.example.xxxxxxx.com] acme: Waiting for DNS record propagation.
2023/04/13 18:33:38 [INFO] [*.example.xxxxxxx.com] acme: Waiting for DNS record propagation.
2023/04/13 18:33:40 [INFO] [*.example.xxxxxxx.com] acme: Waiting for DNS record propagation.
2023/04/13 18:33:42 [INFO] [*.example.xxxxxxx.com] acme: Waiting for DNS record propagation.
2023/04/13 18:33:44 [INFO] [*.example.xxxxxxx.com] acme: Waiting for DNS record propagation.
2023/04/13 18:33:47 [INFO] [*.example.xxxxxxx.com] acme: Waiting for DNS record propagation.
2023/04/13 18:33:49 [INFO] [*.example.xxxxxxx.com] acme: Waiting for DNS record propagation.
2023/04/13 18:33:51 [INFO] [*.example.xxxxxxx.com] acme: Waiting for DNS record propagation.
2023/04/13 18:33:53 [INFO] [*.example.xxxxxxx.com] acme: Waiting for DNS record propagation.
2023/04/13 18:33:55 [INFO] [*.example.xxxxxxx.com] acme: Waiting for DNS record propagation.
2023/04/13 18:33:58 [INFO] [*.example.xxxxxxx.com] acme: Waiting for DNS record propagation.
2023/04/13 18:34:00 [INFO] [*.example.xxxxxxx.com] acme: Waiting for DNS record propagation.
2023/04/13 18:34:02 [INFO] [*.example.xxxxxxx.com] acme: Waiting for DNS record propagation.
2023/04/13 18:34:04 [INFO] [*.example.xxxxxxx.com] acme: Waiting for DNS record propagation.
2023/04/13 18:34:07 [INFO] [*.example.xxxxxxx.com] acme: Waiting for DNS record propagation.
2023/04/13 18:34:09 [INFO] [*.example.xxxxxxx.com] acme: Waiting for DNS record propagation.
2023/04/13 18:34:11 [INFO] [*.example.xxxxxxx.com] acme: Waiting for DNS record propagation.
2023/04/13 18:34:13 [INFO] [*.example.xxxxxxx.com] acme: Waiting for DNS record propagation.
2023/04/13 18:34:16 [INFO] [*.example.xxxxxxx.com] acme: Waiting for DNS record propagation.
2023/04/13 18:34:18 [INFO] [*.example.xxxxxxx.com] acme: Waiting for DNS record propagation.
2023/04/13 18:34:20 [INFO] [*.example.xxxxxxx.com] acme: Waiting for DNS record propagation.
2023/04/13 18:34:32 [INFO] [*.example.xxxxxxx.com] acme: Waiting for DNS record propagation.
2023/04/13 18:34:34 [INFO] [*.example.xxxxxxx.com] acme: Waiting for DNS record propagation.
2023/04/13 18:34:37 [INFO] [*.example.xxxxxxx.com] acme: Waiting for DNS record propagation.
2023/04/13 18:34:39 [INFO] [*.example.xxxxxxx.com] acme: Waiting for DNS record propagation.
2023/04/13 18:34:41 [INFO] [*.example.xxxxxxx.com] acme: Waiting for DNS record propagation.
2023/04/13 18:34:44 [INFO] [*.example.xxxxxxx.com] acme: Waiting for DNS record propagation.
2023/04/13 18:34:46 [INFO] [*.example.xxxxxxx.com] acme: Waiting for DNS record propagation.
2023/04/13 18:34:48 [INFO] [*.example.xxxxxxx.com] acme: Waiting for DNS record propagation.
2023/04/13 18:34:50 [INFO] [*.example.xxxxxxx.com] acme: Waiting for DNS record propagation.
2023/04/13 18:34:53 [INFO] [*.example.xxxxxxx.com] acme: Waiting for DNS record propagation.
2023/04/13 18:34:55 [INFO] [*.example.xxxxxxx.com] acme: Waiting for DNS record propagation.
2023/04/13 18:34:57 [INFO] [*.example.xxxxxxx.com] acme: Waiting for DNS record propagation.
2023/04/13 18:34:59 [INFO] [*.example.xxxxxxx.com] acme: Waiting for DNS record propagation.
2023/04/13 18:35:01 [INFO] [*.example.xxxxxxx.com] acme: Waiting for DNS record propagation.
2023/04/13 18:35:04 [INFO] [*.example.xxxxxxx.com] acme: Waiting for DNS record propagation.
2023/04/13 18:35:06 [INFO] [*.example.xxxxxxx.com] acme: Waiting for DNS record propagation.
2023/04/13 18:35:08 [INFO] [*.example.xxxxxxx.com] acme: Waiting for DNS record propagation.
2023/04/13 18:35:10 [INFO] [*.example.xxxxxxx.com] acme: Waiting for DNS record propagation.
2023/04/13 18:35:13 [INFO] [*.example.xxxxxxx.com] acme: Waiting for DNS record propagation.
2023/04/13 18:35:15 [INFO] [*.example.xxxxxxx.com] acme: Waiting for DNS record propagation.
2023/04/13 18:35:17 [INFO] [*.example.xxxxxxx.com] acme: Waiting for DNS record propagation.
2023/04/13 18:35:19 [INFO] [*.example.xxxxxxx.com] acme: Waiting for DNS record propagation.
2023/04/13 18:35:22 [INFO] [*.example.xxxxxxx.com] acme: Waiting for DNS record propagation.
2023/04/13 18:35:24 [INFO] [*.example.xxxxxxx.com] acme: Waiting for DNS record propagation.
2023/04/13 18:35:26 [INFO] [*.example.xxxxxxx.com] acme: Waiting for DNS record propagation.
2023/04/13 18:35:28 [INFO] [*.example.xxxxxxx.com] acme: Waiting for DNS record propagation.
2023/04/13 18:35:31 [INFO] [*.example.xxxxxxx.com] acme: Waiting for DNS record propagation.
2023/04/13 18:35:33 [INFO] [*.example.xxxxxxx.com] acme: Waiting for DNS record propagation.
2023/04/13 18:35:35 [INFO] [*.example.xxxxxxx.com] acme: Waiting for DNS record propagation.
2023/04/13 18:35:42 [INFO] [*.example.xxxxxxx.com] The server validated our request
2023/04/13 18:35:42 [INFO] [example.xxxxxxx.com] acme: Trying to solve DNS-01
2023/04/13 18:35:42 [INFO] [example.xxxxxxx.com] acme: Checking DNS record propagation using [172.25.96.1:53]
2023/04/13 18:35:44 [INFO] Wait for propagation [timeout: 30m0s, interval: 2s]
2023/04/13 18:35:44 [INFO] [example.xxxxxxx.com] The server validated our request
2023/04/13 18:35:44 [INFO] [*.example.xxxxxxx.com] acme: Cleaning DNS-01 challenge
2023/04/13 18:35:55 [INFO] [example.xxxxxxx.com] acme: Cleaning DNS-01 challenge
2023/04/13 18:36:05 [INFO] [*.example.xxxxxxx.com, example.xxxxxxx.com] acme: Validations succeeded; requesting certificates
2023/04/13 18:36:05 [INFO] Wait for certificate [timeout: 30s, interval: 500ms]
2023/04/13 18:36:06 [INFO] [*.example.xxxxxxx.com] Server responded with a certificate.
```
Andrei-Predoiu: What code inspection tool do you use? I normally just use goland and it doesn't complain about double lines. I installed `golangci-lint` but it seems to give me nonsense
```
/lego/providers/dns/brandit$ golangci-lint run
brandit.go:12:2: could not import github.com/go-acme/lego/v4/providers/dns/brandit/internal (-: # github.com/go-acme/lego/v4/providers/dns/brandit/internal
internal/client.go:78:23: syntax error: unexpected : at end of statement) (typecheck)
        "github.com/go-acme/lego/v4/providers/dns/brandit/internal"
        ^
internal/client.go:1: : # github.com/go-acme/lego/v4/providers/dns/brandit/internal [github.com/go-acme/lego/v4/providers/dns/brandit/internal.test]
internal/client.go:78:23: syntax error: unexpected : at end of statement (typecheck)
package internal
internal/client.go:78:23: expected ';', found ':' (typecheck)
        query := url.Values{}:wq:
```

ldez: You have to run the linter at the root of the project.

FYI, I'm also a core maintainer of golangci-lint :wink: 

Patch:
diff --git a/README.md b/README.md
index dd8ae198..b35ba09e 100644
--- a/README.md
+++ b/README.md
@@ -51,33 +51,34 @@ Detailed documentation is available [here](https://go-acme.github.io/lego/dns).
 |---------------------------------------------------------------------------------|---------------------------------------------------------------------------------|---------------------------------------------------------------------------------|---------------------------------------------------------------------------------|
 | [Akamai EdgeDNS](https://go-acme.github.io/lego/dns/edgedns/)                   | [Alibaba Cloud DNS](https://go-acme.github.io/lego/dns/alidns/)                 | [all-inkl](https://go-acme.github.io/lego/dns/allinkl/)                         | [Amazon Lightsail](https://go-acme.github.io/lego/dns/lightsail/)               |
 | [Amazon Route 53](https://go-acme.github.io/lego/dns/route53/)                  | [ArvanCloud](https://go-acme.github.io/lego/dns/arvancloud/)                    | [Aurora DNS](https://go-acme.github.io/lego/dns/auroradns/)                     | [Autodns](https://go-acme.github.io/lego/dns/autodns/)                          |
-| [Azure](https://go-acme.github.io/lego/dns/azure/)                              | [Bindman](https://go-acme.github.io/lego/dns/bindman/)                          | [Bluecat](https://go-acme.github.io/lego/dns/bluecat/)                          | [Bunny](https://go-acme.github.io/lego/dns/bunny/)                              |
-| [Checkdomain](https://go-acme.github.io/lego/dns/checkdomain/)                  | [Civo](https://go-acme.github.io/lego/dns/civo/)                                | [CloudDNS](https://go-acme.github.io/lego/dns/clouddns/)                        | [Cloudflare](https://go-acme.github.io/lego/dns/cloudflare/)                    |
-| [ClouDNS](https://go-acme.github.io/lego/dns/cloudns/)                          | [CloudXNS](https://go-acme.github.io/lego/dns/cloudxns/)                        | [ConoHa](https://go-acme.github.io/lego/dns/conoha/)                            | [Constellix](https://go-acme.github.io/lego/dns/constellix/)                    |
-| [deSEC.io](https://go-acme.github.io/lego/dns/desec/)                           | [Designate DNSaaS for Openstack](https://go-acme.github.io/lego/dns/designate/) | [Digital Ocean](https://go-acme.github.io/lego/dns/digitalocean/)               | [DNS Made Easy](https://go-acme.github.io/lego/dns/dnsmadeeasy/)                |
-| [dnsHome.de](https://go-acme.github.io/lego/dns/dnshomede/)                     | [DNSimple](https://go-acme.github.io/lego/dns/dnsimple/)                        | [DNSPod (deprecated)](https://go-acme.github.io/lego/dns/dnspod/)               | [Domain Offensive (do.de)](https://go-acme.github.io/lego/dns/dode/)            |
-| [Domeneshop](https://go-acme.github.io/lego/dns/domeneshop/)                    | [DreamHost](https://go-acme.github.io/lego/dns/dreamhost/)                      | [Duck DNS](https://go-acme.github.io/lego/dns/duckdns/)                         | [Dyn](https://go-acme.github.io/lego/dns/dyn/)                                  |
-| [Dynu](https://go-acme.github.io/lego/dns/dynu/)                                | [EasyDNS](https://go-acme.github.io/lego/dns/easydns/)                          | [Epik](https://go-acme.github.io/lego/dns/epik/)                                | [Exoscale](https://go-acme.github.io/lego/dns/exoscale/)                        |
-| [External program](https://go-acme.github.io/lego/dns/exec/)                    | [freemyip.com](https://go-acme.github.io/lego/dns/freemyip/)                    | [G-Core Labs](https://go-acme.github.io/lego/dns/gcore/)                        | [Gandi Live DNS (v5)](https://go-acme.github.io/lego/dns/gandiv5/)              |
-| [Gandi](https://go-acme.github.io/lego/dns/gandi/)                              | [Glesys](https://go-acme.github.io/lego/dns/glesys/)                            | [Go Daddy](https://go-acme.github.io/lego/dns/godaddy/)                         | [Google Cloud](https://go-acme.github.io/lego/dns/gcloud/)                      |
-| [Google Domains](https://go-acme.github.io/lego/dns/googledomains/)             | [Hetzner](https://go-acme.github.io/lego/dns/hetzner/)                          | [Hosting.de](https://go-acme.github.io/lego/dns/hostingde/)                     | [Hosttech](https://go-acme.github.io/lego/dns/hosttech/)                        |
-| [HTTP request](https://go-acme.github.io/lego/dns/httpreq/)                     | [Hurricane Electric DNS](https://go-acme.github.io/lego/dns/hurricane/)         | [HyperOne](https://go-acme.github.io/lego/dns/hyperone/)                        | [IBM Cloud (SoftLayer)](https://go-acme.github.io/lego/dns/ibmcloud/)           |
-| [IIJ DNS Platform Service](https://go-acme.github.io/lego/dns/iijdpf/)          | [Infoblox](https://go-acme.github.io/lego/dns/infoblox/)                        | [Infomaniak](https://go-acme.github.io/lego/dns/infomaniak/)                    | [Internet Initiative Japan](https://go-acme.github.io/lego/dns/iij/)            |
-| [Internet.bs](https://go-acme.github.io/lego/dns/internetbs/)                   | [INWX](https://go-acme.github.io/lego/dns/inwx/)                                | [Ionos](https://go-acme.github.io/lego/dns/ionos/)                              | [iwantmyname](https://go-acme.github.io/lego/dns/iwantmyname/)                  |
-| [Joker](https://go-acme.github.io/lego/dns/joker/)                              | [Joohoi's ACME-DNS](https://go-acme.github.io/lego/dns/acme-dns/)               | [Liara](https://go-acme.github.io/lego/dns/liara/)                              | [Linode (v4)](https://go-acme.github.io/lego/dns/linode/)                       |
-| [Liquid Web](https://go-acme.github.io/lego/dns/liquidweb/)                     | [Loopia](https://go-acme.github.io/lego/dns/loopia/)                            | [LuaDNS](https://go-acme.github.io/lego/dns/luadns/)                            | [Manual](https://go-acme.github.io/lego/dns/manual/)                            |
-| [MyDNS.jp](https://go-acme.github.io/lego/dns/mydnsjp/)                         | [MythicBeasts](https://go-acme.github.io/lego/dns/mythicbeasts/)                | [Name.com](https://go-acme.github.io/lego/dns/namedotcom/)                      | [Namecheap](https://go-acme.github.io/lego/dns/namecheap/)                      |
-| [Namesilo](https://go-acme.github.io/lego/dns/namesilo/)                        | [NearlyFreeSpeech.NET](https://go-acme.github.io/lego/dns/nearlyfreespeech/)    | [Netcup](https://go-acme.github.io/lego/dns/netcup/)                            | [Netlify](https://go-acme.github.io/lego/dns/netlify/)                          |
-| [Nicmanager](https://go-acme.github.io/lego/dns/nicmanager/)                    | [NIFCloud](https://go-acme.github.io/lego/dns/nifcloud/)                        | [Njalla](https://go-acme.github.io/lego/dns/njalla/)                            | [Nodion](https://go-acme.github.io/lego/dns/nodion/)                            |
-| [NS1](https://go-acme.github.io/lego/dns/ns1/)                                  | [Open Telekom Cloud](https://go-acme.github.io/lego/dns/otc/)                   | [Oracle Cloud](https://go-acme.github.io/lego/dns/oraclecloud/)                 | [OVH](https://go-acme.github.io/lego/dns/ovh/)                                  |
-| [plesk.com](https://go-acme.github.io/lego/dns/plesk/)                          | [Porkbun](https://go-acme.github.io/lego/dns/porkbun/)                          | [PowerDNS](https://go-acme.github.io/lego/dns/pdns/)                            | [Rackspace](https://go-acme.github.io/lego/dns/rackspace/)                      |
-| [reg.ru](https://go-acme.github.io/lego/dns/regru/)                             | [RFC2136](https://go-acme.github.io/lego/dns/rfc2136/)                          | [RimuHosting](https://go-acme.github.io/lego/dns/rimuhosting/)                  | [Sakura Cloud](https://go-acme.github.io/lego/dns/sakuracloud/)                 |
-| [Scaleway](https://go-acme.github.io/lego/dns/scaleway/)                        | [Selectel](https://go-acme.github.io/lego/dns/selectel/)                        | [Servercow](https://go-acme.github.io/lego/dns/servercow/)                      | [Simply.com](https://go-acme.github.io/lego/dns/simply/)                        |
-| [Sonic](https://go-acme.github.io/lego/dns/sonic/)                              | [Stackpath](https://go-acme.github.io/lego/dns/stackpath/)                      | [Tencent Cloud DNS](https://go-acme.github.io/lego/dns/tencentcloud/)           | [TransIP](https://go-acme.github.io/lego/dns/transip/)                          |
-| [UKFast SafeDNS](https://go-acme.github.io/lego/dns/safedns/)                   | [Ultradns](https://go-acme.github.io/lego/dns/ultradns/)                        | [Variomedia](https://go-acme.github.io/lego/dns/variomedia/)                    | [VegaDNS](https://go-acme.github.io/lego/dns/vegadns/)                          |
-| [Vercel](https://go-acme.github.io/lego/dns/vercel/)                            | [Versio.[nl/eu/uk]](https://go-acme.github.io/lego/dns/versio/)                 | [VinylDNS](https://go-acme.github.io/lego/dns/vinyldns/)                        | [VK Cloud](https://go-acme.github.io/lego/dns/vkcloud/)                         |
-| [Vscale](https://go-acme.github.io/lego/dns/vscale/)                            | [Vultr](https://go-acme.github.io/lego/dns/vultr/)                              | [Websupport](https://go-acme.github.io/lego/dns/websupport/)                    | [WEDOS](https://go-acme.github.io/lego/dns/wedos/)                              |
-| [Yandex Cloud](https://go-acme.github.io/lego/dns/yandexcloud/)                 | [Yandex PDD](https://go-acme.github.io/lego/dns/yandex/)                        | [Zone.ee](https://go-acme.github.io/lego/dns/zoneee/)                           | [Zonomi](https://go-acme.github.io/lego/dns/zonomi/)                            |
+| [Azure](https://go-acme.github.io/lego/dns/azure/)                              | [Bindman](https://go-acme.github.io/lego/dns/bindman/)                          | [Bluecat](https://go-acme.github.io/lego/dns/bluecat/)                          | [BRANDIT](https://go-acme.github.io/lego/dns/brandit/)                          |
+| [Bunny](https://go-acme.github.io/lego/dns/bunny/)                              | [Checkdomain](https://go-acme.github.io/lego/dns/checkdomain/)                  | [Civo](https://go-acme.github.io/lego/dns/civo/)                                | [CloudDNS](https://go-acme.github.io/lego/dns/clouddns/)                        |
+| [Cloudflare](https://go-acme.github.io/lego/dns/cloudflare/)                    | [ClouDNS](https://go-acme.github.io/lego/dns/cloudns/)                          | [CloudXNS](https://go-acme.github.io/lego/dns/cloudxns/)                        | [ConoHa](https://go-acme.github.io/lego/dns/conoha/)                            |
+| [Constellix](https://go-acme.github.io/lego/dns/constellix/)                    | [deSEC.io](https://go-acme.github.io/lego/dns/desec/)                           | [Designate DNSaaS for Openstack](https://go-acme.github.io/lego/dns/designate/) | [Digital Ocean](https://go-acme.github.io/lego/dns/digitalocean/)               |
+| [DNS Made Easy](https://go-acme.github.io/lego/dns/dnsmadeeasy/)                | [dnsHome.de](https://go-acme.github.io/lego/dns/dnshomede/)                     | [DNSimple](https://go-acme.github.io/lego/dns/dnsimple/)                        | [DNSPod (deprecated)](https://go-acme.github.io/lego/dns/dnspod/)               |
+| [Domain Offensive (do.de)](https://go-acme.github.io/lego/dns/dode/)            | [Domeneshop](https://go-acme.github.io/lego/dns/domeneshop/)                    | [DreamHost](https://go-acme.github.io/lego/dns/dreamhost/)                      | [Duck DNS](https://go-acme.github.io/lego/dns/duckdns/)                         |
+| [Dyn](https://go-acme.github.io/lego/dns/dyn/)                                  | [Dynu](https://go-acme.github.io/lego/dns/dynu/)                                | [EasyDNS](https://go-acme.github.io/lego/dns/easydns/)                          | [Epik](https://go-acme.github.io/lego/dns/epik/)                                |
+| [Exoscale](https://go-acme.github.io/lego/dns/exoscale/)                        | [External program](https://go-acme.github.io/lego/dns/exec/)                    | [freemyip.com](https://go-acme.github.io/lego/dns/freemyip/)                    | [G-Core Labs](https://go-acme.github.io/lego/dns/gcore/)                        |
+| [Gandi Live DNS (v5)](https://go-acme.github.io/lego/dns/gandiv5/)              | [Gandi](https://go-acme.github.io/lego/dns/gandi/)                              | [Glesys](https://go-acme.github.io/lego/dns/glesys/)                            | [Go Daddy](https://go-acme.github.io/lego/dns/godaddy/)                         |
+| [Google Cloud](https://go-acme.github.io/lego/dns/gcloud/)                      | [Google Domains](https://go-acme.github.io/lego/dns/googledomains/)             | [Hetzner](https://go-acme.github.io/lego/dns/hetzner/)                          | [Hosting.de](https://go-acme.github.io/lego/dns/hostingde/)                     |
+| [Hosttech](https://go-acme.github.io/lego/dns/hosttech/)                        | [HTTP request](https://go-acme.github.io/lego/dns/httpreq/)                     | [Hurricane Electric DNS](https://go-acme.github.io/lego/dns/hurricane/)         | [HyperOne](https://go-acme.github.io/lego/dns/hyperone/)                        |
+| [IBM Cloud (SoftLayer)](https://go-acme.github.io/lego/dns/ibmcloud/)           | [IIJ DNS Platform Service](https://go-acme.github.io/lego/dns/iijdpf/)          | [Infoblox](https://go-acme.github.io/lego/dns/infoblox/)                        | [Infomaniak](https://go-acme.github.io/lego/dns/infomaniak/)                    |
+| [Internet Initiative Japan](https://go-acme.github.io/lego/dns/iij/)            | [Internet.bs](https://go-acme.github.io/lego/dns/internetbs/)                   | [INWX](https://go-acme.github.io/lego/dns/inwx/)                                | [Ionos](https://go-acme.github.io/lego/dns/ionos/)                              |
+| [iwantmyname](https://go-acme.github.io/lego/dns/iwantmyname/)                  | [Joker](https://go-acme.github.io/lego/dns/joker/)                              | [Joohoi's ACME-DNS](https://go-acme.github.io/lego/dns/acme-dns/)               | [Liara](https://go-acme.github.io/lego/dns/liara/)                              |
+| [Linode (v4)](https://go-acme.github.io/lego/dns/linode/)                       | [Liquid Web](https://go-acme.github.io/lego/dns/liquidweb/)                     | [Loopia](https://go-acme.github.io/lego/dns/loopia/)                            | [LuaDNS](https://go-acme.github.io/lego/dns/luadns/)                            |
+| [Manual](https://go-acme.github.io/lego/dns/manual/)                            | [MyDNS.jp](https://go-acme.github.io/lego/dns/mydnsjp/)                         | [MythicBeasts](https://go-acme.github.io/lego/dns/mythicbeasts/)                | [Name.com](https://go-acme.github.io/lego/dns/namedotcom/)                      |
+| [Namecheap](https://go-acme.github.io/lego/dns/namecheap/)                      | [Namesilo](https://go-acme.github.io/lego/dns/namesilo/)                        | [NearlyFreeSpeech.NET](https://go-acme.github.io/lego/dns/nearlyfreespeech/)    | [Netcup](https://go-acme.github.io/lego/dns/netcup/)                            |
+| [Netlify](https://go-acme.github.io/lego/dns/netlify/)                          | [Nicmanager](https://go-acme.github.io/lego/dns/nicmanager/)                    | [NIFCloud](https://go-acme.github.io/lego/dns/nifcloud/)                        | [Njalla](https://go-acme.github.io/lego/dns/njalla/)                            |
+| [Nodion](https://go-acme.github.io/lego/dns/nodion/)                            | [NS1](https://go-acme.github.io/lego/dns/ns1/)                                  | [Open Telekom Cloud](https://go-acme.github.io/lego/dns/otc/)                   | [Oracle Cloud](https://go-acme.github.io/lego/dns/oraclecloud/)                 |
+| [OVH](https://go-acme.github.io/lego/dns/ovh/)                                  | [plesk.com](https://go-acme.github.io/lego/dns/plesk/)                          | [Porkbun](https://go-acme.github.io/lego/dns/porkbun/)                          | [PowerDNS](https://go-acme.github.io/lego/dns/pdns/)                            |
+| [Rackspace](https://go-acme.github.io/lego/dns/rackspace/)                      | [reg.ru](https://go-acme.github.io/lego/dns/regru/)                             | [RFC2136](https://go-acme.github.io/lego/dns/rfc2136/)                          | [RimuHosting](https://go-acme.github.io/lego/dns/rimuhosting/)                  |
+| [Sakura Cloud](https://go-acme.github.io/lego/dns/sakuracloud/)                 | [Scaleway](https://go-acme.github.io/lego/dns/scaleway/)                        | [Selectel](https://go-acme.github.io/lego/dns/selectel/)                        | [Servercow](https://go-acme.github.io/lego/dns/servercow/)                      |
+| [Simply.com](https://go-acme.github.io/lego/dns/simply/)                        | [Sonic](https://go-acme.github.io/lego/dns/sonic/)                              | [Stackpath](https://go-acme.github.io/lego/dns/stackpath/)                      | [Tencent Cloud DNS](https://go-acme.github.io/lego/dns/tencentcloud/)           |
+| [TransIP](https://go-acme.github.io/lego/dns/transip/)                          | [UKFast SafeDNS](https://go-acme.github.io/lego/dns/safedns/)                   | [Ultradns](https://go-acme.github.io/lego/dns/ultradns/)                        | [Variomedia](https://go-acme.github.io/lego/dns/variomedia/)                    |
+| [VegaDNS](https://go-acme.github.io/lego/dns/vegadns/)                          | [Vercel](https://go-acme.github.io/lego/dns/vercel/)                            | [Versio.[nl/eu/uk]](https://go-acme.github.io/lego/dns/versio/)                 | [VinylDNS](https://go-acme.github.io/lego/dns/vinyldns/)                        |
+| [VK Cloud](https://go-acme.github.io/lego/dns/vkcloud/)                         | [Vscale](https://go-acme.github.io/lego/dns/vscale/)                            | [Vultr](https://go-acme.github.io/lego/dns/vultr/)                              | [Websupport](https://go-acme.github.io/lego/dns/websupport/)                    |
+| [WEDOS](https://go-acme.github.io/lego/dns/wedos/)                              | [Yandex Cloud](https://go-acme.github.io/lego/dns/yandexcloud/)                 | [Yandex PDD](https://go-acme.github.io/lego/dns/yandex/)                        | [Zone.ee](https://go-acme.github.io/lego/dns/zoneee/)                           |
+| [Zonomi](https://go-acme.github.io/lego/dns/zonomi/)                            |                                                                                 |                                                                                 |                                                                                 |
 
 <!-- END DNS PROVIDERS LIST -->
 
diff --git a/cmd/zz_gen_cmd_dnshelp.go b/cmd/zz_gen_cmd_dnshelp.go
index edaff3e0..f839e949 100644
--- a/cmd/zz_gen_cmd_dnshelp.go
+++ b/cmd/zz_gen_cmd_dnshelp.go
@@ -23,6 +23,7 @@ func allDNSCodes() string {
 		"azure",
 		"bindman",
 		"bluecat",
+		"brandit",
 		"bunny",
 		"checkdomain",
 		"civo",
@@ -332,6 +333,27 @@ func displayDNSHelp(w io.Writer, name string) error {
 		ew.writeln()
 		ew.writeln(`More information: https://go-acme.github.io/lego/dns/bluecat`)
 
+	case "brandit":
+		// generated from: providers/dns/brandit/brandit.toml
+		ew.writeln(`Configuration for BRANDIT.`)
+		ew.writeln(`Code:	'brandit'`)
+		ew.writeln(`Since:	'v4.11.0'`)
+		ew.writeln()
+
+		ew.writeln(`Credentials:`)
+		ew.writeln(`	- "BRANDIT_API_KEY":	The API key`)
+		ew.writeln(`	- "BRANDIT_API_USERNAME":	The API username`)
+		ew.writeln()
+
+		ew.writeln(`Additional Configuration:`)
+		ew.writeln(`	- "BRANDIT_HTTP_TIMEOUT":	API request timeout`)
+		ew.writeln(`	- "BRANDIT_POLLING_INTERVAL":	Time between DNS propagation check`)
+		ew.writeln(`	- "BRANDIT_PROPAGATION_TIMEOUT":	Maximum waiting time for DNS propagation`)
+		ew.writeln(`	- "BRANDIT_TTL":	The TTL of the TXT record used for the DNS challenge`)
+
+		ew.writeln()
+		ew.writeln(`More information: https://go-acme.github.io/lego/dns/brandit`)
+
 	case "bunny":
 		// generated from: providers/dns/bunny/bunny.toml
 		ew.writeln(`Configuration for Bunny.`)
diff --git a/docs/content/dns/zz_gen_brandit.md b/docs/content/dns/zz_gen_brandit.md
new file mode 100644
index 00000000..307dfa57
--- /dev/null
+++ b/docs/content/dns/zz_gen_brandit.md
@@ -0,0 +1,69 @@
+---
+title: "BRANDIT"
+date: 2019-03-03T16:39:46+01:00
+draft: false
+slug: brandit
+dnsprovider:
+  since:    "v4.11.0"
+  code:     "brandit"
+  url:      "https://www.brandit.com/"
+---
+
+<!-- THIS DOCUMENTATION IS AUTO-GENERATED. PLEASE DO NOT EDIT. -->
+<!-- providers/dns/brandit/brandit.toml -->
+<!-- THIS DOCUMENTATION IS AUTO-GENERATED. PLEASE DO NOT EDIT. -->
+
+
+Configuration for [BRANDIT](https://www.brandit.com/).
+
+
+<!--more-->
+
+- Code: `brandit`
+- Since: v4.11.0
+
+
+Here is an example bash command using the BRANDIT provider:
+
+```bash
+BRANDIT_API_KEY=xxxxxxxxxxxxxxxxxxxxx \
+BRANDIT_API_USERNAME=yyyyyyyyyyyyyyyyyyyy \
+lego --email myemail@example.com --dns brandit --domains my.example.org run
+```
+
+
+
+
+## Credentials
+
+| Environment Variable Name | Description |
+|-----------------------|-------------|
+| `BRANDIT_API_KEY` | The API key |
+| `BRANDIT_API_USERNAME` | The API username |
+
+The environment variable names can be suffixed by `_FILE` to reference a file instead of a value.
+More information [here]({{< ref "dns#configuration-and-credentials" >}}).
+
+
+## Additional Configuration
+
+| Environment Variable Name | Description |
+|--------------------------------|-------------|
+| `BRANDIT_HTTP_TIMEOUT` | API request timeout |
+| `BRANDIT_POLLING_INTERVAL` | Time between DNS propagation check |
+| `BRANDIT_PROPAGATION_TIMEOUT` | Maximum waiting time for DNS propagation |
+| `BRANDIT_TTL` | The TTL of the TXT record used for the DNS challenge |
+
+The environment variable names can be suffixed by `_FILE` to reference a file instead of a value.
+More information [here]({{< ref "dns#configuration-and-credentials" >}}).
+
+
+
+
+## More information
+
+- [API documentation](https://portal.brandit.com/apidocv3)
+
+<!-- THIS DOCUMENTATION IS AUTO-GENERATED. PLEASE DO NOT EDIT. -->
+<!-- providers/dns/brandit/brandit.toml -->
+<!-- THIS DOCUMENTATION IS AUTO-GENERATED. PLEASE DO NOT EDIT. -->
diff --git a/docs/data/zz_cli_help.toml b/docs/data/zz_cli_help.toml
index cf08d7e0..f3a65e5f 100644
--- a/docs/data/zz_cli_help.toml
+++ b/docs/data/zz_cli_help.toml
@@ -125,7 +125,7 @@ To display the documentation for a specific DNS provider, run:
   $ lego dnshelp -c code
 
 Supported DNS providers:
-  acme-dns, alidns, allinkl, arvancloud, auroradns, autodns, azure, bindman, bluecat, bunny, checkdomain, civo, clouddns, cloudflare, cloudns, cloudxns, conoha, constellix, desec, designate, digitalocean, dnshomede, dnsimple, dnsmadeeasy, dnspod, dode, domeneshop, dreamhost, duckdns, dyn, dynu, easydns, edgedns, epik, exec, exoscale, freemyip, gandi, gandiv5, gcloud, gcore, glesys, godaddy, googledomains, hetzner, hostingde, hosttech, httpreq, hurricane, hyperone, ibmcloud, iij, iijdpf, infoblox, infomaniak, internetbs, inwx, ionos, iwantmyname, joker, liara, lightsail, linode, liquidweb, loopia, luadns, manual, mydnsjp, mythicbeasts, namecheap, namedotcom, namesilo, nearlyfreespeech, netcup, netlify, nicmanager, nifcloud, njalla, nodion, ns1, oraclecloud, otc, ovh, pdns, plesk, porkbun, rackspace, regru, rfc2136, rimuhosting, route53, safedns, sakuracloud, scaleway, selectel, servercow, simply, sonic, stackpath, tencentcloud, transip, ultradns, variomedia, vegadns, vercel, versio, vinyldns, vkcloud, vscale, vultr, websupport, wedos, yandex, yandexcloud, zoneee, zonomi
+  acme-dns, alidns, allinkl, arvancloud, auroradns, autodns, azure, bindman, bluecat, brandit, bunny, checkdomain, civo, clouddns, cloudflare, cloudns, cloudxns, conoha, constellix, desec, designate, digitalocean, dnshomede, dnsimple, dnsmadeeasy, dnspod, dode, domeneshop, dreamhost, duckdns, dyn, dynu, easydns, edgedns, epik, exec, exoscale, freemyip, gandi, gandiv5, gcloud, gcore, glesys, godaddy, googledomains, hetzner, hostingde, hosttech, httpreq, hurricane, hyperone, ibmcloud, iij, iijdpf, infoblox, infomaniak, internetbs, inwx, ionos, iwantmyname, joker, liara, lightsail, linode, liquidweb, loopia, luadns, manual, mydnsjp, mythicbeasts, namecheap, namedotcom, namesilo, nearlyfreespeech, netcup, netlify, nicmanager, nifcloud, njalla, nodion, ns1, oraclecloud, otc, ovh, pdns, plesk, porkbun, rackspace, regru, rfc2136, rimuhosting, route53, safedns, sakuracloud, scaleway, selectel, servercow, simply, sonic, stackpath, tencentcloud, transip, ultradns, variomedia, vegadns, vercel, versio, vinyldns, vkcloud, vscale, vultr, websupport, wedos, yandex, yandexcloud, zoneee, zonomi
 
 More information: https://go-acme.github.io/lego/dns
 """
diff --git a/providers/dns/brandit/brandit.go b/providers/dns/brandit/brandit.go
new file mode 100644
index 00000000..0b80f490
--- /dev/null
+++ b/providers/dns/brandit/brandit.go
@@ -0,0 +1,197 @@
+package brandit
+
+import (
+	"errors"
+	"fmt"
+	"net/http"
+	"sync"
+	"time"
+
+	"github.com/go-acme/lego/v4/challenge/dns01"
+	"github.com/go-acme/lego/v4/platform/config/env"
+	"github.com/go-acme/lego/v4/providers/dns/brandit/internal"
+)
+
+const defaultTTL = 600
+
+// Environment variables names.
+const (
+	envNamespace = "BRANDIT_"
+
+	EnvAPIKey      = envNamespace + "API_KEY"
+	EnvAPIUsername = envNamespace + "API_USERNAME"
+
+	EnvTTL                           = envNamespace + "TTL"
+	EnvPropagationTimeout            = envNamespace + "PROPAGATION_TIMEOUT"
+	EnvPollingInterval               = envNamespace + "POLLING_INTERVAL"
+	EnvHTTPTimeout                   = envNamespace + "HTTP_TIMEOUT"
+	DefaultBrandItPropagationTimeout = 600 * time.Second
+)
+
+// Config is used to configure the creation of the DNSProvider.
+type Config struct {
+	APIKey      string
+	APIUsername string
+
+	PropagationTimeout time.Duration
+	PollingInterval    time.Duration
+	TTL                int
+	HTTPClient         *http.Client
+}
+
+// NewDefaultConfig returns a default configuration for the DNSProvider.
+func NewDefaultConfig() *Config {
+	return &Config{
+		TTL:                env.GetOrDefaultInt(EnvTTL, defaultTTL),
+		PropagationTimeout: env.GetOrDefaultSecond(EnvPropagationTimeout, DefaultBrandItPropagationTimeout),
+		PollingInterval:    env.GetOrDefaultSecond(EnvPollingInterval, dns01.DefaultPollingInterval),
+		HTTPClient: &http.Client{
+			Timeout: env.GetOrDefaultSecond(EnvHTTPTimeout, 30*time.Second),
+		},
+	}
+}
+
+// DNSProvider implements the challenge.Provider interface.
+type DNSProvider struct {
+	config *Config
+	client *internal.Client
+
+	records   map[string]string
+	recordsMu sync.Mutex
+}
+
+// NewDNSProvider returns a DNSProvider instance configured for BrandIT.
+// Credentials must be passed in the environment variables: BRANDIT_API_KEY, BRANDIT_API_USERNAME.
+func NewDNSProvider() (*DNSProvider, error) {
+	values, err := env.Get(EnvAPIKey, EnvAPIUsername)
+	if err != nil {
+		return nil, fmt.Errorf("brandit: %w", err)
+	}
+
+	config := NewDefaultConfig()
+	config.APIKey = values[EnvAPIKey]
+	config.APIUsername = values[EnvAPIUsername]
+
+	return NewDNSProviderConfig(config)
+}
+
+// NewDNSProviderConfig return a DNSProvider instance configured for BrandIT.
+func NewDNSProviderConfig(config *Config) (*DNSProvider, error) {
+	if config == nil {
+		return nil, errors.New("brandit: the configuration of the DNS provider is nil")
+	}
+
+	client, err := internal.NewClient(config.APIUsername, config.APIKey)
+	if err != nil {
+		return nil, fmt.Errorf("brandit: %w", err)
+	}
+
+	if config.HTTPClient != nil {
+		client.HTTPClient = config.HTTPClient
+	}
+
+	return &DNSProvider{
+		config:  config,
+		client:  client,
+		records: make(map[string]string),
+	}, nil
+}
+
+// Present creates a TXT record using the specified parameters.
+func (d *DNSProvider) Present(domain, token, keyAuth string) error {
+	info := dns01.GetChallengeInfo(domain, keyAuth)
+
+	authZone, err := dns01.FindZoneByFqdn(info.EffectiveFQDN)
+	if err != nil {
+		return fmt.Errorf("brandit: %w", err)
+	}
+
+	subDomain, err := dns01.ExtractSubDomain(info.EffectiveFQDN, authZone)
+	if err != nil {
+		return fmt.Errorf("brandit: %w", err)
+	}
+
+	record := internal.Record{
+		Type:    "TXT",
+		Name:    subDomain,
+		Content: info.Value,
+		TTL:     d.config.TTL,
+	}
+
+	// find the account associated with the domain
+	account, err := d.client.StatusDomain(dns01.UnFqdn(authZone))
+	if err != nil {
+		return fmt.Errorf("brandit: status domain: %w", err)
+	}
+
+	// Find the next record id
+	recordID, err := d.client.ListRecords(account.Response.Registrar[0], dns01.UnFqdn(authZone))
+	if err != nil {
+		return fmt.Errorf("brandit: list records: %w", err)
+	}
+
+	result, err := d.client.AddRecord(dns01.UnFqdn(authZone), account.Response.Registrar[0], fmt.Sprint(recordID.Response.Total[0]), record)
+	if err != nil {
+		return fmt.Errorf("brandit: add record: %w", err)
+	}
+
+	d.recordsMu.Lock()
+	d.records[token] = result.Record
+	d.recordsMu.Unlock()
+
+	return nil
+}
+
+// CleanUp removes the TXT record matching the specified parameters.
+func (d *DNSProvider) CleanUp(domain, token, keyAuth string) error {
+	info := dns01.GetChallengeInfo(domain, keyAuth)
+
+	authZone, err := dns01.FindZoneByFqdn(info.EffectiveFQDN)
+	if err != nil {
+		return fmt.Errorf("brandit: %w", err)
+	}
+
+	// gets the record's unique ID
+	d.recordsMu.Lock()
+	dnsRecord, ok := d.records[token]
+	d.recordsMu.Unlock()
+	if !ok {
+		return fmt.Errorf("brandit: unknown record ID for '%s' '%s'", info.EffectiveFQDN, token)
+	}
+
+	// find the account associated with the domain
+	account, err := d.client.StatusDomain(dns01.UnFqdn(authZone))
+	if err != nil {
+		return fmt.Errorf("brandit: status domain: %w", err)
+	}
+
+	records, err := d.client.ListRecords(account.Response.Registrar[0], dns01.UnFqdn(authZone))
+	if err != nil {
+		return fmt.Errorf("brandit: list records: %w", err)
+	}
+
+	var recordID int
+	for i, r := range records.Response.RR {
+		if r == dnsRecord {
+			recordID = i
+		}
+	}
+
+	_, err = d.client.DeleteRecord(dns01.UnFqdn(authZone), account.Response.Registrar[0], dnsRecord, fmt.Sprint(recordID))
+	if err != nil {
+		return fmt.Errorf("brandit: delete record: %w", err)
+	}
+
+	// deletes record ID from map
+	d.recordsMu.Lock()
+	delete(d.records, token)
+	d.recordsMu.Unlock()
+
+	return nil
+}
+
+// Timeout returns the timeout and interval to use when checking for DNS propagation.
+// Adjusting here to cope with spikes in propagation times.
+func (d *DNSProvider) Timeout() (timeout, interval time.Duration) {
+	return d.config.PropagationTimeout, d.config.PollingInterval
+}
diff --git a/providers/dns/brandit/brandit.toml b/providers/dns/brandit/brandit.toml
new file mode 100644
index 00000000..07346c2b
--- /dev/null
+++ b/providers/dns/brandit/brandit.toml
@@ -0,0 +1,24 @@
+Name = "BRANDIT"
+Description = ''''''
+URL = "https://www.brandit.com/"
+Code = "brandit"
+Since = "v4.11.0"
+
+Example = '''
+BRANDIT_API_KEY=xxxxxxxxxxxxxxxxxxxxx \
+BRANDIT_API_USERNAME=yyyyyyyyyyyyyyyyyyyy \
+lego --email myemail@example.com --dns brandit --domains my.example.org run
+'''
+
+[Configuration]
+  [Configuration.Credentials]
+    BRANDIT_API_KEY = "The API key"
+    BRANDIT_API_USERNAME = "The API username"
+  [Configuration.Additional]
+    BRANDIT_POLLING_INTERVAL = "Time between DNS propagation check"
+    BRANDIT_PROPAGATION_TIMEOUT = "Maximum waiting time for DNS propagation"
+    BRANDIT_TTL = "The TTL of the TXT record used for the DNS challenge"
+    BRANDIT_HTTP_TIMEOUT = "API request timeout"
+
+[Links]
+  API = "https://portal.brandit.com/apidocv3"
diff --git a/providers/dns/brandit/internal/client.go b/providers/dns/brandit/internal/client.go
new file mode 100644
index 00000000..d145315d
--- /dev/null
+++ b/providers/dns/brandit/internal/client.go
@@ -0,0 +1,198 @@
+package internal
+
+import (
+	"crypto/hmac"
+	"crypto/sha256"
+	"encoding/hex"
+	"encoding/json"
+	"errors"
+	"fmt"
+	"io"
+	"net/http"
+	"net/url"
+	"strings"
+	"time"
+)
+
+const defaultBaseURL = "https://portal.brandit.com/api/v3/"
+
+// Client a BrandIT DNS API client.
+type Client struct {
+	apiUsername string
+	apiKey      string
+	BaseURL     string
+	HTTPClient  *http.Client
+}
+
+// NewClient creates a new Client.
+func NewClient(apiUsername, apiKey string) (*Client, error) {
+	if apiKey == "" || apiUsername == "" {
+		return nil, errors.New("credentials missing")
+	}
+
+	return &Client{
+		apiUsername: apiUsername,
+		apiKey:      apiKey,
+		BaseURL:     defaultBaseURL,
+		HTTPClient:  &http.Client{Timeout: 10 * time.Second},
+	}, nil
+}
+
+// ListRecords lists all records.
+// https://portal.brandit.com/apidocv3#listDNSRR
+func (c *Client) ListRecords(account, dnsZone string) (*ListRecords, error) {
+	// Create a new query
+	query := url.Values{}
+	query.Add("command", "listDNSRR")
+	query.Add("account", account)
+	query.Add("dnszone", dnsZone)
+
+	result := &ListRecords{}
+
+	err := c.do(query, result)
+	if err != nil {
+		return nil, fmt.Errorf("do: %w", err)
+	}
+
+	for len(result.Response.RR) < result.Response.Total[0] {
+		query.Add("first", fmt.Sprint(result.Response.Last[0]+1))
+
+		tmp := &ListRecords{}
+		err := c.do(query, tmp)
+		if err != nil {
+			return nil, fmt.Errorf("do: %w", err)
+		}
+
+		result.Response.RR = append(result.Response.RR, tmp.Response.RR...)
+		result.Response.Last = tmp.Response.Last
+	}
+
+	return result, nil
+}
+
+// AddRecord adds a DNS record.
+// https://portal.brandit.com/apidocv3#addDNSRR
+func (c *Client) AddRecord(domainName, account, newRecordID string, record Record) (*AddRecord, error) {
+	// Create a new query
+
+	query := url.Values{}
+	query.Add("command", "addDNSRR")
+	query.Add("account", account)
+	query.Add("dnszone", domainName)
+	query.Add("rrdata", strings.Join([]string{record.Name, fmt.Sprint(record.TTL), "IN", record.Type, record.Content}, " "))
+	query.Add("key", newRecordID)
+
+	result := &AddRecord{}
+
+	err := c.do(query, result)
+	if err != nil {
+		return nil, fmt.Errorf("do: %w", err)
+	}
+	result.Record = strings.Join([]string{record.Name, fmt.Sprint(record.TTL), "IN", record.Type, record.Content}, " ")
+
+	return result, nil
+}
+
+// DeleteRecord deletes a DNS record.
+// https://portal.brandit.com/apidocv3#deleteDNSRR
+func (c *Client) DeleteRecord(domainName, account, dnsRecord, recordID string) (*DeleteRecord, error) {
+	// Create a new query
+	query := url.Values{}
+	query.Add("command", "deleteDNSRR")
+	query.Add("account", account)
+	query.Add("dnszone", domainName)
+	query.Add("rrdata", dnsRecord)
+	query.Add("key", recordID)
+
+	result := &DeleteRecord{}
+
+	err := c.do(query, result)
+	if err != nil {
+		return nil, fmt.Errorf("do: %w", err)
+	}
+
+	return result, nil
+}
+
+// StatusDomain returns the status of a domain and account associated with it.
+// https://portal.brandit.com/apidocv3#statusDomain
+func (c *Client) StatusDomain(domain string) (*StatusDomain, error) {
+	// Create a new query
+	query := url.Values{}
+
+	query.Add("command", "statusDomain")
+	query.Add("domain", domain)
+
+	result := &StatusDomain{}
+
+	err := c.do(query, result)
+	if err != nil {
+		return nil, fmt.Errorf("do: %w", err)
+	}
+
+	return result, nil
+}
+
+func (c *Client) do(query url.Values, result any) error {
+	// Add signature
+	v, err := sign(c.apiUsername, c.apiKey, query)
+	if err != nil {
+		return fmt.Errorf("signature: %w", err)
+	}
+
+	resp, err := c.HTTPClient.PostForm(c.BaseURL, v)
+	if err != nil {
+		return err
+	}
+
+	defer func() { _ = resp.Body.Close() }()
+
+	raw, err := io.ReadAll(resp.Body)
+	if err != nil {
+		return fmt.Errorf("read response body: %w", err)
+	}
+
+	//  Unmarshal the error response, because the API returns a 200 OK even if there is an error.
+	var apiError APIError
+	err = json.Unmarshal(raw, &apiError)
+	if err != nil {
+		return fmt.Errorf("unmarshal error response: %w %s", err, string(raw))
+	}
+
+	if apiError.Code > 299 || apiError.Status != "success" {
+		return apiError
+	}
+
+	err = json.Unmarshal(raw, result)
+	if err != nil {
+		return fmt.Errorf("unmarshal response body: %w %s", err, string(raw))
+	}
+
+	return nil
+}
+
+func sign(apiUsername, apiKey string, query url.Values) (url.Values, error) {
+	location, err := time.LoadLocation("GMT")
+	if err != nil {
+		return nil, fmt.Errorf("time location: %w", err)
+	}
+
+	timestamp := time.Now().In(location).Format("2006-01-02T15:04:05Z")
+
+	canonicalRequest := fmt.Sprintf("%s%s%s", apiUsername, timestamp, defaultBaseURL)
+
+	mac := hmac.New(sha256.New, []byte(apiKey))
+	_, err = mac.Write([]byte(canonicalRequest))
+	if err != nil {
+		return nil, err
+	}
+
+	hashed := mac.Sum(nil)
+	signature := hex.EncodeToString(hashed)
+
+	query.Add("user", apiUsername)
+	query.Add("timestamp", timestamp)
+	query.Add("signature", signature)
+
+	return query, nil
+}
diff --git a/providers/dns/brandit/internal/fixtures/add-record.json b/providers/dns/brandit/internal/fixtures/add-record.json
new file mode 100644
index 00000000..8dbbbdd0
--- /dev/null
+++ b/providers/dns/brandit/internal/fixtures/add-record.json
@@ -0,0 +1,14 @@
+{
+  "response": {
+    "zonetype": [
+      "com"
+    ],
+    "signed": [
+      1
+    ]
+  },
+  "record": "example.com. 600 IN TXT txttxttxt",
+  "code": 200,
+  "status": "success",
+  "error": ""
+}
\ No newline at end of file
diff --git a/providers/dns/brandit/internal/fixtures/delete-record.json b/providers/dns/brandit/internal/fixtures/delete-record.json
new file mode 100644
index 00000000..7c203eda
--- /dev/null
+++ b/providers/dns/brandit/internal/fixtures/delete-record.json
@@ -0,0 +1,5 @@
+{
+  "code": 200,
+  "status": "success",
+  "error": ""
+}
\ No newline at end of file
diff --git a/providers/dns/brandit/internal/fixtures/list-records.json b/providers/dns/brandit/internal/fixtures/list-records.json
new file mode 100644
index 00000000..d2cf7ae6
--- /dev/null
+++ b/providers/dns/brandit/internal/fixtures/list-records.json
@@ -0,0 +1,28 @@
+{
+  "response": {
+    "limit": [
+      100
+    ],
+    "column": [
+      "rr"
+    ],
+    "count": [
+      1
+    ],
+    "first": [
+      0
+    ],
+    "total": [
+      1
+    ],
+    "rr": [
+      "example.com. 600 IN TXT txttxttxt"
+    ],
+    "last": [
+      0
+    ]
+  },
+  "code": 200,
+  "status": "success",
+  "error": ""
+}
\ No newline at end of file
diff --git a/providers/dns/brandit/internal/fixtures/status-domain.json b/providers/dns/brandit/internal/fixtures/status-domain.json
new file mode 100644
index 00000000..fc89713a
--- /dev/null
+++ b/providers/dns/brandit/internal/fixtures/status-domain.json
@@ -0,0 +1,80 @@
+{
+  "response": {
+    "renewalmode": [
+      "DEFAULT"
+    ],
+    "status": [
+      "clientTransferProhibited"
+    ],
+    "transferlock": [
+      1
+    ],
+    "registrar": [
+      "brandit"
+    ],
+    "paiduntildate": [
+      "2021-12-15 05:00:00.0"
+    ],
+    "nameserver": [
+      "NS1.RRPPROXY.NET",
+      "NS2.RRPPROXY.NET"
+    ],
+    "registrationexpirationdate": [
+      "2021-12-15 05:00:00.0"
+    ],
+    "domain": [
+      "example.com"
+    ],
+    "renewaldate": [
+      "2024-01-19 05:00:00.0"
+    ],
+    "updateddate": [
+      "2022-12-16 08:01:27.0"
+    ],
+    "billingcontact": [
+      "example"
+    ],
+    "x-domain-roid": [
+      "example"
+    ],
+    "admincontact": [
+      "example"
+    ],
+    "techcontact": [
+      "example"
+    ],
+    "domainidn": [
+      "example.com"
+    ],
+    "createddate": [
+      "2016-12-16 05:00:00.0"
+    ],
+    "registrartransferdate": [
+      "2021-12-09 05:17:42.0"
+    ],
+    "zone": [
+      "com"
+    ],
+    "auth": [
+      "example"
+    ],
+    "updatedby": [
+      "example"
+    ],
+    "roid": [
+      "example"
+    ],
+    "ownercontact": [
+      "example"
+    ],
+    "createdby": [
+      "example"
+    ],
+    "transfermode": [
+      "auto"
+    ]
+  },
+  "code": 200,
+  "status": "success",
+  "error": ""
+}
\ No newline at end of file
diff --git a/providers/dns/brandit/internal/types.go b/providers/dns/brandit/internal/types.go
new file mode 100644
index 00000000..099c5fe1
--- /dev/null
+++ b/providers/dns/brandit/internal/types.go
@@ -0,0 +1,91 @@
+package internal
+
+import "fmt"
+
+type StatusDomain struct {
+	Response StatusResponse `json:"response,omitempty"`
+	Code     int            `json:"code"`
+	Status   string         `json:"status"`
+	Error    string         `json:"error"`
+}
+
+type StatusResponse struct {
+	RenewalMode                []string `json:"renewalmode"`
+	Status                     []string `json:"status"`
+	TransferLock               []int    `json:"transferlock"`
+	Registrar                  []string `json:"registrar"`
+	PaidUntilDate              []string `json:"paiduntildate"`
+	Nameserver                 []string `json:"nameserver"`
+	RegistrationExpirationDate []string `json:"registrationexpirationdate"`
+	Domain                     []string `json:"domain"`
+	RenewalDate                []string `json:"renewaldate"`
+	UpdatedDate                []string `json:"updateddate"`
+	BillingContact             []string `json:"billingcontact"`
+	XDomainRoID                []string `json:"x-domain-roid"`
+	AdminContact               []string `json:"admincontact"`
+	TechContact                []string `json:"techcontact"`
+	DomainIDN                  []string `json:"domainidn"`
+	CreatedDate                []string `json:"createddate"`
+	RegistrarTransferDate      []string `json:"registrartransferdate"`
+	Zone                       []string `json:"zone"`
+	Auth                       []string `json:"auth"`
+	UpdatedBy                  []string `json:"updatedby"`
+	RoID                       []string `json:"roid"`
+	OwnerContact               []string `json:"ownercontact"`
+	CreatedBy                  []string `json:"createdby"`
+	TransferMode               []string `json:"transfermode"`
+}
+
+type ListRecords struct {
+	Response ListRecordsResponse `json:"response,omitempty"`
+	Code     int                 `json:"code"`
+	Status   string              `json:"status"`
+	Error    string              `json:"error"`
+}
+
+type ListRecordsResponse struct {
+	Limit  []int    `json:"limit,omitempty"`
+	Column []string `json:"column,omitempty"`
+	Count  []int    `json:"count,omitempty"`
+	First  []int    `json:"first,omitempty"`
+	Total  []int    `json:"total,omitempty"`
+	RR     []string `json:"rr,omitempty"`
+	Last   []int    `json:"last,omitempty"`
+}
+
+type APIError struct {
+	Code    int    `json:"code"`
+	Status  string `json:"status"`
+	Message string `json:"error"`
+}
+
+func (a APIError) Error() string {
+	return fmt.Sprintf("code: %d, status: %s, message: %s", a.Code, a.Status, a.Message)
+}
+
+type AddRecord struct {
+	Response AddRecordResponse `json:"response"`
+	Record   string            `json:"record"`
+	Code     int               `json:"code"`
+	Status   string            `json:"status"`
+	Error    string            `json:"error"`
+}
+
+type AddRecordResponse struct {
+	ZoneType []string `json:"zonetype"`
+	Signed   []int    `json:"signed"`
+}
+
+type Record struct {
+	ID      int    `json:"id,omitempty"`
+	Type    string `json:"type,omitempty"`
+	Name    string `json:"name,omitempty"` // subdomain name or @ if you don't want subdomain
+	Content string `json:"content,omitempty"`
+	TTL     int    `json:"ttl,omitempty"` // default 600
+}
+
+type DeleteRecord struct {
+	Code   int    `json:"code"`
+	Status string `json:"status"`
+	Error  string `json:"error"`
+}
diff --git a/providers/dns/dns_providers.go b/providers/dns/dns_providers.go
index d27da5d3..685b6f80 100644
--- a/providers/dns/dns_providers.go
+++ b/providers/dns/dns_providers.go
@@ -14,6 +14,7 @@ import (
 	"github.com/go-acme/lego/v4/providers/dns/azure"
 	"github.com/go-acme/lego/v4/providers/dns/bindman"
 	"github.com/go-acme/lego/v4/providers/dns/bluecat"
+	"github.com/go-acme/lego/v4/providers/dns/brandit"
 	"github.com/go-acme/lego/v4/providers/dns/bunny"
 	"github.com/go-acme/lego/v4/providers/dns/checkdomain"
 	"github.com/go-acme/lego/v4/providers/dns/civo"
@@ -143,6 +144,8 @@ func NewDNSChallengeProviderByName(name string) (challenge.Provider, error) {
 		return bindman.NewDNSProvider()
 	case "bluecat":
 		return bluecat.NewDNSProvider()
+	case "brandit":
+		return brandit.NewDNSProvider()
 	case "bunny":
 		return bunny.NewDNSProvider()
 	case "checkdomain":


Test patch:
diff --git a/providers/dns/brandit/brandit_test.go b/providers/dns/brandit/brandit_test.go
new file mode 100644
index 00000000..156e7c3f
--- /dev/null
+++ b/providers/dns/brandit/brandit_test.go
@@ -0,0 +1,141 @@
+package brandit
+
+import (
+	"testing"
+
+	"github.com/go-acme/lego/v4/platform/tester"
+	"github.com/stretchr/testify/require"
+)
+
+const envDomain = envNamespace + "DOMAIN"
+
+var envTest = tester.NewEnvTest(EnvAPIKey, EnvAPIUsername).WithDomain(envDomain)
+
+func TestNewDNSProvider(t *testing.T) {
+	testCases := []struct {
+		desc     string
+		envVars  map[string]string
+		expected string
+	}{
+		{
+			desc: "success",
+			envVars: map[string]string{
+				EnvAPIKey:      "key",
+				EnvAPIUsername: "test_user",
+			},
+		},
+		{
+			desc: "missing API key",
+			envVars: map[string]string{
+				EnvAPIUsername: "test_user",
+			},
+			expected: "brandit: some credentials information are missing: BRANDIT_API_KEY",
+		},
+		{
+			desc: "missing secret",
+			envVars: map[string]string{
+				EnvAPIKey: "key",
+			},
+			expected: "brandit: some credentials information are missing: BRANDIT_API_USERNAME",
+		},
+		{
+			desc:     "missing credentials",
+			envVars:  map[string]string{},
+			expected: "brandit: some credentials information are missing: BRANDIT_API_KEY,BRANDIT_API_USERNAME",
+		},
+	}
+
+	for _, test := range testCases {
+		t.Run(test.desc, func(t *testing.T) {
+			defer envTest.RestoreEnv()
+			envTest.ClearEnv()
+
+			envTest.Apply(test.envVars)
+
+			p, err := NewDNSProvider()
+
+			if test.expected == "" {
+				require.NoError(t, err)
+				require.NotNil(t, p)
+				require.NotNil(t, p.config)
+				require.NotNil(t, p.client)
+			} else {
+				require.EqualError(t, err, test.expected)
+			}
+		})
+	}
+}
+
+func TestNewDNSProviderConfig(t *testing.T) {
+	testCases := []struct {
+		desc     string
+		apiKey   string
+		user     string
+		expected string
+	}{
+		{
+			desc:   "success",
+			apiKey: "key",
+			user:   "test_user",
+		},
+		{
+			desc:     "missing API key",
+			user:     "test_user",
+			expected: "brandit: credentials missing",
+		},
+		{
+			desc:     "missing secret",
+			apiKey:   "key",
+			expected: "brandit: credentials missing",
+		},
+		{
+			desc:     "missing credentials",
+			expected: "brandit: credentials missing",
+		},
+	}
+
+	for _, test := range testCases {
+		t.Run(test.desc, func(t *testing.T) {
+			config := NewDefaultConfig()
+			config.APIKey = test.apiKey
+			config.APIUsername = test.user
+
+			p, err := NewDNSProviderConfig(config)
+
+			if test.expected == "" {
+				require.NoError(t, err)
+				require.NotNil(t, p)
+				require.NotNil(t, p.config)
+				require.NotNil(t, p.client)
+			} else {
+				require.EqualError(t, err, test.expected)
+			}
+		})
+	}
+}
+
+func TestLivePresent(t *testing.T) {
+	if !envTest.IsLiveTest() {
+		t.Skip("skipping live test")
+	}
+
+	envTest.RestoreEnv()
+	provider, err := NewDNSProvider()
+	require.NoError(t, err)
+
+	err = provider.Present(envTest.GetDomain(), "", "123d==")
+	require.NoError(t, err)
+}
+
+func TestLiveCleanUp(t *testing.T) {
+	if !envTest.IsLiveTest() {
+		t.Skip("skipping live test")
+	}
+
+	envTest.RestoreEnv()
+	provider, err := NewDNSProvider()
+	require.NoError(t, err)
+
+	err = provider.CleanUp(envTest.GetDomain(), "", "123d==")
+	require.NoError(t, err)
+}
diff --git a/providers/dns/brandit/internal/client_test.go b/providers/dns/brandit/internal/client_test.go
new file mode 100644
index 00000000..6e75294d
--- /dev/null
+++ b/providers/dns/brandit/internal/client_test.go
@@ -0,0 +1,149 @@
+package internal
+
+import (
+	"io"
+	"net/http"
+	"net/http/httptest"
+	"os"
+	"testing"
+
+	"github.com/stretchr/testify/assert"
+	"github.com/stretchr/testify/require"
+)
+
+func setupTest(t *testing.T, file string) *Client {
+	t.Helper()
+
+	server := httptest.NewServer(http.HandlerFunc(func(rw http.ResponseWriter, r *http.Request) {
+		open, err := os.Open(file)
+		if err != nil {
+			http.Error(rw, err.Error(), http.StatusInternalServerError)
+			return
+		}
+
+		defer func() { _ = open.Close() }()
+
+		rw.WriteHeader(http.StatusOK)
+		_, err = io.Copy(rw, open)
+		if err != nil {
+			http.Error(rw, err.Error(), http.StatusInternalServerError)
+			return
+		}
+	}))
+	t.Cleanup(server.Close)
+
+	client, err := NewClient("test_user", "apiKey")
+	require.NoError(t, err)
+
+	client.HTTPClient = server.Client()
+	client.BaseURL = server.URL
+
+	return client
+}
+
+func TestClient_StatusDomain(t *testing.T) {
+	client := setupTest(t, "./fixtures/status-domain.json")
+
+	domain, err := client.StatusDomain("example.com")
+	require.NoError(t, err)
+
+	expected := &StatusDomain{
+		Response: StatusResponse{
+			RenewalMode:                []string{"DEFAULT"},
+			Status:                     []string{"clientTransferProhibited"},
+			TransferLock:               []int{1},
+			Registrar:                  []string{"brandit"},
+			PaidUntilDate:              []string{"2021-12-15 05:00:00.0"},
+			Nameserver:                 []string{"NS1.RRPPROXY.NET", "NS2.RRPPROXY.NET"},
+			RegistrationExpirationDate: []string{"2021-12-15 05:00:00.0"},
+			Domain:                     []string{"example.com"},
+			RenewalDate:                []string{"2024-01-19 05:00:00.0"},
+			UpdatedDate:                []string{"2022-12-16 08:01:27.0"},
+			BillingContact:             []string{"example"},
+			XDomainRoID:                []string{"example"},
+			AdminContact:               []string{"example"},
+			TechContact:                []string{"example"},
+			DomainIDN:                  []string{"example.com"},
+			CreatedDate:                []string{"2016-12-16 05:00:00.0"},
+			RegistrarTransferDate:      []string{"2021-12-09 05:17:42.0"},
+			Zone:                       []string{"com"},
+			Auth:                       []string{"example"},
+			UpdatedBy:                  []string{"example"},
+			RoID:                       []string{"example"},
+			OwnerContact:               []string{"example"},
+			CreatedBy:                  []string{"example"},
+			TransferMode:               []string{"auto"},
+		},
+		Code:   200,
+		Status: "success",
+		Error:  "",
+	}
+
+	assert.Equal(t, expected, domain)
+}
+
+func TestClient_ListRecords(t *testing.T) {
+	client := setupTest(t, "./fixtures/list-records.json")
+
+	resp, err := client.ListRecords("example", "example.com")
+	require.NoError(t, err)
+
+	expected := &ListRecords{
+		Response: ListRecordsResponse{
+			Limit:  []int{100},
+			Column: []string{"rr"},
+			Count:  []int{1},
+			First:  []int{0},
+			Total:  []int{1},
+			RR:     []string{"example.com. 600 IN TXT txttxttxt"},
+			Last:   []int{0},
+		},
+		Code:   200,
+		Status: "success",
+		Error:  "",
+	}
+
+	assert.Equal(t, expected, resp)
+}
+
+func TestClient_AddRecord(t *testing.T) {
+	client := setupTest(t, "./fixtures/add-record.json")
+
+	testRecord := Record{
+		ID:      2565,
+		Type:    "TXT",
+		Name:    "example.com",
+		Content: "txttxttxt",
+		TTL:     600,
+	}
+	resp, err := client.AddRecord("example.com", "test", "2565", testRecord)
+	require.NoError(t, err)
+
+	expected := &AddRecord{
+		Response: AddRecordResponse{
+			ZoneType: []string{"com"},
+			Signed:   []int{1},
+		},
+		Record: "example.com 600 IN TXT txttxttxt",
+		Code:   200,
+		Status: "success",
+		Error:  "",
+	}
+
+	assert.Equal(t, expected, resp)
+}
+
+func TestClient_DeleteRecord(t *testing.T) {
+	client := setupTest(t, "./fixtures/delete-record.json")
+
+	resp, err := client.DeleteRecord("example.com", "test", "example.com 600 IN TXT txttxttxt", "2374")
+	require.NoError(t, err)
+
+	expected := &DeleteRecord{
+		Code:   200,
+		Status: "success",
+		Error:  "",
+	}
+
+	assert.Equal(t, expected, resp)
+}