Skip to main content
Version: 2.0

Streaming API

The Streaming API allows your application to listen for events over a live WebSocket connection. It can be used in situations that would otherwise require polling at regular intervals, such as displaying real-time status information in a dashboard. In most other situations, webhooks will provide superior functionality and reliability.

Setup

Since the Streaming API is powered by Socket.IO, the easiest way to interact with it is through a Socket.IO client, which is available in a variety of languages. However, any WebSocket library can also be used. The following Node.js examples show how the Streaming API can be used with both socket.io-client (the official Socket.IO client library) and ws (a generic WebSocket library).

Establishing a connection

The first step is to install the Socket.IO client.

npm install socket.io-client

You can now establish a socket connection using your system ID and a valid system token. See the code tutorial for instructions on requesting system tokens.

const io = require("socket.io-client")
const socket = io(`wss://systems.pdk.io?systemId=${systemId}&token=${systemToken}`)

Subscribing to events

Once a connection is established, you can subscribe to event topics that are relevant to your application.

socket.on("connect", () => {
socket.emit("subscribeIsolated", {
topics: ["device.request.allowed", "device.request.denied", "device.request.unknown"]
})
})

Listening for events

You can now begin listening for events from the access control system. The following example listens for device.request.allowed events, which are emitted when holders are recognized and granted access.

socket.on("device.request.allowed", (event) => {
console.log(event)
})

When an event occurs, the event is passed into the callback function provided to the event listener. The body of the event includes details related to the corresponding event topic. In this example, the event topic is device.request.allowed and the body includes details about the device, holder, and credential.

{
"id": "c9daad36-df91-447e-b199-363e425c3084",
"topic": "device.request.allowed",
"body": {
"deviceId": "1b99bf42-1f9c-4184-9b5a-f7be9b24f4be",
"holderId": "ceee92e3-fdf4-44e6-800a-2d9d51d05583",
"credentialId": "56bed685-aa32-4ae2-a9da-323cdd38ebc0",
"requestFactor": "CARD_ONLY",
"facilityCode": "77",
"cardNumber": "26858",
"device": {
"id": "1b99bf42-1f9c-4184-9b5a-f7be9b24f4be",
"name": "Test Device",
"connection": "5b34aff3-e883-4c32-88e1-b6d36fbce93a",
"port": 1
},
"holder": {
"id": "ceee92e3-fdf4-44e6-800a-2d9d51d05583",
"name": "John Wiegand",
"enabled": true,
"activeDate": null,
"expireDate": null
}
},
"cloudNode": {
"id": "ad69a1c0-1390-4ddd-9d49-01c388c3744b",
"serialNumber": "1234ABC",
"name": "Test Cloud Node"
},
"occurred": 1719356407640
}

Renewing the system token

When an event occurs after a system token has expired, an invalidToken event will be emitted in its place. You can renew system tokens automatically by listening for invalidToken events and emitting a renewedToken event in response. Once the new token is received, the Streaming API will immediately emit any events that occurred while the previous token was expired.

socket.on("invalidToken", async (event) => {
const systemToken = await getSystemToken()
socket.emit("renewedToken", { token: systemToken })
})

Events

In addition to the standard Socket.IO events, your application can also listen for the following access control events.

tip

The Streaming API only supports a small subset of events. For a complete set of events, use webhooks instead.

device.alarm.forced

This event is emitted when a device equipped with a door position sensor (DPS) is forced open.

{
"id": "eb3accb3-f66c-4d62-aa68-2291bdd77b39",
"topic": "device.alarm.forced",
"body": {
"deviceId": "27e9674c-dd41-4404-b030-cc697c6f599d",
"device": {
"id": "09098929-9415-442f-b108-4093b39b25d2",
"name": "Test Device",
"connection": "ce7ae800-7327-45f7-ad70-4d4a8d6347f6",
"port": 1
}
},
"cloudNode": {
"id": "2c1ec505-6ed1-4bf4-b82a-6bc8fcf6267b",
"serialNumber": "1234ABC",
"name": "Test Cloud Node"
},
"occurred": 1712593100540
}

device.alarm.forced.cleared

This event is emitted when a forced alarm has cleared.

{
"id": "eb3accb3-f66c-4d62-aa68-2291bdd77b39",
"topic": "device.alarm.forced.cleared",
"body": {
"deviceId": "27e9674c-dd41-4404-b030-cc697c6f599d",
"device": {
"id": "09098929-9415-442f-b108-4093b39b25d2",
"name": "Test Device",
"connection": "ce7ae800-7327-45f7-ad70-4d4a8d6347f6",
"port": 1
}
},
"cloudNode": {
"id": "2c1ec505-6ed1-4bf4-b82a-6bc8fcf6267b",
"serialNumber": "1234ABC",
"name": "Test Cloud Node"
},
"occurred": 1712593100540
}

device.alarm.propped.off

This event is emitted when a prop alarm has cleared for a device.

{
"id": "eb3accb3-f66c-4d62-aa68-2291bdd77b39",
"topic": "device.alarm.propped.off",
"body": {
"deviceId": "27e9674c-dd41-4404-b030-cc697c6f599d",
"device": {
"id": "09098929-9415-442f-b108-4093b39b25d2",
"name": "Test Device",
"connection": "ce7ae800-7327-45f7-ad70-4d4a8d6347f6",
"port": 1
}
},
"cloudNode": {
"id": "2c1ec505-6ed1-4bf4-b82a-6bc8fcf6267b",
"serialNumber": "1234ABC",
"name": "Test Cloud Node"
},
"occurred": 1712593100540
}

device.alarm.propped.on

This event is emitted when a device equipped with a door position sensor (DPS) is propped open.

{
"id": "eb3accb3-f66c-4d62-aa68-2291bdd77b39",
"topic": "device.alarm.propped.on",
"body": {
"deviceId": "27e9674c-dd41-4404-b030-cc697c6f599d",
"device": {
"id": "09098929-9415-442f-b108-4093b39b25d2",
"name": "Test Device",
"connection": "ce7ae800-7327-45f7-ad70-4d4a8d6347f6",
"port": 1
}
},
"cloudNode": {
"id": "2c1ec505-6ed1-4bf4-b82a-6bc8fcf6267b",
"serialNumber": "1234ABC",
"name": "Test Cloud Node"
},
"occurred": 1712593100540
}

device.autoopen.off

This event is emitted when auto open is deactivated.

{
"id": "05158b99-82c0-47f9-96db-9c715625d431",
"topic": "device.autoopen.off",
"body": {
"deviceId": "6e3948a3-63c8-441b-a2d3-13039bdc5843",
"device": {
"id": "6e3948a3-63c8-441b-a2d3-13039bdc5843",
"name": "Test Device",
"connection": "3a897840-33a7-4e6d-841d-a35e2906960b",
"port": 1
}
},
"cloudNode": {
"id": "b1add759-dfce-4473-9116-8ca55a59cb77",
"name": "Test Cloud Node",
"serialNumber": "1234ABC"
},
"occurred": 1712593109999
}

device.autoopen.on

This event is emitted when auto open is activated.

{
"id": "9e6bdc19-5cda-4f5a-aee8-99ee0b58f6f8",
"topic": "device.autoopen.on",
"body": {
"deviceId": "6e3948a3-63c8-441b-a2d3-13039bdc5843",
"device": {
"id": "6e3948a3-63c8-441b-a2d3-13039bdc5843",
"name": "Test Device",
"connection": "3a897840-33a7-4e6d-841d-a35e2906960b",
"port": 1
}
},
"cloudNode": {
"id": "b1add759-dfce-4473-9116-8ca55a59cb77",
"name": "Test Cloud Node",
"serialNumber": "1234ABC"
},
"occurred": 1712593109999
}

device.forceclose.off

This event is emitted when do not disturb (DND) is deactivated.

{
"id": "eb3accb3-f66c-4d62-aa68-2291bdd77b39",
"topic": "device.forceclose.off",
"body": {
"deviceId": "27e9674c-dd41-4404-b030-cc697c6f599d",
"device": {
"id": "09098929-9415-442f-b108-4093b39b25d2",
"name": "Test Device",
"connection": "ce7ae800-7327-45f7-ad70-4d4a8d6347f6",
"port": 1
}
},
"cloudNode": {
"id": "2c1ec505-6ed1-4bf4-b82a-6bc8fcf6267b",
"serialNumber": "1234ABC",
"name": "Test Cloud Node"
},
"occurred": 1712593100540
}

device.forceclose.on

This event is emitted when do not disturb (DND) is activated.

{
"id": "eb3accb3-f66c-4d62-aa68-2291bdd77b39",
"topic": "device.forceclose.on",
"body": {
"deviceId": "27e9674c-dd41-4404-b030-cc697c6f599d",
"device": {
"id": "09098929-9415-442f-b108-4093b39b25d2",
"name": "Test Device",
"connection": "ce7ae800-7327-45f7-ad70-4d4a8d6347f6",
"port": 1
}
},
"cloudNode": {
"id": "2c1ec505-6ed1-4bf4-b82a-6bc8fcf6267b",
"serialNumber": "1234ABC",
"name": "Test Cloud Node"
},
"occurred": 1712593100540
}

device.forceopen.off

This event is emitted when force unlock is deactivated.

{
"id": "eb3accb3-f66c-4d62-aa68-2291bdd77b39",
"topic": "device.forceopen.off",
"body": {
"deviceId": "27e9674c-dd41-4404-b030-cc697c6f599d",
"device": {
"id": "09098929-9415-442f-b108-4093b39b25d2",
"name": "Test Device",
"connection": "ce7ae800-7327-45f7-ad70-4d4a8d6347f6",
"port": 1
}
},
"cloudNode": {
"id": "2c1ec505-6ed1-4bf4-b82a-6bc8fcf6267b",
"serialNumber": "1234ABC",
"name": "Test Cloud Node"
},
"occurred": 1712593100540
}

device.forceopen.on

This event is emitted when force unlock is activated.

{
"id": "eb3accb3-f66c-4d62-aa68-2291bdd77b39",
"topic": "device.forceopen.on",
"body": {
"deviceId": "27e9674c-dd41-4404-b030-cc697c6f599d",
"device": {
"id": "09098929-9415-442f-b108-4093b39b25d2",
"name": "Test Device",
"connection": "ce7ae800-7327-45f7-ad70-4d4a8d6347f6",
"port": 1
}
},
"cloudNode": {
"id": "2c1ec505-6ed1-4bf4-b82a-6bc8fcf6267b",
"serialNumber": "1234ABC",
"name": "Test Cloud Node"
},
"occurred": 1712593100540
}

device.input.dps.closed

This event is emitted when a door position sensor (DPS) changes to a closed state.

{
"id": "eb3accb3-f66c-4d62-aa68-2291bdd77b39",
"topic": "device.input.dps.closed",
"body": {
"deviceId": "27e9674c-dd41-4404-b030-cc697c6f599d",
"device": {
"id": "09098929-9415-442f-b108-4093b39b25d2",
"name": "Test Device",
"connection": "ce7ae800-7327-45f7-ad70-4d4a8d6347f6",
"port": 1
}
},
"cloudNode": {
"id": "2c1ec505-6ed1-4bf4-b82a-6bc8fcf6267b",
"serialNumber": "1234ABC",
"name": "Test Cloud Node"
},
"occurred": 1712593100540
}

device.input.dps.opened

This event is emitted when a door position sensor (DPS) changes to an open state.

{
"id": "eb3accb3-f66c-4d62-aa68-2291bdd77b39",
"topic": "device.input.dps.opened",
"body": {
"deviceId": "27e9674c-dd41-4404-b030-cc697c6f599d",
"device": {
"id": "09098929-9415-442f-b108-4093b39b25d2",
"name": "Test Device",
"connection": "ce7ae800-7327-45f7-ad70-4d4a8d6347f6",
"port": 1
}
},
"cloudNode": {
"id": "2c1ec505-6ed1-4bf4-b82a-6bc8fcf6267b",
"serialNumber": "1234ABC",
"name": "Test Cloud Node"
},
"occurred": 1712593100540
}

device.input.relay.off

This event is emitted when a device is locked.

{
"id": "eb3accb3-f66c-4d62-aa68-2291bdd77b39",
"topic": "device.input.relay.off",
"body": {
"deviceId": "27e9674c-dd41-4404-b030-cc697c6f599d",
"device": {
"id": "09098929-9415-442f-b108-4093b39b25d2",
"name": "Test Device",
"connection": "ce7ae800-7327-45f7-ad70-4d4a8d6347f6",
"port": 1
}
},
"cloudNode": {
"id": "2c1ec505-6ed1-4bf4-b82a-6bc8fcf6267b",
"serialNumber": "1234ABC",
"name": "Test Cloud Node"
},
"occurred": 1712593100540
}

device.input.relay.on

This event is emitted when a device is unlocked.

{
"id": "eb3accb3-f66c-4d62-aa68-2291bdd77b39",
"topic": "device.input.relay.on",
"body": {
"deviceId": "27e9674c-dd41-4404-b030-cc697c6f599d",
"device": {
"id": "09098929-9415-442f-b108-4093b39b25d2",
"name": "Test Device",
"connection": "ce7ae800-7327-45f7-ad70-4d4a8d6347f6",
"port": 1
}
},
"cloudNode": {
"id": "2c1ec505-6ed1-4bf4-b82a-6bc8fcf6267b",
"serialNumber": "1234ABC",
"name": "Test Cloud Node"
},
"occurred": 1712593100540
}

device.input.rex.off

This event is emitted when the request to exit (REX) is deactivated.

{
"id": "eb3accb3-f66c-4d62-aa68-2291bdd77b39",
"topic": "device.input.rex.off",
"body": {
"deviceId": "27e9674c-dd41-4404-b030-cc697c6f599d",
"device": {
"id": "09098929-9415-442f-b108-4093b39b25d2",
"name": "Test Device",
"connection": "ce7ae800-7327-45f7-ad70-4d4a8d6347f6",
"port": 1
}
},
"cloudNode": {
"id": "2c1ec505-6ed1-4bf4-b82a-6bc8fcf6267b",
"serialNumber": "1234ABC",
"name": "Test Cloud Node"
},
"occurred": 1712593100540
}

device.input.rex.on

This event is emitted when the request to exit (REX) is activated.

{
"id": "eb3accb3-f66c-4d62-aa68-2291bdd77b39",
"topic": "device.input.rex.on",
"body": {
"deviceId": "27e9674c-dd41-4404-b030-cc697c6f599d",
"device": {
"id": "09098929-9415-442f-b108-4093b39b25d2",
"name": "Test Device",
"connection": "ce7ae800-7327-45f7-ad70-4d4a8d6347f6",
"port": 1
}
},
"cloudNode": {
"id": "2c1ec505-6ed1-4bf4-b82a-6bc8fcf6267b",
"serialNumber": "1234ABC",
"name": "Test Cloud Node"
},
"occurred": 1712593100540
}

device.request.allowed

This event is emitted when a holder is recognized and granted access.

{
"id": "c9daad36-df91-447e-b199-363e425c3084",
"topic": "device.request.allowed",
"body": {
"deviceId": "1b99bf42-1f9c-4184-9b5a-f7be9b24f4be",
"holderId": "ceee92e3-fdf4-44e6-800a-2d9d51d05583",
"credentialId": "56bed685-aa32-4ae2-a9da-323cdd38ebc0",
"requestFactor": "CARD_ONLY",
"facilityCode": "77",
"cardNumber": "26858",
"device": {
"id": "1b99bf42-1f9c-4184-9b5a-f7be9b24f4be",
"name": "Test Device",
"connection": "5b34aff3-e883-4c32-88e1-b6d36fbce93a",
"port": 1
},
"holder": {
"id": "ceee92e3-fdf4-44e6-800a-2d9d51d05583",
"name": "John Wiegand",
"enabled": true,
"activeDate": null,
"expireDate": null
}
},
"cloudNode": {
"id": "ad69a1c0-1390-4ddd-9d49-01c388c3744b",
"serialNumber": "1234ABC",
"name": "Test Cloud Node"
},
"occurred": 1719356407640
}

device.request.denied

This event is emitted when a holder is recognized but denied access.

{
"id": "c9daad36-df91-447e-b199-363e425c3084",
"topic": "device.request.denied",
"body": {
"deviceId": "1b99bf42-1f9c-4184-9b5a-f7be9b24f4be",
"holderId": "ceee92e3-fdf4-44e6-800a-2d9d51d05583",
"credentialId": "56bed685-aa32-4ae2-a9da-323cdd38ebc0",
"requestFactor": "CARD_ONLY",
"facilityCode": "77",
"cardNumber": "26858",
"device": {
"id": "1b99bf42-1f9c-4184-9b5a-f7be9b24f4be",
"name": "Test Device",
"connection": "5b34aff3-e883-4c32-88e1-b6d36fbce93a",
"port": 1
},
"holder": {
"id": "ceee92e3-fdf4-44e6-800a-2d9d51d05583",
"name": "John Wiegand",
"enabled": true,
"activeDate": null,
"expireDate": null
}
},
"cloudNode": {
"id": "ad69a1c0-1390-4ddd-9d49-01c388c3744b",
"serialNumber": "1234ABC",
"name": "Test Cloud Node"
},
"occurred": 1719356407640
}

device.request.unknown

This event is emitted when a credential is presented but the holder is not recognized.

{
"id": "c9daad36-df91-447e-b199-363e425c3084",
"topic": "device.request.unknown",
"body": {
"deviceId": "1b99bf42-1f9c-4184-9b5a-f7be9b24f4be",
"facilityCode": "77",
"cardNumber": "26858",
"device": {
"id": "1b99bf42-1f9c-4184-9b5a-f7be9b24f4be",
"name": "Test Device",
"connection": "5b34aff3-e883-4c32-88e1-b6d36fbce93a",
"port": 1
}
},
"cloudNode": {
"id": "ad69a1c0-1390-4ddd-9d49-01c388c3744b",
"serialNumber": "1234ABC",
"name": "Test Cloud Node"
},
"occurred": 1719356407640
}

endpoint.sync.finished

This event is emitted when a controller has finished syncing.

{
"id": "0942d921-09ff-48e2-9092-cb3de0a96c42",
"topic": "endpoint.sync.finished",
"body": {
"connectionId": "3a897840-33a7-4e6d-841d-a35e2906960b",
"address": "",
"type": "ao_rules"
},
"cloudNode": {
"id": "19a808d6-0e6a-4202-9dde-64a20ec3ad09",
"name": "Test Cloud Node",
"serialNumber": "1234ABC"
},
"occurred": 1712593109999
}

endpoint.sync.finished.all

This event is emitted when all controllers connected to a cloud node have finished syncing.

{
"id": "0942d921-09ff-48e2-9092-cb3de0a96c42",
"topic": "endpoint.sync.finished.all",
"body": {
"connectionId": "3a897840-33a7-4e6d-841d-a35e2906960b",
"address": "",
"type": "ao_rules"
},
"cloudNode": {
"id": "19a808d6-0e6a-4202-9dde-64a20ec3ad09",
"name": "Test Cloud Node",
"serialNumber": "1234ABC"
},
"occurred": 1712593109999
}

endpoint.sync.started

This event is emitted when a controller has started syncing.

{
"id": "0942d921-09ff-48e2-9092-cb3de0a96c42",
"topic": "endpoint.sync.started",
"body": {
"connectionId": "3a897840-33a7-4e6d-841d-a35e2906960b",
"address": "",
"type": "ao_rules"
},
"cloudNode": {
"id": "19a808d6-0e6a-4202-9dde-64a20ec3ad09",
"name": "Test Cloud Node",
"serialNumber": "1234ABC"
},
"occurred": 1712593109999
}

liveEvent

This aggregate event is emitted when auditable access events occur. Each event includes a description that can be used in human-readable event streams.

{
"topic": "device.request.allowed",
"info": "Person \"%s\" has requested access to the device \"%s\". Access allowed. Person used card for requesting access.",
"placeholders": [
{
"text": "John Wiegand",
"id": "ceee92e3-fdf4-44e6-800a-2d9d51d05583",
"type": "holder"
},
{
"text": "Test Device",
"id": "1b99bf42-1f9c-4184-9b5a-f7be9b24f4be",
"type": "device"
}
],
"cloudNode": {
"id": "19a808d6-0e6a-4202-9dde-64a20ec3ad09",
"name": "Test Cloud Node",
"serialNumber": "1234ABC"
},
"occurred": 1719358795980
}

sync.not_synced

This event is emitted when a cloud node needs to be synced.

{
"systemId": "19a808d6-0e6a-4202-9dde-64a20ec3ad09",
"panelSn": "1234ABC",
"details": {
"dataFlowStatus": "Pending",
"timestamp": 1712591860790
}
}

sync.synced

This event is emitted when a cloud node has finished syncing.

{
"systemId": "19a808d6-0e6a-4202-9dde-64a20ec3ad09",
"panelSn": "1234ABC",
"details": {
"timestamp": 1712591860790
}
}