# VIMS API Documentation ## Base URL ``` Production: https://vims.landvex.com/api/v1 Development: http://localhost:3450/api/v1 ``` ## Authentication All endpoints require Bearer token authentication: ``` Authorization: Bearer ``` ## Endpoints ### Objects #### List Objects ```http GET /api/v1/objects ``` Query Parameters: - `type` - Filter by object type (atm, charging_station, parking_meter, defibrillator) - `status` - Filter by status (green, yellow, orange, red, unknown) - `customerId` - Filter by customer - `page` - Page number (default: 1) - `limit` - Items per page (default: 20) - `search` - Search in name, externalId, address Response: ```json { "objects": [ { "id": "uuid", "name": "ATM Sveavägen 123", "objectType": { "name": "Bankomat", "category": "payment" }, "currentStatus": "green", "location": { "latitude": 59.3368, "longitude": 18.0555 }, "lastInspection": "2026-07-08T10:00:00Z" } ], "pagination": { "page": 1, "limit": 20, "total": 100, "pages": 5 } } ``` #### Create Object ```http POST /api/v1/objects ``` Request Body: ```json { "objectTypeId": "uuid", "customerId": "uuid", "name": "ATM Sveavägen 123", "externalId": "ATM-001", "location": { "latitude": 59.3368, "longitude": 18.0555 }, "address": "Sveavägen 123, Stockholm", "manufacturer": "NCR", "model": "SelfServ 22", "installationDate": "2025-01-15" } ``` #### Set Baseline Images ```http POST /api/v1/objects/:id/baseline ``` Request Body: ```json { "images": [ { "angle": "front", "imageUrl": "https://s3.landvex.com/baseline/atm-001-front.jpg" }, { "angle": "back", "imageUrl": "https://s3.landvex.com/baseline/atm-001-back.jpg" } ] } ``` ### Observations #### Upload Observation ```http POST /api/v1/observations ``` Content-Type: `multipart/form-data` Fields: - `images` - Image files (JPEG, PNG, WebP) - `objectId` - Object UUID - `angle` - Camera angle (front, back, left, right, top, detail) - `zoomerId` - Zoomer UUID (optional) - `missionId` - Mission UUID (optional) - `takenAt` - ISO timestamp (optional) - `gpsAccuracy` - GPS accuracy in meters (optional) Response: ```json { "observations": [ { "id": "uuid", "status": "pending", "imageUrl": "https://s3.landvex.com/obs/..." } ], "objectId": "uuid", "processed": 1 } ``` #### Get Observation ```http GET /api/v1/observations/:id ``` Response includes detections: ```json { "id": "uuid", "imageUrl": "...", "angle": "front", "status": "analyzed", "detections": [ { "componentType": "card_reader", "confidence": 0.95, "boundingBox": { "x": 0.1, "y": 0.2, "width": 0.3, "height": 0.1 }, "isAnomaly": false } ] } ``` #### Compare with Baseline ```http GET /api/v1/observations/:id/compare ``` Response: ```json { "observationId": "uuid", "isSignificant": true, "changeType": "structural", "metrics": { "pixelDifference": 0.15, "structuralDifference": 0.25, "overallDifference": 0.20 }, "confidence": 0.92, "diffVisualization": "base64encoded..." } ``` ### Detections #### List Detections ```http GET /api/v1/detections ``` Query Parameters: - `objectId` - Filter by object - `componentType` - Filter by component (card_reader, pin_pad, etc.) - `isAnomaly` - Filter anomalies (true/false) - `severity` - Filter by severity (low, medium, high, critical) #### Verify Detection ```http POST /api/v1/detections/:id/verify ``` Request Body: ```json { "isCorrect": true, "correctedType": "card_reader", "notes": "Verified by security team" } ``` ### Alerts #### List Alerts ```http GET /api/v1/alerts ``` Query Parameters: - `status` - open, acknowledged, investigating, resolved, false_positive - `riskLevel` - green, yellow, orange, red - `objectId` - Filter by object #### Update Alert Status ```http PUT /api/v1/alerts/:id/status ``` Request Body: ```json { "status": "resolved", "resolution": "False positive - approved maintenance", "assignedTo": "user-uuid" } ``` #### Escalate Alert ```http POST /api/v1/alerts/:id/escalate ``` Request Body: ```json { "reason": "Potential skimmer device detected", "escalateTo": "security-team" } ``` ### Dashboard #### Overview Statistics ```http GET /api/v1/dashboard/overview ``` Response: ```json { "summary": { "totalObjects": 150, "activeAlerts": 12, "recentObservations": 45, "overdueObjects": 3, "compliance": "98.0" }, "objectStats": { "green": 130, "yellow": 10, "orange": 5, "red": 2 }, "alertRiskStats": { "orange": 8, "red": 4 } } ``` #### Map Objects ```http GET /api/v1/dashboard/objects ``` Query Parameters: - `bounds` - Geo bounds: `{"sw":{"lat":59.3,"lng":18.0},"ne":{"lat":59.4,"lng":18.1}}` - `status` - Filter by status #### Activity Timeline ```http GET /api/v1/dashboard/timeline?days=7 ``` Response: ```json { "observations": [ {"date": "2026-07-01", "count": 15}, {"date": "2026-07-02", "count": 20} ], "alerts": [ {"date": "2026-07-01", "riskLevel": "orange", "count": 2} ] } ``` #### Top Priority Alerts ```http GET /api/v1/dashboard/top-alerts ``` ## Webhooks VIMS can send webhooks to your endpoint: ### Alert Webhook ```json { "event": "vims.alert", "timestamp": "2026-07-08T12:00:00Z", "data": { "alertId": "uuid", "riskLevel": "red", "title": "Skimmer detected", "message": "Potential skimmer device found on ATM", "objectId": "uuid", "customerId": "uuid" } } ``` ### Observation Webhook ```json { "event": "vims.observation", "timestamp": "2026-07-08T12:00:00Z", "data": { "observationId": "uuid", "objectId": "uuid", "status": "analyzed", "riskLevel": "green" } } ``` ## Error Responses ```json { "error": "Validation Error", "message": "Missing required fields", "fields": ["objectId", "angle"] } ``` Status Codes: - `200` - Success - `201` - Created - `400` - Bad Request - `401` - Unauthorized - `403` - Forbidden - `404` - Not Found - `409` - Conflict - `500` - Internal Server Error