Streaming with SSE (live telemetry)
Instead of refreshing every few seconds to ask "where is the vehicle now?", you open a single connection and the server pushes updates the moment they happen — GPS positions, trip events, anything live. That's Server-Sent Events (SSE).
Think of it like a live news feed: you tune in once, and updates appear on screen as they're broadcast. No refresh, no polling, no delay.
The subscription endpoints (/api/v1/monitoring/unit/{id}, /api/v1/monitoring/vehicle/{id}/primary) and everything else in the Monitoring + SSE collections are listed in the API Reference with full parameters and response shapes.
How it works — the mental model
There are three things going on, in this order:
┌─────────────┐ 1. open stream ┌──────────────┐
│ your code │ ─────────────────────────────► │ Destiny SSE │
│ (or browser)│ ◄──── stream_id event ──────── │ server │
└─────┬───────┘ └───── ─┬───────┘
│ │
│ 2. subscribe per vehicle/unit (REST POST) │
│ /api/v1/monitoring/unit/{id} │
│ ─────────────────────────────────────────────►│
│ │
│ ◄──── gps / event messages stream in ─────────│
│ ◄──── periodic "ping" event ──────────────────│
│ │
│ 3. answer the ping (REST POST) │
│ /sse/pong/{stream_id} │
│ ─────────────────────────────────────────────►│
You open one SSE connection and can subscribe to many vehicles/units over
it. The server sends a stream_id after you connect — you'll need it to
subscribe and to answer pings.
Try it in your terminal (5 minutes, real API)
This uses the live API at https://www.acmdestiny.net. You'll need a Destiny
username and password.
1. Get your bearer token
The Destiny login is unusual: the token comes back in the Authorization
response header, not the body. The -D - flag below dumps the response
headers so you can grab it.
curl -D - -s -o /dev/null \
-X POST https://www.acmdestiny.net/api/v1/auth/login \
-H "Content-Type: application/json" \
-d '{"username":"YOUR_USERNAME","password":"YOUR_PASSWORD"}' \
| grep -i '^authorization:'
You'll see something like:
Authorization: bearer eyJ0eXAiOiJKV1...
Copy the long string after bearer — that's YOUR_TOKEN for the next steps.
The token rotates every few minutes. In a real integration, read the
Authorizationresponse header on every call and update your stored token when a new one comes back (old ones stay valid for 7 days).
2. Find a unit you want to watch
curl -s https://www.acmdestiny.net/api/v1/units/listing \
-H "Authorization: bearer YOUR_TOKEN" | head -c 800
Pick a unit_id from the response. We'll call it UNIT_ID below.
3. Open the live stream — leave this terminal running
curl --no-buffer -N \
-H "Authorization: bearer YOUR_TOKEN" \
https://www.acmdestiny.net/sse/connect
--no-buffer -N tells curl to flush output as data arrives. You should
immediately see a stream_id event, then periodic ping events:
event: stream_id
data: {"type":"stream_id","stream_id":"abcd1234..."}
event: ping
data: {"type":"ping"}
Copy the stream_id.
4. In a SECOND terminal, subscribe to that unit
curl -X POST \
-H "Authorization: bearer YOUR_TOKEN" \
https://www.acmdestiny.net/api/v1/monitoring/unit/UNIT_ID
Within seconds, the first terminal starts receiving gps events as the
unit reports its position:
event: gps
data: {"type":"gps","telemetry":{"gps":{"latitude":-26.10,"longitude":28.05,...}}}
That's it — you're watching live telemetry stream in real time.
5. Keep the connection alive (ping/pong)
The server sends a ping event once every minute. Your client has
10 seconds to answer with a pong POST. If it doesn't, the server closes
the SSE connection entirely — you can't just resume. You have to:
- Open a brand-new SSE connection (back to step 3).
- Re-subscribe to every unit/vehicle you were watching (back to step 4).
In a real app the pong looks like:
curl -X POST -H "Authorization: bearer YOUR_TOKEN" \
https://www.acmdestiny.net/sse/pong/STREAM_ID
…fired every time a ping arrives.
Try it in your browser (DevTools console)
Open any page on acmdestiny.net (so the session cookie is set), open
DevTools → Console, and paste:
const base = 'https://www.acmdestiny.net';
const token = 'YOUR_TOKEN'; // from step 1 above
const unitId = 1; // from step 2
const es = new EventSource(`${base}/sse/connect`);
let streamId = null;
es.onmessage = async (e) => {
const msg = JSON.parse(e.data);
if (msg.type === 'stream_id') {
streamId = msg.stream_id;
console.log('stream_id:', streamId);
// now subscribe to the unit
await fetch(`${base}/api/v1/monitoring/unit/${unitId}`, {
headers: { Authorization: `bearer ${token}` },
});
} else if (msg.type === 'ping') {
await fetch(`${base}/sse/pong/${streamId}`, {
method: 'POST',
headers: { Authorization: `bearer ${token}` },
});
} else if (msg.type === 'gps') {
const g = msg.telemetry?.gps;
console.log(`live: ${g.latitude}, ${g.longitude}`);
}
};
es.onerror = (err) => console.error('SSE error — browser will auto-reconnect', err);
Watch the console — every GPS update from that unit will print live.
Important browser quirk: the native
EventSourceAPI doesn't let you set custom headers (so noAuthorization: bearer …on the SSE call itself). The snippet above relies on a session cookie already being set byacmdestiny.net. If you need bearer auth on the stream from a non-cookie context, use a fetch-based polyfill likeeventsource-polyfillthat supports custom headers, or pass the token as a query parameter (check the API Reference for the exact pattern).
Things to know before shipping it
- One connection, many subscriptions — but with a practical ceiling. You don't need a separate SSE connection per vehicle — open one, subscribe to all the units/vehicles you care about over it. SSE is designed for a single user watching a manageable set live (a dispatcher with a map showing 5–50 vehicles, a control-room tab, a driver-app screen). It is not the right tool for bulk live telemetry across an entire fleet of hundreds or thousands of units — see "When SSE isn't the right tool" below. Browsers also cap you at 6 SSE connections per origin (shared across tabs).
- The token rotates. Read the
Authorizationresponse header after every REST call and update your stored token. Old tokens stay valid for 7 days. - Answer pings within 10 seconds. The server sends a
pingevery minute and expects apongPOST within 10 seconds. Miss it once and the connection is closed — you'll need to open a new SSE connection and re-subscribe to every unit/vehicle. - Browsers may freeze background tabs. When a tab is inactive (or the user's
computer goes to sleep), the browser can pause your JS — pings stop being
answered and the server drops you. Detect the disconnect (
onerror) and reconnect + re-subscribe when the tab becomes visible again (document.visibilitychange). - It auto-reconnects in the browser. The native
EventSourceretries on disconnect automatically. In Node or a server-side client, you may need to reconnect yourself (and re-subscribe to your units). - SSE is one-way. Subscriptions and pongs go through normal REST calls; only the event stream is push.
When SSE isn't the right tool
- You want yesterday's trip — use the History Query API, not SSE.
- You want a snapshot right now — a single
GET /units/{id}/telemetrycall is simpler than opening a stream. - You want bulk live telemetry across hundreds or thousands of units at once — that's outside SSE's design. Use LDBS (Live Data Bridge Services) instead. LDBS is a separate ACM service built specifically for high-volume, fleet-wide live data feeds (think: piping every event into your data warehouse, or running fleet-wide analytics in real time). Contact your ACM account manager to get an LDBS connection provisioned.
Use SSE when you genuinely want live, ongoing updates for a user watching a specific set of vehicles — a dashboard map, a control room view, a real-time alert handler. Use LDBS for fleet-wide programmatic streaming.
Not comfortable writing this yourself?
Paste this URL into Claude or Claude Code along with what you want to build:
https://api.acmtrack.com/llms-full.txt
Example prompt: "Here's the ACM Destiny API: https://api.acmtrack.com/llms-full.txt. I have a Destiny username and password and the ID of one of my vehicles. Write me a Python script that opens an SSE stream, subscribes to that vehicle, prints each GPS update with a timestamp, and answers pings automatically."
The AI gets the full API context (this guide included) and writes the integration for you.