191 lines
3.1 KiB
Markdown
191 lines
3.1 KiB
Markdown
|
|
# 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: <file>
|
||
|
|
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: <file1>, <file2>, ...
|
||
|
|
```
|
||
|
|
|
||
|
|
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}
|
||
|
|
```
|