# MyIndygo — Platform Overview & API Reference **Base URL**: `https://qualif.myindygo.com` **Purpose**: Pool-focused platform — filtration scheduling, water chemistry, pool level monitoring **Relation to MySOLEM**: Same backend database and Sails.js server. Both platforms share all module data, sensor readings, and programs. MyIndygo adds a pool admin/management layer on top. --- ## Authentication Identical to MySOLEM — same cookie name, same credentials work on both platforms. ```bash curl -c cookies.txt https://qualif.myindygo.com/login curl -c cookies.txt -b cookies.txt \ -X POST \ -H "Content-Type: application/x-www-form-urlencoded" \ -d "email=YOUR_EMAIL&password=YOUR_PASSWORD" \ "https://qualif.myindygo.com/login" ``` Cookie: `qualification-mysolem-solem-irrigation-platform.sid` (same name as MySOLEM) --- ## User IDs — MyIndygo vs MySOLEM The test API account (`arnaud.nelissen.api@icloud.com`) has **different ObjectIds** on each platform: | Platform | User ID | |---|---| | MySOLEM | `5de53bca7ed4c45c2cfe067f` | | MyIndygo | `6a21c3db5ebe0fa5f7885460` | The MyIndygo user ID appears in the page HTML: ```html ``` The pool/site ID `5de53c1c7ed4c45c2cfe0688` is the main account's pool record on MyIndygo — it's only accessible when logged in as the main account (`anelissen@solem.fr`), not the test API account. --- ## Feature flags (MyIndygo-specific) `GET /features` returns pool-focused flags including: | Flag | Value | Meaning | |---|---|---| | `ocedisWaterChemistryCorrection` | `true` | Water chemistry correction (OCEDIS dosing) | | `authenticationMyIndygoUIV2` | `true` | MyIndygo-specific login UI | | `enableBSTSubscriptions` | `true` | BST subscription management | | `enablePWAIndygoInstallation` | `true` | Pool app PWA install | | `clusterTurfOpened` | `true` | Turf cluster watering | | `enablePolytropicAPI` | `true` | Polytropic pump integration | | `enableGraphicalProgrammation` | `true` | Visual program editor | | `enableNdviSatellite` | `true` | NDVI satellite data | | `enableEvapotranspiration` | `true` | ET-based watering | | `enableHPA` | `true` | HPA (high-pressure assist?) | --- ## Pool Admin System (B2B) MyIndygo has a pool dealer admin layer for managing multiple customer pools. These endpoints are **admin-only** — not accessible with a standard user account. ``` GET /pools/admin list all managed pools POST /pools/admin/search search pools (DataTables format) POST /pools/admin/sendMessage send a message to a pool customer GET /pools/admin/getMessages get admin messages DELETE /pools/admin/dissociateAndRemove/{id} remove pool from admin ``` Pool data is fetched via: ``` GET /user/pools current user's pools (returns {"pools": []} for test account) GET /user/pools?userId= another user's pools (IDOR — no ownership check) ``` --- ## Pool-Specific Endpoints ### Last sensor tick (no date range needed) ``` GET /input/getLastTickFromInput?inputId={inputId} ``` Returns the single most-recent raw tick for an input. Much lighter than `getComputedSensorData`. Response: ```json { "tick": { "input": "6480da07c2c0896da120eccd", "value": 635, "timestamp": "2026-06-04T01:03:00.000Z", "createdAt": "2026-06-04T01:03:11.000Z", "id": "..." } } ``` Note: `value` is **raw** (not expression-computed). For LRPS pH: `635` = 6.35 pH (divide by 100). For LRPS temp: `2331` = 23.31°C. ### Live pool sensor snapshot ```python import requests BASE = "https://qualif.myindygo.com" s = requests.Session() s.get(f"{BASE}/login") s.post(f"{BASE}/login", data={"email": "...", "password": "..."}) POOL_INPUTS = { "temp": "6480da07c2c0896da120eccc", "pH": "6480da07c2c0896da120eccd", "ORP": "6480da07c2c0896da120ecce", "pressure": "6a17218be0b88ea3e9255251", "level": "6a174dd1e0b88ea3e925531e", } readings = {} for name, input_id in POOL_INPUTS.items(): r = s.get(f"{BASE}/input/getLastTickFromInput", params={"inputId": input_id}).json() readings[name] = r.get("tick", {}) # Current values (raw): # temp → divide by 100 → °C # pH → divide by 100 → pH units # ORP → raw mV # pressure → raw ADC (apply expression for bar) # level → 0=low/fill needed, 1=OK ``` ### Output events history ``` GET /output/events?moduleId={moduleId} GET /output/events?outputId={outputId} GET /output/events?moduleId={id}&startDate={iso8601}&endDate={iso8601} ``` Returns `[]` if no events or empty. Tracks when outputs have been triggered. ### Output watering forecast ``` GET /output/forecast?moduleId={moduleId} GET /output/forecast?outputId={outputId} ``` Returns upcoming scheduled watering windows. ### Real-time module informations (via LoRa) ``` GET /remote/module/informations ?moduleId={relayModuleId} &childrenSerialNumber={childSerialNumber} ``` Or via socket.io (as seen in JS): ```js io.socket.request({ method: "get", url: "/remote/module/informations", data: { moduleId: relayId, // LRMB10 gateway ID moduleUuid: uuid, moduleSerialNumber: serialNumber } }, callback) ``` Returns real-time device state polled over LoRa. Fails with `module_not_reachable` if device is offline. ### Real-time combined config + programs ``` GET /remote/module/configuration/and/programs?moduleId={moduleId} ``` Returns configuration + programs in a single LoRa roundtrip. Requires device online. ### Pool controller control (linesControl) JSON body (verified from real network capture): ``` POST /remote/module/control Content-Type: application/json ``` ```json { "moduleSerialNumber": "150302F1DA270001", "linesControl": [ { "index": 1, "action": 2, "time": "30:00" } ] } ``` Known `action` codes for LRPC pool controller: | action | meaning | extra params | |---|---|---| | `0` | Stop pump output (index 0 only) | — | | `1` | **Stop / cancel** any running manual command | — | | `2` | Timed impulse | `time`: `"MM:SS"` string (e.g. `"30:00"` = 30 minutes) | | `3` | Boost filtration | `time`: `"MM:SS"` | | `4` | Start indefinitely | — | | `5` | Pause N days (blocks manual + scheduled) | `manualDuration`: N (integer days) | | `11` | Backwash cycle | `time`: encoded duration string, `speed`: pump speed level | Response pool state includes `"pause": N` (days remaining) when an output is paused. Response always reflects **pre-command state** — the command takes effect on the next LoRa downlink. For backwash, duration is encoded using `encodeBackwashDuration(durationMinutes, minMinutes, maxMinutes)`. > **Corrected from JS analysis**: duration is `time: "MM:SS"` (string), NOT `manualDuration` in seconds. Verified from real Safari capture. ### Module advertising profile ``` GET /remote/module/advertisingProfile?moduleId={moduleId} GET /remote/modules/advertisingProfile (bulk) ``` BLE advertising profile data. Likely used for Bluetooth pairing. ### Team pool access ``` GET /teams/pools/{poolId}/membersAccessGranted ``` Returns `{ teamMembersAlreadyGrantedPool: [...] }` — team members with access to a specific pool. --- ## LRPC Pool Controller — Program Structure (MyIndygo extended) MyIndygo exposes more program fields than MySOLEM for `lr-pc` modules: ``` GET /programs/modules?moduleIds={moduleId} ``` ```json { "programs": [ { "id": "6481bcea8782b78554c02bf4", "name": "", "module": "6481bcea8782b78554c02bed", "index": 0, "weekDays": 127, "numberOfDays": 2, "synchroDay": 0, "waterBudget": 100, "startTimes": [-1, -1, -1, -1, -1, -1, -1, -1], "programCharacteristics": { "programType": 4, "mode": 2, "onSpeed": 1, "speedSequence": 4368, "microFilteringTemperature": 5, "microFilteringDuration": 10, "microFilteringPeriod": 480, "microFilteringSpeed": 1, "auxiliaryCyclicDuration": 0, "frostFreeSpeed": 1, "defaultProgramSpeed": 1, "adaptOffset": 0, "isShutterDependant": false, "isRandom": false, "isUsingButton": false }, "windows": [ { "start": 300, "end": 360, "on": 3600, "off": 0, "runningDays": 127 } ] } ] } ``` **`programType` codes** (pool controller): | code | meaning | |---|---| | `4` | Main filtration (pump runs on schedule) | | `2` | Auxiliary / cyclic (treatment dosing, UV, etc.) | | `0` | Disabled / empty slot | **`mode`**: `2` = active, `0` = disabled **`speedSequence`**: pump speed bitmask for variable-speed pumps (`4368` = 0x1110) **`windows[].runningDays`**: per-window day bitmask (127 = every day, unlike mysolem where weekDays is per-program) **`startTimes`**: array of 8 fixed start times in minutes from midnight (-1 = unused) ### Domicile LRPC filtration schedule | Program | Type | Windows | Total | |---|---|---|---| | 0 (Filtration) | 4 | 05:00–06:00 (1h), 12:00–14:00 (2h), 22:00–23:00 (1h) | 4h/day | | 1 (Auxiliary) | 2 | 21:30–22:30 (1h) | 1h/day | | 2 | — | empty | — | --- ## LRPC Outputs (Pool Controller) | Output ID | Name | Index | |---|---|---| | `6481bcea8782b78554c02bf1` | Station 1 | 0 | | `6481bcea8782b78554c02bf2` | Station 2 | 1 | | `6481bcea8782b78554c02bf3` | Station 3 | 2 | --- ## New Module Types (found via modules/search on MyIndygo) | Type | Name | Description | |---|---|---| | `lr-pc-vs` | LRPCVS | Pool controller with variable speed pump | | `lr-mv` | LRMV/LRPM1 | Motor valve (multi-output) | | `lr-mb-30` | LRMB30 | LoRa gateway v30 | | `lr-mb-100` | LRMB100 | LoRa gateway v100 | | `lr-ip-fl` | LR1IPFL | IP flow metering | | `lr-ip-fl-v2` | LR6IP | IP flow v2 | | `lr-ip-wan-v2` | LRIP6 WAN | IP WAN v2 | | `lr-is` | LR6IS/LR12IS | LoRa input sensor (multi-input) | | `lr-is-city` | LR6IS | City-variant input sensor | | `lr-is-city-wan` | LR12IS | City WAN sensor | | `lr-ms-eco` | LRMS_ECO | Eco sensor station | | `lr-ms-rs485` | LRMSRS485 | RS485 sensor station | | `lr-ms-v2` | LRMS v2 | Sensor station v2 | | `lr-ol` | LROL4 | LoRa OL (lighting?) | | `lr-bst-100` | LRBST100 | BST 100 (booster?) | | `lr-bst-react-4g` | LR-BST R4G | BST 4G reactive (booster 4G) | | `joro` / `joro-v2` | WB-xxxx | Joro water balance meter | | `smart-is` | SmartIS | Smart input sensor | | `smart-is-lcd` | VILLA-/SMT-HOME | Smart IS with LCD display | | `bl-ip-v2` | BL6IP | Bluetooth IP v2 | | `ipx` | GEN_xxxx | IPX controller (generic) | --- ## Shared Endpoints (same on both MySOLEM and MyIndygo) All endpoints from `api-docs/endpoints.md` work identically on `https://qualif.myindygo.com`. The backend database is shared — module IDs, input IDs, programs, and sensor data are identical on both platforms. Key shared endpoints that work well for pool monitoring: - `GET /remote/input/getComputedSensorData?inputId=...` — time-series sensor data - `GET /remote/module/getComputedSensorsData?moduleId=...` — all inputs for a module - `POST /module/sendManualModuleCommand` — send commands to devices - `GET /modules/{moduleId}/notebook?startDate={unix_epoch}` — event log - `GET /programs/modules?moduleIds=...` — read/write programs --- ## Pool Monitoring Quick Reference Current pool sensor IDs and live values (2026-06-04): | Sensor | Input ID | Last Raw Value | Computed | |---|---|---|---| | Water temp (LRPS) | `6480da07c2c0896da120eccc` | 2331 | 23.31 °C | | pH (LRPS) | `6480da07c2c0896da120eccd` | 635 | 6.35 (low — target 7.2–7.6) | | ORP/Redox (LRPS) | `6480da07c2c0896da120ecce` | 646 | 646 mV | | Filter pressure (LRPR) | `6a17218be0b88ea3e9255251` | 956 | — | | Pool level switch | `6a174dd1e0b88ea3e925531e` | 1 | OK (1=full) | | Fill flow volume | `6a1c4b153d6c33ab843edc15` | 0 | 0 L (no active fill) | | Fill valve state | `6a1c4b153d6c33ab843edc16` | 1 | Closed |