Skip to content

viktorholk/push-notifications-api

Folders and files

NameName
Last commit message
Last commit date

Latest commit

Β 

History

128 Commits
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 

Repository files navigation

Push Notifications API

Send push notifications to your Android phone through a simple REST API, powered by Server-Sent Events.

Google Play GitHub Release License

App Preview

About

Push Notifications API is an open-source tool for developers who need a simple way to send notifications to their phone. The application is great for IoT projects β€” for example, post a notification when a sensor detects low soil moisture, or when a build pipeline fails.

How it works: The Android app maintains a persistent SSE (Server-Sent Events) connection to the server. When you send a notification via the REST API, the server pushes it to the connected device in real-time.

Getting Started

1. Get the App

Download the Android app from Google Play, IzzyOnDroid, or grab the latest APK from GitHub Releases.

2. Set Up the Server

  1. Clone and install

    git clone https://github.com/viktorholk/push-notifications-api.git
    cd push-notifications-api/server
    npm install
  2. Configure (optional) β€” create a .env file:

    HOST=0.0.0.0
    PORT=3000
  3. Start the server

    npm run start

    The server runs on port 3000 by default.

3. Connect the App

  1. Open the Android app and enter your server address (e.g. http://YOUR_IP:3000)
  2. Tap Register & Connect β€” a device token is generated automatically
  3. Start sending notifications!

API Reference

Replace YOUR_SERVER with your server address (e.g. http://127.0.0.1:3000).

Register Device

Creates a new device and returns a unique token. The Android app calls this automatically when you tap Register & Connect β€” you only need this endpoint if you're building a custom client.

POST /register

Response 200 OK

{
  "token": "a1b2c3d4-e5f6-7890-abcd-ef1234567890"
}

Send Notification

Sends a notification to a specific device or broadcasts to all devices.

POST /notifications

Body

Field Type Required Description
title string Yes Notification title
message string No Notification body text
token string No Target device token. If provided, the notification is sent only to that device. If omitted, the notification is broadcast to all connected devices.
url string No URL to open when notification is tapped
icon string No Icon filename (server loads from icons/ directory and converts to base64)
color string No Hex color code (e.g. #FF0000)

The token can be provided in the request body, as a query parameter (?token=...), or via the x-access-token header.

Device-Specific Notification

Send to a single device by including the token:

curl -X POST http://YOUR_SERVER:3000/notifications \
  -H "Content-Type: application/json" \
  -d '{
    "token": "YOUR_TOKEN",
    "title": "Garden Alert",
    "message": "The soil moisture is low. Time to water the plants!",
    "url": "https://example.com/garden-cam",
    "color": "#1554F0"
  }'

Global Broadcast Notification

Omit the token entirely to broadcast to all connected devices:

curl -X POST http://YOUR_SERVER:3000/notifications \
  -H "Content-Type: application/json" \
  -d '{
    "title": "System Update",
    "message": "Maintenance window starts in 30 minutes."
  }'

Response 201 Created


Get All Notifications

Retrieves notifications for a device, including both device-specific and broadcast notifications.

GET /notifications

Query Parameters

Parameter Type Required Description
token string Yes Your device token
since string No ISO 8601 timestamp β€” only return notifications created after this time
curl "http://YOUR_SERVER:3000/notifications?token=YOUR_TOKEN&since=2025-01-01T00:00:00.000Z"
Example Response
[
  {
    "id": "b2c3d4e5-f6a7-8901-bcde-f12345678901",
    "title": "Garden Alert",
    "message": "The soil moisture is low. Time to water the plants!",
    "url": "https://example.com/garden-cam",
    "color": "#1554F0",
    "token": "a1b2c3d4-e5f6-7890-abcd-ef1234567890",
    "createdAt": "2025-01-15T12:30:00.000Z"
  },
  {
    "id": "c3d4e5f6-a7b8-9012-cdef-123456789012",
    "title": "System Update",
    "message": "Maintenance window starts in 30 minutes.",
    "token": null,
    "createdAt": "2025-01-15T10:00:00.000Z"
  }
]

Get Latest Notification

Returns the most recent notification for a device.

GET /latest

Query Parameters

Parameter Type Required Description
token string Yes Your device token
curl "http://YOUR_SERVER:3000/latest?token=YOUR_TOKEN"

Response 200 OK β€” notification object, or 404 if none exist.


SSE Event Stream

Connect to the real-time event stream. This is what the Android app uses internally.

GET /events

Query Parameters

Parameter Type Required Description
token string No Device token to filter events
curl -N "http://YOUR_SERVER:3000/events?token=YOUR_TOKEN"

The server sends:

  • data: Connected\n\n on initial connection
  • : heartbeat\n\n every 30 seconds to keep the connection alive
  • data: {notification JSON}\n\n when a new notification is created

Authentication

The token can be provided in any of these ways (checked in this order):

  1. Query parameter: ?token=YOUR_TOKEN
  2. Header: x-access-token: YOUR_TOKEN
  3. Request body: { "token": "YOUR_TOKEN" }

Architecture

β”Œβ”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”       POST /notifications        β”Œβ”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”
β”‚              β”‚ ──────────────────────────────▢  β”‚              β”‚
β”‚  Your Script β”‚                                  β”‚    Server    β”‚
β”‚  or Service  β”‚                                  β”‚  (Express +  β”‚
β”‚              β”‚                                  β”‚   SQLite)    β”‚
β””β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”˜                                  β””β”€β”€β”€β”€β”€β”€β”¬β”€β”€β”€β”€β”€β”€β”€β”˜
                                                         β”‚
                                                    SSE  β”‚  Real-time push
                                                         β”‚
                                                  β”Œβ”€β”€β”€β”€β”€β”€β–Όβ”€β”€β”€β”€β”€β”€β”€β”
                                                  β”‚   Android    β”‚
                                                  β”‚     App      β”‚
                                                  β””β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”˜

Server: Node.js + Express + TypeScript with SQLite (via better-sqlite3 + Kysely) for persistence and in-memory SSE client tracking for real-time delivery.

Android App: Kotlin + Jetpack Compose with a foreground service that maintains a persistent SSE connection. Features automatic reconnection with smart backoff and network-aware retry.

Troubleshooting

Notifications are not showing up

Make sure notifications are enabled in your Android settings:

Settings > Notifications > App notifications

notification settings

Connection keeps dropping
  • Ensure your server is reachable from the device's network
  • Check that the port (default 3000) is open and accessible
  • The app will automatically reconnect on network changes
How do broadcast vs device-specific notifications work?
  • Device-specific: Include a token in the notification body. Only the device with that token receives it.
  • Broadcast: Omit the token field or set it to null. All connected devices receive the notification.
  • When fetching notifications, both broadcast (token = null) and device-specific notifications are returned.

License

Push Notifications API is licensed under the MIT License.