Chamberlain MyQ
Cloud driver for residential and light-commercial garage door openers sold under the Chamberlain, LiftMaster, Craftsman, and Merlin brands — anything that surfaces in the myQ mobile app. GEM polls the door state and surfaces open / close / get-status commands; everything traverses the myq-cloud.com REST API because the openers do not speak a LAN protocol.
This is a quoting-grade integration. It is the right pick for residential garage zones, automated arming routines that need confirmation the door is closed, and gate macros that fire on a schedule. It is not the right pick for hard real-time gate control (a touchscreen tap should never wait on a round-trip to Azure) — for that use a LAN-attached relay driver against a LiftMaster commercial controller.
Prerequisites
-
A working Chamberlain / LiftMaster / Craftsman account with at least one opener paired in the myQ mobile app, online with a steady blue gateway LED.
-
A long-lived access_token for that account. MyQ does not publish a third-party OAuth flow, so the token has to be minted by replaying the official mobile-app login against Azure AD B2C. The community-maintained
pymyqPython module is the canonical helper:pip install pymyqpython -m pymyq --email you@example.com --password REDACTED --token-onlyPaste the value it prints into the device row. Tokens are time-bounded but typically valid for several months; budget for re-bootstrapping when authentication errors start flapping.
-
Outbound HTTPS reachability from the GEM host to
*.myq-cloud.comon port 443. There is no LAN-only mode for MyQ.
Chamberlain has rotated the official mobile-app client_id at least twice since 2021. If tokens that used to work suddenly return 401 across every account, the cloud has rotated again — check for an updated pymyq release before assuming an outage.
Setup steps
- Mint the token. Run the helper above and capture the bearer string. The same token can be reused for every GEM device that points at the same MyQ account.
- Add the device. Admin → Devices → Add.
- Driver:
chamberlain_myq - Name: e.g. Garage Opener Controller
- Subsystem:
gate(orgarage) - Paste the bearer string into the Access Token attribute. Leave Account ID empty unless you have already harvested it elsewhere — the driver will fetch it on first connect from
/api/v6.0/My.
- Driver:
- Discover openers. Open the device and switch to the Commands tab (it appears once the device has been saved with its
chamberlain_myqcommand set, which GEM assigns automatically). Select get_devices, run it, and read the response console — it lists every opener on the account with itsserial_number(e.g.CG0812345678),name, anddevice_family. If you prefer code, run the same call from System → Script Console:await gem.command({device_id: <device_id>, command: 'get_devices'}). - Create zones. Admin → Zones → Add a zone per opener.
- Address: the
serial_numberfrom step 3, copied verbatim. This is the key the driver uses to bind cloud devices to GEM zones. - Subsystem: pick
gatefor a driveway gate,garagefor an overhead door, ordoorfor a side door — the subsystem decides the zone's control surface (its open / close verbs and gate / garage / door iconography). This is a cloud driver that reports the door's actual position, so there is no relay contact to interpret; the subsystem only governs how the zone presents and is commanded.
- Address: the
- Sanity-check. Trigger an open from the GEM admin. The driver schedules a follow-up status read 6 seconds later, so the zone state should flip from
closed→moving→openwithin ~10 seconds.
Attribute reference
| Attribute | Required | Default | Notes |
|---|---|---|---|
access_token | yes | — | Bearer string minted externally. Secure — stored encrypted at rest. |
account_id | no | discovered | UUID for the MyQ account. Setting it explicitly skips the discovery round-trip; clearing it forces a fresh /My lookup on next connect. |
api_base | no | https://devices.myq-cloud.com | Override for the per-device REST host. Only change if Chamberlain migrates your account to a new region. |
accounts_base | no | https://accounts.myq-cloud.com | Override for the account-discovery host used during /api/v6.0/My. |
brand_id | no | myQ | Value sent in the MyQApplicationId and x-MyQ-Brand headers. LiftMaster commercial accounts may need a different brand string. |
status_interval | no | 30000 ms | Cloud poll cadence. The cloud throttles below ~15 seconds — leave this at 30 s unless you can tolerate 429s during status checks. |
request_timeout | no | 15000 ms | Per-request HTTP timeout. |
Zone address format
Each zone's address is the serial_number printed on the opener motor (and returned by the get_devices command). Format is alphanumeric, typically 12 characters; some older devices use a longer hex string. Copy it verbatim — character matching is case-sensitive on the wire.
zone.address = "CG0812345678"
One zone per opener. A single GEM chamberlain_myq device row can drive every opener on the account; you only need a second device row if you want to separate accounts.
Commands
| Command | Args | What it does |
|---|---|---|
open | address | Issues PUT /actions {"action_type":"open"} against the serial number. Fire-and-forget on the cloud side; the driver re-polls after 6 s to surface the resulting state. |
close | address | Same as open with action_type: "close". |
get_status | address | Returns the device record for the given serial number from the last poll. If nothing is cached yet (e.g. immediately after a reload, before the first poll lands), it fetches once from the cloud. Use get_devices to force a full-account refresh. |
get_devices | — | Returns the full account device list including serial_number, name, device_family, and the per-device state block. |
A command whose address is blank, an unfilled template token such as [@zone.address], . / .., or not a plain string is refused inside GEM and never reaches the cloud. open and close send the serial number exactly as given; get_status ignores surrounding spaces when it looks the serial up. An open or close the cloud answers with anything other than a 2xx status, or with an HTML page (a captive portal or proxy login), is returned as an error rather than as success.
Once the zones exist, operate the door from the zone's control (or gem.command({zone_id: <zone_id>, command: 'open'})) instead of passing a serial by hand — GEM fills the address argument from the zone's address automatically. Supply address yourself only when you command the device directly without a zone.
Door-state mapping
The MyQ cloud reports door state as a string. The driver normalises it onto the GEM zone state:
| MyQ raw | GEM state |
|---|---|
open | open |
closed | closed |
opening, closing, transition | moving |
stopped | stopped |
autoreverse | open (treated as not-closed for safety) |
Any other value, including unknown, writes nothing: the zone keeps its last known state rather than showing a position the cloud did not report.
The driver also writes online_state (online / offline) onto the zone when the cloud reports it — useful for macros that need to skip the open command when the opener is unreachable.
Connection state and retries
- The device shows connected once the cloud answers with a 2xx status, and disconnected when it answers
401(the token was refused) or cannot be reached at all. Other errors, such as429rate limiting or a5xxoutage, leave the connection state as it was. - If the cloud cannot be reached, or answers with an error, while the device is connecting, the driver tries again after 30 seconds, doubling the wait each time up to 5 minutes. It keeps trying until it succeeds, so a cloud outage at boot clears by itself without a reload. These retries only read the account and its device list; they never send a door command.
- After three failed status polls in a row, the poll interval doubles on each further failure, up to 5 minutes (or
status_interval, if that is longer). The first good poll restores the normal interval. While the polls keep failing, the warning is logged once and then summarised instead of repeating on every poll. status_intervalandrequest_timeoutaccept plain numbers of milliseconds. An unreadablestatus_intervalfalls back to 30000 ms; one below 15000 ms is raised to 15000 ms. An unreadable, zero or negativerequest_timeoutfalls back to 15000 ms.openandcloseare never retried or resent by the driver.
Known limitations
- No push channel. MyQ does not expose a third-party WebSocket. Manual operation at the wall button is visible only after the next poll — latency is bounded by
status_interval. - Cloud throughput. A handful of zones polling at 30 s each is comfortably under the cloud's rate limit; dozens of openers on one account may need the interval bumped to 60 s.
- No camera support. MyQ Smart Cameras are out of scope. This driver only handles door openers.
- No lamp / scene support. Some LiftMaster models drive an attached light; that endpoint is not yet wired into the driver.
Troubleshooting
| Symptom | Where to look |
|---|---|
Every request returns 401 unauthorized | Token expired or the upstream client_id rotated. Re-run pymyq --token-only and paste the new token. Verify the host clock is correct — tokens are time-bounded. |
get_devices returns an empty list | The token is for an account with no openers paired, or the explicit account_id points at the wrong account. Clear account_id and reconnect to force fresh discovery. |
open / close returns success but the door does not move | The opener is offline at the cloud. The gateway LED should be steady blue; if it is blinking, power-cycle the bridge and confirm it re-registers in the mobile app. The driver cannot distinguish a "queued but undelivered" command from a successful one. |
| Zone state never updates after a manual press of the wall button | Confirm the mobile app shows live state — if the cloud sees it, the driver will too on the next poll. Dropping status_interval to 15000 ms gets quicker reflection at the cost of more 429s. |
get_devices returns the door list but state is missing | Newer openers occasionally drop the state block when the gateway is briefly offline. Wait one more poll cycle; the next response should include state. |
Related
meross_garage— second-source garage opener using Meross hardware (LAN-direct).genie_aladdin_connect— Genie's cloud equivalent for Aladdin Connect openers.