Data API

Everything the dashboard shows is a plain REST endpoint you can call yourself. Telemetry comes back as JSON, so you can pull device data into your own backend, a script, a spreadsheet, or another service.

How you authenticate depends on which server you’re talking to:

  • Hosted (pulsync.in) — an API key you generate in the portal, sent as a Bearer token. This is the path built for external/programmatic access.
  • Self-hosted — a single admin password gate. There’s no per-key auth; you either leave the gate open on a trusted LAN or log in to get a session cookie.

Hosted: API keys

1. Generate a key

In the portal, create an API key. It’s returned once — store it immediately, it’s never shown again. Keys look like psk_ followed by 40 hex characters and authenticate as your workspace (tenant), automatically scoped to your own devices.

You can also create one over the API from a logged-in portal session:

curl -X POST https://pulsync.in/api/keys 
  -H "Content-Type: application/json" 
  -d '{"label": "my-backend"}'
# → { "key": "psk_ab12cd34...", "record": { ... } }

2. List your devices

curl https://pulsync.in/api/devices 
  -H "Authorization: Bearer psk_ab12cd34..."
# → { "devices": [ { "id": "...", "name": "...", ... } ] }

3. Pull telemetry

curl "https://pulsync.in/api/devices/DEVICE_ID/data?limit=100" 
  -H "Authorization: Bearer psk_ab12cd34..."

From Node:

const res = await fetch(
  `https://pulsync.in/api/devices/${deviceId}/data?limit=100`,
  { headers: { Authorization: `Bearer ${process.env.PULSYNC_API_KEY}` } }
);
const { data } = await res.json();

Keys can be revoked from the portal (or DELETE /api/keys/:id); a revoked key stops working immediately.


Self-hosted: admin gate

The self-hosted server exposes the same telemetry, but device-management routes are mounted under /api/device/ and share the single ADMIN_PASSWORD gate — there are no per-key tokens.

If ADMIN_PASSWORD is unset (the default on a trusted LAN), the endpoints are open and you can call them directly:

curl "http://pulsync.local:3456/api/device/devices/DEVICE_ID/data?limit=100"

If ADMIN_PASSWORD is set, log in first to get a session cookie, then send that cookie on later calls:

# 1. Log in — stores the ps_admin cookie in a cookie jar
curl -c jar.txt -X POST http://pulsync.local:3456/api/device/admin/login 
  -H "Content-Type: application/json" 
  -d '{"password": "your-admin-password"}'

# 2. Use the cookie to pull data
curl -b jar.txt "http://pulsync.local:3456/api/device/devices/DEVICE_ID/data?limit=100"

List devices to find a device ID:

curl -b jar.txt http://pulsync.local:3456/api/device/devices
# → { "devices": [ ... ], "ws_connections": N }

No API keys in self-hosted. Auth is one shared admin password plus a session cookie, which is awkward for headless scripts. On a trusted LAN, leaving the gate open is the simplest option. If you expose the server beyond your network, set ADMIN_PASSWORD and put it behind a TLS proxy.


Query parameters

Both servers accept the same parameters on the data endpoint:

ParameterDefaultDescription
limit100Max number of data points to return (hosted caps this at 1000)
since(none)ISO 8601 timestamp — return only points received after this time

Example:

?limit=500&since=2026-09-01T00:00:00Z

Response shape

Both servers return telemetry in the same shape. Each point carries the raw payload the device sent plus the server receive time:

{
  "data": [
    {
      "data": { "temperature": 25.3, "humidity": 60 },
      "timestamp": "2026-09-07T10:42:11.000Z"
    },
    {
      "data": { "temperature": 25.1, "humidity": 61 },
      "timestamp": "2026-09-07T10:42:06.000Z"
    }
  ]
}

Points are newest-first. data is whatever key-value payload the device sent via Pulsync.send().


Live data (WebSocket)

Polling the data endpoint gives you history. On the self-hosted server you can also receive updates the moment a device sends them by connecting to the live WebSocket instead of polling in a loop.

Connect

ws://pulsync.local:3456/api/live

On connect the server sends a welcome frame, then pushes an event every time something happens on any device:

const ws = new WebSocket("ws://pulsync.local:3456/api/live");

ws.onmessage = (msg) => {
  const evt = JSON.parse(msg.data);
  if (evt.type === "device_data" && evt.deviceId === MY_DEVICE_ID) {
    console.log("new data:", evt.data, "at", evt.timestamp);
  }
};

Event types

typeFieldsMeaning
connectedclientsSent once on connect
device_datadeviceId, data, timestampNew telemetry — data is the payload the device sent
heartbeatdeviceId, status, timestampDevice checked in
enrolleddeviceId, pairingCodeA device enrolled
ota_statusdeviceId, status, versionFirmware offered or applied
command_sentdeviceId, command, payloadA command was dispatched

Things to know

  • It’s a firehose. Every connected client receives events for all devices — there’s no per-device subscription. Filter by deviceId in your handler.
  • No history on connect. The stream only carries events that happen after you connect. For past data, use the REST endpoint above.
  • The stream is not gated by ADMIN_PASSWORD. Unlike the REST management routes, /api/live accepts any connection. That’s fine on a trusted LAN, but if you expose the server, anyone who can reach it can read the live stream. Put the server behind a TLS reverse proxy with its own access control if it’s reachable beyond your network.

Other operations

The same endpoints and auth let you drive devices, not just read from them:

ActionMethod + path
List devicesGET /devices
Device detailsGET /devices/:id
Query telemetryGET /devices/:id/data
Push configPUT /devices/:id/config — body { "key": value, ... }
Send a commandPOST /devices/:id/command — body { "command": "...", "payload": {} }

Prefix with /api on hosted and /api/device on self-hosted. Config changes and commands reach the device over MQTT (on the next heartbeat, or immediately if the device is connected).

Keep keys secret

API keys and admin passwords are credentials — treat them like passwords. Don’t commit them to source control or ship them in frontend code; keep them in environment variables on a server you control. Hosted keys are shown once at creation, so store them right away, and revoke any key you suspect is leaked.