What's New in v9.4.0
🔄 On-Demand Chat History, Per-Device Webhook Fan-Out & Status Media Control
Version 9.4.0 lets you pull older chat history from the phone on demand, allows a device's own webhook to add to the global targets instead of replacing them, and adds a switch to skip status media downloads. History sync naming, device purge, webhook delivery, and route ordering all get reliability fixes, and whatsmeow is updated to the latest revision.
✨ Features
On-Demand Chat History (#834)
- Adds
POST /chat/{chat_jid}/historyto request older messages from the phone, anchored at the oldest message currently stored locally for that chat - Accepts a
countof older messages to request and returns the requested count, with percent-encoded chat JIDs accepted on the path - Documents the endpoint in OpenAPI and rejects requests for a chat with no stored message to anchor on
Per-Device Webhooks Can Add to the Global Targets (#842)
- Adds
--webhook-device-merge-global/WHATSAPP_WEBHOOK_DEVICE_MERGE_GLOBALso a device with its own webhook also delivers its events to the global--webhookURLs - Leaves the default unchanged: a per-device webhook still replaces the global ones
- Documents the flag in the README,
.env.example, and the webhook payload reference
Ignore Status Media Downloads (#836)
- Adds
--ignore-status-media/WHATSAPP_IGNORE_STATUS_MEDIAto skip downloading media attached to status broadcasts - Keeps status events flowing while avoiding the storage and bandwidth cost of their media
🐛 Bug Fixes
History Sync Chat Naming (#845)
- Names 1:1 chats from the contact store instead of the history-sync
DisplayName - Keeps
DisplayNamefor group and newsletter chats, where it is the authoritative title - Preserves the disappearing-messages timer when a chat is refreshed by an on-demand sync
Device Purge and Path Decoding (#843)
- Percent-decodes the
:device_idpath parameter so clients can safely sendencodeURIComponentvalues - Resolves purge targets verbatim instead of trimming, so distinct slots are never confused, and keeps the registry entry when local cleanup fails so
DELETEcan be retried - Skips the keep-slot callback on a purge-triggered logout, purges both the registry id and the paired JID partition when they differ, and broadcasts
DEVICE_REMOVEDwith the refreshed device list - Surfaces shared-JID lookup failures instead of silently continuing when companion slots share one number
Chatwoot Config Routes and Device Route Order (#837)
- Registers the Chatwoot config routes before the header-based device group so
DeviceMiddlewareno longer intercepts them - Keeps the device group as the last registration on the API group —
Group("")installs a root handler matching every path — and pins the order with a regression test - Hardens the status-media guard to match on the JID's shape, so a device-qualified status JID is still recognised
Slow Device Webhook No Longer Starves the Global Leg
- Runs the device and global webhook legs concurrently so one slow endpoint burning its retry backoff cannot leave the global leg a dead context
- Dedupes a global URL against the device URLs only when the device leg will actually deliver, so an event rejected by the device's own filter still reaches the global subscription
🔧 Technical Improvements
Dependency & Documentation Updates
- Updates whatsmeow to the latest revision
- Streamlines the AGENTS documentation across chatstorage, chatwoot, whatsapp, ui, usecase, and validations
What's Changed
- chore: update whatsmeow to latest by @aldinokemal
- refactor: streamline AGENTS documentation and improve clarity across multiple sections by @aldinokemal
- fix(history-sync): name 1:1 chats from the contact store, not DisplayName (#845) by @arivelli
- fix(device): make DELETE purge reliable and decode path device_id (#843) by @hanlest
- feat(webhook): let a per-device webhook add to the global targets instead of replacing them (#842) by @Kizuno18
- fix(device): compare purge slot id verbatim and surface shared-JID lookup failures by @aldinokemal
- fix(webhook): stop a slow device webhook starving the global leg by @aldinokemal
- fix(history-sync): keep DisplayName for group and newsletter chats by @aldinokemal
- fix(rest): register chatwoot config routes before DeviceMiddleware (#837) by @aguinaldotupy
- feat: add flag to ignore downloading status media (#836) by @danihidayatx
- feat(chat): add on-demand history sync endpoint (#834) by @Kizuno18
- fix(history-sync): keep the disappearing-messages timer on on-demand sync by @aldinokemal
- fix(rest): keep the device group last, and harden the status-media guard by @aldinokemal
- feat: update SKILL by @aldinokemal
- chore(release): v9.4.0 by @aldinokemal
Contributors
Full Changelog: v9.3.1...v9.4.0