A Home Assistant custom integration for wwebjs-api, designed for multiple WhatsApp sender sessions.
Warning
wwebjs-api uses an unofficial WhatsApp Web client. Use it at your own risk; WhatsApp may restrict or block accounts using unofficial clients.
- Home Assistant UI configuration
- Multiple WWebJS sessions / senders
- Phone-number pairing codes
- Plain text messages
- Images, video, audio and document media from HTTP(S) URLs or local files
- Send media directly from Home Assistant
camera.*andimage.*entities notify.wwebjs_<session>services with dynamic recipients- Send a WhatsApp location from a
person.*ordevice_tracker.*entity - Session health monitoring
- Start, stop and restart buttons for each sender session
- Automatic recovery with authentication-aware suspension and escalating retry backoff
- Persisted outbound message history diagnostics
- Message lifecycle/cleanup support is implemented, but deletion is currently blocked by an upstream
whatsapp-web.jsmessage-ID regression (see below)
- Open HACS in Home Assistant.
- Add
https://github.com/ricobach/HA-WWebJSas a custom repository of type Integration. - Install WWebJS.
- Restart Home Assistant.
- Go to Settings → Devices & services → Add integration and search for WWebJS.
action: wwebjs.send_message
data:
session: rico
target: "+4512345678"
message: "Hello from Home Assistant"Each configured sender session also registers a notify service using the same session name.
For a session named rico:
action: notify.wwebjs_rico
data:
target: "+4512345678"
message: "Hello from the Rico sender"Multiple recipients can be supplied as a list:
action: notify.wwebjs_rico
data:
target:
- "+4511111111"
- "+4522222222"
message: "The alarm is armed"Local Home Assistant file:
action: wwebjs.send_message
data:
session: rico
target: "+4512345678"
message: "Someone is at the front door"
image: "/config/www/snapshots/frontdoor.jpg"URL:
action: wwebjs.send_message
data:
session: rico
target: "+4512345678"
message: "Camera snapshot"
media: "https://example.com/snapshot.jpg"The message becomes the media caption.
WWebJS can request the current image directly from a Home Assistant camera.* or image.* entity and send it without first writing a snapshot file.
action: wwebjs.send_message
data:
session: rico
target: "+4512345678"
message: "Front door camera"
media_entity: camera.front_doorAn image entity works the same way:
action: wwebjs.send_message
data:
session: rico
target: "+4512345678"
message: "Latest generated image"
media_entity: image.latest_snapshotThe same option can be used through a session notify service:
action: notify.wwebjs_rico
data:
target: "+4512345678"
message: "Front door camera"
data:
media_entity: camera.front_doorA person.* or device_tracker.* entity that exposes latitude and longitude can be sent as a native WhatsApp location.
action: wwebjs.send_location
data:
session: rico
target: "+4512345678"
location_entity: person.ricoAn optional label can be supplied:
action: wwebjs.send_location
data:
session: rico
target: "+4512345678"
location_entity: device_tracker.phone
description: "Current phone location"Each configured sender gets Home Assistant controls for:
- Start
- Restart
- Stop
The session device also exposes:
- Session status
- Recovery count
- Message history
Health checks run every 60 seconds. Automatic recovery starts after three consecutive transient failures. Retry delays increase from 1 minute to 5, 15 and then 30 minutes to avoid restart loops.
Authentication, pairing, blocked-account/proxy and deprecated-client states suspend automatic recovery instead of repeatedly restarting a session that needs user or upstream action. Pressing Start or Restart resumes recovery. Pressing Stop intentionally suspends automatic recovery for that running Home Assistant instance.
If the API server itself is unreachable, WWebJS reports API_UNAVAILABLE and does not repeatedly restart sessions.
Each session has a Message history diagnostic sensor. It stores a small persisted ring buffer of recent outbound attempts, including:
- Timestamp
- Recipient
- Message type (
text,media,entity_media, orlocation) - Sent/failed state
- Short message/caption preview
- Source Home Assistant entity when applicable
- Error details for failed sends
The sensor state reflects the latest send result and its recent attribute contains the latest history entries.
Important
Message deletion/cleanup does not currently work with the normal upstream wwebjs-api / whatsapp-web.js combination.
The lifecycle options are implemented in this Home Assistant integration, but current whatsapp-web.js builds are affected by a WhatsApp Web change where the serialized message-ID property moved from _serialized to $1. As a result, wwebjs-api can successfully send a message while returning only { "success": true } without the message object/ID that deletion and other /message/* operations require.
Upstream whatsapp-web.js PR #201832 addresses this regression, including the sendMessage empty-result problem. Until an upstream fix is merged and included in the version used by wwebjs-api, treat the cleanup options below as not operational.
The intended cleanup interface is documented below so automations can be prepared for when upstream message IDs are reliable again.
Always revoke after 10 minutes:
action: wwebjs.send_message
data:
session: rico
target: "+4512345678"
message: "Front door opened"
delete_after: 600Revoke after five minutes only if WWebJS does not report that it was read:
action: wwebjs.send_message
data:
session: rico
target: "+4512345678"
message: "Motion at the front door"
image: "/config/www/snapshots/frontdoor.jpg"
delete_if_unread_after: 300Keep only the newest notification for a logical event:
action: wwebjs.send_message
data:
session: rico
target: "+4512345678"
message: "Latest front-door state"
cleanup_key: "front_door"
delete_after: 900When the upstream message-ID issue is resolved, a newer message with the same session, recipient and cleanup_key will allow older tracked messages to be revoked.
delete_for_everyone defaults to true. WhatsApp ultimately decides whether a message can still be revoked for all participants.
Unread cleanup depends on two upstream capabilities: a reliable message ID from the send operation and /message/getInfo read-receipt data. At the moment, the message-ID regression described above prevents lifecycle cleanup from being scheduled reliably. Once message IDs are available again, read information from WhatsApp Web may still vary by version; if read information cannot be obtained, WWebJS keeps the tracked message and retries instead of deleting it blindly.
MIT