Continued docs
This commit is contained in:
		
							parent
							
								
									7ba268887b
								
							
						
					
					
						commit
						246061829b
					
				
					 17 changed files with 421 additions and 54 deletions
				
			
		|  | @ -1,6 +1,235 @@ | |||
| # Subscribe via API | ||||
| You can create and subscribe to a topic either in the [web UI](web.md), via the [phone app](phone.md), or in your own  | ||||
| app or script by subscribing the API. This page describes how to subscribe via API. You may also want to check out the  | ||||
| page that describes how to [publish messages](../publish.md). | ||||
| 
 | ||||
| The subscription API relies on a simple HTTP GET request with a streaming HTTP response, i.e **you open a GET request and | ||||
| the connection stays open forever**, sending messages back as they come in. There are three different API endpoints, which  | ||||
| only differ in the response format: | ||||
| 
 | ||||
| * [JSON stream](#subscribe-as-json-stream): `<topic>/json` returns a JSON stream, with one JSON message object per line | ||||
| * [SSE stream](#subscribe-as-sse-stream): `<topic>/sse` returns messages as [Server-Sent Events (SSE)](https://en.wikipedia.org/wiki/Server-sent_events), which | ||||
|   can be used with [EventSource](https://developer.mozilla.org/en-US/docs/Web/API/EventSource) | ||||
| * [Raw stream](#subscribe-as-raw-stream): `<topic>/raw` returns messages as raw text, with one line per message | ||||
| 
 | ||||
| ## Subscribe as JSON stream | ||||
| Here are a few examples of how to consume the JSON endpoint (`<topic>/json`). For almost all languages, **this is the  | ||||
| recommended way to subscribe to a topic**. The notable exception is JavaScript, for which the  | ||||
| [SSE/EventSource stream](#subscribe-as-sse-stream) is much easier to work with. | ||||
| 
 | ||||
| === "Command line (curl)" | ||||
|     ``` | ||||
|     $ curl -s ntfy.sh/disk-alerts/json | ||||
|     {"id":"SLiKI64DOt","time":1635528757,"event":"open","topic":"mytopic"} | ||||
|     {"id":"hwQ2YpKdmg","time":1635528741,"event":"message","topic":"mytopic","message":"Disk full"} | ||||
|     {"id":"DGUDShMCsc","time":1635528787,"event":"keepalive","topic":"mytopic"} | ||||
|     ... | ||||
|     ``` | ||||
| 
 | ||||
| === "HTTP" | ||||
|     ``` http | ||||
|     GET /disk-alerts/json HTTP/1.1 | ||||
|     Host: ntfy.sh | ||||
| 
 | ||||
|     HTTP/1.1 200 OK | ||||
|     Content-Type: application/x-ndjson; charset=utf-8 | ||||
|     Transfer-Encoding: chunked | ||||
|      | ||||
| ## Fetching cached messages | ||||
|     {"id":"SLiKI64DOt","time":1635528757,"event":"open","topic":"mytopic"} | ||||
|     {"id":"hwQ2YpKdmg","time":1635528741,"event":"message","topic":"mytopic","message":"Disk full"} | ||||
|     {"id":"DGUDShMCsc","time":1635528787,"event":"keepalive","topic":"mytopic"} | ||||
|     ... | ||||
|     ``` | ||||
| 
 | ||||
| === "Go" | ||||
|     ``` go | ||||
|     resp, err := http.Get("https://ntfy.sh/disk-alerts/json") | ||||
|     if err != nil { | ||||
|         log.Fatal(err) | ||||
|     } | ||||
|     defer resp.Body.Close() | ||||
|     scanner := bufio.NewScanner(resp.Body) | ||||
|     for scanner.Scan() { | ||||
|         println(scanner.Text()) | ||||
|     } | ||||
|     ``` | ||||
| 
 | ||||
| === "PHP" | ||||
|     ``` php-inline | ||||
|     $fp = fopen('https://ntfy.sh/disk-alerts/json', 'r'); | ||||
|     if (!$fp) die('cannot open stream'); | ||||
|     while (!feof($fp)) { | ||||
|         echo fgets($fp, 2048); | ||||
|         flush(); | ||||
|     } | ||||
|     fclose($fp); | ||||
|     ``` | ||||
| 
 | ||||
| ## Subscribe as SSE stream | ||||
| Using [EventSource](https://developer.mozilla.org/en-US/docs/Web/API/EventSource) in JavaScript, you can consume | ||||
| notifications via a [Server-Sent Events (SSE)](https://en.wikipedia.org/wiki/Server-sent_events) stream. It's incredibly  | ||||
| easy to use. Here's what it looks like. You may also want to check out the [live example](/example.html). | ||||
| 
 | ||||
| === "Command line (curl)" | ||||
|     ``` | ||||
|     $ curl -s ntfy.sh/mytopic/sse | ||||
|     event: open | ||||
|     data: {"id":"weSj9RtNkj","time":1635528898,"event":"open","topic":"mytopic"} | ||||
|      | ||||
|     data: {"id":"p0M5y6gcCY","time":1635528909,"event":"message","topic":"mytopic","message":"Hi!"} | ||||
|      | ||||
|     event: keepalive | ||||
|     data: {"id":"VNxNIg5fpt","time":1635528928,"event":"keepalive","topic":"test"} | ||||
|     ... | ||||
|     ``` | ||||
| 
 | ||||
| === "HTTP" | ||||
|     ``` http | ||||
|     GET /mytopic/sse HTTP/1.1 | ||||
|     Host: ntfy.sh | ||||
| 
 | ||||
|     HTTP/1.1 200 OK | ||||
|     Content-Type: text/event-stream; charset=utf-8 | ||||
|     Transfer-Encoding: chunked | ||||
| 
 | ||||
|     event: open | ||||
|     data: {"id":"weSj9RtNkj","time":1635528898,"event":"open","topic":"mytopic"} | ||||
|      | ||||
|     data: {"id":"p0M5y6gcCY","time":1635528909,"event":"message","topic":"mytopic","message":"Hi!"} | ||||
|      | ||||
|     event: keepalive | ||||
|     data: {"id":"VNxNIg5fpt","time":1635528928,"event":"keepalive","topic":"test"} | ||||
|     ... | ||||
|     ``` | ||||
| 
 | ||||
| === "JavaScript" | ||||
|     ``` javascript | ||||
|     const eventSource = new EventSource('https://ntfy.sh/mytopic/sse'); | ||||
|     eventSource.onmessage = (e) => { | ||||
|       console.log(e.data); | ||||
|     }; | ||||
|     ``` | ||||
| 
 | ||||
| ## Subscribe as raw stream | ||||
| The `/raw` endpoint will output one line per message, and **will only include the message body**. It's useful for extremely | ||||
| simple scripts, and doesn't include all the data. Additional fields such as [priority](../publish.md#message-priority),  | ||||
| [tags](../publish.md#tags--emojis--) or [message title](../publish.md#message-title) are not included in this output  | ||||
| format. Keepalive messages are sent as empty lines. | ||||
| 
 | ||||
| === "Command line (curl)" | ||||
|     ``` | ||||
|     $ curl -s ntfy.sh/disk-alerts/raw | ||||
|      | ||||
|     Disk full | ||||
|     ... | ||||
|     ``` | ||||
| 
 | ||||
| === "HTTP" | ||||
|     ``` http | ||||
|     GET /disk-alerts/raw HTTP/1.1 | ||||
|     Host: ntfy.sh | ||||
| 
 | ||||
|     HTTP/1.1 200 OK | ||||
|     Content-Type: text/plain; charset=utf-8 | ||||
|     Transfer-Encoding: chunked | ||||
| 
 | ||||
|     Disk full | ||||
|     ... | ||||
|     ``` | ||||
| 
 | ||||
| === "Go" | ||||
|     ``` go | ||||
|     resp, err := http.Get("https://ntfy.sh/disk-alerts/raw") | ||||
|     if err != nil { | ||||
|         log.Fatal(err) | ||||
|     } | ||||
|     defer resp.Body.Close() | ||||
|     scanner := bufio.NewScanner(resp.Body) | ||||
|     for scanner.Scan() { | ||||
|         println(scanner.Text()) | ||||
|     } | ||||
|     ``` | ||||
| 
 | ||||
| === "PHP" | ||||
|     ``` php-inline | ||||
|     $fp = fopen('https://ntfy.sh/disk-alerts/raw', 'r'); | ||||
|     if (!$fp) die('cannot open stream'); | ||||
|     while (!feof($fp)) { | ||||
|         echo fgets($fp, 2048); | ||||
|         flush(); | ||||
|     } | ||||
|     fclose($fp); | ||||
|     ``` | ||||
| 
 | ||||
| ## JSON message format | ||||
| Both the [`/json` endpoint](#subscribe-as-json-stream) and the [`/sse` endpoint](#subscribe-as-sse-stream) return a JSON | ||||
| format of the message. It's very straight forward: | ||||
| 
 | ||||
| | Field | Required | Type | Example | Description | | ||||
| |---|---|---|---|---| | ||||
| | `id` | ✔️ | *string* | `hwQ2YpKdmg` | Randomly chosen message identifier | | ||||
| | `time` | ✔️ | *int* | 1635528741 | Message date time, as Unix time stamp |   | ||||
| | `event` | ✔️ | `open`, `keepalive` or `message` | `message` | Message type, typically you'd be only interested in `message` | | ||||
| | `topic` | ✔️ | *string* | `topic1,topic2` | Comma-separated list of topics the message is associated with; only one for all `message` events, but may be a list in `open` events | | ||||
| | `message` | - | *string* | `Some message` | Message body; always present in `message` events | | ||||
| | `title` | - | *string* | `Some title` | Message [title](../publish.md#message-title); if not set defaults to `ntfy.sh/<topic>` | | ||||
| | `tags` | - | *string array* | `["tag1","tag2"]` | List of [tags](../publish.md#tags--emojis--) that may or not map to emojis | | ||||
| | `priority` | - | *1, 2, 3, 4, or 5* | `4` | Message [priority](../publish.md#message-priority) with 1=min, 3=default and 5=max | | ||||
| 
 | ||||
| Here's an example for each message type: | ||||
| 
 | ||||
| === "Notification message" | ||||
|     ``` json | ||||
|     { | ||||
|       "id": "wze9zgqK41", | ||||
|       "time": 1638542110, | ||||
|       "event": "message", | ||||
|       "topic": "phil_alerts", | ||||
|       "priority": 5, | ||||
|       "tags": [ | ||||
|         "warning", | ||||
|         "skull" | ||||
|       ], | ||||
|       "title": "Unauthorized access detected", | ||||
|       "message": "Remote access to phils-laptop detected. Act right away." | ||||
|     } | ||||
|     ``` | ||||
| 
 | ||||
| 
 | ||||
| === "Notification message (minimal)" | ||||
|     ``` json | ||||
|     { | ||||
|       "id": "wze9zgqK41", | ||||
|       "time": 1638542110, | ||||
|       "event": "message", | ||||
|       "topic": "phil_alerts", | ||||
|       "message": "Remote access to phils-laptop detected. Act right away." | ||||
|     } | ||||
|     ``` | ||||
| 
 | ||||
| === "Open message" | ||||
|     ``` json | ||||
|     { | ||||
|       "id": "2pgIAaGrQ8", | ||||
|       "time": 1638542215, | ||||
|       "event": "open", | ||||
|       "topic": "phil_alerts" | ||||
|     } | ||||
|     ``` | ||||
| 
 | ||||
| === "Keepalive message"  | ||||
|     ``` json | ||||
|     { | ||||
|       "id": "371sevb0pD", | ||||
|       "time": 1638542275, | ||||
|       "event": "keepalive", | ||||
|       "topic": "phil_alerts" | ||||
|     } | ||||
|     ```     | ||||
| 
 | ||||
| ## Advanced features | ||||
| 
 | ||||
| ### Fetching cached messages | ||||
| Messages may be cached for a couple of hours (see [message caching](../config.md#message-cache)) to account for network | ||||
| interruptions of subscribers. If the server has configured message caching, you can read back what you missed by using  | ||||
| the `since=` query parameter. It takes either a duration (e.g. `10m` or `30s`), a Unix timestamp (e.g. `1635528757`)  | ||||
|  | @ -10,7 +239,7 @@ or `all` (all cached messages). | |||
| curl -s "ntfy.sh/mytopic/json?since=10m" | ||||
| ``` | ||||
| 
 | ||||
| ## Polling | ||||
| ### Polling | ||||
| You can also just poll for messages if you don't like the long-standing connection using the `poll=1` | ||||
| query parameter. The connection will end after all available messages have been read. This parameter can be | ||||
| combined with `since=` (defaults to `since=all`). | ||||
|  | @ -19,7 +248,7 @@ combined with `since=` (defaults to `since=all`). | |||
| curl -s "ntfy.sh/mytopic/json?poll=1" | ||||
| ``` | ||||
| 
 | ||||
| ## Subscribing to multiple topics | ||||
| ### Subscribing to multiple topics | ||||
| It's possible to subscribe to multiple topics in one HTTP call by providing a | ||||
| comma-separated list of topics in the URL. This allows you to reduce the number of connections you have to maintain: | ||||
| 
 | ||||
|  |  | |||
|  | @ -3,5 +3,20 @@ You can use the [ntfy Android App](https://play.google.com/store/apps/details?id | |||
| notifications directly on your phone. Just like the server, this app is also [open source](https://github.com/binwiederhier/ntfy-android). | ||||
| Since I don't have an iPhone or a Mac, I didn't make an iOS app yet. I'd be awesome if [someone else could help out](https://github.com/binwiederhier/ntfy/issues/4). | ||||
| 
 | ||||
| <a href="https://play.google.com/store/apps/details?id=io.heckel.ntfy"><img src="static/img/badge-googleplay.png"></a> | ||||
| <a href="https://github.com/binwiederhier/ntfy/issues/4"><img src="static/img/badge-appstore.png"></a> | ||||
| ## Android | ||||
| You can get the Android app from both [Google Play](https://play.google.com/store/apps/details?id=io.heckel.ntfy) and  | ||||
| from [F-Droid](https://f-droid.org/en/packages/io.heckel.ntfy/). Both are largely identical, with the one exception that | ||||
| the F-Droid flavor does not use Firebase. | ||||
| 
 | ||||
| <a href="https://play.google.com/store/apps/details?id=io.heckel.ntfy"><img src="../../static/img/badge-googleplay.png"></a> | ||||
| <a href="https://f-droid.org/en/packages/io.heckel.ntfy/"><img src="../../static/img/badge-fdroid.png"></a> | ||||
| 
 | ||||
| ### Firebase + Instant delivery | ||||
| 
 | ||||
| 
 | ||||
| 
 | ||||
| ## iPhone/iOS | ||||
| I almost feel devious for putting the *Download on the App Store* button on this page. Currently, there is no iOS app | ||||
| for ntfy, but it's in the works. You can track the status on GitHub. | ||||
| 
 | ||||
| <a href="https://github.com/binwiederhier/ntfy/issues/4"><img src="../../static/img/badge-appstore.png"></a> | ||||
|  |  | |||
|  | @ -1 +1,11 @@ | |||
| # Subscribe from the web UI | ||||
| # Subscribe from the Web UI | ||||
| You can use the Web UI to subscribe to topics as well. If you do, and you keep the website open, **notifications will | ||||
| pop up as desktop notifications**. Simply type in the topic name and click the *Subscribe* button. The browser will  | ||||
| keep a connection open and listen for incoming notifications. | ||||
| 
 | ||||
| <figure markdown> | ||||
|   { width=300 } | ||||
|   <figcaption>Subscribe via Web UI</figcaption> | ||||
| </figure> | ||||
| 
 | ||||
| Once subscribed, you can [publish messages](../publish.md) via `curl` or from without any of your scripts. | ||||
|  |  | |||
		Loading…
	
	Add table
		Add a link
		
	
		Reference in a new issue