Server Integration — Node.js / Express
A minimal Express server that exposes PickPoint to your frontend via @pickpoint/sdk. The API key lives in an environment variable and never reaches the client.
1
Install dependencies
npm install express ws @pickpoint/sdk dotenv2
Environment variables
# .env
PICKPOINT_KEY=your_key_here
PORT=3000Load with dotenv/config in development. In production set the variable in your hosting environment - never commit .env to git.
3
SDK client
// server.js
import express from 'express';
import { PickPoint } from '@pickpoint/sdk';
import 'dotenv/config';
const app = express();
app.use(express.json());
const pp = new PickPoint({ apiKey: process.env.PICKPOINT_KEY });4
Geocoding endpoints
Query parameters from the client are passed straight to the SDK:
// ── Geocoding ──────────────────────────────────────────────────────────────
// Forward: GET /geo/forward?q=Eiffel+Tower&limit=5
app.get('/geo/forward', async (req, res) => {
try {
res.json(await pp.forward(req.query));
} catch (e) {
res.status(e.status ?? 502).json({ error: e.message });
}
});
// Reverse: GET /geo/reverse?lat=48.85&lon=2.29&zoom=18
app.get('/geo/reverse', async (req, res) => {
try {
res.json(await pp.reverse(req.query));
} catch (e) {
res.status(e.status ?? 502).json({ error: e.message });
}
});
// Search: GET /geo/search?q=Baker+St&viewbox=…
app.get('/geo/search', async (req, res) => {
try {
res.json(await pp.search(req.query));
} catch (e) {
res.status(e.status ?? 502).json({ error: e.message });
}
});5
Routing endpoints
// ── Routing ───────────────────────────────────────────────────────────────
// Route: POST /route { locations, costing, … }
app.post('/route', async (req, res) => {
try {
res.json(await pp.route(req.body));
} catch (e) {
res.status(e.status ?? 502).json({ error: e.message });
}
});
// Optimized route: POST /route/optimized
app.post('/route/optimized', async (req, res) => {
try {
res.json(await pp.optimizedRoute(req.body));
} catch (e) {
res.status(e.status ?? 502).json({ error: e.message });
}
});6
Device tracking - REST
// ── Device tracking - REST ────────────────────────────────────────────────
// List devices: GET /devices
app.get('/devices', async (req, res) => {
try {
res.json(await pp.devices.list(req.query));
} catch (e) {
res.status(e.status ?? 502).json({ error: e.message });
}
});
app.listen(process.env.PORT || 3000);Track history is REST-only today — see the Device Tracking guide for the GET /v2/devices/:uid/tracks curl example.
7
Device tracking - WebSocket subscriber relay
Your server mints a client token, subscribes with @pickpoint/sdk/tracking, and fans events out to browser clients over a plain WebSocket:
// ── Device tracking - WebSocket subscriber relay ─────────────────────────
import { WebSocketServer } from 'ws';
import { connect } from '@pickpoint/sdk/tracking';
const wss = new WebSocketServer({ port: 3001 });
async function mintToken() {
// Client-token mint is server-side only (no JS SDK helper yet)
const r = await fetch('https://api.pickpoint.io/v2/client-tokens', {
method: 'POST',
headers: {
'X-Api-Key': process.env.PICKPOINT_KEY,
'Content-Type': 'application/json',
},
body: JSON.stringify({ scopes: ['devices'], ttlSec: 600 }),
});
const { accessToken } = await r.json();
return accessToken;
}
wss.on('connection', async (client, req) => {
const deviceUid = new URL(req.url, 'http://x').searchParams.get('deviceUid');
if (!deviceUid) { client.close(1008, 'deviceUid required'); return; }
const session = await connect({
endpoint: 'wss://tracking.pickpoint.io',
auth: { accessToken: await mintToken() },
subscribe: deviceUid,
reconnect: false,
});
const off = session.on('location', (msg) => {
if (client.readyState === 1) client.send(JSON.stringify(msg.point));
});
client.on('close', () => { off(); session.close(); });
});