Actually apply the pre-commit fixers to the codebase.

This can be redone manually with
`pre-commit run --all`

While the pre-commit hook could be merged to run locally,
it is much cleaner to align all the files to best-practice
syntax in a single commit. It is also required for server-side
validation.
This commit is contained in:
Nick Farrell 2022-12-17 18:22:37 +11:00
parent 108ad3c7c3
commit b218e62ffc
No known key found for this signature in database
GPG key ID: 740D3A86CF435835
151 changed files with 42251 additions and 31034 deletions

View file

@ -1,6 +1,6 @@
# Publishing
Publishing messages can be done via HTTP PUT/POST or via the [ntfy CLI](install.md). Topics are created on the fly by
subscribing or publishing to them. Because there is no sign-up, **the topic is essentially a password**, so pick
Publishing messages can be done via HTTP PUT/POST or via the [ntfy CLI](install.md). Topics are created on the fly by
subscribing or publishing to them. Because there is no sign-up, **the topic is essentially a password**, so pick
something that's not easily guessable.
Here's an example showing how to publish a simple message using a POST request:
@ -43,7 +43,7 @@ Here's an example showing how to publish a simple message using a POST request:
=== "Python"
``` python
requests.post("https://ntfy.sh/mytopic",
requests.post("https://ntfy.sh/mytopic",
data="Backup successful 😀".encode(encoding='utf-8'))
```
@ -65,7 +65,7 @@ If you have the [Android app](subscribe/phone.md) installed on your phone, this
<figcaption>Android notification</figcaption>
</figure>
There are more features related to publishing messages: You can set a [notification priority](#message-priority),
There are more features related to publishing messages: You can set a [notification priority](#message-priority),
a [title](#message-title), and [tag messages](#tags-emojis) 🥳 🎉. Here's an example that uses some of them at together:
=== "Command line (curl)"
@ -95,7 +95,7 @@ a [title](#message-title), and [tag messages](#tags-emojis) 🥳 🎉. Here's an
Title: Unauthorized access detected
Priority: urgent
Tags: warning,skull
Remote access to phils-laptop detected. Act right away.
```
@ -128,10 +128,10 @@ a [title](#message-title), and [tag messages](#tags-emojis) 🥳 🎉. Here's an
$headers = @{ Title="Unauthorized access detected"
Priority="urgent"
Tags="warning,skull" }
$body = "Remote access to phils-laptop detected. Act right away."
$body = "Remote access to phils-laptop detected. Act right away."
Invoke-RestMethod -Method 'Post' -Uri $uri -Headers $headers -Body $body -UseBasicParsing
```
=== "Python"
``` python
requests.post("https://ntfy.sh/phil_alerts",
@ -174,8 +174,8 @@ an [external image attachment](#attach-file-from-a-url) and [email publishing](#
-H "Actions: http, Open door, https://api.nest.com/open/yAxkasd, clear=true" \
-H "Email: phil@example.com" \
-d "There's someone at the door. 🐶
Please check if it's a good boy or a hooman.
Please check if it's a good boy or a hooman.
Doggies have been known to ring the doorbell." \
ntfy.sh/mydoorbell
```
@ -189,8 +189,8 @@ an [external image attachment](#attach-file-from-a-url) and [email publishing](#
--email="phil@example.com" \
mydoorbell \
"There's someone at the door. 🐶
Please check if it's a good boy or a hooman.
Please check if it's a good boy or a hooman.
Doggies have been known to ring the doorbell."
```
@ -202,13 +202,13 @@ an [external image attachment](#attach-file-from-a-url) and [email publishing](#
Attach: https://nest.com/view/yAxkasd.jpg
Actions: http, Open door, https://api.nest.com/open/yAxkasd, clear=true
Email: phil@example.com
There's someone at the door. 🐶
Please check if it's a good boy or a hooman.
Please check if it's a good boy or a hooman.
Doggies have been known to ring the doorbell.
```
=== "JavaScript"
``` javascript
fetch('https://ntfy.sh/mydoorbell', {
@ -220,8 +220,8 @@ an [external image attachment](#attach-file-from-a-url) and [email publishing](#
'Email': 'phil@example.com'
},
body: `There's someone at the door. 🐶
Please check if it's a good boy or a hooman.
Please check if it's a good boy or a hooman.
Doggies have been known to ring the doorbell.`,
})
```
@ -230,8 +230,8 @@ an [external image attachment](#attach-file-from-a-url) and [email publishing](#
``` go
req, _ := http.NewRequest("POST", "https://ntfy.sh/mydoorbell",
strings.NewReader(`There's someone at the door. 🐶
Please check if it's a good boy or a hooman.
Please check if it's a good boy or a hooman.
Doggies have been known to ring the doorbell.`))
req.Header.Set("Click", "https://home.nest.com/")
req.Header.Set("Attach", "https://nest.com/view/yAxkasd.jpg")
@ -249,7 +249,7 @@ an [external image attachment](#attach-file-from-a-url) and [email publishing](#
Email="phil@example.com" }
$body = @'
There's someone at the door. 🐶
Please check if it's a good boy or a hooman.
Doggies have been known to ring the doorbell.
'@
@ -283,7 +283,7 @@ an [external image attachment](#attach-file-from-a-url) and [email publishing](#
"Actions": "http, Open door, https://api.nest.com/open/yAxkasd, clear=true\r\n" .
"Email": "phil@example.com\r\n",
'content' => 'There\'s someone at the door. 🐶
Please check if it\'s a good boy or a hooman.
Doggies have been known to ring the doorbell.'
]
@ -298,7 +298,7 @@ an [external image attachment](#attach-file-from-a-url) and [email publishing](#
## Message title
_Supported on:_ :material-android: :material-apple: :material-firefox:
The notification title is typically set to the topic short URL (e.g. `ntfy.sh/mytopic`). To override the title,
The notification title is typically set to the topic short URL (e.g. `ntfy.sh/mytopic`). To override the title,
you can set the `X-Title` header (or any of its aliases: `Title`, `ti`, or `t`).
=== "Command line (curl)"
@ -320,7 +320,7 @@ you can set the `X-Title` header (or any of its aliases: `Title`, `ti`, or `t`).
POST /controversial HTTP/1.1
Host: ntfy.sh
Title: Dogs are better than cats
Oh my ...
```
@ -400,7 +400,7 @@ You can set the priority with the header `X-Priority` (or any of its aliases: `P
=== "ntfy CLI"
```
ntfy publish \
ntfy publish \
-p 5 \
phil_alerts An urgent message
```
@ -437,7 +437,7 @@ You can set the priority with the header `X-Priority` (or any of its aliases: `P
$body = "An urgent message"
Invoke-RestMethod -Method 'Post' -Uri $uri -Headers $headers -Body $body -UseBasicParsing
```
=== "Python"
``` python
requests.post("https://ntfy.sh/phil_alerts",
@ -468,12 +468,12 @@ _Supported on:_ :material-android: :material-apple: :material-firefox:
You can tag messages with emojis and other relevant strings:
* **Emojis**: If a tag matches an [emoji short code](emojis.md), it'll be converted to an emoji and prepended
* **Emojis**: If a tag matches an [emoji short code](emojis.md), it'll be converted to an emoji and prepended
to title or message.
* **Other tags:** If a tag doesn't match, it will be listed below the notification.
* **Other tags:** If a tag doesn't match, it will be listed below the notification.
This feature is useful for things like warnings (⚠️, ️🚨, or 🚩), but also to simply tag messages otherwise (e.g. script
names, hostnames, etc.). Use [the emoji short code list](emojis.md) to figure out what tags can be converted to emojis.
This feature is useful for things like warnings (⚠️, ️🚨, or 🚩), but also to simply tag messages otherwise (e.g. script
names, hostnames, etc.). Use [the emoji short code list](emojis.md) to figure out what tags can be converted to emojis.
Here's an **excerpt of emojis** I've found very useful in alert messages:
<table class="remove-md-box"><tr>
@ -488,7 +488,7 @@ Here's an **excerpt of emojis** I've found very useful in alert messages:
</tbody></table>
</td>
<td>
<table><thead><tr><th>Tag</th><th>Emoji</th></tr></thead><tbody>
<table><thead><tr><th>Tag</th><th>Emoji</th></tr></thead><tbody>
<tr><td><code>-1</code></td><td>👎️</td></tr>
<tr><td><code>warning</code></td><td>⚠️</td></tr>
<tr><td><code>rotating_light</code></td><td>️🚨</td></tr>
@ -502,7 +502,7 @@ Here's an **excerpt of emojis** I've found very useful in alert messages:
<tr><td><code>facepalm</code></td><td>🤦</td></tr>
<tr><td><code>no_entry</code></td><td></td></tr>
<tr><td><code>no_entry_sign</code></td><td>🚫</td></tr>
<tr><td><code>cd</code></td><td>💿</td></tr>
<tr><td><code>cd</code></td><td>💿</td></tr>
<tr><td><code>computer</code></td><td>💻</td></tr>
<tr><td>...</td><td>...</td></tr>
</tbody></table>
@ -531,7 +531,7 @@ them with a comma, e.g. `tag1,tag2,tag3`.
POST /backups HTTP/1.1
Host: ntfy.sh
Tags: warning,mailsrv13,daily-backup
Backup of mailsrv13 failed
```
@ -587,22 +587,22 @@ them with a comma, e.g. `tag1,tag2,tag3`.
## Scheduled delivery
_Supported on:_ :material-android: :material-apple: :material-firefox:
You can delay the delivery of messages and let ntfy send them at a later date. This can be used to send yourself
You can delay the delivery of messages and let ntfy send them at a later date. This can be used to send yourself
reminders or even to execute commands at a later date (if your subscriber acts on messages).
Usage is pretty straight forward. You can set the delivery time using the `X-Delay` header (or any of its aliases: `Delay`,
`X-At`, `At`, `X-In` or `In`), either by specifying a Unix timestamp (e.g. `1639194738`), a duration (e.g. `30m`,
`3h`, `2 days`), or a natural language time string (e.g. `10am`, `8:30pm`, `tomorrow, 3pm`, `Tuesday, 7am`,
[and more](https://github.com/olebedev/when)).
Usage is pretty straight forward. You can set the delivery time using the `X-Delay` header (or any of its aliases: `Delay`,
`X-At`, `At`, `X-In` or `In`), either by specifying a Unix timestamp (e.g. `1639194738`), a duration (e.g. `30m`,
`3h`, `2 days`), or a natural language time string (e.g. `10am`, `8:30pm`, `tomorrow, 3pm`, `Tuesday, 7am`,
[and more](https://github.com/olebedev/when)).
As of today, the minimum delay you can set is **10 seconds** and the maximum delay is **3 days**. This can currently
not be configured otherwise ([let me know](https://github.com/binwiederhier/ntfy/issues) if you'd like to change
not be configured otherwise ([let me know](https://github.com/binwiederhier/ntfy/issues) if you'd like to change
these limits).
For the purposes of [message caching](config.md#message-cache), scheduled messages are kept in the cache until 12 hours
For the purposes of [message caching](config.md#message-cache), scheduled messages are kept in the cache until 12 hours
after they were delivered (or whatever the server-side cache duration is set to). For instance, if a message is scheduled
to be delivered in 3 days, it'll remain in the cache for 3 days and 12 hours. Also note that naturally,
[turning off server-side caching](#message-caching) is not possible in combination with this feature.
to be delivered in 3 days, it'll remain in the cache for 3 days and 12 hours. Also note that naturally,
[turning off server-side caching](#message-caching) is not possible in combination with this feature.
=== "Command line (curl)"
```
@ -650,7 +650,7 @@ to be delivered in 3 days, it'll remain in the cache for 3 days and 12 hours. Al
$body = "Good morning"
Invoke-RestMethod -Method 'Post' -Uri $uri -Headers $headers -Body $body -UseBasicParsing
```
=== "Python"
``` python
requests.post("https://ntfy.sh/hello",
@ -686,19 +686,19 @@ Here are a few examples (assuming today's date is **12/10/2021, 9am, Eastern Tim
</td>
</tr></table>
## Webhooks (publish via GET)
## Webhooks (publish via GET)
_Supported on:_ :material-android: :material-apple: :material-firefox:
In addition to using PUT/POST, you can also send to topics via simple HTTP GET requests. This makes it easy to use
In addition to using PUT/POST, you can also send to topics via simple HTTP GET requests. This makes it easy to use
a ntfy topic as a [webhook](https://en.wikipedia.org/wiki/Webhook), or if your client has limited HTTP support (e.g.
like the [MacroDroid](https://play.google.com/store/apps/details?id=com.arlosoft.macrodroid) Android app).
To send messages via HTTP GET, simply call the `/publish` endpoint (or its aliases `/send` and `/trigger`). Without
any arguments, this will send the message `triggered` to the topic. However, you can provide all arguments that are
also supported as HTTP headers as URL-encoded arguments. Be sure to check the list of all
To send messages via HTTP GET, simply call the `/publish` endpoint (or its aliases `/send` and `/trigger`). Without
any arguments, this will send the message `triggered` to the topic. However, you can provide all arguments that are
also supported as HTTP headers as URL-encoded arguments. Be sure to check the list of all
[supported parameters and headers](#list-of-all-parameters) for details.
For instance, assuming your topic is `mywebhook`, you can simply call `/mywebhook/trigger` to send a message
For instance, assuming your topic is `mywebhook`, you can simply call `/mywebhook/trigger` to send a message
(aka trigger the webhook):
=== "Command line (curl)"
@ -730,7 +730,7 @@ For instance, assuming your topic is `mywebhook`, you can simply call `/mywebhoo
=== "PowerShell"
``` powershell
Invoke-RestMethod -Method 'Get' -Uri "ntfy.sh/mywebhook/trigger"
```
```
=== "Python"
``` python
@ -742,8 +742,8 @@ For instance, assuming your topic is `mywebhook`, you can simply call `/mywebhoo
file_get_contents('https://ntfy.sh/mywebhook/trigger');
```
To add a custom message, simply append the `message=` URL parameter. And of course you can set the
[message priority](#message-priority), the [message title](#message-title), and [tags](#tags-emojis) as well.
To add a custom message, simply append the `message=` URL parameter. And of course you can set the
[message priority](#message-priority), the [message title](#message-title), and [tags](#tags-emojis) as well.
For a full list of possible parameters, check the list of [supported parameters and headers](#list-of-all-parameters).
Here's an example with a custom message, tags and a priority:
@ -794,8 +794,8 @@ Here's an example with a custom message, tags and a priority:
## Publish as JSON
_Supported on:_ :material-android: :material-apple: :material-firefox:
For some integrations with other tools (e.g. [Jellyfin](https://jellyfin.org/), [overseerr](https://overseerr.dev/)),
adding custom headers to HTTP requests may be tricky or impossible, so ntfy also allows publishing the entire message
For some integrations with other tools (e.g. [Jellyfin](https://jellyfin.org/), [overseerr](https://overseerr.dev/)),
adding custom headers to HTTP requests may be tricky or impossible, so ntfy also allows publishing the entire message
as JSON in the request body.
To publish as JSON, simple PUT/POST the JSON object directly to the ntfy root URL. The message format is described below
@ -803,9 +803,9 @@ the example.
!!! info
To publish as JSON, you must **PUT/POST to the ntfy root URL**, not to the topic URL. Be sure to check that you're
POST-ing to `https://ntfy.sh/` (correct), and not to `https://ntfy.sh/mytopic` (incorrect).
POST-ing to `https://ntfy.sh/` (correct), and not to `https://ntfy.sh/mytopic` (incorrect).
Here's an example using most supported parameters. Check the table below for a complete list. The `topic` parameter
Here's an example using most supported parameters. Check the table below for a complete list. The `topic` parameter
is the only required one:
=== "Command line (curl)"
@ -863,9 +863,9 @@ is the only required one:
=== "Go"
``` go
// You should probably use json.Marshal() instead and make a proper struct,
// or even just use req.Header.Set() like in the other examples, but for the
// or even just use req.Header.Set() like in the other examples, but for the
// sake of the example, this is easier.
body := `{
"topic": "mytopic",
"message": "Disk space is low at 5.1 GB",
@ -894,7 +894,7 @@ is the only required one:
tags = @("warning", "cd")
click = "https://homecamera.lan/xasds1h2xsSsa/"
actions = @(
@{
@{
action = "view"
label = "Admin panel"
url = "https://filesrv.lan/admin"
@ -942,7 +942,7 @@ is the only required one:
]));
```
The JSON message format closely mirrors the format of the message you can consume when you [subscribe via the API](subscribe/api.md)
The JSON message format closely mirrors the format of the message you can consume when you [subscribe via the API](subscribe/api.md)
(see [JSON message format](subscribe/api.md#json-message-format) for details), but is not exactly identical. Here's an overview of
all the supported fields:
@ -964,9 +964,9 @@ all the supported fields:
_Supported on:_ :material-android: :material-apple: :material-firefox:
You can add action buttons to notifications to allow yourself to react to a notification directly. This is incredibly
useful and has countless applications.
useful and has countless applications.
You can control your home appliances (open/close garage door, change temperature on thermostat, ...), react to common
You can control your home appliances (open/close garage door, change temperature on thermostat, ...), react to common
monitoring alerts (clear logs when disk is full, ...), and many other things. The sky is the limit.
As of today, the following actions are supported:
@ -987,7 +987,7 @@ Here's an example of what that a notification with actions can look like:
You can define **up to three user actions** in your notifications, using either of the following methods:
* In the [`X-Actions` header](#using-a-header), using a simple comma-separated format
* As a [JSON array](#using-a-json-array) in the `actions` key, when [publishing as JSON](#publish-as-json)
* As a [JSON array](#using-a-json-array) in the `actions` key, when [publishing as JSON](#publish-as-json)
#### Using a header
To define actions using the `X-Actions` header (or any of its aliases: `Actions`, `Action`), use the following format:
@ -1002,14 +1002,14 @@ To define actions using the `X-Actions` header (or any of its aliases: `Actions`
<action1>, <label1>, paramN=... [; <action2>, <label2>, ...]
```
Multiple actions are separated by a semicolon (`;`), and key/value pairs are separated by commas (`,`). Values may be
quoted with double quotes (`"`) or single quotes (`'`) if the value itself contains commas or semicolons.
Multiple actions are separated by a semicolon (`;`), and key/value pairs are separated by commas (`,`). Values may be
quoted with double quotes (`"`) or single quotes (`'`) if the value itself contains commas or semicolons.
The `action=` and `label=` prefix are optional in all actions, and the `url=` prefix is optional in the `view` and
`http` action. The only limitation of this format is that depending on your language/library, UTF-8 characters may not
The `action=` and `label=` prefix are optional in all actions, and the `url=` prefix is optional in the `view` and
`http` action. The only limitation of this format is that depending on your language/library, UTF-8 characters may not
work. If they don't, use the [JSON array format](#using-a-json-array) instead.
As an example, here's how you can create the above notification using this format. Refer to the [`view` action](#open-websiteapp) and
As an example, here's how you can create the above notification using this format. Refer to the [`view` action](#open-websiteapp) and
[`http` action](#send-http-request) section for details on the specific actions:
=== "Command line (curl)"
@ -1046,8 +1046,8 @@ As an example, here's how you can create the above notification using this forma
fetch('https://ntfy.sh/myhome', {
method: 'POST',
body: 'You left the house. Turn down the A/C?',
headers: {
'Actions': 'view, Open portal, https://home.nest.com/, clear=true; http, Turn down, https://api.nest.com/, body=\'{"temperature": 65}\''
headers: {
'Actions': 'view, Open portal, https://home.nest.com/, clear=true; http, Turn down, https://api.nest.com/, body=\'{"temperature": 65}\''
}
})
```
@ -1086,9 +1086,9 @@ As an example, here's how you can create the above notification using this forma
]
]));
```
#### Using a JSON array
Alternatively, the same actions can be defined as **JSON array**, if the notification is defined as part of the JSON body
Alternatively, the same actions can be defined as **JSON array**, if the notification is defined as part of the JSON body
(see [publish as JSON](#publish-as-json)):
=== "Command line (curl)"
@ -1189,7 +1189,7 @@ Alternatively, the same actions can be defined as **JSON array**, if the notific
``` go
// You should probably use json.Marshal() instead and make a proper struct,
// but for the sake of the example, this is easier.
body := `{
"topic": "myhome",
"message": "You left the house. Turn down the A/C?",
@ -1291,16 +1291,16 @@ Alternatively, the same actions can be defined as **JSON array**, if the notific
]));
```
The required/optional fields for each action depend on the type of the action itself. Please refer to
[`view` action](#open-websiteapp), [`broadcasst` action](#send-android-broadcast), and [`http` action](#send-http-request)
The required/optional fields for each action depend on the type of the action itself. Please refer to
[`view` action](#open-websiteapp), [`broadcasst` action](#send-android-broadcast), and [`http` action](#send-http-request)
for details.
### Open website/app
_Supported on:_ :material-android: :material-apple: :material-firefox:
The `view` action **opens a website or app when the action button is tapped**, e.g. a browser, a Google Maps location, or
even a deep link into Twitter or a show ntfy topic. How exactly the action is handled depends on how Android and your
desktop browser treat the links. Normally it'll just open a link in the browser.
even a deep link into Twitter or a show ntfy topic. How exactly the action is handled depends on how Android and your
desktop browser treat the links. Normally it'll just open a link in the browser.
Examples:
@ -1343,8 +1343,8 @@ Here's an example using the [`X-Actions` header](#using-a-header):
fetch('https://ntfy.sh/myhome', {
method: 'POST',
body: 'Somebody retweeted your tweet.',
headers: {
'Actions': 'view, Open Twitter, https://twitter.com/binwiederhier/status/1467633927951163392'
headers: {
'Actions': 'view, Open Twitter, https://twitter.com/binwiederhier/status/1467633927951163392'
}
})
```
@ -1456,7 +1456,7 @@ And the same example using [JSON publishing](#publish-as-json):
``` go
// You should probably use json.Marshal() instead and make a proper struct,
// but for the sake of the example, this is easier.
body := `{
"topic": "myhome",
"message": "Somebody retweeted your tweet.",
@ -1585,8 +1585,8 @@ Here's an example using the [`X-Actions` header](#using-a-header):
fetch('https://ntfy.sh/wifey', {
method: 'POST',
body: 'Your wife requested you send a picture of yourself.',
headers: {
'Actions': 'broadcast, Take picture, extras.cmd=pic, extras.camera=front'
headers: {
'Actions': 'broadcast, Take picture, extras.cmd=pic, extras.camera=front'
}
})
```
@ -1710,7 +1710,7 @@ And the same example using [JSON publishing](#publish-as-json):
``` go
// You should probably use json.Marshal() instead and make a proper struct,
// but for the sake of the example, this is easier.
body := `{
"topic": "wifey",
"message": "Your wife requested you send a picture of yourself.",
@ -1812,7 +1812,7 @@ The `http` action **sends a HTTP request when the action button is tapped**. You
for whatever systems you have, e.g. opening the garage door, or turning on/off lights.
By default, this action sends a **POST request** (not GET!), though this can be changed with the `method` parameter.
The only required parameter is `url`. Headers can be passed along using the `headers` parameter.
The only required parameter is `url`. Headers can be passed along using the `headers` parameter.
Here's an example using the [`X-Actions` header](#using-a-header):
@ -1846,8 +1846,8 @@ Here's an example using the [`X-Actions` header](#using-a-header):
fetch('https://ntfy.sh/myhome', {
method: 'POST',
body: 'Garage door has been open for 15 minutes. Close it?',
headers: {
'Actions': 'http, Close door, https://api.mygarage.lan/, method=PUT, headers.Authorization=Bearer zAzsx1sk.., body={\"action\": \"close\"}'
headers: {
'Actions': 'http, Close door, https://api.mygarage.lan/, method=PUT, headers.Authorization=Bearer zAzsx1sk.., body={\"action\": \"close\"}'
}
})
```
@ -1979,7 +1979,7 @@ And the same example using [JSON publishing](#publish-as-json):
``` go
// You should probably use json.Marshal() instead and make a proper struct,
// but for the sake of the example, this is easier.
body := `{
"topic": "myhome",
"message": "Garage door has been open for 15 minutes. Close it?",
@ -2002,7 +2002,7 @@ And the same example using [JSON publishing](#publish-as-json):
=== "PowerShell"
``` powershell
# Powershell requires the 'Depth' argument to equal 3 here to expand 'headers',
# Powershell requires the 'Depth' argument to equal 3 here to expand 'headers',
# otherwise it will read System.Collections.Hashtable in the returned JSON
$uri = "https://ntfy.sh"
@ -2088,13 +2088,13 @@ The `http` action supports the following fields:
## Click action
_Supported on:_ :material-android: :material-apple: :material-firefox:
You can define which URL to open when a notification is clicked. This may be useful if your notification is related
You can define which URL to open when a notification is clicked. This may be useful if your notification is related
to a Zabbix alert or a transaction that you'd like to provide the deep-link for. Tapping the notification will open
the web browser (or the app) and open the website.
To define a click action for the notification, pass a URL as the value of the `X-Click` header (or its aliase `Click`).
If you pass a website URL (`http://` or `https://`) the web browser will open. If you pass another URI that can be handled
by another app, the responsible app may open.
by another app, the responsible app may open.
Examples:
@ -2126,7 +2126,7 @@ Here's an example that will open Reddit when the notification is clicked:
``` http
POST /reddit_alerts HTTP/1.1
Host: ntfy.sh
Click: https://www.reddit.com/message/messages
Click: https://www.reddit.com/message/messages
New messages on Reddit
```
@ -2181,19 +2181,19 @@ _Supported on:_ :material-android: :material-firefox:
You can **send images and other files to your phone** as attachments to a notification. The attachments are then downloaded
onto your phone (depending on size and setting automatically), and can be used from the Downloads folder.
There are two different ways to send attachments:
There are two different ways to send attachments:
* sending [a local file](#attach-local-file) via PUT, e.g. from `~/Flowers/flower.jpg` or `ringtone.mp3`
* or by [passing an external URL](#attach-file-from-a-url) as an attachment, e.g. `https://f-droid.org/F-Droid.apk`
* or by [passing an external URL](#attach-file-from-a-url) as an attachment, e.g. `https://f-droid.org/F-Droid.apk`
### Attach local file
To **send a file from your computer** as an attachment, you can send it as the PUT request body. If a message is greater
than the maximum message size (4,096 bytes) or consists of non UTF-8 characters, the ntfy server will automatically
detect the mime type and size, and send the message as an attachment file. To send smaller text-only messages or files
as attachments, you must pass a filename by passing the `X-Filename` header or query parameter (or any of its aliases
`Filename`, `File` or `f`).
To **send a file from your computer** as an attachment, you can send it as the PUT request body. If a message is greater
than the maximum message size (4,096 bytes) or consists of non UTF-8 characters, the ntfy server will automatically
detect the mime type and size, and send the message as an attachment file. To send smaller text-only messages or files
as attachments, you must pass a filename by passing the `X-Filename` header or query parameter (or any of its aliases
`Filename`, `File` or `f`).
By default, and how ntfy.sh is configured, the **max attachment size is 15 MB** (with 100 MB total per visitor).
By default, and how ntfy.sh is configured, the **max attachment size is 15 MB** (with 100 MB total per visitor).
Attachments **expire after 3 hours**, which typically is plenty of time for the user to download it, or for the Android app
to auto-download it. Please also check out the [other limits below](#limitations).
@ -2220,7 +2220,7 @@ Here's an example showing how to upload an image:
Host: ntfy.sh
Filename: flower.jpg
Content-Type: 52312
(binary JPEG data)
```
@ -2256,7 +2256,7 @@ Here's an example showing how to upload an image:
'header' =>
"Content-Type: application/octet-stream\r\n" . // Does not matter
"Filename: flower.jpg",
'content' => file_get_contents('flower.jpg') // Dangerous for large files
'content' => file_get_contents('flower.jpg') // Dangerous for large files
]
]));
```
@ -2270,13 +2270,13 @@ Here's what that looks like on Android:
### Attach file from a URL
Instead of sending a local file to your phone, you can use **an external URL** to specify where the attachment is hosted.
This could be a Dropbox link, a file from social media, or any other publicly available URL. Since the files are
This could be a Dropbox link, a file from social media, or any other publicly available URL. Since the files are
externally hosted, the expiration or size limits from above do not apply here.
To attach an external file, simple pass the `X-Attach` header or query parameter (or any of its aliases `Attach` or `a`)
to specify the attachment URL. It can be any type of file.
to specify the attachment URL. It can be any type of file.
ntfy will automatically try to derive the file name from the URL (e.g `https://example.com/flower.jpg` will yield a
ntfy will automatically try to derive the file name from the URL (e.g `https://example.com/flower.jpg` will yield a
filename `flower.jpg`). To override this filename, you may send the `X-Filename` header or query parameter (or any of its
aliases `Filename`, `File` or `f`).
@ -2354,7 +2354,7 @@ _Supported on:_ :material-android:
You can include an icon that will appear next to the text of the notification. Simply pass the `X-Icon` header or query
parameter (or its alias `Icon`) to specify the URL that the icon is located at. The client will automatically download
the icon (unless it is already cached locally, and less than 24 hours old), and show it in the notification. Icons are
the icon (unless it is already cached locally, and less than 24 hours old), and show it in the notification. Icons are
cached locally in the client until the notification is deleted. **Only JPEG and PNG images are supported at this time**.
Here's an example showing how to include an icon:
@ -2394,7 +2394,7 @@ Here's an example showing how to include an icon:
``` javascript
fetch('https://ntfy.sh/tvshows', {
method: 'POST',
headers: {
headers: {
'Icon': 'https://styles.redditmedia.com/t5_32uhe/styles/communityIcon_xnt6chtnr2j21.png',
'Title': 'Kodi: Resuming Playback',
'Tags': 'arrow_forward'
@ -2458,14 +2458,14 @@ Here's an example of how it will look on Android:
## E-mail notifications
_Supported on:_ :material-android: :material-apple: :material-firefox:
You can forward messages to e-mail by specifying an address in the header. This can be useful for messages that
you'd like to persist longer, or to blast-notify yourself on all possible channels.
You can forward messages to e-mail by specifying an address in the header. This can be useful for messages that
you'd like to persist longer, or to blast-notify yourself on all possible channels.
Usage is easy: Simply pass the `X-Email` header (or any of its aliases: `X-E-mail`, `Email`, `E-mail`, `Mail`, or `e`).
Only one e-mail address is supported.
Since ntfy does not provide auth (yet), the rate limiting is pretty strict (see [limitations](#limitations)). In the
default configuration, you get **16 e-mails per visitor** (IP address) and then after that one per hour. On top of
Since ntfy does not provide auth (yet), the rate limiting is pretty strict (see [limitations](#limitations)). In the
default configuration, you get **16 e-mails per visitor** (IP address) and then after that one per hour. On top of
that, your IP address appears in the e-mail body. This is to prevent abuse.
=== "Command line (curl)"
@ -2476,7 +2476,7 @@ that, your IP address appears in the e-mail body. This is to prevent abuse.
-H "Priority: high" \
-d "Unknown login from 5.31.23.83 to backups.example.com" \
ntfy.sh/alerts
curl -H "Email: phil@example.com" -d "You've Got Mail"
curl -H "Email: phil@example.com" -d "You've Got Mail"
curl -d "You've Got Mail" "ntfy.sh/alerts?email=phil@example.com"
```
@ -2505,7 +2505,7 @@ that, your IP address appears in the e-mail body. This is to prevent abuse.
fetch('https://ntfy.sh/alerts', {
method: 'POST',
body: "Unknown login from 5.31.23.83 to backups.example.com",
headers: {
headers: {
'Email': 'phil@example.com',
'Tags': 'warning,skull,backup-host,ssh-login',
'Priority': 'high'
@ -2515,7 +2515,7 @@ that, your IP address appears in the e-mail body. This is to prevent abuse.
=== "Go"
``` go
req, _ := http.NewRequest("POST", "https://ntfy.sh/alerts",
req, _ := http.NewRequest("POST", "https://ntfy.sh/alerts",
strings.NewReader("Unknown login from 5.31.23.83 to backups.example.com"))
req.Header.Set("Email", "phil@example.com")
req.Header.Set("Tags", "warning,skull,backup-host,ssh-login")
@ -2538,7 +2538,7 @@ that, your IP address appears in the e-mail body. This is to prevent abuse.
``` python
requests.post("https://ntfy.sh/alerts",
data="Unknown login from 5.31.23.83 to backups.example.com",
headers={
headers={
"Email": "phil@example.com",
"Tags": "warning,skull,backup-host,ssh-login",
"Priority": "high"
@ -2571,11 +2571,11 @@ Here's what that looks like in Google Mail:
_Supported on:_ :material-android: :material-apple: :material-firefox:
You can publish messages to a topic via e-mail, i.e. by sending an email to a specific address. For instance, you can
publish a message to the topic `sometopic` by sending an e-mail to `ntfy-sometopic@ntfy.sh`. This is useful for e-mail
publish a message to the topic `sometopic` by sending an e-mail to `ntfy-sometopic@ntfy.sh`. This is useful for e-mail
based integrations such as for statuspage.io (though these days most services also support webhooks and HTTP calls).
Depending on the [server configuration](config.md#e-mail-publishing), the e-mail address format can have a prefix to
prevent spam on topics. For ntfy.sh, the prefix is configured to `ntfy-`, meaning that the general e-mail address
Depending on the [server configuration](config.md#e-mail-publishing), the e-mail address format can have a prefix to
prevent spam on topics. For ntfy.sh, the prefix is configured to `ntfy-`, meaning that the general e-mail address
format is:
```
@ -2583,7 +2583,7 @@ ntfy-$topic@ntfy.sh
```
As of today, e-mail publishing only supports adding a [message title](#message-title) (the e-mail subject). Tags, priority,
delay and other features are not supported (yet). Here's an example that will publish a message with the
delay and other features are not supported (yet). Here's an example that will publish a message with the
title `You've Got Mail` to topic `sometopic` (see [ntfy.sh/sometopic](https://ntfy.sh/sometopic)):
<figure markdown>
@ -2596,17 +2596,17 @@ title `You've Got Mail` to topic `sometopic` (see [ntfy.sh/sometopic](https://nt
### Authentication
Depending on whether the server is configured to support [access control](config.md#access-control), some topics
may be read/write protected so that only users with the correct credentials can subscribe or publish to them.
To publish/subscribe to protected topics, you can:
To publish/subscribe to protected topics, you can:
* Use [basic auth](#basic-auth), e.g. `Authorization: Basic dGVzdHVzZXI6ZmFrZXBhc3N3b3Jk`
* or use the [`auth` query parameter](#query-param), e.g. `?auth=QmFzaWMgZEdWemRIVnpaWEk2Wm1GclpYQmhjM04zYjNKaw`
!!! warning
Base64 only encodes username and password. It **is not encrypting it**. For your self-hosted server,
**be sure to use HTTPS to avoid eavesdropping** and exposing your password.
Base64 only encodes username and password. It **is not encrypting it**. For your self-hosted server,
**be sure to use HTTPS to avoid eavesdropping** and exposing your password.
#### Basic auth
Here's an example using [Basic auth](https://en.wikipedia.org/wiki/Basic_access_authentication), with a user `testuser`
Here's an example using [Basic auth](https://en.wikipedia.org/wiki/Basic_access_authentication), with a user `testuser`
and password `fakepassword`:
=== "Command line (curl)"
@ -2685,8 +2685,8 @@ and password `fakepassword`:
]));
```
To generate the `Authorization` header, use **standard base64** to encode the colon-separated `<username>:<password>`
and prepend the word `Basic`, i.e. `Authorization: Basic base64(<username>:<password>)`. Here's some pseudo-code that
To generate the `Authorization` header, use **standard base64** to encode the colon-separated `<username>:<password>`
and prepend the word `Basic`, i.e. `Authorization: Basic base64(<username>:<password>)`. Here's some pseudo-code that
hopefully explains it better:
```
@ -2766,8 +2766,8 @@ Here's an example using the `auth` query parameter:
]));
```
To generate the value of the `auth` parameter, encode the value of the `Authorization` header (see anove) using
**raw base64 encoding** (like base64, but strip any trailing `=`). Here's some pseudo-code that hopefully
To generate the value of the `auth` parameter, encode the value of the `Authorization` header (see anove) using
**raw base64 encoding** (like base64, but strip any trailing `=`). Here's some pseudo-code that hopefully
explains it better:
```
@ -2777,7 +2777,7 @@ authHeader = "Basic " + base64(username + ":" + password) // -> Basic dGVzdHVzZX
authParam = base64_raw(authHeader) // -> QmFzaWMgZEdWemRIVnpaWEk2Wm1GclpYQmhjM04zYjNKaw (no trailing =)
// If your language does not have a function to encode raw base64, simply use normal base64
// and REMOVE TRAILING "=" characters.
// and REMOVE TRAILING "=" characters.
```
The following command will generate the appropriate value for you on *nix systems:
@ -2788,17 +2788,17 @@ echo -n "Basic `echo -n 'testuser:fakepassword' | base64`" | base64 | tr -d '='
### Message caching
!!! info
If `Cache: no` is used, messages will only be delivered to connected subscribers, and won't be re-delivered if a
client re-connects. If a subscriber has (temporary) network issues or is reconnecting momentarily,
If `Cache: no` is used, messages will only be delivered to connected subscribers, and won't be re-delivered if a
client re-connects. If a subscriber has (temporary) network issues or is reconnecting momentarily,
**messages might be missed**.
By default, the ntfy server caches messages on disk for 12 hours (see [message caching](config.md#message-cache)), so
all messages you publish are stored server-side for a little while. The reason for this is to overcome temporary
all messages you publish are stored server-side for a little while. The reason for this is to overcome temporary
client-side network disruptions, but arguably this feature also may raise privacy concerns.
To avoid messages being cached server-side entirely, you can set `X-Cache` header (or its alias: `Cache`) to `no`.
To avoid messages being cached server-side entirely, you can set `X-Cache` header (or its alias: `Cache`) to `no`.
This will make sure that your message is not cached on the server, even if server-side caching is enabled. Messages
are still delivered to connected subscribers, but [`since=`](subscribe/api.md#fetch-cached-messages) and
are still delivered to connected subscribers, but [`since=`](subscribe/api.md#fetch-cached-messages) and
[`poll=1`](subscribe/api.md#poll-for-messages) won't return the message anymore.
=== "Command line (curl)"
@ -2869,12 +2869,12 @@ are still delivered to connected subscribers, but [`since=`](subscribe/api.md#fe
### Disable Firebase
!!! info
If `Firebase: no` is used and [instant delivery](subscribe/phone.md#instant-delivery) isn't enabled in the Android
app (Google Play variant only), **message delivery will be significantly delayed (up to 15 minutes)**. To overcome
If `Firebase: no` is used and [instant delivery](subscribe/phone.md#instant-delivery) isn't enabled in the Android
app (Google Play variant only), **message delivery will be significantly delayed (up to 15 minutes)**. To overcome
this delay, simply enable instant delivery.
The ntfy server can be configured to use [Firebase Cloud Messaging (FCM)](https://firebase.google.com/docs/cloud-messaging)
(see [Firebase config](config.md#firebase-fcm)) for message delivery on Android (to minimize the app's battery footprint).
(see [Firebase config](config.md#firebase-fcm)) for message delivery on Android (to minimize the app's battery footprint).
The ntfy.sh server is configured this way, meaning that all messages published to ntfy.sh are also published to corresponding
FCM topics.
@ -2949,7 +2949,7 @@ to `no`. This will instruct the server not to forward messages to Firebase.
### UnifiedPush
!!! info
This setting is not relevant to users, only to app developers and people interested in [UnifiedPush](https://unifiedpush.org).
This setting is not relevant to users, only to app developers and people interested in [UnifiedPush](https://unifiedpush.org).
[UnifiedPush](https://unifiedpush.org) is a standard for receiving push notifications without using the Google-owned
[Firebase Cloud Messaging (FCM)](https://firebase.google.com/docs/cloud-messaging) service. It puts push notifications
@ -2957,16 +2957,16 @@ in the control of the user. ntfy can act as a **UnifiedPush distributor**, forwa
When publishing messages to a topic, apps using ntfy as a UnifiedPush distributor can set the `X-UnifiedPush` header or query
parameter (or any of its aliases `unifiedpush` or `up`) to `1` to [disable Firebase](#disable-firebase). As of today, this
option is mostly equivalent to `Firebase: no`, but was introduced to allow future flexibility. The flag additionally
option is mostly equivalent to `Firebase: no`, but was introduced to allow future flexibility. The flag additionally
enables auto-detection of the message encoding. If the message is binary, it'll be encoded as base64.
### Matrix Gateway
The ntfy server implements a [Matrix Push Gateway](https://spec.matrix.org/v1.2/push-gateway-api/) (in combination with
[UnifiedPush](https://unifiedpush.org) as the [Provider Push Protocol](https://unifiedpush.org/developers/gateway/)). This makes it easier to integrate
with self-hosted [Matrix](https://matrix.org/) servers (such as [synapse](https://github.com/matrix-org/synapse)), since
with self-hosted [Matrix](https://matrix.org/) servers (such as [synapse](https://github.com/matrix-org/synapse)), since
you don't have to set up a separate push proxy (such as [common-proxies](https://github.com/UnifiedPush/common-proxies)).
In short, ntfy accepts Matrix messages on the `/_matrix/push/v1/notify` endpoint (see [Push Gateway API](https://spec.matrix.org/v1.2/push-gateway-api/)),
In short, ntfy accepts Matrix messages on the `/_matrix/push/v1/notify` endpoint (see [Push Gateway API](https://spec.matrix.org/v1.2/push-gateway-api/)),
and forwards them to the ntfy topic defined in the `pushkey` of the message. The message will then be forwarded to the
ntfy Android app, and passed on to the Matrix client there.
@ -2989,7 +2989,7 @@ that you can use to try out what [authentication and access control](#authentica
| [mytopic-wo](https://ntfy.sh/mytopic-wo) | `testuser` (password: `testuser`) | Write-only for `testuser`, no access for anyone else | Test topic |
## Limitations
There are a few limitations to the API to prevent abuse and to keep the server healthy. Almost all of these settings
There are a few limitations to the API to prevent abuse and to keep the server healthy. Almost all of these settings
are configurable via the server side [rate limiting settings](config.md#rate-limiting). Most of these limits you won't run into,
but just in case, let's list them all: