Subscriber Protocols

Subscribers are invoked by a topic when an event is sent to that topic. You can find all currently supported subscriber protocols below.

Subscriber Commonalities

Common Flags

  • Volatile: The subscription will be removed upon any failure to send to it.
  • Retry: The subscription will retry automatically (backing off) for 3 days. At a rate of 2^n * 15 where n is number of attempts. Incompatible with volatile.

Url Templating

You can use handlebars-style string templating for your subscription URL to populate it with items from the payload. Any population will be URL-Encoded. (It actually uses lodash.get under-the-hood. You can use any format supported by it.)

For example, if you receive an event with the data:

{"name": "test", b: {"val" : 123}}

you might have a subscriber URL that uses the field name in it:{{name}}&nested={{b.val}}

CLI Application

One of the easiest ways to get started is to look at events with the cli app. You can read more about it here


The event will be sent over normal http/https, with the method of your choosing.

Any HTTP method is supported. There is a special method, SOURCE, that will use the same method to invoke the subscriber that was used to invoke the topic.

HTTP Authorization

The key, if one is provided, will be included as a bearer on the Authorization header.

HTTP Headers

In addition to the payload, additional headers will be added to the HTTP request to identify where the request came from:

  • X-Topic-Chain A comma-separated list of topic ids the event has traversed. Used to identify source, as well as prevent circular references.
  • X-Topic-Id The id of the topic invoking the subscription
  • X-Topic-Name The name of the topic invoking the subscription
  • X-User-Id The id of the user who owns the topic and subscription
  • X-Router-Signature Router signature. See Advanced section for more details.

The response will be recorded, and can be used again by the topic's invoker.


  • By default, the HTTP handler will follow redirects, up to 4 times
  • The request will timeout in 5 seconds

Example Request

User-Agent: UbSub/1.0
X-Topic-Chain: 94jkNna,B1xFdvBv4b
X-Topic-Id: B1xFdvBv4b
X-User-Id: 4uHAh4nan
X-Topic-Name: test
Authorization: Bearer mykey
host: localhost:8080
accept: application/json
content-type: application/json
content-length: 2
Connection: close


Topic Chaining

Sometimes it makes sense for one topic to invoke another topic. This is called topic chaining.

While it works fine to simply copy-paste the HTTP url of the other topic, there's a shorthand: topic://<topicId>?key=<key>.

Example: topic://Byg2kKB3SZ?key=HJ3ytS3SW

If there is no key, you can simply leave it off. You are not required to add a key if you are sending it to a topic you own.


You can trigger a simple email to be sent (serialized JSON) with the following format: mail://

Optionally, you can add parameters: (eg. mail://


  • subject Specify the subject line of the email. If not present, check payload.subject (Default: Topic Id)
  • from The name that should be on the from line. If not present, check payload.from (Default: User Id)
  • bodykey The key to grab the body of the email from. If not present, use payload.body (Default: Raw JSON)



SocketIO is the preferred method for on-the-fly subscribing to a topic. It isn't supported directly by the router, but rather, a supporting component.

There are two ways to connect/subscribe to a socket.

Subscribing via Query Params

When connecting via SIO, connect directly to the url /socket?userId=xxx&topicId=yyy&userKey=zzz.

Optionally, you can provide a name param to name the socket as well.

If you connect to specific topic via the handshake mechanism (query params), and there is an error, an event called handshake-error will be emitted, and the socket will be immediately disconnected.

const io = socketio('');
io.on('connect', (socket) => {
    io.on('handshake-error', err => {
      // After this event, it will immediately be disconnected
    io.on('event', data => {

Subscribing After Connection

The other option, is to connect to just /socket, and emit a packet on connection:

Example client:

const io = socketio('');
io.on('connect', (socket) => {
    io.emit('subscribe', {
        userId: 'xxx',
        userKey: 'xxx',
        topicId: 'xxx',
        name: 'my socket', // OPTIONAL name
    }, (err, data) => { // OPTIONAL callback
        if (err)
            console.log('ERROR: ' + err);
        console.dir(data); // contains {connectionId, subscriptionId, listenerId}

    // Unsubscribe a listener from a given subscription
    io.emit('unsubscribe', {
      listenerId: '...'
    }, (err) => {});

    io.on('event', data => {

Technically you can combine both strategies.

Event Payload

When receiving an event that is sent to the subscription, it will be in the following form:

  "topicId": "abc",
  "payload" : {...}

Emitting an Event

You can also emit an event to any topic directly over the socket. Simply emit an event with the following data:

  "topicId" : "abc",
  "topicKey" : "def", // optional topic key
  "payload" : {...}

Shutting down

Sometimes it is necessary to request the server disconnect the client to mae sure all the data has been received first. To do this, simply emit the event shutdown and the client will be disconnected.

More Examples

Visit our github for more examples.


WebSockets are available to connect to in a very similar way as SocketIO is, with the main difference being that a given connection will only connect to a single topic (rather than many). This gives us the ability to stream the raw data without worrying about too much overhead.


Host: wss://

To connect to a web socket endpoint, you might make a call like this:

const client = ws('wss://');

The query parameters are required.

  • userId - The user (or token) you wish to connect as
  • userKey - The user (or token) key you wish to authenticate with
  • topicId - The topic you wish to receive events from
  • name - OPTIONAL extra parameter to specify the name of the subscription
  • direction (default: out). The direction of the data you wish to send, either in or out


Every event is sent as a new message to the websocket client as JSON. Events may only travel in one direction since it's unlikely that you would want to receive an event you just sent. By default this direction is from ubsub to your client (out).


From time to time the streaming server may have to restart. Please be sure to gracefully manage any disconnection by attempting a reconnect.


Requirements: npm install --save ws

const WebSocket = require('ws');
const config = require('../config');

const ws = new WebSocket(`wss://${config.USER_ID}&userKey=${config.USER_KEY}&topicId=${config.TOPIC_ID}`);
ws.on('message', payload => {
  console.log(`Received: ${payload}`);

// If direction=in, you can send data to ubsub
ws.on('open', () => {
  ws.send(JSON.stringify({ test: 'event', data: { a: 444 } }));


Do not confuse the udp:// protocol with the IoT protocol. The latter is secure and encrypted. More details can be found here.

Version 0 (Keyless)

WARNING: The UDPv0 protocol is not secure. Anyone can watch packets over-the-wire, and you are subject to a man-in-the-middle attack. Please use https for better security.

IMPORTANT: Unlike https, UDP does not wait for the payload to be acknowledged or delivered in any way. This method should be considered lossy, but good when performance or compatibility are important factors.

UDP is added for support for and low-level applications.

Example subscriber uri: udp://

Because a UDP subscriber doesn't wait for a response, the response in the topic invoke will look like this:

  "response": {
    "bytesSent": 105,   // Number of bytes sent
    "bufferSize": 105   // Number of bytes that were attempted to be sent
  "subscription": {
    "id": "...",        // The ID of the subsription
    "topicId": "..."    // The ID of the topic

The payload is formatted similar to HTTP, with \n being the delimiter. \n\n will be found directly before the payload. In the future, more header-like lines may be added.


POST /path
SUBID abcdef

{...JSON payload...}

Version 2/3 (For IoT)

The specification and details for UDPv3 can be found here.

It provides in additional functionality such as guaranteed-delivery, encryption/security/validation, NAT negotiation, etc.

C++ Implementation for Embedded Platforms


The store service allows you to store small pieces of information. See store for details.


Run a subscription, but always succeed, and don't send the data anywhere.

The response will be the parsed form of the requested query and the post-template payload.

Example: (void://test?v=1&b=2)

"response": {
  "void": {
    "protocol": "void",
    "hostname": "test",
    "path": "/",
    "query": "v=1&b=2"
  "payload": {
    "nesting": {
      "a": 1233


UbSub supports MQTT by proxying through a Eclipse Mosquitto.

Go to mqtt for more information.