From d2a372be76552fcb23f440c2dc607139c4650946 Mon Sep 17 00:00:00 2001 From: "Ian C." <108159253+ic-dev21@users.noreply.github.com> Date: Sun, 25 Oct 2026 13:40:19 -0400 Subject: [PATCH 1/3] Ajout de payload json Pour fins de documentation --- .../onAnyDeviceUpdated-cee.json | 33 +++++++++++++++++++ .../onAnyDeviceUpdated-meter.json | 22 +++++++++++++ 2 files changed, 55 insertions(+) create mode 100644 doc/Device Replies/onAnyDeviceUpdated-cee.json create mode 100644 doc/Device Replies/onAnyDeviceUpdated-meter.json diff --git a/doc/Device Replies/onAnyDeviceUpdated-cee.json b/doc/Device Replies/onAnyDeviceUpdated-cee.json new file mode 100644 index 0000000..628756e --- /dev/null +++ b/doc/Device Replies/onAnyDeviceUpdated-cee.json @@ -0,0 +1,33 @@ +{ + "data": { + "onAnyDeviceUpdated": { + "deviceType": "cee", + "locationHiloId": "urn:hilo:crm:00000-abcdef:0", + "transmissionTime": "2026-10-24T19:46:35.207Z", + "operationId": "00000000-0000-0000-0000-000000000002", + "status": "REPORT", + "device": { + "deviceType": "cee", + "hiloId": "urn:hilo:philo:4a5b6c7d8e9f0001:0", + "physicalAddress": "4A5B6C7D8E9F0001", + "connectionStatus": "CONNECTED", + "gDState": "EXCLUDED", + "version": "45", + "probeTemp": { + "value": 54, + "kind": "DEGREE_CELSIUS" + }, + "zigbeeVersion": "45", + "state": "ON", + "ccrType": "WATER_HEATER", + "alerts": [ + "0" + ], + "power": { + "value": 0, + "kind": "WATT" + } + } + } + } +} \ No newline at end of file diff --git a/doc/Device Replies/onAnyDeviceUpdated-meter.json b/doc/Device Replies/onAnyDeviceUpdated-meter.json new file mode 100644 index 0000000..41f3810 --- /dev/null +++ b/doc/Device Replies/onAnyDeviceUpdated-meter.json @@ -0,0 +1,22 @@ +{ + "data": { + "onAnyDeviceUpdated": { + "deviceType": "meter", + "locationHiloId": "urn:hilo:crm:00000-abcdef:0", + "transmissionTime": "2026-10-24T19:48:54.966Z", + "operationId": "00000000-0000-0000-0000-000000000001", + "status": "REPORT", + "device": { + "deviceType": "meter", + "hiloId": "urn:hilo:philo:0x006baa0000000001-smart_meter:0", + "physicalAddress": "0x006BAA0000000001-smart_meter", + "connectionStatus": "CONNECTED", + "zigBeeChannel": 24, + "power": { + "value": 0.572, + "kind": "KILOWATT" + } + } + } + } +} \ No newline at end of file From c4ec22204637eb809c290dceb4fea4c269acab73 Mon Sep 17 00:00:00 2001 From: "Ian C." <108159253+ic-dev21@users.noreply.github.com> Date: Sun, 25 Oct 2026 14:02:39 -0400 Subject: [PATCH 2/3] REST API jsons MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit D'autre réponses --- doc/REST/location_weather.json | 7 ++++ doc/REST/season_events_ch_2025.json | 42 +++++++++++++++++++++++ doc/REST/season_events_ch_2026_empty.json | 5 +++ doc/REST/season_events_hilo_2024.json | 36 +++++++++++++++++++ doc/REST/seasons_summary.json | 27 +++++++++++++++ 5 files changed, 117 insertions(+) create mode 100644 doc/REST/location_weather.json create mode 100644 doc/REST/season_events_ch_2025.json create mode 100644 doc/REST/season_events_ch_2026_empty.json create mode 100644 doc/REST/season_events_hilo_2024.json create mode 100644 doc/REST/seasons_summary.json diff --git a/doc/REST/location_weather.json b/doc/REST/location_weather.json new file mode 100644 index 0000000..ce950f7 --- /dev/null +++ b/doc/REST/location_weather.json @@ -0,0 +1,7 @@ +{ + "temperature": 10.0, + "time": "0001-01-01T00:00:00Z", + "condition": "Clear", + "icon": 0, + "humidity": 72.0 +} diff --git a/doc/REST/season_events_ch_2025.json b/doc/REST/season_events_ch_2025.json new file mode 100644 index 0000000..976b1ec --- /dev/null +++ b/doc/REST/season_events_ch_2025.json @@ -0,0 +1,42 @@ +{ + "season": 2025, + "events": [ + { + "id": 378, + "startDateUtc": "2026-03-18T08:00:00+00:00", + "period": "AM", + "reward": 11.68, + "energySavingsWh": 20570, + "status": "Success", + "isPreseasonEvent": false, + "isCredited": true, + "isFlatRate": false, + "isInsufficientReduction": false + }, + { + "id": 377, + "startDateUtc": "2026-03-03T09:00:00+00:00", + "period": "AM", + "reward": 17.95, + "energySavingsWh": 31620, + "status": "Success", + "isPreseasonEvent": false, + "isCredited": true, + "isFlatRate": false, + "isInsufficientReduction": false + }, + { + "id": 373, + "startDateUtc": "2026-02-08T09:00:00+00:00", + "period": "AM", + "reward": 20.56, + "energySavingsWh": 36220, + "status": "Success", + "isPreseasonEvent": false, + "isCredited": true, + "isFlatRate": false, + "isInsufficientReduction": false + } + ], + "periodId": "Q0h8dXJuOmhpbG86Y3JtOjAwMDAwLWFiY2RlZjowfDIwMjUtMTEtMDFUMTM6MDE6MTcuODA4Nzc4NVo=" +} diff --git a/doc/REST/season_events_ch_2026_empty.json b/doc/REST/season_events_ch_2026_empty.json new file mode 100644 index 0000000..0a38862 --- /dev/null +++ b/doc/REST/season_events_ch_2026_empty.json @@ -0,0 +1,5 @@ +{ + "season": 2026, + "events": [], + "periodId": "Q0h8dXJuOmhpbG86Y3JtOjAwMDAwLWFiY2RlZjowfDIwMjUtMTEtMDFUMTM6MDE6MTcuODA4Nzc4NVo=" +} diff --git a/doc/REST/season_events_hilo_2024.json b/doc/REST/season_events_hilo_2024.json new file mode 100644 index 0000000..264f4e0 --- /dev/null +++ b/doc/REST/season_events_hilo_2024.json @@ -0,0 +1,36 @@ +{ + "season": 2024, + "events": [ + { + "id": 303, + "startDateUtc": "2025-03-03T09:00:00+00:00", + "period": "AM", + "reportId": 1000000, + "reward": 20.39, + "energySavingsWh": 37081.6845703125, + "status": "Success", + "isPreseasonEvent": false + }, + { + "id": 302, + "startDateUtc": "2025-02-19T09:00:00+00:00", + "period": "AM", + "reportId": 1000001, + "reward": 21.85, + "energySavingsWh": 39730.3349609375, + "status": "Success", + "isPreseasonEvent": false + }, + { + "id": 301, + "startDateUtc": "2025-02-18T09:00:00+00:00", + "period": "AM", + "reportId": 1000002, + "reward": 23.91, + "energySavingsWh": 43477.09521484375, + "status": "Success", + "isPreseasonEvent": false + } + ], + "periodId": "SGlsb3x1cm46aGlsbzpjcm06MDAwMDAtYWJjZGVmOjB8MjAyMi0wNi0yMlQxOTo1MDozOC4wMDAwMDAwWg==" +} diff --git a/doc/REST/seasons_summary.json b/doc/REST/seasons_summary.json new file mode 100644 index 0000000..3da1679 --- /dev/null +++ b/doc/REST/seasons_summary.json @@ -0,0 +1,27 @@ +[ + { + "season": 2026, + "ratePlan": "CH", + "periodId": "Q0h8dXJuOmhpbG86Y3JtOjAwMDAwLWFiY2RlZjowfDIwMjUtMTEtMDFUMTM6MDE6MTcuODA4Nzc4NVo=" + }, + { + "season": 2025, + "ratePlan": "CH", + "periodId": "Q0h8dXJuOmhpbG86Y3JtOjAwMDAwLWFiY2RlZjowfDIwMjUtMTEtMDFUMTM6MDE6MTcuODA4Nzc4NVo=" + }, + { + "season": 2024, + "ratePlan": "Hilo", + "periodId": "SGlsb3x1cm46aGlsbzpjcm06MDAwMDAtYWJjZGVmOjB8MjAyMi0wNi0yMlQxOTo1MDozOC4wMDAwMDAwWg==" + }, + { + "season": 2023, + "ratePlan": "Hilo", + "periodId": "SGlsb3x1cm46aGlsbzpjcm06MDAwMDAtYWJjZGVmOjB8MjAyMi0wNi0yMlQxOTo1MDozOC4wMDAwMDAwWg==" + }, + { + "season": 2022, + "ratePlan": "Hilo", + "periodId": "SGlsb3x1cm46aGlsbzpjcm06MDAwMDAtYWJjZGVmOjB8MjAyMi0wNi0yMlQxOTo1MDozOC4wMDAwMDAwWg==" + } +] From 9988b205769bd87a9e6cd31d02657de386c238e9 Mon Sep 17 00:00:00 2001 From: "Ian C." <108159253+ic-dev21@users.noreply.github.com> Date: Sun, 25 Oct 2026 18:14:45 +0000 Subject: [PATCH 3/3] Reorganize doc payloads by transport The doc folder mixed transports under ad-hoc names (spaces, parentheses, accented characters), and GraphQL onAnyDeviceUpdated payloads sat next to a SignalR DeviceHub message. Grouping by REST, GraphQL and SignalR hub mirrors the api.py / graphql.py / signalr.py split, so a payload's location tells which module decodes it. The README now indexes the folders and documents the Postman collection's built-in OAuth2 and negotiate flow, replacing the outdated get_tokens.py instructions that referenced a script no longer in the repo. Co-Authored-By: Claude Opus 5.5 --- doc/README.md | 92 +++++++++++++++ doc/Readme.md | 111 ------------------ .../onAnyDeviceUpdated-cee.json | 0 .../onAnyDeviceUpdated-meter.json | 0 .../hilo-prod.postman_environment.json} | 0 .../hilo.postman_collection.json} | 0 doc/{REST => rest}/location_weather.json | 0 doc/{REST => rest}/season_events_ch_2025.json | 0 .../season_events_ch_2026_empty.json | 0 .../season_events_hilo_2024.json | 0 doc/{REST => rest}/seasons_summary.json | 0 .../challengehub}/ChallengeAdded.json | 0 .../challengehub}/EventAdded.json | 0 ...ionUpdatedValuesReceived-during-event.json | 0 ...entCHConsumptionUpdatedValuesReceived.json | 0 .../EventCHDetailsInitialValuesReceived.json | 0 .../EventCHDetailsUpdatedValuesReceived.json | 0 ...tFlexConsumptionUpdatedValuesReceived.json | 0 ...EventFlexDetailsInitialValuesReceived.json | 0 ...EventFlexDetailsUpdatedValuesReceived.json | 0 .../legacy-pre-2025}/ChallengeAdded.json | 0 ...lengeConsumptionUpdatedValuesReceived.json | 0 ...ChallengeDetailsInitialValuesReceived.json | 0 .../ChallengeListInitialValuesReceived.json | 0 .../ChallengeListUpdatedValuesReceived.json | 0 .../DeviceListInitialValuesReceived.json | 0 26 files changed, 92 insertions(+), 111 deletions(-) create mode 100644 doc/README.md delete mode 100644 doc/Readme.md rename doc/{Device Replies => graphql}/onAnyDeviceUpdated-cee.json (100%) rename doc/{Device Replies => graphql}/onAnyDeviceUpdated-meter.json (100%) rename doc/{Postman/Hilo Prod.postman_environment.json => postman/hilo-prod.postman_environment.json} (100%) rename doc/{Postman/Hilo.postman_collection.json => postman/hilo.postman_collection.json} (100%) rename doc/{REST => rest}/location_weather.json (100%) rename doc/{REST => rest}/season_events_ch_2025.json (100%) rename doc/{REST => rest}/season_events_ch_2026_empty.json (100%) rename doc/{REST => rest}/season_events_hilo_2024.json (100%) rename doc/{REST => rest}/seasons_summary.json (100%) rename doc/{Challenge(Event) JSON => signalr/challengehub}/ChallengeAdded.json (100%) rename doc/{Challenge(Event) JSON => signalr/challengehub}/EventAdded.json (100%) rename "doc/Challenge(Event) JSON/EventCHConsumptionUpdatedValuesReceived(en cours de d\303\251fi).json" => doc/signalr/challengehub/EventCHConsumptionUpdatedValuesReceived-during-event.json (100%) rename doc/{Challenge(Event) JSON => signalr/challengehub}/EventCHConsumptionUpdatedValuesReceived.json (100%) rename doc/{Challenge(Event) JSON => signalr/challengehub}/EventCHDetailsInitialValuesReceived.json (100%) rename doc/{Challenge(Event) JSON => signalr/challengehub}/EventCHDetailsUpdatedValuesReceived.json (100%) rename doc/{Challenge(Event) JSON => signalr/challengehub}/EventFlexConsumptionUpdatedValuesReceived.json (100%) rename doc/{Challenge(Event) JSON => signalr/challengehub}/EventFlexDetailsInitialValuesReceived.json (100%) rename doc/{Challenge(Event) JSON => signalr/challengehub}/EventFlexDetailsUpdatedValuesReceived.json (100%) rename doc/{Old JSONs (pre 2025-26 season) => signalr/challengehub/legacy-pre-2025}/ChallengeAdded.json (100%) rename doc/{Old JSONs (pre 2025-26 season) => signalr/challengehub/legacy-pre-2025}/ChallengeConsumptionUpdatedValuesReceived.json (100%) rename doc/{Old JSONs (pre 2025-26 season) => signalr/challengehub/legacy-pre-2025}/ChallengeDetailsInitialValuesReceived.json (100%) rename doc/{Old JSONs (pre 2025-26 season) => signalr/challengehub/legacy-pre-2025}/ChallengeListInitialValuesReceived.json (100%) rename doc/{Old JSONs (pre 2025-26 season) => signalr/challengehub/legacy-pre-2025}/ChallengeListUpdatedValuesReceived.json (100%) rename doc/{Device Replies => signalr/devicehub}/DeviceListInitialValuesReceived.json (100%) diff --git a/doc/README.md b/doc/README.md new file mode 100644 index 0000000..0966a33 --- /dev/null +++ b/doc/README.md @@ -0,0 +1,92 @@ +# Hilo API reference payloads + +Captured responses from Hilo's services, grouped by transport to mirror the library modules. +IDs, URNs and serial numbers in the payload files are anonymized. + +| Folder | Transport | Library module | Contents | +|---|---|---|---| +| [`rest/`](rest/) | HTTPS REST | `pyhilo/api.py` | Automation (`/Locations`, `/Weather`) and challenge season endpoints | +| [`graphql/`](graphql/) | GraphQL subscription | `pyhilo/graphql.py` | `onAnyDeviceUpdated` payloads per device type | +| [`signalr/devicehub/`](signalr/devicehub/) | SignalR WebSocket | `pyhilo/signalr.py` | DeviceHub messages | +| [`signalr/challengehub/`](signalr/challengehub/) | SignalR WebSocket | `pyhilo/signalr.py` | ChallengeHub messages, 2025-26 season onward (CH = Winter Credits, Flex = Flex D) | +| [`signalr/challengehub/legacy-pre-2025/`](signalr/challengehub/legacy-pre-2025/) | SignalR WebSocket | — | Challenge messages before the CH/Flex split; kept for reference | +| [`postman/`](postman/) | — | — | Postman collection and environment for manual testing | + +## Adding a payload + +1. Strip tokens, location URNs, serial numbers and personal data before committing. +2. Name REST files after the endpoint (`season_events_ch_2025.json`) and SignalR/GraphQL files after the message target (`EventCHDetailsInitialValuesReceived.json`). +3. Add a short suffix for variants (`-during-event`, `-empty`, `-meter`). + +# Using Postman to query Hilo + +Import [`postman/hilo.postman_collection.json`](postman/hilo.postman_collection.json) and [`postman/hilo-prod.postman_environment.json`](postman/hilo-prod.postman_environment.json), then select the **Hilo Prod** environment. + +## Authentication + +The collection uses OAuth 2.0 at the collection level. Open the collection's **Authorization** tab, click **Get New Access Token**, log in with your Hilo credentials in the browser window, then click **Use Token**. Every request in the collection inherits that token. + +Tokens are short-lived and contain personally identifiable information. Do not share them or commit an exported environment that contains them. + +## REST requests + +With the access token set, the REST requests (`1-Get Locations`, `Get SeasonsSummary`, `Get CHEvents`, `Get FlexEvents`, ...) can be sent directly. + +## Connecting to a hub + +Each hub folder (`DeviceHub`, `ChallengeHub`) contains two negotiate requests. Send them in order: + +1. `1-API Hilo ... Hub Negotiate` stores the hub URL and hub access token in the environment (`_deviceHubUrl` / `_deviceHubAccessToken`, or `_challengeHubUrl` / `_challengeHubAccessToken`). +2. `2-... Hub Negotiate` stores the connection token (`_deviceHubConnectionToken` or `_challengeHubConnectionToken`). + +Then open a new WebSocket request in Postman: + +1. Use the hub URL from the environment (`{{_deviceHubUrl}}` or `{{_challengeHubUrl}}`). +2. In **Headers**, add `Authorization` with the value `Bearer {{_deviceHubAccessToken}}` (or `Bearer {{_challengeHubAccessToken}}`). +3. Connect, then send the handshake below. The trailing record separator character `chr(30)` is required after every message. + +``` +{ + "protocol": "json", + "version": 1 +} +``` + +### DeviceHub + +Invoke `SubscribeToLocation` with your location ID to get your device information: + +``` +{ + "arguments": [ + 69420 + ], + "invocationId": "0", + "target": "SubscribeToLocation", + "type": 1 +} +``` + +You should receive a [`DeviceListInitialValuesReceived`](signalr/devicehub/DeviceListInitialValuesReceived.json) message back. + +### ChallengeHub + +Since the 2025-2026 season and the addition of Flex D, messages are split between Winter Credits (Crédit Hivernal) and Flex D. Winter Credits targets contain `CH` and Flex D targets contain `Flex`. Each rate has its own event ID; for example, event 337 was for Winter Credits and event 338 for Flex D, both at the same time. You only have access to the one matching your rate. + +#### SubscribeToEventCH or SubscribeToEventFlex + +``` +{ + "arguments": [ + { + "locationHiloId": "urn:YOUR-URN", + "eventId": ID(numeric) + } + ], + "invocationId": "1", + "target": "SubscribeToEventCH", + "type": 1 +} +``` + +Returns [`EventCHDetailsInitialValuesReceived`](signalr/challengehub/EventCHDetailsInitialValuesReceived.json) or [`EventFlexDetailsInitialValuesReceived`](signalr/challengehub/EventFlexDetailsInitialValuesReceived.json). diff --git a/doc/Readme.md b/doc/Readme.md deleted file mode 100644 index 6a38936..0000000 --- a/doc/Readme.md +++ /dev/null @@ -1,111 +0,0 @@ -# Using get_tokens.py - -This python script will let you use it to log in to your Hilo account. - -From there, you will be asked to copy the full HA redirect(callback) URL and go back to your python script and press enter. - -Negotiation will take place and you will receive three distinct tokens: - -- Your access token -- Your devicehub token -- Your challengehub token - -Take care not to share your tokens as they are not encrypted and contain personally identifiable information. - -1. Run get_tokens.py, you will be provided with a link. Either click it or copy it in your favourite browser. - image - -2. Login using your Hilo Credentials - - image - -3. Once you get to this page, select the URL and copy it to clipboard - image - image - -4. Go back to get_tokens.py and press enter, you'll get all 3 tokens: - -image - -# Using Postman to send payloads to devicehub or challengehub - -## Prerequisite: you need to have your tokens on hand, they are relatively short lived so once you have them, get to connecting! - -### DeviceHub - -1. Open up a new websocket connection and paste the DeviceHub URL -2. In Headers, add "Authorization". -3. In the Authorization field, type in "Bearer" then a space, and paste your DeviceHub token. - image -4. Go to the "Messages" tab and type in. Notice the control character at the end chr(30). It is required. - -``` -{ - "protocol": "json", - "version": 1 -} -``` - -5. You can then invoke "SubscribeToLocation" to get your device information. - -``` -{ - "arguments": [ - 69420 - ], - "invocationId": "0", - "target": "SubscribeToLocation", - "type": 1 -} -``` - -6. You should received the DeviceListInitialValuesReceived message back. - -### ChallengeHub - -1. Open up a new websocket connection and paste the DeviceHub URL -2. In Headers, add "Authorization". -3. In the Authorization field, type in "Bearer" then a space, and paste your DeviceHub token. - image -4. Go to the "Messages" tab and type in. Notice the control character at the end chr(30). It is required. - -``` -{ - "protocol": "json", - "version": 1 -} -``` - -5. You can send various messages to the ChallengeHub to request different information. For the 2025-2026 season with the addition of Flex D, the messages were split between Winter Credit (Crédit Hivernal) and Flex D. Winter Credit messages will contain CH in their target, and Flex D event will contain Flex in their target. Each of rates has its own event id, for example, event 337 was for Winter Credits, and event 338 was for Flex D, both occurred at the same time. You will have access to one, or the other, depending on your rate. - -### Examples of various invokesto the ChallengeHub - -#### SubscribeToEventCH or SubscribeToEventFlex - -This invoke is used: - -``` -{ - "arguments": [ - { - "locationHiloId": "urn:YOUR-URN", - "eventId": ID(numeric) - } - ], - "invocationId": "1", - "target": "SubscribeToEventCH", - "type": 1 -} -``` - -And should return - -``` -EventCHDetailsInitialValuesReceived -``` - -Or - -``` -EventFlexDetailsInitialValuesReceived -``` diff --git a/doc/Device Replies/onAnyDeviceUpdated-cee.json b/doc/graphql/onAnyDeviceUpdated-cee.json similarity index 100% rename from doc/Device Replies/onAnyDeviceUpdated-cee.json rename to doc/graphql/onAnyDeviceUpdated-cee.json diff --git a/doc/Device Replies/onAnyDeviceUpdated-meter.json b/doc/graphql/onAnyDeviceUpdated-meter.json similarity index 100% rename from doc/Device Replies/onAnyDeviceUpdated-meter.json rename to doc/graphql/onAnyDeviceUpdated-meter.json diff --git a/doc/Postman/Hilo Prod.postman_environment.json b/doc/postman/hilo-prod.postman_environment.json similarity index 100% rename from doc/Postman/Hilo Prod.postman_environment.json rename to doc/postman/hilo-prod.postman_environment.json diff --git a/doc/Postman/Hilo.postman_collection.json b/doc/postman/hilo.postman_collection.json similarity index 100% rename from doc/Postman/Hilo.postman_collection.json rename to doc/postman/hilo.postman_collection.json diff --git a/doc/REST/location_weather.json b/doc/rest/location_weather.json similarity index 100% rename from doc/REST/location_weather.json rename to doc/rest/location_weather.json diff --git a/doc/REST/season_events_ch_2025.json b/doc/rest/season_events_ch_2025.json similarity index 100% rename from doc/REST/season_events_ch_2025.json rename to doc/rest/season_events_ch_2025.json diff --git a/doc/REST/season_events_ch_2026_empty.json b/doc/rest/season_events_ch_2026_empty.json similarity index 100% rename from doc/REST/season_events_ch_2026_empty.json rename to doc/rest/season_events_ch_2026_empty.json diff --git a/doc/REST/season_events_hilo_2024.json b/doc/rest/season_events_hilo_2024.json similarity index 100% rename from doc/REST/season_events_hilo_2024.json rename to doc/rest/season_events_hilo_2024.json diff --git a/doc/REST/seasons_summary.json b/doc/rest/seasons_summary.json similarity index 100% rename from doc/REST/seasons_summary.json rename to doc/rest/seasons_summary.json diff --git a/doc/Challenge(Event) JSON/ChallengeAdded.json b/doc/signalr/challengehub/ChallengeAdded.json similarity index 100% rename from doc/Challenge(Event) JSON/ChallengeAdded.json rename to doc/signalr/challengehub/ChallengeAdded.json diff --git a/doc/Challenge(Event) JSON/EventAdded.json b/doc/signalr/challengehub/EventAdded.json similarity index 100% rename from doc/Challenge(Event) JSON/EventAdded.json rename to doc/signalr/challengehub/EventAdded.json diff --git "a/doc/Challenge(Event) JSON/EventCHConsumptionUpdatedValuesReceived(en cours de d\303\251fi).json" b/doc/signalr/challengehub/EventCHConsumptionUpdatedValuesReceived-during-event.json similarity index 100% rename from "doc/Challenge(Event) JSON/EventCHConsumptionUpdatedValuesReceived(en cours de d\303\251fi).json" rename to doc/signalr/challengehub/EventCHConsumptionUpdatedValuesReceived-during-event.json diff --git a/doc/Challenge(Event) JSON/EventCHConsumptionUpdatedValuesReceived.json b/doc/signalr/challengehub/EventCHConsumptionUpdatedValuesReceived.json similarity index 100% rename from doc/Challenge(Event) JSON/EventCHConsumptionUpdatedValuesReceived.json rename to doc/signalr/challengehub/EventCHConsumptionUpdatedValuesReceived.json diff --git a/doc/Challenge(Event) JSON/EventCHDetailsInitialValuesReceived.json b/doc/signalr/challengehub/EventCHDetailsInitialValuesReceived.json similarity index 100% rename from doc/Challenge(Event) JSON/EventCHDetailsInitialValuesReceived.json rename to doc/signalr/challengehub/EventCHDetailsInitialValuesReceived.json diff --git a/doc/Challenge(Event) JSON/EventCHDetailsUpdatedValuesReceived.json b/doc/signalr/challengehub/EventCHDetailsUpdatedValuesReceived.json similarity index 100% rename from doc/Challenge(Event) JSON/EventCHDetailsUpdatedValuesReceived.json rename to doc/signalr/challengehub/EventCHDetailsUpdatedValuesReceived.json diff --git a/doc/Challenge(Event) JSON/EventFlexConsumptionUpdatedValuesReceived.json b/doc/signalr/challengehub/EventFlexConsumptionUpdatedValuesReceived.json similarity index 100% rename from doc/Challenge(Event) JSON/EventFlexConsumptionUpdatedValuesReceived.json rename to doc/signalr/challengehub/EventFlexConsumptionUpdatedValuesReceived.json diff --git a/doc/Challenge(Event) JSON/EventFlexDetailsInitialValuesReceived.json b/doc/signalr/challengehub/EventFlexDetailsInitialValuesReceived.json similarity index 100% rename from doc/Challenge(Event) JSON/EventFlexDetailsInitialValuesReceived.json rename to doc/signalr/challengehub/EventFlexDetailsInitialValuesReceived.json diff --git a/doc/Challenge(Event) JSON/EventFlexDetailsUpdatedValuesReceived.json b/doc/signalr/challengehub/EventFlexDetailsUpdatedValuesReceived.json similarity index 100% rename from doc/Challenge(Event) JSON/EventFlexDetailsUpdatedValuesReceived.json rename to doc/signalr/challengehub/EventFlexDetailsUpdatedValuesReceived.json diff --git a/doc/Old JSONs (pre 2025-26 season)/ChallengeAdded.json b/doc/signalr/challengehub/legacy-pre-2025/ChallengeAdded.json similarity index 100% rename from doc/Old JSONs (pre 2025-26 season)/ChallengeAdded.json rename to doc/signalr/challengehub/legacy-pre-2025/ChallengeAdded.json diff --git a/doc/Old JSONs (pre 2025-26 season)/ChallengeConsumptionUpdatedValuesReceived.json b/doc/signalr/challengehub/legacy-pre-2025/ChallengeConsumptionUpdatedValuesReceived.json similarity index 100% rename from doc/Old JSONs (pre 2025-26 season)/ChallengeConsumptionUpdatedValuesReceived.json rename to doc/signalr/challengehub/legacy-pre-2025/ChallengeConsumptionUpdatedValuesReceived.json diff --git a/doc/Old JSONs (pre 2025-26 season)/ChallengeDetailsInitialValuesReceived.json b/doc/signalr/challengehub/legacy-pre-2025/ChallengeDetailsInitialValuesReceived.json similarity index 100% rename from doc/Old JSONs (pre 2025-26 season)/ChallengeDetailsInitialValuesReceived.json rename to doc/signalr/challengehub/legacy-pre-2025/ChallengeDetailsInitialValuesReceived.json diff --git a/doc/Old JSONs (pre 2025-26 season)/ChallengeListInitialValuesReceived.json b/doc/signalr/challengehub/legacy-pre-2025/ChallengeListInitialValuesReceived.json similarity index 100% rename from doc/Old JSONs (pre 2025-26 season)/ChallengeListInitialValuesReceived.json rename to doc/signalr/challengehub/legacy-pre-2025/ChallengeListInitialValuesReceived.json diff --git a/doc/Old JSONs (pre 2025-26 season)/ChallengeListUpdatedValuesReceived.json b/doc/signalr/challengehub/legacy-pre-2025/ChallengeListUpdatedValuesReceived.json similarity index 100% rename from doc/Old JSONs (pre 2025-26 season)/ChallengeListUpdatedValuesReceived.json rename to doc/signalr/challengehub/legacy-pre-2025/ChallengeListUpdatedValuesReceived.json diff --git a/doc/Device Replies/DeviceListInitialValuesReceived.json b/doc/signalr/devicehub/DeviceListInitialValuesReceived.json similarity index 100% rename from doc/Device Replies/DeviceListInitialValuesReceived.json rename to doc/signalr/devicehub/DeviceListInitialValuesReceived.json