sinluz · API

Public REST API for power outage monitoring

← back to dashboard

Overview

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:

https://<location>.sinluz.top/api/api.php

Responses are JSON. CORS is enabled for sinluz.top and its subdomains.

Locations

CodeNameSubdomainTimezone
rdRepública Dominicanard.sinluz.topAmerica/Santo_Domingo
chSchweizch.sinluz.topEurope/Zurich
mxMéxicoreservedAmerica/Mexico_City
htHaïtireservedAmerica/Port-au-Prince

Current state

GET/api/api.php?action=stats

Returns all active devices in the location with their current power status, online state, today's outage seconds, and recent events.

Response

{
  "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"
    }
  ]
}

Example

curl https://rd.sinluz.top/api/api.php?action=stats

Outage history

GET/api/api.php?action=history&hours=24

Returns power-off phases for each device over the requested window.

Query parameters

ParamTypeDefaultRangeNotes
hoursint241 – 720Window length. 720 = 30 days.

Response

{
  "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.

Device heartbeat

POST/api/api.php?action=heartbeat

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.

Auth

Token via header X-Ingest-Token: <token> or query string ?token=<token>. The token must match the device's location subdomain.

Rate limit

Minimum 10 seconds between heartbeats per device. Returns 429 otherwise.

Example

curl -X POST -H "X-Ingest-Token: $TOKEN" \
  https://rd.sinluz.top/api/api.php?action=heartbeat

Power events

POST/api/api.php?action=power_off
POST/api/api.php?action=power_on

Devices report power transitions. Each call writes an event row and updates the device's current state.

Auth

Same token mechanism as heartbeat.

Rate limit

Minimum 5 seconds between events of the same type per device. Returns 429 otherwise.

Example

curl -X POST -H "X-Ingest-Token: $TOKEN" \
  https://rd.sinluz.top/api/api.php?action=power_off
Devices should only emit power events on actual transitions, not periodically. The 5-second rate limit guards against duplicates from network retries.

Status badge

GET/badge/<location>.svg

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.

Examples

rd rd power status
ch ch power status

Markdown

![sinluz rd](https://rd.sinluz.top/badge/rd.svg)
![sinluz ch](https://ch.sinluz.top/badge/ch.svg)

HTML

<a href="https://sinluz.top">
  <img src="https://rd.sinluz.top/badge/rd.svg" alt="sinluz rd">
</a>

Errors

StatusBodyWhen
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.