Skip to content

Sensor API

The Sensor API allows you to send real-time data to update building states in WhookTown.

Endpoint

POST https://sensor.whook.town/sensors

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

{
  "id": "550e8400-e29b-41d4-a716-446655440000",
  "status": "online",
  "activity": "normal"
}

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

{
  "extra": {
    "quantity": "high",
    "amount": 42000
  }
}
Field Type Values
quantity string none, low, medium, high
amount int any

Display A

{
  "extra": {
    "ringCount": 5,
    "text1": "Line 1",
    "text2": "Line 2",
    "text3": "Line 3"
  }
}
Field Type Range
ringCount int 1-8
text1 string any
text2 string any
text3 string any

Tower A / Tower B

{
  "extra": {
    "towerText": "ONLINE",
    "towerBText": "STATUS OK"
  }
}

Arcade

{
  "extra": {
    "signText": "ARCADE",
    "dancerEnabled": true,
    "musicEnabled": true
  }
}

Supervisor

{
  "extra": {
    "faceRotationEnabled": true
  }
}

Monitor Tube

{
  "extra": {
    "bandCount": 5,
    "bands": [80, 60, 40, 70, 55]
  }
}

Response

Success (200 OK)

{
  "success": true,
  "message": "Sensor data received"
}

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)