# 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 something that's not easily guessable. Here's an example showing how to publish a simple message using a POST request: === "Command line (curl)" ``` curl -d "Backup successful 😀" ntfy.sh/mytopic ``` === "ntfy CLI" ``` ntfy publish mytopic "Backup successful 😀" ``` === "HTTP" ``` http POST /mytopic HTTP/1.1 Host: ntfy.sh Backup successful 😀 ``` === "JavaScript" ``` javascript fetch('https://ntfy.sh/mytopic', { method: 'POST', // PUT works too body: 'Backup successful 😀' }) ``` === "Go" ``` go http.Post("https://ntfy.sh/mytopic", "text/plain", strings.NewReader("Backup successful 😀")) ``` === "PowerShell" ``` powershell Invoke-RestMethod -Method 'Post' -Uri https://ntfy.sh/topic -Body "Backup successful 😀" -UseBasicParsing ``` === "Python" ``` python requests.post("https://ntfy.sh/mytopic", data="Backup successful 😀".encode(encoding='utf-8')) ``` === "PHP" ``` php-inline file_get_contents('https://ntfy.sh/mytopic', false, stream_context_create([ 'http' => [ 'method' => 'POST', // PUT also works 'header' => 'Content-Type: text/plain', 'content' => 'Backup successful 😀' ] ])); ``` If you have the [Android app](subscribe/phone.md) installed on your phone, this will create a notification that looks like this:
![basic notification](static/img/android-screenshot-basic-notification.png){ width=500 }
Android notification
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)" ``` curl \ -H "Title: Unauthorized access detected" \ -H "Priority: urgent" \ -H "Tags: warning,skull" \ -d "Remote access to phils-laptop detected. Act right away." \ ntfy.sh/phil_alerts ``` === "ntfy CLI" ``` ntfy publish \ --title "Unauthorized access detected" \ --tags warning,skull \ --priority urgent \ mytopic \ "Remote access to phils-laptop detected. Act right away." ``` === "HTTP" ``` http POST /phil_alerts HTTP/1.1 Host: ntfy.sh Title: Unauthorized access detected Priority: urgent Tags: warning,skull Remote access to phils-laptop detected. Act right away. ``` === "JavaScript" ``` javascript fetch('https://ntfy.sh/phil_alerts', { method: 'POST', // PUT works too body: 'Remote access to phils-laptop detected. Act right away.', headers: { 'Title': 'Unauthorized access detected', 'Priority': 'urgent', 'Tags': 'warning,skull' } }) ``` === "Go" ``` go req, _ := http.NewRequest("POST", "https://ntfy.sh/phil_alerts", strings.NewReader("Remote access to phils-laptop detected. Act right away.")) req.Header.Set("Title", "Unauthorized access detected") req.Header.Set("Priority", "urgent") req.Header.Set("Tags", "warning,skull") http.DefaultClient.Do(req) ``` === "PowerShell" ``` powershell $uri = "https://ntfy.sh/phil_alerts" $headers = @{ Title="Unauthorized access detected" Priority="urgent" Tags="warning,skull" } $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", data="Remote access to phils-laptop detected. Act right away.", headers={ "Title": "Unauthorized access detected", "Priority": "urgent", "Tags": "warning,skull" }) ``` === "PHP" ``` php-inline file_get_contents('https://ntfy.sh/phil_alerts', false, stream_context_create([ 'http' => [ 'method' => 'POST', // PUT also works 'header' => "Content-Type: text/plain\r\n" . "Title: Unauthorized access detected\r\n" . "Priority: urgent\r\n" . "Tags: warning,skull", 'content' => 'Remote access to phils-laptop detected. Act right away.' ] ])); ```
![priority notification](static/img/priority-notification.png){ width=500 }
Urgent notification with tags and title
## Message 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)" ``` curl -H "X-Title: Dogs are better than cats" -d "Oh my ..." ntfy.sh/controversial curl -H "Title: Dogs are better than cats" -d "Oh my ..." ntfy.sh/controversial curl -H "t: Dogs are better than cats" -d "Oh my ..." ntfy.sh/controversial ``` === "ntfy CLI" ``` ntfy publish \ -t "Dogs are better than cats" \ controversial "Oh my ..." ``` === "HTTP" ``` http POST /controversial HTTP/1.1 Host: ntfy.sh Title: Dogs are better than cats Oh my ... ``` === "JavaScript" ``` javascript fetch('https://ntfy.sh/controversial', { method: 'POST', body: 'Oh my ...', headers: { 'Title': 'Dogs are better than cats' } }) ``` === "Go" ``` go req, _ := http.NewRequest("POST", "https://ntfy.sh/controversial", strings.NewReader("Oh my ...")) req.Header.Set("Title", "Dogs are better than cats") http.DefaultClient.Do(req) ``` === "PowerShell" ``` powershell $uri = "https://ntfy.sh/controversial" $headers = @{ Title="Dogs are better than cats" } $body = "Oh my ..." Invoke-RestMethod -Method 'Post' -Uri $uri -Headers $headers -Body $body -UseBasicParsing ``` === "Python" ``` python requests.post("https://ntfy.sh/controversial", data="Oh my ...", headers={ "Title": "Dogs are better than cats" }) ``` === "PHP" ``` php-inline file_get_contents('https://ntfy.sh/controversial', false, stream_context_create([ 'http' => [ 'method' => 'POST', 'header' => "Content-Type: text/plain\r\n" . "Title: Dogs are better than cats", 'content' => 'Oh my ...' ] ])); ```
![notification with title](static/img/notification-with-title.png){ width=500 }
Detail view of notification with title
## Message priority All messages have a priority, which defines how urgently your phone notifies you. You can set custom notification sounds and vibration patterns on your phone to map to these priorities (see [Android config](subscribe/phone.md)). The following priorities exist: | Priority | Icon | ID | Name | Description | |----------------------|--------------------------------------------|-----|----------------|--------------------------------------------------------------------------------------------------------| | Max priority | ![min priority](static/img/priority-5.svg) | `5` | `max`/`urgent` | Really long vibration bursts, default notification sound with a pop-over notification. | | High priority | ![min priority](static/img/priority-4.svg) | `4` | `high` | Long vibration burst, default notification sound with a pop-over notification. | | **Default priority** | *(none)* | `3` | `default` | Short default vibration and sound. Default notification behavior. | | Low priority | ![min priority](static/img/priority-2.svg) | `2` | `low` | No vibration or sound. Notification will not visibly show up until notification drawer is pulled down. | | Min priority | ![min priority](static/img/priority-1.svg) | `1` | `min` | No vibration or sound. The notification will be under the fold in "Other notifications". | You can set the priority with the header `X-Priority` (or any of its aliases: `Priority`, `prio`, or `p`). === "Command line (curl)" ``` curl -H "X-Priority: 5" -d "An urgent message" ntfy.sh/phil_alerts curl -H "Priority: low" -d "Low priority message" ntfy.sh/phil_alerts curl -H p:4 -d "A high priority message" ntfy.sh/phil_alerts ``` === "ntfy CLI" ``` ntfy publish \ -p 5 \ phil_alerts An urgent message ``` === "HTTP" ``` http POST /phil_alerts HTTP/1.1 Host: ntfy.sh Priority: 5 An urgent message ``` === "JavaScript" ``` javascript fetch('https://ntfy.sh/phil_alerts', { method: 'POST', body: 'An urgent message', headers: { 'Priority': '5' } }) ``` === "Go" ``` go req, _ := http.NewRequest("POST", "https://ntfy.sh/phil_alerts", strings.NewReader("An urgent message")) req.Header.Set("Priority", "5") http.DefaultClient.Do(req) ``` === "PowerShell" ``` powershell $uri = "https://ntfy.sh/phil_alerts" $headers = @{ Priority="5" } $body = "An urgent message" Invoke-RestMethod -Method 'Post' -Uri $uri -Headers $headers -Body $body -UseBasicParsing ``` === "Python" ``` python requests.post("https://ntfy.sh/phil_alerts", data="An urgent message", headers={ "Priority": "5" }) ``` === "PHP" ``` php-inline file_get_contents('https://ntfy.sh/phil_alerts', false, stream_context_create([ 'http' => [ 'method' => 'POST', 'header' => "Content-Type: text/plain\r\n" . "Priority: 5", 'content' => 'An urgent message' ] ])); ```
![priority notification](static/img/priority-detail-overview.png){ width=500 }
Detail view of priority notifications
## Tags & emojis 🥳 🎉 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 to title or message. * **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. Here's an **excerpt of emojis** I've found very useful in alert messages:
TagEmoji
+1👍
partying_face🥳
tada🎉
heavy_check_mark✔️
loudspeaker📢
......
TagEmoji
-1👎️
warning⚠️
rotating_light️🚨
triangular_flag_on_post🚩
skull💀
......
TagEmoji
facepalm🤦
no_entry
no_entry_sign🚫
cd💿
computer💻
......
You can set tags with the `X-Tags` header (or any of its aliases: `Tags`, `tag`, or `ta`). Specify multiple tags by separating them with a comma, e.g. `tag1,tag2,tag3`. === "Command line (curl)" ``` curl -H "X-Tags: warning,mailsrv13,daily-backup" -d "Backup of mailsrv13 failed" ntfy.sh/backups curl -H "Tags: horse,unicorn" -d "Unicorns are just horses with unique horns" ntfy.sh/backups curl -H ta:dog -d "Dogs are awesome" ntfy.sh/backups ``` === "ntfy CLI" ``` ntfy publish \ --tags=warning,mailsrv13,daily-backup \ backups "Backup of mailsrv13 failed" ``` === "HTTP" ``` http POST /backups HTTP/1.1 Host: ntfy.sh Tags: warning,mailsrv13,daily-backup Backup of mailsrv13 failed ``` === "JavaScript" ``` javascript fetch('https://ntfy.sh/backups', { method: 'POST', body: 'Backup of mailsrv13 failed', headers: { 'Tags': 'warning,mailsrv13,daily-backup' } }) ``` === "Go" ``` go req, _ := http.NewRequest("POST", "https://ntfy.sh/backups", strings.NewReader("Backup of mailsrv13 failed")) req.Header.Set("Tags", "warning,mailsrv13,daily-backup") http.DefaultClient.Do(req) ``` === "PowerShell" ``` powershell $uri = "https://ntfy.sh/backups" $headers = @{ Tags="warning,mailsrv13,daily-backup" } $body = "Backup of mailsrv13 failed" Invoke-RestMethod -Method 'Post' -Uri $uri -Headers $headers -Body $body -UseBasicParsing ``` === "Python" ``` python requests.post("https://ntfy.sh/backups", data="Backup of mailsrv13 failed", headers={ "Tags": "warning,mailsrv13,daily-backup" }) ``` === "PHP" ``` php-inline file_get_contents('https://ntfy.sh/backups', false, stream_context_create([ 'http' => [ 'method' => 'POST', 'header' => "Content-Type: text/plain\r\n" . "Tags: warning,mailsrv13,daily-backup", 'content' => 'Backup of mailsrv13 failed' ] ])); ```
![priority notification](static/img/notification-with-tags.png){ width=500 }
Detail view of notifications with tags
## Scheduled delivery 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)). 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 these limits). 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. === "Command line (curl)" ``` curl -H "At: tomorrow, 10am" -d "Good morning" ntfy.sh/hello curl -H "In: 30min" -d "It's 30 minutes later now" ntfy.sh/reminder curl -H "Delay: 1639194738" -d "Unix timestamps are awesome" ntfy.sh/itsaunixsystem ``` === "ntfy CLI" ``` ntfy publish \ --at="tomorrow, 10am" \ hello "Good morning" ``` === "HTTP" ``` http POST /hello HTTP/1.1 Host: ntfy.sh At: tomorrow, 10am Good morning ``` === "JavaScript" ``` javascript fetch('https://ntfy.sh/hello', { method: 'POST', body: 'Good morning', headers: { 'At': 'tomorrow, 10am' } }) ``` === "Go" ``` go req, _ := http.NewRequest("POST", "https://ntfy.sh/hello", strings.NewReader("Good morning")) req.Header.Set("At", "tomorrow, 10am") http.DefaultClient.Do(req) ``` === "PowerShell" ``` powershell $uri = "https://ntfy.sh/hello" $headers = @{ At="tomorrow, 10am" } $body = "Good morning" Invoke-RestMethod -Method 'Post' -Uri $uri -Headers $headers -Body $body -UseBasicParsing ``` === "Python" ``` python requests.post("https://ntfy.sh/hello", data="Good morning", headers={ "At": "tomorrow, 10am" }) ``` === "PHP" ``` php-inline file_get_contents('https://ntfy.sh/backups', false, stream_context_create([ 'http' => [ 'method' => 'POST', 'header' => "Content-Type: text/plain\r\n" . "At: tomorrow, 10am", 'content' => 'Good morning' ] ])); ``` Here are a few examples (assuming today's date is **12/10/2021, 9am, Eastern Time Zone**):
Delay/At/In headerMessage will be delivered atExplanation
30m12/10/2021, 9:30am30 minutes from now
2 hours12/10/2021, 11:30am2 hours from now
1 day12/11/2021, 9am24 hours from now
10am12/10/2021, 10amToday at 10am (same day, because it's only 9am)
8am12/11/2021, 8amTomorrow at 8am (because it's 9am already)
163915200012/10/2021, 11am (EST) Today at 11am (EST)
## Webhooks (publish via GET) 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 [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 (aka trigger the webhook): === "Command line (curl)" ``` curl ntfy.sh/mywebhook/trigger ``` === "ntfy CLI" ``` ntfy trigger mywebhook ``` === "HTTP" ``` http GET /mywebhook/trigger HTTP/1.1 Host: ntfy.sh ``` === "JavaScript" ``` javascript fetch('https://ntfy.sh/mywebhook/trigger') ``` === "Go" ``` go http.Get("https://ntfy.sh/mywebhook/trigger") ``` === "PowerShell" ``` powershell Invoke-RestMethod -Method 'Get' -Uri "ntfy.sh/mywebhook/trigger" ``` === "Python" ``` python requests.get("https://ntfy.sh/mywebhook/trigger") ``` === "PHP" ``` php-inline 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. 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: === "Command line (curl)" ``` curl "ntfy.sh/mywebhook/publish?message=Webhook+triggered&priority=high&tags=warning,skull" ``` === "ntfy CLI" ``` ntfy publish \ -p 5 --tags=warning,skull \ mywebhook "Webhook triggered" ``` === "HTTP" ``` http GET /mywebhook/publish?message=Webhook+triggered&priority=high&tags=warning,skull HTTP/1.1 Host: ntfy.sh ``` === "JavaScript" ``` javascript fetch('https://ntfy.sh/mywebhook/publish?message=Webhook+triggered&priority=high&tags=warning,skull') ``` === "Go" ``` go http.Get("https://ntfy.sh/mywebhook/publish?message=Webhook+triggered&priority=high&tags=warning,skull") ``` === "PowerShell" ``` powershell Invoke-RestMethod -Method 'Get' -Uri "ntfy.sh/mywebhook/publish?message=Webhook+triggered&priority=high&tags=warning,skull" ``` === "Python" ``` python requests.get("https://ntfy.sh/mywebhook/publish?message=Webhook+triggered&priority=high&tags=warning,skull") ``` === "PHP" ``` php-inline file_get_contents('https://ntfy.sh/mywebhook/publish?message=Webhook+triggered&priority=high&tags=warning,skull'); ``` ## Publish as JSON 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 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). 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)" ``` curl ntfy.sh \ -d '{ "topic": "mytopic", "message": "Disk space is low at 5.1 GB", "title": "Low disk space alert", "tags": ["warning","cd"], "priority": 4, "attach": "https://filesrv.lan/space.jpg", "filename": "diskspace.jpg", "click": "https://homecamera.lan/xasds1h2xsSsa/" }' ``` === "HTTP" ``` http POST / HTTP/1.1 Host: ntfy.sh { "topic": "mytopic", "message": "Disk space is low at 5.1 GB", "title": "Low disk space alert", "tags": ["warning","cd"], "priority": 4, "attach": "https://filesrv.lan/space.jpg", "filename": "diskspace.jpg", "click": "https://homecamera.lan/xasds1h2xsSsa/" } ``` === "JavaScript" ``` javascript fetch('https://ntfy.sh', { method: 'POST', body: JSON.stringify({ "topic": "mytopic", "message": "Disk space is low at 5.1 GB", "title": "Low disk space alert", "tags": ["warning","cd"], "priority": 4, "attach": "https://filesrv.lan/space.jpg", "filename": "diskspace.jpg", "click": "https://homecamera.lan/xasds1h2xsSsa/" }) }) ``` === "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 // sake of the example, this is easier. body := `{ "topic": "mytopic", "message": "Disk space is low at 5.1 GB", "title": "Low disk space alert", "tags": ["warning","cd"], "priority": 4, "attach": "https://filesrv.lan/space.jpg", "filename": "diskspace.jpg", "click": "https://homecamera.lan/xasds1h2xsSsa/" }` req, _ := http.NewRequest("POST", "https://ntfy.sh/", strings.NewReader(body)) http.DefaultClient.Do(req) ``` === "PowerShell" ``` powershell $uri = "https://ntfy.sh" $body = @{ "topic"="powershell" "title"="Low disk space alert" "message"="Disk space is low at 5.1 GB" "priority"=4 "attach"="https://filesrv.lan/space.jpg" "filename"="diskspace.jpg" "tags"=@("warning","cd") "click"= "https://homecamera.lan/xasds1h2xsSsa/" } | ConvertTo-Json Invoke-RestMethod -Method 'Post' -Uri $uri -Body $body -ContentType "application/json" -UseBasicParsing ``` === "Python" ``` python requests.post("https://ntfy.sh/", data=json.dumps({ "topic": "mytopic", "message": "Disk space is low at 5.1 GB", "title": "Low disk space alert", "tags": ["warning","cd"], "priority": 4, "attach": "https://filesrv.lan/space.jpg", "filename": "diskspace.jpg", "click": "https://homecamera.lan/xasds1h2xsSsa/" }) ) ``` === "PHP" ``` php-inline file_get_contents('https://ntfy.sh/', false, stream_context_create([ 'http' => [ 'method' => 'POST', 'header' => "Content-Type: application/json", 'content' => json_encode([ "topic": "mytopic", "message": "Disk space is low at 5.1 GB", "title": "Low disk space alert", "tags": ["warning","cd"], "priority": 4, "attach": "https://filesrv.lan/space.jpg", "filename": "diskspace.jpg", "click": "https://homecamera.lan/xasds1h2xsSsa/" ]) ] ])); ``` 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: | Field | Required | Type | Example | Description | |------------|----------|----------------------------------|-------------------------------------------|-----------------------------------------------------------------------| | `topic` | ✔️ | *string* | `topic1` | Target topic name | | `message` | - | *string* | `Some message` | Message body; set to `triggered` if empty or not passed | | `title` | - | *string* | `Some title` | Message [title](#message-title) | | `tags` | - | *string array* | `["tag1","tag2"]` | List of [tags](#tags-emojis) that may or not map to emojis | | `priority` | - | *int (one of: 1, 2, 3, 4, or 5)* | `4` | Message [priority](#message-priority) with 1=min, 3=default and 5=max | | `actions` | - | *JSON array* | *(see [actiom buttons](#action-buttons))* | Custom [user action buttons](#action-buttons) for notifications | | `click` | - | *URL* | `https://example.com` | Website opened when notification is [clicked](#click-action) | | `attach` | - | *URL* | `https://example.com/file.jpg` | URL of an attachment, see [attach via URL](#attach-file-from-url) | | `filename` | - | *string* | `file.jpg` | File name of the attachment | | `delay` | - | *string* | `30min`, `9am` | Timestamp or duration for delayed delivery | | `email` | - | *e-mail address* | `phil@example.com` | E-mail address for e-mail notifications | ## Action buttons You can add action buttons to notifications to allow yourself to react to a notification directly. This is incredibly useful and has countless applications. As of today, the following actions are supported: * [`view`](#open-websiteapp): Opens a website or app when the action button is tapped * [`broadcast`](#send-android-broadcast): Sends an [Android broadcast](https://developer.android.com/guide/components/broadcasts) intent when the action button is tapped * [`http`](#send-http-request): Sends HTTP POST/GET/PUT request when the action button is tapped To define the user actions, you can either pass the `actions` field as part of the JSON body (if you're [publishing via JSON](#publish-as-json)), or use the `X-Actions` header (or any of its aliases: `Actions`, `Action`). Here's an example of what that a notification with actions can look like:
![notification with actions](static/img/notification-with-tags.png){ width=500 }
XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX
Using the `X-Actions` header and the **simple format** (details see below), you can create the above notification like this. This format is much easier to write, but less powerful: === "Command line (curl)" ``` curl \ -d "You left the house. Turn down the A/C?" \ -H "Actions: view, Open portal, https://home.nest.com/; \ http, Turn down, https://api.nest.com/device/XZ1D2, body=target_temp_f=65" \ ntfy.sh/myhome ``` === "ntfy CLI" ``` ntfy publish \ --actions="view, Open portal, https://home.nest.com/; \ http, Turn down, https://api.nest.com/device/XZ1D2, body=target_temp_f=65" \ myhome \ "You left the house. Turn down the A/C?" ``` === "HTTP" ``` http POST /myhome HTTP/1.1 Host: ntfy.sh Actions: view, Open portal, https://home.nest.com/; http, Turn down, https://api.nest.com/device/XZ1D2, body=target_temp_f=65 You left the house. Turn down the A/C? ``` === "JavaScript" ``` javascript 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/; http, Turn down, https://api.nest.com/device/XZ1D2, body=target_temp_f=65' } }) ``` === "Go" ``` go req, _ := http.NewRequest("POST", "https://ntfy.sh/myhome", strings.NewReader("You left the house. Turn down the A/C?")) req.Header.Set("Actions", "view, Open portal, https://home.nest.com/; http, Turn down, https://api.nest.com/device/XZ1D2, body=target_temp_f=65") http.DefaultClient.Do(req) ``` === "PowerShell" ``` powershell $uri = "https://ntfy.sh/myhome" $headers = @{ Actions="view, Open portal, https://home.nest.com/; http, Turn down, https://api.nest.com/device/XZ1D2, body=target_temp_f=65" } $body = "You left the house. Turn down the A/C?" Invoke-RestMethod -Method 'Post' -Uri $uri -Headers $headers -Body $body -UseBasicParsing ``` === "Python" ``` python requests.post("https://ntfy.sh/myhome", data="You left the house. Turn down the A/C?", headers={ "Actions": "view, Open portal, https://home.nest.com/; http, Turn down, https://api.nest.com/device/XZ1D2, body=target_temp_f=65" }) ``` === "PHP" ``` php-inline file_get_contents('https://ntfy.sh/reddit_alerts', false, stream_context_create([ 'http' => [ 'method' => 'POST', 'header' => "Content-Type: text/plain\r\n" . "Actions: view, Open portal, https://home.nest.com/; http, Turn down, https://api.nest.com/device/XZ1D2, body=target_temp_f=65", 'content' => 'You left the house. Turn down the A/C?' ] ])); ``` Alternatively, you can define actions as **JSON array** (details see below), and pass them as part of the JSON body (see [publish as JSON](#publish-as-json)): === "Command line (curl)" ``` curl ntfy.sh \ -d '{ "topic": "myhome", "message": "You left the house. Turn down the A/C?", "actions": [ { "action": "view", "label": "Open portal", "url": "https://home.nest.com/" }, { "action": "http", "label": "Turn down", "url": "https://api.nest.com/device/XZ1D2", "body": "target_temp_f=65" } ] }' ``` === "ntfy CLI" ``` ntfy publish \ --actions '[ { "action": "view", "label": "Open portal", "url": "https://home.nest.com/" }, { "action": "http", "label": "Turn down", "url": "https://api.nest.com/device/XZ1D2", "body": "target_temp_f=65" } ]' \ myhome \ "You left the house. Turn down the A/C?" ``` === "HTTP" ``` http POST / HTTP/1.1 Host: ntfy.sh { "topic": "myhome", "message": "You left the house. Turn down the A/C?", "actions": [ { "action": "view", "label": "Open portal", "url": "https://home.nest.com/" }, { "action": "http", "label": "Turn down", "url": "https://api.nest.com/device/XZ1D2", "body": "target_temp_f=65" } ] } ``` === "JavaScript" ``` javascript fetch('https://ntfy.sh', { method: 'POST', body: JSON.stringify({ topic: "myhome", message": "You left the house. Turn down the A/C?", actions: [ { action: "view", label: "Open portal", url: "https://home.nest.com/" }, { action: "http", label: "Turn down", url: "https://api.nest.com/device/XZ1D2", body: "target_temp_f=65" } ] }) }) ``` === "Go" ``` 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?", "actions": [ { "action": "view", "label": "Open portal", "url": "https://home.nest.com/" }, { "action": "http", "label": "Turn down", "url": "https://api.nest.com/device/XZ1D2", "body": "target_temp_f=65" } ] }` req, _ := http.NewRequest("POST", "https://ntfy.sh/", strings.NewReader(body)) http.DefaultClient.Do(req) ``` === "PowerShell" ``` powershell $uri = "https://ntfy.sh" $body = @{ "topic"="myhome" "message"="You left the house. Turn down the A/C?" "actions"=@( @{ "action"="view" "label"="Open portal" "url"="https://home.nest.com/" }, @{ "action"="http", "label"="Turn down" "url"="https://api.nest.com/device/XZ1D2" "body"="target_temp_f=65" } ) } | ConvertTo-Json Invoke-RestMethod -Method 'Post' -Uri $uri -Body $body -ContentType "application/json" -UseBasicParsing ``` === "Python" ``` python requests.post("https://ntfy.sh/", data=json.dumps({ "topic": "myhome", "message": "You left the house. Turn down the A/C?", "actions": [ { "action": "view", "label": "Open portal", "url": "https://home.nest.com/" }, { "action": "http", "label": "Turn down", "url": "https://api.nest.com/device/XZ1D2", "body": "target_temp_f=65" } ] }) ) ``` === "PHP" ``` php-inline file_get_contents('https://ntfy.sh/', false, stream_context_create([ 'http' => [ 'method' => 'POST', 'header' => "Content-Type: application/json", 'content' => json_encode([ "topic": "myhome", "message": "You left the house. Turn down the A/C?", "actions": [ [ "action": "view", "label": "Open portal", "url": "https://home.nest.com/" ], [ "action": "http", "label": "Turn down", "url": "https://api.nest.com/device/XZ1D2", "headers": [ "Authorization": "Bearer ..." ], "body": "target_temp_f=65" ] ] ]) ] ])); ``` **Simple format syntax:** Generally, the `X-Actions` header is formatted like this: ``` Actions: ,