Skip to main content

Moen Flo Smart Water Shutoff

Remote valve control, system-mode switching (home / away / sleep), periodic telemetry (flow, water temperature, PSI, battery) and standing-alert monitoring for Flo by Moen / Moen Flo Smart Water Monitor + Shutoff devices via the api-gw.meetflo.com cloud REST API.

Shutoffs found on the account are created as water zones automatically. Auth is email + password; the driver mints a short-lived JWT session token, keeps it in memory, and re-mints it on 401 or when the token expiry passes. There is no persistent token stored on disk.

Accounts migrated to Moen

Moen is migrating Flo accounts onto its own platform. A migrated account is refused by the v2 auth endpoint with 403 "User migrated to Moen" — while the v1 auth endpoint still mints a token that the entire v2 API accepts. The driver tries v2, falls back to v1 automatically, and remembers which one worked so the refusal is not repeated on every token refresh. Every data call stays on v2 either way. No configuration is needed; the fallback shows up in the log as moen flo authenticated on /api/v1.

Cloud-only path

Moen Flo does not publish a local LAN API. This driver is a cloud driver — the GEM host must have outbound HTTPS to api-gw.meetflo.com. If the internet path is unavailable, valve commands cannot be sent even if GEM and the shutoff are on the same LAN.

Prerequisites

  • A working Moen Flo (formerly Flo by Moen) cloud account with the shutoff already onboarded through the mobile app.
  • The GEM host must be able to reach https://api-gw.meetflo.com on port 443.
  • The account credentials used in GEM must belong to the account owner or a household member with control permission. Read-only shares can enumerate devices but the API returns 403 on valve actuation.
  • MFA must be disabled on the account used with GEM. The password-grant /users/auth endpoint does not accept a second factor; if MFA is enabled the driver will loop on auth failed. If you want MFA on your main account, create a sub-account for GEM without MFA.

Setup

  1. Navigate to Admin → Devices and click Add Device.
  2. Choose moen_flo as the driver.
  3. Fill in:
    • Moen Flo Account Email (username) — the address used to log in to the Flo mobile app.
    • Moen Flo Account Password (password) — stored encrypted.
  4. Save the device. GEM will authenticate and discover all locations and shutoffs on the account.
  5. On the first poll the driver creates one Water zone per shutoff, addressed by the Flo device id and using the Water (On/Off) control labelled Open / Close.
  6. Optional: run the get_devices command on the device (from the device detail page, Commands tab) to list the shutoffs. The response includes each device's id, nickname, macAddress, and location_id.
  7. The zone's state attribute populates on that same poll (open / closed). Telemetry attributes (flow_rate, water_pressure, water_temperature, battery_level, alert_severity) follow.

Zone auto-creation

Auto-creation is on by default and can be turned off with the auto_create_zones device attribute, which leaves zone mapping entirely manual (Address = the Flo device id, subsystem = water or plumbing).

Zones land on the first subsystem that matches water, falling back to plumbing. The label comes from the shutoff's nickname in the Flo app — a shutoff nicknamed 1" Smart Water Shutoff becomes a zone with that label and the name <device>_1_smart_water_shutoff. Without a nickname the label falls back to the location name plus the device model, then to the model plus a device-id prefix.

Each new zone is seeded with four presentation attributes so the Water (On/Off) control speaks this valve's vocabulary — on_text/off_text (Open/Close) and on_state/off_state (open/closed). They are written once, at create, so relabelling the buttons afterwards sticks.

The driver will not recreate a zone you disabled — disabling a zone is how you tell it to leave a shutoff alone. If the derived zone name collides with an unrelated zone, the new zone is created with the device id appended; if that is taken too, the create is skipped and logged.

Shutoffs are enumerated once per connect. A shutoff added to the Flo account afterwards appears on the next device reload.

Attribute reference

Device attributes

AttributeRequiredDescription
usernameyesMoen Flo cloud account email.
passwordyesCloud account password. Stored encrypted (gem-crypt: envelope).
api_basenoCloud endpoint. Defaults to https://api-gw.meetflo.com. Only change if Moen migrates the API host.
status_intervalnoPoll interval in ms. Default 60000, floor 15000.
request_timeoutnoHTTP request timeout in ms. Default 15000.
auto_create_zonesnoCreate a Water zone per shutoff the account reports. Default true; turn off to map zones by hand.

Zone attributes (populated by the driver)

AttributeTypeDescription
statestringopen if the valve permits flow, closed if shut.
flow_ratefloatInstantaneous flow in gallons per minute. Zero during no-flow windows.
water_pressurefloatStatic line PSI at the shutoff.
water_temperatureintWater temperature at the shutoff in °F.
battery_levelintBattery percentage when the device reports it (mains-powered shutoffs may omit this).
alert_severitystringSeverity of the top standing alert: clear, info, warning, or critical.
alert_countintHow many alerts are standing triggered on this shutoff (warning and critical tiers). 0 when clear.
alert_titlestringShort name of the top standing alert as Flo labels it — Water System Shutoff, Unusual Activity, Valve Error. Empty when clear.
alert_messagestringFlo's full text for that alert, including flow rate and duration where it carries them. Empty when clear.
alert_idstringFlo alert UUID, for correlating a GEM alarm with the entry in the Flo app. Empty when clear.
alert_timestringISO timestamp Flo first raised the alert. Can be months old — see Alerts.
location_idstringThe Flo location UUID this shutoff belongs to. Populated on connect; used by set_system_mode.
connectedboolWhether the Flo cloud can currently reach the shutoff, mirrored from the device payload's isConnected.

Zone address format

zone.address = the Moen Flo device id UUID, e.g. a1b2c3d4-e5f6-7890-abcd-ef1234567890. Filled in automatically when auto_create_zones is on.

Run get_devices on the driver device to enumerate; the response contains one entry per shutoff with id, nickname, macAddress, location_id, deviceModel, and firmwareVersion.

Commands

CommandArgsNotes
openaddressOpens the valve (allows flow). Fires a status refresh 2 s later.
closeaddressCloses the valve (stops flow). Fires a status refresh 2 s later.
onaddressAlias for open, so GEM's generic on verb reaches the valve.
offaddressAlias for close, so GEM's generic off verb reaches the valve.
set_system_modeaddress, mode, revert_minutesSets the whole-location mode to home, away, or sleep. revert_minutes (2–1440) only applies to sleep; defaults to 120. The driver resolves the location from the zone or (if there's exactly one) from the account.
get_statusaddressRefreshes and returns the full Flo device payload for the zone.
get_devicesLists every shutoff visible to the account.
get_locationsLists every location owned by the account, including the current systemMode.
get_alertsaddress, location_idLists standing triggered alerts (warning and critical) with title, message, severity and timestamp. Both args optional: address limits the result to one shutoff, location_id to one location.

Voice control

Once a shutoff has a zone on a water or plumbing subsystem, it is reachable from Ask GEM — "shut off the water", "is the water shut off?", "turn the water back on". The assistant reads the zone's state (open / closed) for valve position and flow_rate for whether water is actually running, and reports any active leak signal alongside them.

Shutting off may sweep every accessible valve. Re-opening needs an unambiguous target and is refused while any leak sensor is still wet until the user is told which sensor and confirms — so a Flo left closed after a leak stays closed until the cause is dealt with. Consumption questions are answered from the meter attributes instead, which for a Flo means live flow_rate and water_pressure rather than daily totals (see Known limitations).

Alerts

Alerts are a location-scoped feed, not part of the device payload. /devices/{id} carries pending counts only — enough to say "one critical" but not which one, so counts alone cannot tell a catastrophic leak from a long irrigation run. The driver polls /alerts once per location per cycle (one request covers every shutoff under that location) and publishes the top standing alert onto each zone as alert_severity, alert_count, alert_title, alert_message, alert_id and alert_time.

Alerts rank critical before warning, newest first inside a tier, so the alert_* attributes always describe the one worth acting on.

Critical alerts raise an alarm

A critical alert raises the water_alert system alarm against the zone, carrying Flo's own title and message — so a leak or an automatic shutoff reaches notification profiles, the alarm dashboard, and any macro bound to alarm activation without an integrator wiring a trigger by hand.

Warning-tier alerts publish to the attributes only. A valve self-test that wants attention next week is not a 2am phone call, and an alert nobody has to act on is what teaches people to ignore the ones they do. Build an attribute trigger on alert_severity if a site wants warnings escalated too.

If a different critical alert takes over — "Unusual Activity" becoming "Water System Shutoff" — the driver closes the open event and raises a new one, so the escalation gets its own row and its own notification rather than hiding under a stale title.

Standing alerts can be old

Flo holds an alert in triggered until somebody resolves it in the mobile app. A shutoff whose alerts were never cleared therefore raises its alarm on the first poll after upgrading, including alerts weeks or months old — and that is faithful, because the condition is still open at the vendor. Run get_alerts to see exactly what is standing.

To settle one: clear it in the Flo app and the GEM alarm clears on the next poll. GEM cannot dismiss it — the API exposes no path for this driver. If an alert is being left open deliberately, acknowledge or shelve the GEM alarm instead.

If the location alert query fails, the driver keeps the previous alert set rather than treating silence as "everything cleared" — a network blip must not drop a live alarm. Until the first successful query for a shutoff, alert_severity falls back to the pending counts on the device payload; alert_title and the rest stay empty, which is the signal that the fallback is in play.

Zone connection state

Each device payload carries isConnected — whether the Flo cloud can currently reach the shutoff. The driver mirrors it onto the zone's connected attribute on every poll, so a shutoff that has dropped off wifi reads as offline instead of showing a stale valve position indefinitely. A sustained disconnect raises the standard zone_offline alarm through the connection monitor, and clears when the shutoff comes back.

Telemetry is still published while the shutoff is offline — the values are the last ones the cloud saw, not live readings, and the offline zone is what tells you so. When the cloud omits isConnected entirely the driver leaves the zone's connection state alone: an absent field means not reported, not down.

Known limitations

  • Alert clearing must be done in the Moen Flo mobile app. The driver reads alerts and raises alarms from them; the API gives it no way to dismiss one. See Alerts.
  • Historic water-usage graphs (daily / monthly consumption) are not exposed by this driver. Only the live telemetry the cloud publishes on the device payload is mirrored.
  • Sleep mode requires a revert; the API will reject set_system_mode(sleep) without a revertMinutes. The driver injects a 120-minute default, which reverts to home.
  • Valve actuation is blocked while in sleep mode — the Flo cloud returns 403. Change to home or away first.
  • Multi-shutoff accounts are supported (one zone per shutoff), but the driver polls sequentially with a 750 ms gap between devices to stay well under the account rate limit. If you have more than ~10 shutoffs on one account, consider raising status_interval.

Troubleshooting

SymptomLikely cause
Log shows http 403 (User migrated to Moen)Informational. Moen migrated this account off the legacy Flo platform; the driver retries on the v1 auth endpoint and carries on. If the v1 attempt also fails, the credentials are wrong or the account moved to a backend this driver has no path to.
No zones were createdConfirm a water (or plumbing) subsystem exists and auto_create_zones is on. Run get_devices — a shutoff the account does not report cannot be auto-created. A zone you previously disabled is deliberately not recreated.
Log shows moen flo auth failed on connect with http 401Wrong email/password, or MFA is enabled on the account. Sign in via the Flo mobile app to confirm credentials. Disable MFA or create a sub-account.
get_devices returns an empty listThe account has no shutoffs, or the account is a read-only share. Confirm ownership in the Flo app.
open / close returns 403Location is in sleep mode. Call set_system_mode with mode: home first.
Zone shows offline but still reports a valve positionThe Flo cloud reports isConnected: false for that shutoff — check its wifi from the Flo app. The attributes shown are the last values the cloud saw, not live readings.
Zone state never reflects a manual actuation at the physical shutoffThe Flo cloud reflects hardware changes on its own schedule (typically 30–60 s). Lowering status_interval below that window will not help — the cloud is the bottleneck.
state reports null for a fresh zoneThe first poll hasn't run yet. Wait status_interval ms, or run get_status manually.
A water_alert alarm fires on an alert months oldExpected. Flo holds an alert triggered until it is resolved in the mobile app, so the condition is still open at the vendor. Run get_alerts to see what is standing, then clear it in the Flo app — the alarm clears on the next poll. Acknowledge or shelve it in GEM if the alert is being left open deliberately.
alert_title stays empty while alert_severity movesThe location alert query is failing (rate limit, or a read-only share with no location access) and the driver is on its count-only fallback. Run get_alerts — an empty result with no error means genuinely nothing standing; an error names the cause.

References

  • Flo by Moen (product page): meetflo.com
  • Community protocol reference: pyflowater / Home Assistant flo integration source (unofficial).