# ATM Anomaly Detection API ## REST API Endpoints ### Health Check ``` GET /health ``` Response: ```json { "status": "healthy", "model_loaded": true, "model_version": "v1.0.0", "timestamp": "2026-07-11T06:00:00Z" } ``` ### Single Image Prediction ``` POST /predict Content-Type: multipart/form-data image: atm_id: "atm_001" (optional) camera_angle: "front" (optional) ``` Response: ```json { "success": true, "atm_id": "atm_001", "timestamp": "2026-07-11T06:00:00Z", "detections": [ { "class_id": 5, "class_name": "skimming_device", "confidence": 0.94, "bbox": [0.45, 0.52, 0.57, 0.60], "severity": 5, "requires_action": true } ], "summary": { "total_anomalies": 1, "max_severity": 5, "requires_action": true, "anomaly_types": ["skimming_device"] } } ``` ### Batch Prediction ``` POST /predict/batch Content-Type: multipart/form-data images: , , ... ``` Response: ```json { "success": true, "results": [ { "filename": "atm_001.jpg", "detections": [...], "summary": {...} } ] } ``` ### Get ATM Status ``` GET /atm/{atm_id}/status ``` Response: ```json { "atm_id": "atm_001", "location": { "latitude": 59.3293, "longitude": 18.0686 }, "last_check": "2026-07-11T05:30:00Z", "status": "anomaly_detected", "open_anomalies": 2, "max_severity": 4 } ``` ### Get Anomaly History ``` GET /atm/{atm_id}/anomalies?start_date=2026-07-01&end_date=2026-07-11 ``` Response: ```json { "atm_id": "atm_001", "period": { "start": "2026-07-01", "end": "2026-07-11" }, "total_anomalies": 15, "anomalies": [ { "id": "anom_001", "type": "graffiti", "detected_at": "2026-07-10T14:23:00Z", "confidence": 0.87, "status": "resolved", "resolved_at": "2026-07-10T16:00:00Z" } ] } ``` ### Submit Annotation (Human Verification) ``` POST /anomalies/{anomaly_id}/verify Content-Type: application/json { "verdict": "confirmed", "notes": "Confirmed skimming device attached to card reader", "verified_by": "technician_001" } ``` ## WebSocket API Real-time anomaly alerts: ```javascript const ws = new WebSocket('wss://api.landvex.com/ws/alerts'); ws.onmessage = (event) => { const alert = JSON.parse(event.data); console.log(`Critical anomaly at ${alert.atm_id}: ${alert.anomaly_type}`); }; ``` Alert format: ```json { "alert_id": "alert_001", "atm_id": "atm_001", "timestamp": "2026-07-11T06:00:00Z", "severity": 5, "anomaly_type": "skimming_device", "confidence": 0.94, "image_url": "https://cdn.landvex.com/captures/atm_001_20260711060000.jpg", "location": { "latitude": 59.3293, "longitude": 18.0686 }, "recommended_action": "Dispatch security team immediately" } ``` ## Error Responses ```json { "success": false, "error": { "code": "INVALID_IMAGE", "message": "Image format not supported. Use JPG or PNG.", "details": {} } } ``` ## Rate Limits - `/predict`: 100 requests/minute - `/predict/batch`: 10 requests/minute - `/atm/*`: 1000 requests/minute ## Authentication API key in header: ``` Authorization: Bearer {api_key} ```