Each Surqo ESP32 node goes through a four-stage lifecycle before it begins contributing sensor data: it registers itself on boot, becomes discoverable in the UI, gets claimed by a user to a specific farm, and then routes all future readings to that farm automatically — whether they arrive over MQTT or via the HTTP fallback. No manual device configuration is needed beyond connecting the node to WiFi and powering it on.Documentation Index
Fetch the complete documentation index at: https://mintlify.com/ricardomb-tech/surqo/llms.txt
Use this file to discover all available pages before exploring further.
Device Pairing Flow
ESP32 boots and registers
The node calls
POST /api/v1/devices/register with its MAC address and firmware version. If no record exists for that MAC a new device is created; if it already exists, last_seen is updated.Claim code is derived
The backend derives a
claim_code from the last 6 characters of the normalized MAC address (e.g. MAC a4:cf:12:a3:f2:c1 → claim code A3F2C1). This code is returned to the node and printed to the serial monitor.Device appears as discoverable
For 20 minutes after the last
register call the device appears in GET /api/v1/devices/discoverable. The frontend polls this endpoint to enable zero-code auto-discovery: power on the node and it appears automatically in the dashboard.Endpoints
POST /api/v1/devices/register
Public endpoint — called by the ESP32 on every boot. Rate limit: 30 requests/minute per IP. Creates a device record if the MAC is new. If the device already exists, onlylast_seen and (optionally) firmware_version are updated.
Raw MAC address in any standard format (colons, hyphens, or plain hex). The backend normalizes it to lowercase plain hex (e.g.
a4cf12a3f2c1). Maximum 32 characters. Returns 400 if the normalized result is shorter than 6 characters.Firmware version string (e.g.
"2.0.0"). Maximum 20 characters.200 OK
Uppercase 6-character code the user enters to pair this node to a farm.
true if the device is already paired to a farm.GET /api/v1/devices/
Auth required. Returns the list of devices paired to the authenticated user’s account. Response —200 OK — list[DeviceResponse]
GET /api/v1/devices/discoverable
Auth required. Returns unpaired devices (farm_id is null) that have been seen within the last 20 minutes, ordered by last_seen descending.
This endpoint powers the auto-discovery UX: when a user powers on a new node it appears in the list automatically — no code entry required until the claim step.
Response — 200 OK — list[DeviceResponse]
POST /api/v1/devices/claim
Auth required. Pairs a device to one of the user’s farms. Rate limit: 20 requests/minute per IP.Uppercase claim code displayed on the ESP32 serial monitor or shown in the app. Between 4 and 12 characters. The backend strips whitespace and uppercases automatically.
UUID of the farm to pair the device to. The user must own this farm.
Optional human-readable nickname for the node (e.g.
"Nodo Norte"). Maximum 200 characters. Defaults to "Nodo {claim_code}" if not provided.201 Created — DeviceResponse
Error responses
| Status | Condition |
|---|---|
403 | farm_id not found or not owned by the user |
404 | No device found with this claim code — verify the node is powered on |
409 | Device already claimed by a different user account |
PATCH /api/v1/devices/{device_id}
Auth required. Rename a paired device.UUID of the device record. Returns
404 if not found or not owned by the user.New display name for the device. Maximum 200 characters.
200 OK — Updated DeviceResponse
DELETE /api/v1/devices/{device_id}
Auth required. Unlinks the device from the user’s account and farm. After this call the device has nouser_id or farm_id and will re-appear in the discoverable list the next time it boots and calls /register.
UUID of the device to unpair. Returns
404 if not found or not owned by the user.204 No Content
POST /api/v1/devices/{device_mac}/reading
Public endpoint — ESP32 HTTP fallback. Rate limit: 120 requests/minute per IP. Called by the ESP32 when MQTT is unavailable. The backend resolves which farm to write data to using the device’s MAC. If the device is not yet claimed the reading is discarded and the claim code is returned so the user can pair it.Raw MAC address of the device. Normalized the same way as in
/register.firmware_version to keep the device record updated.
Response — 202 Accepted
Device Object
The discovery window is 20 minutes — deliberately longer than the ESP32’s default deep sleep cycle of 15 minutes, so a node that woke up once and went back to sleep is still visible in the UI when the user opens the dashboard.