Public REST API for power outage monitoring
The sinluz API exposes two surfaces:
Each location is served from its own subdomain. The base URL determines which location's data you read or write:
Responses are JSON. CORS is enabled for sinluz.top and its subdomains.
| Code | Name | Subdomain | Timezone |
|---|---|---|---|
rd | República Dominicana | rd.sinluz.top | America/Santo_Domingo |
ch | Schweiz | ch.sinluz.top | Europe/Zurich |
mx | México | reserved | America/Mexico_City |
ht | Haïti | reserved | America/Port-au-Prince |
Returns all active devices in the location with their current power status, online state, today's outage seconds, and recent events.
{
"location": "rd",
"aggregate_power": "on", // on | off | partial | unknown
"today_off_seconds_max": 0,
"devices": [
{
"id": 1,
"name": "Casa Tower",
"region": "Distrito Nacional",
"city": "Santo Domingo",
"lat": 18.4861,
"lng": -69.9312,
"online": true,
"last_heartbeat": "2026-04-26T12:34:56+00:00",
"power_status": "on", // on | off | unknown
"power_since": "2026-04-26T08:12:00+00:00",
"device_status": "up",
"today_off_seconds": 0,
"week_uptime_pct": 99.42,
"month_uptime_pct": 98.17
}
],
"events": [
{
"device_id": 1,
"device_name": "Casa Tower",
"type": "power_on", // power_on | power_off | device_up | device_down
"at": "2026-04-26T08:12:00+00:00"
}
]
}
curl https://rd.sinluz.top/api/api.php?action=stats
Returns power-off phases for each device over the requested window.
| Param | Type | Default | Range | Notes |
|---|---|---|---|---|
hours | int | 24 | 1 – 720 | Window length. 720 = 30 days. |
{
"location": "rd",
"window": {
"from": "2026-04-25T12:34:56+00:00",
"to": "2026-04-26T12:34:56+00:00",
"hours": 24
},
"devices": [
{
"id": 1,
"name": "Casa Tower",
"off_phases": [
{ "from": "2026-04-25T18:02:00+00:00", "to": "2026-04-25T20:14:00+00:00" }
],
"total_off_seconds": 7920,
"uptime_pct": 90.83
}
]
}
Off-phases that began before the window are clipped to window.from. An open outage at query time has to set to window.to.
Devices call this regularly (recommended every 30–60 seconds) to signal they're alive. A device is considered online if its last heartbeat is within 90 seconds.
Token via header X-Ingest-Token: <token> or query string ?token=<token>. The token must match the device's location subdomain.
Minimum 10 seconds between heartbeats per device. Returns 429 otherwise.
curl -X POST -H "X-Ingest-Token: $TOKEN" \
https://rd.sinluz.top/api/api.php?action=heartbeat
Devices report power transitions. Each call writes an event row and updates the device's current state.
Same token mechanism as heartbeat.
Minimum 5 seconds between events of the same type per device. Returns 429 otherwise.
curl -X POST -H "X-Ingest-Token: $TOKEN" \
https://rd.sinluz.top/api/api.php?action=power_off
Embeddable shields.io-style SVG badge showing the current power state of a location. Cached briefly server-side; safe to embed in READMEs and dashboards.
rd ch 

<a href="https://sinluz.top">
<img src="https://rd.sinluz.top/badge/rd.svg" alt="sinluz rd">
</a>
| Status | Body | When |
|---|---|---|
| 400 | {"error":"unknown_action"} | Unrecognized action param. |
| 401 | {"error":"unauthorized"} | Missing or invalid token. |
| 403 | {"error":"wrong_location"} | Token belongs to a different location than the subdomain. |
| 429 | {"error":"rate_limited"} | Heartbeat (<10s) or event (<5s) too soon after the previous one. |