Sensor API
The Sensor API allows you to send real-time data to update building states in WhookTown.
Endpoint
Authentication
Requires a Bearer token with sensor:w permission.
curl -X POST https://sensor.whook.town/sensors \
-H "Authorization: Bearer <your-token>" \
-H "Content-Type: application/json" \
-d '{ ... }'
Request Body
Basic Payload
With Extra Fields
{
"id": "550e8400-e29b-41d4-a716-446655440000",
"status": "warning",
"activity": "fast",
"extra": {
"cpuUsage": 85,
"ramUsage": 72,
"temperature": 65
}
}
Fields
Required
| Field | Type | Description |
|---|---|---|
id |
string (UUID) | Building ID from your layout |
Optional
| Field | Type | Values | Description |
|---|---|---|---|
status |
string | online, offline, warning, critical | Building status |
activity |
string | slow, normal, fast | Animation speed |
extra |
object | varies | Building-specific fields |
Status Values
| Status | Description | Visual Effect |
|---|---|---|
online |
Service operational | Green glow, active |
offline |
Service stopped | Grey, desaturated |
warning |
Service degraded | Orange pulsing |
critical |
Service in error | Red pulsing, fire |
Legacy Values
These values are automatically converted:
| Legacy | Converted To |
|---|---|
running |
online |
failure |
critical |
Invalid status values return HTTP 400.
Activity Values
| Activity | Speed Multiplier |
|---|---|
slow |
0.5× |
normal |
1.0× |
fast |
2.0× |
Extra Fields by Building Type
Data Center
{
"extra": {
"cpuUsage": 75,
"ramUsage": 60,
"networkTraffic": 45,
"activeConnections": 1234,
"temperature": 42,
"alertLevel": "normal"
}
}
| Field | Type | Range |
|---|---|---|
cpuUsage |
int | 0-100 |
ramUsage |
int | 0-100 |
networkTraffic |
int | 0-100 |
activeConnections |
int | any |
temperature |
int | 0-100 |
alertLevel |
string | normal/warning/critical |
Bank
| Field | Type | Values |
|---|---|---|
quantity |
string | none, low, medium, high |
amount |
int | any |
Display A
| Field | Type | Range |
|---|---|---|
ringCount |
int | 1-8 |
text1 |
string | any |
text2 |
string | any |
text3 |
string | any |
Tower A / Tower B
Arcade
Supervisor
Monitor Tube
Response
Success (200 OK)
Invalid Status (400 Bad Request)
{
"success": false,
"error": {
"code": "INVALID_STATUS",
"message": "Invalid status value: 'unknown'. Must be one of: online, offline, warning, critical"
}
}
Invalid Token (401 Unauthorized)
{
"success": false,
"error": {
"code": "INVALID_TOKEN",
"message": "The provided token is invalid or expired"
}
}
Building Not Found (404 Not Found)
{
"success": false,
"error": {
"code": "BUILDING_NOT_FOUND",
"message": "No building found with ID: ..."
}
}
Examples
cURL
curl -X POST https://sensor.whook.town/sensors \
-H "Authorization: Bearer eyJhbGciOiJIUzI1NiIs..." \
-H "Content-Type: application/json" \
-d '{
"id": "550e8400-e29b-41d4-a716-446655440000",
"status": "online",
"activity": "normal"
}'
Python
import requests
url = "https://sensor.whook.town/sensors"
headers = {
"Authorization": "Bearer <your-token>",
"Content-Type": "application/json"
}
data = {
"id": "550e8400-e29b-41d4-a716-446655440000",
"status": "online",
"activity": "normal",
"extra": {
"cpuUsage": 45
}
}
response = requests.post(url, json=data, headers=headers)
print(response.json())
JavaScript/Node.js
const response = await fetch('https://sensor.whook.town/sensors', {
method: 'POST',
headers: {
'Authorization': 'Bearer <your-token>',
'Content-Type': 'application/json'
},
body: JSON.stringify({
id: '550e8400-e29b-41d4-a716-446655440000',
status: 'online',
activity: 'normal'
})
});
const result = await response.json();
console.log(result);
Go
package main
import (
"bytes"
"encoding/json"
"net/http"
)
func main() {
data := map[string]interface{}{
"id": "550e8400-e29b-41d4-a716-446655440000",
"status": "online",
"activity": "normal",
}
body, _ := json.Marshal(data)
req, _ := http.NewRequest("POST", "https://sensor.whook.town/sensors", bytes.NewBuffer(body))
req.Header.Set("Authorization", "Bearer <your-token>")
req.Header.Set("Content-Type", "application/json")
client := &http.Client{}
resp, _ := client.Do(req)
defer resp.Body.Close()
}
Integration Examples
Prometheus AlertManager
Configure AlertManager to send webhooks:
receivers:
- name: whooktown
webhook_configs:
- url: 'https://your-webhook-handler.com/prometheus-to-whooktown'
Then create a handler that transforms alerts to WhookTown format.
Grafana
Use Grafana's webhook notification channel to POST to a handler that calls the Sensor API.
Nagios/Icinga
Create a notification command:
#!/bin/bash
BUILDING_ID="$1"
STATUS="$2"
case $STATUS in
OK) WT_STATUS="online" ;;
WARNING) WT_STATUS="warning" ;;
CRITICAL) WT_STATUS="critical" ;;
*) WT_STATUS="offline" ;;
esac
curl -X POST https://sensor.whook.town/sensors \
-H "Authorization: Bearer $WT_TOKEN" \
-H "Content-Type: application/json" \
-d "{\"id\": \"$BUILDING_ID\", \"status\": \"$WT_STATUS\"}"
Custom Monitoring
Poll your services and update WhookTown:
import requests
import time
BUILDINGS = {
"api-server": "uuid-1",
"database": "uuid-2",
"cache": "uuid-3"
}
def check_service(name):
# Your health check logic
try:
response = requests.get(f"http://{name}:8080/health", timeout=5)
return response.status_code == 200
except:
return False
def update_whooktown(building_id, is_healthy):
status = "online" if is_healthy else "critical"
requests.post(
"https://sensor.whook.town/sensors",
headers={"Authorization": f"Bearer {TOKEN}"},
json={"id": building_id, "status": status}
)
while True:
for name, building_id in BUILDINGS.items():
is_healthy = check_service(name)
update_whooktown(building_id, is_healthy)
time.sleep(30)