I have a deployed MATTERMOST and I want to receive notifications about a successful backup, about an error during a backup there, a web hook is created, I add it to the parameter
–send-http-url=https://************************
–send-http-message=‘{“text”:“Test from Duplicati”}’
during the backup it gives an error:
HTTP Response request failed for: https://*********************** => Response status code does not indicate success: 400 (Bad Request).
Failed to send message: System.Net.Http.HttpRequestException: Response status code does not indicate success: 400 (Bad Request).
=> Response status code does not indicate success: 400 (Bad Request).
I thought the problem was in the format, I experimented, but I could not get the message to be sent.
I tried specifying the output format from duplicate to json. The link is correct, I removed it for security.
The message is sent correctly via powershell.
No, I don't do it in powershell, these are built-in functions in duplicate canary, but I can't use them because they have the wrong format, and it's not clear what's wrong with them.
I think the dev was asking what that means. Basically how does powershell get used?
If you mean you found a way to send directly from powershell, can you give example?
Redact sensitive information, but right now seeing a 400 error is not enough guidance.
There are many different ways to send HTTP, and receivers have their own limitations.
Next question would therefore be what’s the webhook sent to? That controls rejections.
Possibly the provider or software can be researched. Without that it gets into guessing,
unless of course your webhook receiver is unencrypted, in which case looking can help.
Http notifications and ntfy.sh is an example of a webhook receiver limitation.
Yours might be different, but there’s no information on that or on powershell.
Another way to compare against something that works is to use a tester site. webhook.site is an example, but there are other sites that can show result.
Does “during a backup there” mean a backup of Mattermost by Duplicati, reporting
elsewhere, a backup of external Duplicati system reporting to Mattermost, or what?
Incoming webhooks documentation sounds very particular about a lot of the format.
Using PowerShell or curl (or Duplicati) would probably want customization to satisfy.
Duplicati is less configurable than curl or Invoke-WebRequest. Is that your test use?
Some things are probably optional, so if you have a minimal example, please post it.
This is still guessing too much about your webhook usage, so please also clarify that.
If you’re trying to receive webhook into Mattermost from something, it’s unclear if the:
Content-Type: application/json can be replaced with another Content-Type, but
reference to Slack webhooks could probably be researched, but what’s the use case?
EDIT 1:
I tried looking at Slack docs, and about all I could tell is they want application/json.
Maybe you need this one:
--send-http-json-urls (String): HTTP report URLs for sending JSON data
Use this option to set HTTP report URLs for sending JSON data. This option
accepts multiple URLs, seperated by a semi-colon. All URLs will receive the
same data. Note that this option ignores the format and verb settings.
Lots of questions and suggestions above, but when original post says:
do you mean by
--send-http-result-output-format (Enumeration): Select the output format for results
Use this option to select the output format for results. Available formats:
Duplicati, Json
* values: Duplicati, Json
* default value: Duplicati
I think they are predefined message formats, certainly not just as Mattermost might like.
This gets back to the question of what you want. A webhook per their format directions?
You can certainly create Scripts to do what you like, and send what you like, as you like.
My task is simple, there is a built-in function waiting for POST with HEADER application/json, with the body content "text".
When sending with standard tools, I get 400 - which means the format received for the Mattermost API is incorrect. The API is standard and webhooks are used in the CE version of the service, without any additional add-ons and works completely natively.
I tried, but standard messages are not sent with the same error 400, when specifying the format and including with a custom message, as if the body calls the parameter “text” differently.
Probably the problem lies in the header itself because it clearly expects not application/x-www-form-urlencoded but application/json and this can cause problems, but how to change it, maybe there is some parameter? If there is, then I did not find it.
I’m still not hearing anything about PowerShell. Was that once used? Did it work?
Meanwhile, it looks like you try to use Python with requests, and it’s failing. See More complicated POST requests whose example looks a lot to me like your plan.
It reads like it should be setting right header and content, but I don’t use requests.
The hope was to see some send that works, to try to get Duplicati to do the same.
If nothing at all sends to your receiver (is that in Mattermost), hope of that is small.
Built into Mattermost? Got a link saying how that works?
If it never works with anything, that’s out of scope here.
Test adding send-http-message with default value Duplicati %OPERATIONNAME% report for %backup-name% (%machine-id%, %backup-id%, %machine-name%)%RESULT% looks similar. I wonder if it doesn’t work with send-http-json-urls? Not my area of expertise.
You don’t say what options you use, but I’d guess the above is the “custom message” (but maybe not respected in my test). I previously guessed on “specifying the format”, so next I
Test adding send-http-result-output-format=Json, and it still sends the same format.
Test changing send-http-json-urls to send-http-url. Still sends the same old format.
Test changing to send-http-result-output-format=Duplicati, and its format changes:
POST / HTTP/1.1
Host: 192.168.86.178:8000
Content-Type: application/x-www-form-urlencoded
Content-Length: 3398
message=Duplicati%20Backup%20report%20for%20test%204%20%285719973b9fa74b9d93d70300e8a5fd58%2C%20DB-7%2C%20HP4%29%0D%0A%0D%0ADeletedFiles%3A%200%0D%0ADeletedFolders%3A%200%0D%0AModifiedFiles%3A%200%0D%0AExaminedFiles%3A%201%0D%0AOpenedFiles%3A%200%0D%0AAddedFiles%3A%200%0D%0ASizeOfModifiedFiles%3A%200%0D%0ASizeOfAddedFiles%3A%200%0D%0ASizeOfExaminedFiles%3A%2039%0D%0ASizeOfOpenedFiles%3A%200%0D%0ANotProcessedFiles%3A%200%0D%0AAddedFolders%3A%200%0D%0ATooLargeFiles%3A%200%0D%0AFilesWithError%3A%200%0D%0AModifiedFolders%3A%200%0D%0AModifiedSymlinks%3A%200%0D%0AAddedSymlinks%3A%200%0D%0ADeletedSymlinks%3A%200%0D%0APartialBackup%3A%20False%0D%0ADryrun%3A%20False%0D%0AMainOperation%3A%20Backup%0D%0AParsedResult%3A%20Success%0D%0AInterrupted%3A%20False%0D%0AFatal%3A%20False%0D%0AVersion%3A%202.1.0.5%20%282.1.0.5_stable_2025-03-04%29%0D%0AEndTime%3A%208%2F22%2F2025%205%3A40%3A54%20PM%20%281755898854%29%0D%0ABeginTime%3A%208%2F22%2F2025%205%3A40%3A53%20PM%20%281755898853%29%0D%0ADuration%3A%2000%3A00%3A01.2718811%0D%0AMessagesActualLength%3A%2012%0D%0AWarningsActualLength%3A%200%0D%0AErrorsActualLength%3A%200%0D%0ALimitedMessages%3A%20%5B%0D%0A%20%20%20%202025-08-22%2017%3A40%3A53%20-04%20-%20%5BInformation-Duplicati.Library.Main.Controller-StartingOperation%5D%3A%20The%20operation%20Backup%20has%20started%2C%0D%0A%20%20%20%202025-08-22%2017%3A40%3A53%20-04%20-%20%5BInformation-Duplicati.Library.Main.BasicResults-BackendEvent%5D%3A%20Backend%20event%3A%20List%20-%20Started%3A%20%20%28%29%2C%0D%0A%20%20%20%202025-08-22%2017%3A40%3A53%20-04%20-%20%5BInformation-Duplicati.Library.Main.BasicResults-BackendEvent%5D%3A%20Backend%20event%3A%20List%20-%20Completed%3A%20%20%283%20bytes%29%2C%0D%0A%20%20%20%202025-08-22%2017%3A40%3A54%20-04%20-%20%5BInformation-Duplicati.Library.Main.BasicResults-BackendEvent%5D%3A%20Backend%20event%3A%20List%20-%20Started%3A%20%20%28%29%2C%0D%0A%20%20%20%202025-08-22%2017%3A40%3A54%20-04%20-%20%5BInformation-Duplicati.Library.Main.BasicResults-BackendEvent%5D%3A%20Backend%20event%3A%20List%20-%20Completed%3A%20%20%283%20bytes%29%2C%0D%0A%20%20%20%202025-08-22%2017%3A40%3A54%20-04%20-%20%5BInformation-Duplicati.Library.Main.BasicResults-BackendEvent%5D%3A%20Backend%20event%3A%20Get%20-%20Started%3A%20duplicati-20250601T194642Z.dlist.zip.aes%20%281021%20bytes%29%2C%0D%0A%20%20%20%202025-08-22%2017%3A40%3A54%20-04%20-%20%5BInformation-Duplicati.Library.Main.BasicResults-BackendEvent%5D%3A%20Backend%20event%3A%20Get%20-%20Completed%3A%20duplicati-20250601T194642Z.dlist.zip.aes%20%281021%20bytes%29%2C%0D%0A%20%20%20%202025-08-22%2017%3A40%3A54%20-04%20-%20%5BInformation-Duplicati.Library.Main.BasicResults-BackendEvent%5D%3A%20Backend%20event%3A%20Get%20-%20Started%3A%20duplicati-i3b430982f6bf4fbfb75a9add96646723.dindex.zip.aes%20%28989%20bytes%29%2C%0D%0A%20%20%20%202025-08-22%2017%3A40%3A54%20-04%20-%20%5BInformation-Duplicati.Library.Main.BasicResults-BackendEvent%5D%3A%20Backend%20event%3A%20Get%20-%20Completed%3A%20duplicati-i3b430982f6bf4fbfb75a9add96646723.dindex.zip.aes%20%28989%20bytes%29%2C%0D%0A%20%20%20%202025-08-22%2017%3A40%3A54%20-04%20-%20%5BInformation-Duplicati.Library.Main.BasicResults-BackendEvent%5D%3A%20Backend%20event%3A%20Get%20-%20Started%3A%20duplicati-b025305832d4940ff81ba5a3e732914f8.dblock.zip.aes%20%281.04%20KB%29%2C%0D%0A...%0D%0A%5D%0D%0ALimitedWarnings%3A%20%5B%5D%0D%0ALimitedErrors%3A%20%5B%5D
So now change to --send-http-message=test for something more custom and compact.
POST / HTTP/1.1
Host: 192.168.86.178:8000
Content-Type: application/x-www-form-urlencoded
Content-Length: 12
message=test
Change send-http-url back to send-http-json-urls and it’s back to application/json, however it’s also back to the standard JSON stats that were typical early on in these tests.
I don’t know what you did or even if you did it in Duplicati. What’s body and parameter talk?
Regardless, there’s some Duplicati testing for you on 2.1.0.5, and I didn’t test a newer one.
For your Python script, I added indentation back and tried it to webhook.site which reports:
content-type application/json and content {"username": "Telegram", "text": "test", "icon_url": ""}
From Duplicati view, some option interactions (or lack thereof) could be documented more.
EDIT 1:
Added send-http-extra-parameters=parameter1=value1 but had to send-http-url.
POST / HTTP/1.1
Host: 192.168.86.178:8000
Content-Type: application/x-www-form-urlencoded
Content-Length: 32
message=test¶meter1%3Dvalue1
The combination of application/json plus customized data send still appears elusive, meaning you might have to send post with an external tool – except those are failing too.
Can’t help much more if external sender can’t communicate with your webhook receiver.
EDIT 2:
These new options allows multiple urls to be set, and will ignore the verb and format parameters, but otherwise work the same.
is the change and says some of what is ignored, but how are the users informed of that?
I wonder if some other options have long been ignored so aren’t specifically named now.
Having seen send-http-url respect send-http-extra-parameters and send-http-message just above, but with unwanted Content-Type and not JSON, change options to send-http-result-output-format=Json and both those data options are now ignored.
Not sure I agree with that (as seen from the outputs I posted), but getting JSON exactly as one might desire looks hard. Duplicati is not a general-purpose tool for arbitrary webhooks.
--send-http-extra-parameters (String): Extra parameters for the message sent
Use this option to set extra parameters for the message body. This
parameter can either be a querystring (e.g.
'parameter1=value1¶meter2=value2') or a JSON key/value object.
So far I have 2.1.1.100_canary_2025-08-08 sending JSON which pretty-prints like this:
As for sending custom data, I used the example from help text and the data did get sent, however it might not be exactly in JSON position that a webhook receiver might prefer it.
EDIT 1:
The issue that was closed says:
The --send-http-extra-parameters were added as a hacky way to add custom data.
With #6078 this is changed to be data input. For JSON reports, this will add any values into the Extra element in the JSON object.
For template based (i.e. text) the keys need to be in the template or they will be ignored.
and I’m not sure if the last line says that JSON templates don’t work. They don’t seem to.
Here’s what I was trying to force. I see it reading from file, but the contents don’t get sent:
The last line here also dims my hope that a JSON template works (but why shouldn’t it?):
EDIT 3:
One reason that JSON template could get complicated is that replacements might turn what used to be good JSON into bad JSON, so one would have to plan some handling.
EDIT 4:
Additionally, the template mechanism has inherent limitations. A script that looks at the results of the operation, decides what to say, and sends it will have a lot more flexibility.
EDIT 5:
I’d think that an alternative to getting the webhook format perfect on first send is to have something receive it, look it over (fields are already well broken out), and send webhook.
On character escapes question, there seem to be lots of libraries available that can do it. Something’s fortunately already doing it for the extra values that I configured in ngax UI (because ngclient seems to trip over special characters). For example, if I set the option:
The issue is I believe he needs to specify a totally custom body so as to be accepted by the API on mattermost and enforce the application/json which there isn’t really a way to do.
I am not even sure how he would deal with authentication needs of his endpoint.
IMO the only route is for him to run a script where he can tailor the request and handle authentication process.
It depends on what is being used. Incoming webhooks documentation gives example:
POST /hooks/xxx-generatedkey-xxx HTTP/1.1
Host: your-mattermost-server.com
Content-Type: application/json
Content-Length: 630
{
"channel": "town-square",
"username": "test-automation",
"icon_url": "https://mattermost.com/wp-content/uploads/2022/02/icon.png",
"text": "#### Test results for July 27th, 2017\n@channel please review failed tests.\n\n| Component | Tests Run | Tests Failed |\n|:-----------|:-----------:|:-----------------------------------------------|\n| Server | 948 | ✅ 0 |\n| Web Client | 123 | ⚠️ 2 [(see details)](https://linktologs) |\n| iOS Client | 78 | ⚠️ 3 [(see details)](https://linktologs) |"
}
and for security, it cautions:
You will end up with a webhook endpoint that looks like so:
https://your-mattermost-server.com/hooks/xxx-generatedkey-xxx
Treat this endpoint as a secret. Anyone who has it will be able to post messages to your Mattermost instance.
Not if the standard incoming webhook feature is used. The auth is by data in the URL.
I would note that the Python script is using username, text, and icon_url from this doc.
Maybe the intent is to hit the Mattermost incoming webhook facility, but we don’t know.
EDIT 1:
I posted an edit to prior post, suggesting a Python receiver and resender if it’s needed.
I think that the Content-Type is handled, JSON template isn’t, and headers aren’t either.
The issue is when you opt for ResultExportFormat.Json, then there is no such thing as a template that is formatted as with using Duplicati’s format.
Perhaps it could be expanded into ResultExportFormat.CustomJson, where the variables are avaliable such as they are when using ResultExportFormat.Duplicati, including an extra one like %REPORTJSON% so it could be added as a child to the custom json.