Device Service API Documentation
Base URL
/api/devices
📘 TypeScript Interfaces
Use these interfaces for your frontend integration.
// Device Object
export interface Device {
id: number;
name: string;
uniqueId: string;
status: 'online' | 'offline' | 'unknown';
lastUpdate: string | null; // ISO 8601
positionId: number | null;
phone: string | null;
model: string | null;
contact: string | null;
category: string | null;
disabled: boolean;
expirationTime: string | null;
groupId: number | null;
calendarId: number | null;
attributes: Record<string, any>;
claimToken?: string; // Only for claimed devices (owner only)
// Sharing/Permissions
isOwner: boolean;
permissions: DevicePermissions;
sharedBy?: number; // User ID who shared (only for non-owners)
}
// Device Permissions
export interface DevicePermissions {
position: boolean; // View positions and history
events: boolean; // View device events
geofences: boolean; // View geofences
notifications: boolean; // Receive notifications
commands: boolean; // Send commands to device
}
// Device Create Request
export interface DeviceCreateRequest {
name: string;
uniqueId: string;
phone?: string;
model?: string;
contact?: string;
category?: string;
groupId?: number;
attributes?: Record<string, any>;
deviceToken?: string; // Optional: claim token to mark as claimed
}
// Device Update Request
export interface DeviceUpdateRequest {
name?: string;
phone?: string;
model?: string;
contact?: string;
category?: string;
groupId?: number;
disabled?: boolean;
attributes?: Record<string, any>;
}
// Token Validation Request
export interface TokenValidateRequest {
token: string;
}
// Token Validation Response (Success)
export interface TokenValidateSuccess {
success: true;
uniqueId: string;
model: string;
modelCode: string;
}
// Token Validation Response (Error)
export interface TokenValidateError {
success: false;
errorCode: 'TOKEN_REQUIRED' | 'TOKEN_INVALID' | 'TOKEN_ALREADY_CLAIMED';
errorMessage: string;
}
export type TokenValidateResponse = TokenValidateSuccess | TokenValidateError;
// Device Claim Request
export interface DeviceClaimRequest {
token: string;
}
// Device Claim Response
export interface DeviceClaimResponse {
success: boolean;
device?: Device;
alreadyClaimed?: boolean;
}
// Health Check Response
export interface HealthResponse {
status: 'healthy' | 'degraded';
service: string;
ready: boolean;
database: 'connected' | 'disconnected';
}
🛠️ Frontend Integration Guide
1. Authentication
All device endpoints (except health and validate-token) require authentication.
The gateway validates JWT tokens and passes X-User-Id header to the service.
Frontend Requirement:
You MUST include the JWT token in the Authorization header for all authenticated requests.
await fetch('/api/devices', {
method: 'GET',
headers: {
'Authorization': `Bearer ${accessToken}`
}
});
2. Device Claiming Flow
- User enters claim token (from device packaging/QR code)
- Call
POST /api/devices/validate-tokento verify token and preview device - If valid, call
POST /api/devices/claimto claim the device - Device is now linked to user account
3. Error Handling
| Status | Meaning | Action |
|---|---|---|
| 401 Unauthorized | Not logged in | Redirect to login |
| 403 Forbidden | Access denied to device | Show access error |
| 404 Not Found | Device/token not found | Show not found error |
| 409 Conflict | Device already exists or claimed | Show conflict message |
📡 Endpoints
1. Device CRUD
List Devices
GET /
- Auth Required: Yes
- Query Params:
userId: Filter by user (optional)uniqueId: Filter by unique IDs (optional, can repeat)id: Filter by device IDs (optional, can repeat)
- Response:
Device[]
[
{
"id": 1,
"name": "My Car Tracker",
"uniqueId": "123456789012345",
"status": "online",
"lastUpdate": "2024-12-08T12:30:00Z",
"model": "S21L",
"disabled": false,
"attributes": {}
}
]
Get Device
GET /{id}
- Auth Required: Yes
- Response:
Device - Errors:
- 403 Forbidden: User doesn't own this device
- 404 Not Found: Device doesn't exist
Create Device
POST /
- Auth Required: Yes
- Content-Type:
application/json - Body:
DeviceCreateRequest
{
"name": "My GPS Tracker",
"uniqueId": "123456789012345",
"phone": "+39123456789",
"model": "S21L",
"category": "car"
}
- Response: 201 Created
Device - Errors:
- 409 Conflict: Device with this uniqueId already exists
Update Device
PUT /{id}
- Auth Required: Yes
- Content-Type:
application/json - Body:
DeviceUpdateRequest
{
"name": "Updated Name",
"phone": "+39987654321",
"disabled": false
}
- Response:
Device - Errors:
- 403 Forbidden: User doesn't own this device
- 404 Not Found: Device doesn't exist
Delete Device
DELETE /{id}
- Auth Required: Yes
- Response: 204 No Content
- Errors:
- 403 Forbidden: User doesn't own this device
- 404 Not Found: Device doesn't exist
2. Token Validation & Claiming
Validate Token (Public)
POST /validate-token
- Auth Required: No
- Purpose: Check if a claim token is valid and preview device info before claiming
- Content-Type:
application/json - Body:
TokenValidateRequest
{
"token": "CLAIM_TOKEN_HERE"
}
- Response (Success):
{
"success": true,
"uniqueId": "123456789012345",
"model": "Visla S21L",
"modelCode": "S21L"
}
- Response (Error):
{
"success": false,
"errorCode": "TOKEN_ALREADY_CLAIMED",
"errorMessage": "Device already claimed"
}
- Error Codes:
TOKEN_REQUIRED: No token providedTOKEN_INVALID: Token not found or invalid statusTOKEN_ALREADY_CLAIMED: Device already claimed by another user
Claim Device
POST /claim
- Auth Required: Yes
- Purpose: Claim a device using a token (creates device if needed, links to user)
- Content-Type:
application/json - Body:
DeviceClaimRequest
{
"token": "CLAIM_TOKEN_HERE"
}
- Response (Success):
{
"success": true,
"device": {
"id": 1,
"name": "Visla S21L",
"uniqueId": "123456789012345",
"status": "offline",
"model": "S21L"
}
}
- Response (Already Claimed by Same User):
{
"success": true,
"device": { ... },
"alreadyClaimed": true
}
- Errors:
- 400 Bad Request: Token missing or device not configured
- 404 Not Found: Token doesn't exist
- 409 Conflict: Token already used by another user
3. Health
Health Check (Public)
GET /health
- Auth Required: No
- Response:
{
"status": "healthy",
"service": "device-service",
"ready": true,
"database": "connected"
}