Chemistry settings
Both endpoints take the complete settings object as returned by chemistryCard. The controller replaces every field with what you send, and any field you omit is sent as 0 or false. Always read, modify and write back the whole object.
Values of 0 are treated as “not set” by validation and pass through unchanged, so a missing numeric field will not be rejected; it will silently reset that setting on the controller.
pH dosing
Section titled “pH dosing”POST…/setPhSettings
{ "ph_dosing": true, "ph_dosing_time": 60, "desired_ph_level": 74, "acid_drum_volume": 20000, "remain_acid_volume": 10000, "reset_acid_volume": false, "max_dose_pre_day": 10, "dose_intervals": 30, "ph_dose_rate": 100}| Field | Type | Range | Meaning |
|---|---|---|---|
ph_dosing |
bool | Acid dosing enabled | |
desired_ph_level |
int | 60 to 85 | Target pH × 10 |
ph_dosing_time |
int | 1 to 600 | Length of one dose |
dose_intervals |
int | 1 to 120 | Minimum gap between doses |
max_dose_pre_day |
int | 1 to 50 | Daily dose limit |
acid_drum_volume |
int | 1 to 1,000,000 | Drum capacity, mL |
remain_acid_volume |
int | 0 to 1,000,000 | Acid remaining, mL |
reset_acid_volume |
bool | Set true once after refilling the drum to reset the remaining volume |
|
ph_dose_rate |
int | Doser flow rate; keep the value the controller reports |
current_dose_today and ph_doser_timer are read-only and ignored if sent.
Response: 200 with data.message holding the controller’s acknowledgement; the write waits up to 3 seconds and a timeout returns 500 with failed to set pH settings: timeout waiting for response. Out-of-range values return 400, listing every violation:
{ "status": "FAILED", "message": "invalid pH settings: desired_ph_level must be 60-85 (got 90); dose_intervals must be 1-120 (got 121)" }Chlorine and ORP
Section titled “Chlorine and ORP”POST…/setChlorineSettings
{ "orp_controlled": true, "desired_orp_level_mineral": 650, "liquid_chlorine_dosing": false, "desired_orp_level_liquid": 650, "chlorine_dosing_time": 60, "chlorine_drum_volume": 20000, "remain_chlorine_volume": 15000, "reset_chlorine_volume": false, "max_dose_pre_day": 10, "dose_intervals": 30, "liquid_dose_rate": 100}| Field | Type | Range | Meaning |
|---|---|---|---|
orp_controlled |
bool | Chlorinator output follows the ORP set point | |
desired_orp_level_mineral |
int | 300 to 900 | ORP target for the mineral or salt chlorinator, mV |
liquid_chlorine_dosing |
bool | Liquid chlorine dosing enabled | |
desired_orp_level_liquid |
int | 300 to 900 | ORP target for liquid chlorine, mV |
chlorine_dosing_time |
int | 1 to 600 | Length of one liquid dose |
dose_intervals |
int | 1 to 120 | Minimum gap between doses |
max_dose_pre_day |
int | 1 to 50 | Daily dose limit |
chlorine_drum_volume |
int | 1 to 1,000,000 | Drum capacity, mL |
remain_chlorine_volume |
int | 0 to 1,000,000 | Chlorine remaining, mL |
reset_chlorine_volume |
bool | Set true once after refilling |
|
liquid_dose_rate |
int | Doser flow rate; keep the reported value |
The *_today, *_timer and mineral_* fields are read-only. Validation errors use the prefix invalid chlorine settings:.
This write also waits up to 3 seconds; a timeout returns 500 with timeout waiting for response.
Both writes clear the cached dashboardInfo and the relevant settings read, so the next chemistryCard shows the new values.

