# 📋 API Response Format Documentation

## Real-Time Data Endpoints Response Format

---

## 1️⃣ Send Sensor Data

### Endpoint
```
POST /api/v1/devices/data
```

### Request
```json
{
  "data": [
    {
      "type": "gempa",
      "value": 250,
      "timestamp": "2026-05-19T10:30:45Z"
    }
  ]
}
```

### Success Response (200)
```json
{
  "success": true,
  "message": "Data ingested successfully",
  "count": 1,
  "device_status": "online"
}
```

### Error Response (401 - No API Key)
```json
{
  "success": false,
  "message": "API key required"
}
```

### Error Response (401 - Invalid API Key)
```json
{
  "success": false,
  "message": "Invalid API key"
}
```

### Error Response (422 - Validation Error)
```json
{
  "success": false,
  "errors": {
    "data.0.type": ["The data.0.type field is required."],
    "data.0.value": ["The data.0.value field is required."]
  }
}
```

---

## 2️⃣ Get Device Statistics

### Endpoint
```
GET /api/v1/devices/{deviceId}/statistics
Authorization: Bearer {token}
```

### Success Response (200)
```json
{
  "success": true,
  "data": {
    "total_data": 150,
    "last_24h": 45,
    "last_7d": 280,
    "avg_value": 23.5,
    "max_value": 89.2,
    "min_value": 2.1,
    "last_activity": "2026-05-19T10:30:45Z",
    "uptime_percentage": 98.5,
    "data_by_type": [
      {
        "type": "gempa",
        "count": 120
      },
      {
        "type": "vibration",
        "count": 30
      }
    ]
  }
}
```

### Error Response (404 - Device Not Found)
```json
{
  "success": false,
  "message": "Device not found"
}
```

---

## 3️⃣ Get Device Data History

### Endpoint
```
GET /api/v1/devices/{deviceId}/data?limit=50
Authorization: Bearer {token}
```

### Query Parameters
- `limit` (optional, default: 50): Jumlah data yang dikembalikan

### Success Response (200)
```json
[
  {
    "id": 1,
    "recorded_at": "19 May 2026 10:35:45",
    "data_type": "gempa",
    "value": 250,
    "raw_data": {
      "intensitas": 250,
      "magnitude": 5.2,
      "kedalaman": 10
    }
  },
  {
    "id": 2,
    "recorded_at": "19 May 2026 10:30:45",
    "data_type": "vibration",
    "value": 120,
    "raw_data": {}
  }
]
```

**Note:** Response adalah array langsung (bukan wrapped dalam object), untuk memudahkan template rendering di JavaScript.

---

## 4️⃣ Get Device Details (API Key)

### Endpoint
```
GET /api/v1/devices/{deviceId}
Authorization: Bearer {token}
```

### Success Response (200)
```json
{
  "success": true,
  "data": {
    "id": 2,
    "device_id": "SENSOR-001",
    "name": "Seismic Sensor Jakarta",
    "type": "sensor",
    "api_key": "grRGXrKxx2nQpKr5mL8vXyZ9aB7cDeFg",
    "status": "online",
    "firmware_version": "1.0.0",
    "last_heartbeat": "2026-05-19T10:30:45Z",
    "metadata": {
      "location": "Jakarta",
      "latitude": -6.2088,
      "longitude": 106.8456
    },
    "capabilities": ["vibration", "magnitude"],
    "recent_data": [
      {
        "id": 1,
        "data_type": "gempa",
        "value": 250,
        "recorded_at": "2026-05-19T10:30:45Z"
      }
    ],
    "stats": {
      "total_readings": 150,
      "last_heartbeat": "2026-05-19T10:30:45Z",
      "uptime": "2 minutes ago"
    }
  }
}
```

---

## 5️⃣ Device Heartbeat

### Endpoint
```
POST /api/v1/devices/heartbeat
Header: X-API-Key: {api_key}
```

### Request (Optional)
```json
{
  "metadata": {
    "uptime": 12345,
    "cpu_temp": 45.2,
    "memory_usage": 256
  }
}
```

### Success Response (200)
```json
{
  "success": true,
  "message": "Heartbeat received",
  "server_time": "2026-05-19T10:30:45Z",
  "device": {
    "id": "SENSOR-001",
    "status": "online"
  }
}
```

---

## 6️⃣ Get Active Stations (Public)

### Endpoint
```
GET /api/v1/public/stations
```

### Success Response (200)
```json
{
  "success": true,
  "data": [
    {
      "id": 2,
      "device_id": "SENSOR-001",
      "name": "Seismic Sensor Jakarta",
      "type": "sensor",
      "status": "online",
      "latitude": -6.2088,
      "longitude": 106.8456,
      "location": "Jakarta",
      "last_heartbeat": "2026-05-19T10:30:45Z",
      "capabilities": ["vibration", "magnitude"]
    }
  ],
  "count": 1
}
```

---

## 7️⃣ Get Station Details (Public)

### Endpoint
```
GET /api/v1/public/stations/{stationId}
```

### Success Response (200)
```json
{
  "success": true,
  "data": {
    "id": 2,
    "device_id": "SENSOR-001",
    "name": "Seismic Sensor Jakarta",
    "type": "sensor",
    "status": "online",
    "latitude": -6.2088,
    "longitude": 106.8456,
    "location": "Jakarta",
    "firmware_version": "1.0.0",
    "last_heartbeat": "2026-05-19T10:30:45Z",
    "capabilities": ["vibration", "magnitude"],
    "metadata": {
      "location": "Jakarta",
      "latitude": -6.2088,
      "longitude": 106.8456
    },
    "recent_readings": [
      {
        "recorded_at": "2026-05-19T10:30:45Z",
        "data_type": "gempa",
        "value": 250,
        "raw_data": {
          "intensitas": 250,
          "magnitude": 5.2
        }
      }
    ],
    "reading_count": 150,
    "today_count": 45
  }
}
```

---

## HTTP Status Codes

| Status | Meaning | Example |
|--------|---------|---------|
| 200 | Success | Data sent, statistics retrieved |
| 201 | Created | Device registered |
| 400 | Bad Request | Invalid JSON format |
| 401 | Unauthorized | Missing/invalid API key or token |
| 404 | Not Found | Device not found |
| 422 | Validation Error | Invalid data fields |
| 500 | Server Error | Database error |

---

## Data Types (type field)

### Supported Data Types

```
"gempa"         - Earthquake/seismic data
"vibration"     - Vibration measurements
"acceleration"  - Acceleration data
"frequency"     - Frequency data
"temperature"   - Temperature readings
"humidity"      - Humidity readings
"pressure"      - Pressure readings
"custom"        - Custom sensor data
```

---

## Value Field Examples

### Single Value
```json
{
  "type": "temperature",
  "value": 35.5
}
```

### Complex Value (Object)
```json
{
  "type": "gempa",
  "value": {
    "intensitas": 250,
    "magnitude": 5.2,
    "kedalaman": 10,
    "latitude": -6.2,
    "longitude": 106.8
  }
}
```

### Array Value
```json
{
  "type": "acceleration",
  "value": {
    "x": 5.2,
    "y": 3.1,
    "z": 2.8
  }
}
```

---

## Real-Time Display Integration

### JavaScript Real-Time Handler

File: `/public/js/realtime.js`

Cara kerja:
1. Scan semua element dengan `data-realtime-url` attribute
2. Fetch data dari URL secara berkala
3. Extract value menggunakan `data-realtime-key` path
4. Render template jika `data-realtime-template` ada

### Example HTML

```html
<!-- Show total readings -->
<span data-realtime-url="/api/v1/devices/2/statistics" 
      data-realtime-key="data.total_data"
      data-realtime-interval="5000">
  Loading...
</span>

<!-- Show average value -->
<span data-realtime-url="/api/v1/devices/2/statistics" 
      data-realtime-key="data.avg_value"
      data-realtime-interval="5000">
  Loading...
</span>

<!-- Render data table with template -->
<table>
  <tbody data-realtime-url="/api/v1/devices/2/data"
         data-realtime-template="<tr>
           <td>{{ recorded_at }}</td>
           <td>{{ data_type }}</td>
           <td>{{ value }}</td>
         </tr>">
  </tbody>
</table>
```

---

## Batching Multiple Sensor Values

### Optimal Request Format

```json
{
  "data": [
    {
      "type": "gempa",
      "value": 250,
      "timestamp": "2026-05-19T10:30:45Z"
    },
    {
      "type": "temperature",
      "value": 35.5,
      "timestamp": "2026-05-19T10:30:46Z"
    },
    {
      "type": "vibration",
      "value": {
        "x": 5.2,
        "y": 3.1,
        "z": 2.8
      },
      "timestamp": "2026-05-19T10:30:47Z"
    }
  ]
}
```

**Keuntungan:**
- Satu request untuk multiple readings
- Lebih efisien bandwidth
- Automatic timestamp support

---

## Caching & Performance

### API Response Caching

- Statistics endpoint: Cached untuk 60 detik
- Data history: Cached untuk 30 detik
- Public endpoints: Cached untuk 5 menit

### Recommended Polling Intervals

| Endpoint | Recommended Interval | Use Case |
|----------|---------------------|----------|
| `/statistics` | 5-10 seconds | Dashboard metrics |
| `/data` | 3-5 seconds | Real-time table |
| `/devices/{id}` | 15-30 seconds | Device status |
| Heartbeat | 300 seconds (5 min) | Keep-alive |

---

## Error Handling

### Common Error Scenarios

#### 1. Invalid API Key
```json
{
  "success": false,
  "message": "Invalid API key",
  "code": "INVALID_API_KEY"
}
```

#### 2. Validation Error
```json
{
  "success": false,
  "errors": {
    "data.0.value": ["The value must be numeric"]
  }
}
```

#### 3. Rate Limiting (Future)
```json
{
  "success": false,
  "message": "Too many requests",
  "retry_after": 60
}
```

---

## Best Practices

1. **Always include timestamp** untuk data accuracy
2. **Batch multiple readings** dalam single request
3. **Send heartbeat** minimal setiap 5 menit
4. **Use appropriate data type** untuk setiap sensor
5. **Implement retry logic** untuk failed requests
6. **Log all API responses** untuk debugging
7. **Monitor device status** di dashboard
8. **Use correct headers** saat send data

---

**Last Updated:** 2026-05-19
