Device API · v1
M5Stack occupancy protocol
Each doorway reports persistent cumulative directional totals. DoorSync calculates only the new difference and returns the authoritative building occupancy plus the next check-in interval.
Base URL
https://project--d4ce00fd-3456-4c2e-aee0-07b3bfb30a56.lovable.appAuthentication
Every counter shares one system key, shown on the operator dashboard. Send it as a Bearer token on every request and identify the individual unit with device_id.
Authorization: Bearer occ_your_system_key
Content-Type: application/jsonA device_id that has never been seen is registered automatically on its first report; the operator can rename it and set its doorway afterwards. Use a stable per-unit value such as the ESP32 MAC/UUID.
/api/public/v1/device/reportReport cumulative counters
Send after a person is counted and at every scheduled check-in. Both counters are totals since the device was first seen or last reset.
{
"device_id": "m5-AABBCCDDEEFF",
"entries": 123,
"exits": 118,
"firmware_version": "1.0.0",
"rssi": -61
}200 response
{
"occupancy": 42,
"checkin_time": 30,
"accepted": { "entries": 1, "exits": 0 },
"counter_reset": false,
"registered": false,
"server_time": "2026-09-11T00:00:00.000Z"
}| Field | Type | Rule |
|---|---|---|
| device_id | string | Required, stable hardware UUID/MAC |
| entries | integer | Required, cumulative, ≥ 0 |
| exits | integer | Required, cumulative, ≥ 0 |
| firmware_version | string | Optional, max 40 chars |
| rssi | integer | Optional, −150 to 10 dBm |
/api/public/v1/device/state?device_id=…Get current state
Use at boot, after reconnecting Wi-Fi, or any time the display needs a proactive refresh. No request body is required; the optional device_id query parameter records the check-in.
{
"occupancy": 42,
"checkin_time": 30,
"server_time": "2026-09-11T00:00:00.000Z"
}Required firmware behavior
- Persist both cumulative counters in NVS/Preferences before sending.
- Reuse unchanged totals when retrying. Duplicate reports are idempotent.
- Replace the local polling interval with every valid
checkin_timeresponse. - Update the local display from the returned
occupancy. - Use exponential backoff for network failures and 5xx responses.
- Stop repeated retries on 400, 401, or 422 and surface a device error.
- If counters decrease after a device reset, the server accepts them as a new baseline and sets
counter_reset: true.
Status codes
200 accepted · 400 malformed payload · 401 invalid system key or disabled counter · 422 invalid counter or safety-limit rejection · 500 temporary server failure.
Prompt for Claude
Copy this implementation brief into Claude with your sensor and display details.
Write production Arduino/C++ firmware for an M5Stack people counter using WiFiClientSecure and ArduinoJson. Every device is flashed with the SAME shared system key; each device identifies itself with a stable device_id derived from its hardware UUID (e.g. the ESP32 efuse MAC formatted as "m5-AABBCCDDEEFF"). The server auto-registers an unknown device_id on its first report, so no manual provisioning is needed. Persist cumulative unsigned 64-bit entries and exits in Preferences/NVS so retries and reboots are safe. POST to https://project--d4ce00fd-3456-4c2e-aee0-07b3bfb30a56.lovable.app/api/public/v1/device/report with Authorization: Bearer SYSTEM_API_KEY and Content-Type: application/json. The JSON body is {"device_id":"m5-AABBCCDDEEFF","entries":123,"exits":118,"firmware_version":"1.0.0","rssi":-61}. Read occupancy and checkin_time from every successful response. Also GET https://project--d4ce00fd-3456-4c2e-aee0-07b3bfb30a56.lovable.app/api/public/v1/device/state?device_id=m5-AABBCCDDEEFF with the same Authorization header to proactively synchronize. Use the server-provided checkin_time in seconds, never reset cumulative totals after a successful request, retry with exponential backoff on network/5xx errors, do not retry 400/401/422 indefinitely, validate TLS, and never log the API key.