Overview
The Nordsat Integration API allows your TMS to create orders, build routes, assign drivers, and receive real-time status updates via webhooks. The driver workflow is handled through the Nordsat Driver App.
Base URL: https://nordsat.vercel.app/api/integration
Format: All requests and responses use JSON. Set Content-Type: application/json for all POST/PATCH requests.
Authentication
All integration endpoints require an API key. API keys are managed in the Nordsat dashboard under Settings > API Keys for Integrations.
Include your key in the X-API-Key header:
curl -H "X-API-Key: CTRK.YOUR_KEY_HERE" \ https://nordsat.vercel.app/api/integration/orders
Scopes
| Scope | Allows |
|---|---|
read | GET requests (query orders, routes, drivers, locations, history) |
write | POST, PATCH, DELETE requests (create/update orders, routes, drivers) |
When creating an API key, select the scopes you need. For full TMS integration, use ["read", "write"].
Integration Workflow
Create orders in your TMS
Assign vehicles to delivery points with addresses, cargo types, and delivery dates.
Upload data to Nordsat
Use POST /api/integration/orders to transfer all details automatically.
Create a route on Nordsat
Use POST /api/integration/routes to build routes combining loading/unloading tasks with rest stops.
Send the route to the driver
The driver opens /driver.html and follows the task sequence with turn-by-turn navigation.
Monitor task progress
Use the Task Map in the dispatcher panel or poll GET /api/integration/orders for real-time status.
Synchronise with TMS
Register webhooks to receive order.status_changed and order.completed events, or poll the orders endpoint.
Orders
Orders represent delivery tasks. Each order can optionally be linked to a tracking device and assigned to a driver.
POST/api/integration/orders
Create one or more orders from your TMS.
Scope: write
{
"orders": [
{
"externalId": "TMS-ORD-12345",
"reference": "ORD-12345",
"deviceId": "868373079552768",
"driverId": "driver-abc123",
"pickupAddress": "Warehouse A, Helsinki",
"deliveryAddress": "Customer B, Espoo",
"pickupLat": 60.1699,
"pickupLng": 24.9384,
"deliveryLat": 60.2055,
"deliveryLng": 24.6559,
"cargoType": "electronics",
"weight": "250 kg",
"plannedPickup": "2026-02-22T08:00:00Z",
"plannedDelivery": "2026-02-22T12:00:00Z",
"priority": "high",
"notes": "Fragile cargo, handle with care"
}
]
}
Response (201):
{
"created": [
{ "externalId": "TMS-ORD-12345", "orderId": "order-1740...", "status": "planned" }
],
"count": 1
}
GET/api/integration/orders
Query orders with filters. Returns current device telemetry alongside each order.
Scope: read
| Parameter | Type | Description |
|---|---|---|
| status | string | Filter by status: planned, in_transit, arrived, delayed, missed |
| externalId | string | Filter by your TMS external ID |
| driverId | string | Filter by driver |
| from | ISO date | Created after this date |
| to | ISO date | Created before this date |
| limit | int | Max results (default 500, max 5000) |
curl -H "X-API-Key: CTRK.YOUR_KEY" \ "https://nordsat.vercel.app/api/integration/orders?status=in_transit"
PATCH/api/integration/orders
Update an order's status, driver, or priority.
Scope: write
{
"orderId": "order-1740...",
"status": "in_transit",
"driverId": "driver-abc123"
}
DELETE/api/integration/orders?id=order-1740...
Cancel an order (sets status to "cancelled").
Scope: write
Routes
Routes combine multiple orders into an ordered sequence of stops for a driver, including rest breaks or fuel stations.
POST/api/integration/routes
Create a route plan with ordered stops. The system calculates total distance and estimated duration automatically.
Scope: write
{
"driverId": "driver-abc123",
"date": "2026-02-22",
"stops": [
{
"orderId": "order-1740...",
"type": "pickup",
"address": "Warehouse A, Helsinki",
"lat": 60.1699,
"lng": 24.9384,
"plannedArrival": "2026-02-22T08:00:00Z",
"plannedDeparture": "2026-02-22T08:30:00Z"
},
{
"type": "fuel",
"address": "Neste Station, Ring I",
"lat": 60.1872,
"lng": 24.8103,
"notes": "Refuel before long leg"
},
{
"orderId": "order-1740...",
"type": "delivery",
"address": "Customer B, Espoo",
"lat": 60.2055,
"lng": 24.6559,
"plannedArrival": "2026-02-22T11:30:00Z"
}
]
}
Response (201):
{
"routeId": "rp-1740...",
"driverId": "driver-abc123",
"date": "2026-02-22",
"totalDistanceKm": 28.4,
"totalDurationMin": 34,
"stops": [ ... ]
}
GET/api/integration/routes
List route plans with optional filters.
Scope: read
| Parameter | Description |
|---|---|
| driverId | Filter by driver |
| date | Filter by date (YYYY-MM-DD) |
| status | Filter by status (draft, active, completed) |
Drivers
GET/api/integration/drivers
List all drivers for your tenant.
Scope: read
POST/api/integration/drivers
Create or update a driver.
Scope: write
{
"name": "John Smith",
"email": "john@company.com",
"phone": "+358 40 123 4567",
"vehiclePlate": "ABC-123",
"vehicleType": "truck",
"capacity": "1000 kg"
}
Locations (Live Telemetry)
GET/api/integration/locations
Get the latest GPS position, battery, temperature, and speed for all devices in your fleet.
Scope: read
curl -H "X-API-Key: CTRK.YOUR_KEY" \ https://nordsat.vercel.app/api/integration/locations
Telemetry History
GET/api/integration/history
Get historical telemetry points for a specific device within a time range.
Scope: read
| Parameter | Required | Description |
|---|---|---|
| deviceId | Yes | Device ID or IMEI |
| from | No | Start time (ISO, default: 24h ago) |
| to | No | End time (ISO, default: now) |
| limit | No | Max points (default: 2000, max: 10000) |
Webhooks
Register webhook URLs to receive real-time notifications when order statuses change, deliveries complete, or route deviations are detected.
Event Types
| Event | Triggered When |
|---|---|
order.status_changed | Any status change (planned → in_transit → arrived, etc.) |
order.completed | Order is marked as delivered/arrived |
order.deviated | Device is detected off the planned route corridor |
route.started | Driver begins executing a route plan |
route.completed | All stops in a route are completed |
Register a Webhook
Webhooks are managed via the dashboard (session-authenticated, not API key).
POST /api/webhooks
{
"url": "https://your-tms.com/nordsat-webhook",
"events": ["order.status_changed", "order.completed"],
"secret": "your-signing-secret"
}
Payload Format
Each webhook delivery is a POST request to your registered URL:
{
"event": "order.status_changed",
"timestamp": "2026-02-22T10:30:00.000Z",
"data": {
"orderId": "order-1740...",
"externalId": "TMS-ORD-12345",
"status": "in_transit",
"previousStatus": "planned",
"driverId": "driver-abc123"
}
}
Verifying Signatures
Each request includes an X-Webhook-Signature header containing an HMAC-SHA256 signature of the request body using your registered secret:
const crypto = require('crypto');
function verifySignature(body, signature, secret) {
const expected = crypto
.createHmac('sha256', secret)
.update(body)
.digest('hex');
return expected === signature;
}
Error Codes
| Code | Meaning |
|---|---|
| 400 | Bad request — missing or invalid parameters |
| 401 | Unauthorized — missing or invalid API key |
| 403 | Forbidden — API key lacks the required scope |
| 404 | Not found — resource does not exist |
| 405 | Method not allowed |
| 413 | Payload too large |
| 500 | Internal server error |
All error responses follow this format:
{ "error": "Description of the error" }