Two useful integration patterns
- MQTT: a local, asynchronous publish/subscribe bus. Great for device state and commands.
- Webhook: an HTTP request pushed to a URL. Great for an event crossing systems such as a form submission, n8n workflow, or external API.
Neither is “better.” Use MQTT for continuous local state/event streams; use webhooks for explicit cross-system requests.
MQTT vocabulary
| Term | Meaning |
|---|---|
| Broker | Server that routes messages |
| Topic | Hierarchical address, e.g. home/coop/door/state |
| Publisher | Sends a message |
| Subscriber | Receives matching messages |
| Payload | Message body, often JSON |
| Retained message | Broker remembers last value for new subscribers |
| QoS | Delivery assurance level |
| LWT | Last Will and Testament availability message |
Topic design
Use predictable nouns and state/action separation:
home/coop/door/state
home/coop/door/command
home/coop/door/availability
home/water-feature/pump/state
Avoid vague or versionless topics such as data or status2. Plan the schema so another system can understand it without reverse-engineering firmware.
Retained state and commands
Retain current state, not one-time commands. A retained .../command can cause a device to repeat an old action after reconnecting.
// state payload
{"state":"open","updated_at":"2026-07-16T10:00:00Z"}
Home Assistant MQTT discovery
HA can create entities from discovery messages. Use it when devices are genuinely dynamic or custom, but document the discovery prefix, unique IDs, and availability topics. For a small fixed integration, an explicit HA configuration can be easier to reason about.
Secure MQTT baseline
[ ] Authentication enabled; one credential per integration where practical
[ ] TLS for untrusted networks/remote paths
[ ] ACLs limit publish/subscribe scope
[ ] Broker not exposed directly to public internet
[ ] Availability/LWT configured for devices
[ ] Secrets stored outside source control
Webhook design
A webhook receiver must assume incoming data is malformed, duplicated, delayed, or malicious until proven otherwise.
Authenticate → validate schema → deduplicate event ID → process → record outcome → respond
Example payload shape
{
"event_id": "evt_123",
"event_type": "lead.created",
"occurred_at": "2026-07-16T10:00:00Z",
"data": {"source": "website"}
}
Use a stable event_id to make retries idempotent: processing the same event twice should not send two emails or create duplicate leads.
n8n + Home Assistant boundary
Use webhooks for n8n workflows that receive a defined event. Validate a secret/header and restrict the endpoint. Keep physical actions behind HA and give n8n a monitored, approval-gated role unless the automation is low-risk and well-tested.
Debugging checklist
MQTT:
[ ] Broker reachable and authenticated?
[ ] Correct topic spelling/case?
[ ] Publisher actually sending?
[ ] Subscriber has expected wildcard/filter?
[ ] Retained state appropriate?
[ ] JSON valid and schema expected?
[ ] LWT/availability correct?
Webhooks:
[ ] URL and method correct?
[ ] Auth/signature valid?
[ ] Payload valid and complete?
[ ] Event duplicate handled?
[ ] Receiver logs response/error safely?
[ ] Downstream action visible and reversible?
Design rule
Messages are contracts. Document topic/payload shapes and failure behaviour as carefully as you document an API. That is what keeps small automations from becoming an untraceable tangle.