Subscribing
There are three ways to receive messages from a topic.
- Push: register a device and subscribe it to a topic.
- SSE: keep a live stream open for new messages.
- Polling: read the message list when you need it.
Concepts
A device is any client endpoint that can receive a push: a browser, an iOS app, an Android app (planned), or anything else that owns a push token. A subscription connects one device to one concrete topic.
1. Push (browsers and iOS)
Register a device with a push token, subscribe it to topics, and pingd will deliver pushes through the appropriate channel. This is the only path that works when the receiver is offline / app is closed.
Register the device
POST/devices
Authorization: Bearer <token>
{
"name": "Vi's iPhone",
"platform": "ios",
"pushType": "apns",
"pushToken": "apns-token-here",
"deliveryEnabled": true
}
Web Push devices use platform: "web" and pushType: "webpush" with the serialized PushSubscription as pushToken. See Web Push.
Subscribe to topics
POST/devices/:id/subscriptions
Authorization: Bearer <token>
X-Topic-Token: tk_... # optional
{ "topicName": "alerts.cpu" }
One topic per call. Subscribe to alerts.cpu, alerts.disk, etc. separately. Include X-Topic-Token when read access comes from a share token.
Unsubscribe
DELETE/devices/:id/subscriptions/:topicName
Authorization: Bearer <token>
List subscriptions
GET/devices/:id/subscriptions
Authorization: Bearer <token>
GET/users/:username/subscriptions
Authorization: Bearer <token>
The user-scoped variant returns every subscription across the user's devices, with topic identity attached. The dashboard uses it to rebuild a logged-in user's topic list across refreshes.
2. Live SSE stream
For terminals, dashboards, and long-running scripts:
GET/topics/:name/stream
The response is text/event-stream. Each new message published to the topic is delivered as a single event. Read access uses the same rules as GET /topics/:name.
curl -N http://localhost:7685/topics/alerts/stream \
-H "Authorization: Bearer $TOKEN"
The CLI wraps this with auto-reconnect:
pingd-cli messages watch --topic alerts
proxy_buffering off and a long
read timeout. See Configuration.
3. Polling the message list
For batch jobs and HTTP-only environments:
GET/topics/:name/messages
Returns recent messages in reverse chronological order. Expired messages are filtered.
For change-detection, sort by time and remember the last ID you saw.
Anonymous subscribers (guest sessions)
Anonymous device registration is not allowed. Apps that want push without forcing user signup
should call POST /auth/guest first to get a guest bearer token, then register a
device and subscribe with that token. Guests behave like anonymous callers for topic access:
they can use public topics and share tokens, but they do not receive permission grants.
See Users & tokens.
Delivery toggle
Devices have a deliveryEnabled flag. Set to false if a device should
keep its subscriptions for membership tracking but should not actually receive pushes
(useful for read-only mirrors). The default is true.
Logout-time deactivation
When a user logs out from a device, send the device's push token to deactivate it server-side:
DELETE/auth/logout
Authorization: Bearer <token>
X-Push-Token: <push token>
The device is only deactivated if the push token belongs to the current user. Omitting the header revokes the bearer token only.
Subscription access rules
| Access source | Who can subscribe |
|---|---|
publicRead=true | Any authenticated user, including guests |
| Owner or admin | Always allowed |
| Share token | Authenticated caller with a valid ro or rw X-Topic-Token |
| Permission | Non-guest user with matching ro or rw permission |
wo, deny, expired grant, or no read source | Denied |