What's New in v8.10.0
🚀 Minor Release: Passkey Pairing, Per-Device Webhooks, Newsletter Message History & Media Download Fix
This release adds phone-initiated passkey device pairing, per-device webhook URL overrides with global fallback, a REST endpoint to fetch newsletter (WhatsApp channel) message history, and a broad MCP tool expansion for media sends and message manipulation. It also fixes incoming media downloads that failed with "no url present", makes device logout disconnect the session without deleting the device slot, and stops POST /send/file from panicking on non-multipart requests.
✨ New Features
Passkey Pairing Support (#754)
- Adds
GET /app/passkeyto poll a pending WebAuthn challenge or pairing code and its status (none/awaiting_response/awaiting_confirmation) - Adds
POST /app/passkey/responseto submit the signed WebAuthn assertion, andPOST /app/passkey/confirmto confirm the pairing code when the phone's 5-minute handoff window has lapsed - Broadcasts
PASSKEY_REQUEST/PASSKEY_CONFIRMATION/PASSKEY_ERRORover the existing websocket, with minimal web UI toasts - Pending passkey state is stored per device and cleared on pair success, logout, error, or fresh login; the QR login loop no longer logs passkey channel events as errors
Per-Device Webhook URLs (#671)
- Adds
PATCH /devices/{device_id}/webhookandGET /devices/{device_id}/webhookso each device can override the global webhook URL, falling back toWHATSAPP_WEBHOOKwhen unset - Closes gaps found in review: label appstate events now forward correctly on a device-only webhook, a device-webhook lookup failure falls back to global instead of aborting delivery, and
POST /devicesnow acceptswebhook_secret,webhook_events, andwebhook_insecure_skip_verify(previously silently dropped)
Newsletter Message History (#749)
- Adds
GET /newsletter/messages?newsletter_id=...&count=...&before=..., backed by whatsmeow'sGetNewsletterMessages, returningserver_id,message_id,type,timestamp,views_count,reaction_counts, and extractedtext countdefaults to 50 (max 100);beforepages backward by server message id- Rejects non-newsletter JIDs up front with a clear validation error instead of failing deep inside a WhatsApp protocol round-trip
Expanded MCP Send & Message Tools (#722)
- Adds MCP send tools for video, document, audio, and polls
- Adds message-manipulation tools: react, edit, revoke, delete, mark-as-read, and star/unstar, with destructive-hint annotations on revoke/delete
- Send handlers migrated to
mcp-go's typed request helpers (RequireString/GetBool/GetInt/GetStringSlice), matching the existing query tool conventions
🐛 Bug Fixes
Incoming Media Downloads Failing with "no url present" (#722)
- whatsmeow's
Client.Downloadreads onlyDirectPath, never the storedURL, so every reconstructed media message failed to download even though a URL was on file - Derives
DirectPathfrom the already-stored URL at download time (utils.DeriveDirectPath) for both the REST/MCP download path and Chatwoot media sync — no migration or backfill needed, previously-received media is downloadable immediately - Also fixes dropped incoming location messages: adds
FormatLocationSummaryand location/live-location handling to message-text extraction, plus a caption-less extended-text fallback
Device Logout No Longer Deletes the Device Slot (#728)
POST /devices/{id}/logout,GET /app/logout, and a remote unlink from the phone now disconnect the session and clear keys while keeping the device listed, so it can be re-paired under the same id- Deleting a slot entirely is now exclusively
DELETE /devices/{id}, which performs a full purge (logout + WhatsApp unlink + registry removal) instead of leaving orphaned rows - Chat history is preserved on logout and only cleared on delete, matching WhatsApp Web's own behavior; a new
DEVICE_LOGGED_OUTwebsocket event keeps the current UI selection
Non-Multipart POST /send/file Panic (#748)
SendFileunconditionally panicked when no multipart file part was present, unlike the siblingSendImage/SendVideo/SendAudio/SendStickerhandlers, which all guard the lookup- This made the existing
file_urlJSON-body path unreachable dead code; a non-multipart request now falls through to usecase-level validation instead of a 500
Chatwoot Contact Creation on Newsletter JIDs
- WhatsApp channel (
@newsletter) JIDs carry an 18-digit channel id rather than a phone number, so relaying one to Chatwoot failed contact creation with a 422 e164 error - Adds a shared
utils.IsNewsletterJIDguard to both the live webhook-forward path and the history importer
Broadcast Messages Leaking to Webhooks with Chatwoot Enabled
status@broadcastmessages were only skipped from webhook forwarding when Chatwoot was disabled, so enabling Chatwoot let broadcast/status noise reach plain webhook consumers- Broadcast/status messages are now skipped unconditionally;
SetDeviceWebhookConfigalso now returnssql.ErrNoRowsinstead of silently no-oping when the target device doesn't exist
🔧 Technical Improvements
Dependency Updates
go.mau.fi/whatsmeow: refreshed tov0.0.0-20260630180629-b572e5bcb92bgithub.com/vektah/gqlparser/v2: updated tov2.5.36
Documentation
- OpenAPI spec adds the public health endpoint and marks reserved device-login routes as deprecated
- Documents per-device webhook configuration and new label-related webhook events; refreshed README defaults and event list
Release Metadata
AppVersionis nowv8.10.0, so runtime status matches the published release tag
What's Changed
- fix: don't panic on non-multipart POST /send/file requests by @aldinokemal in #748
- feat(newsletter): add endpoint to get latest newsletter messages by @aldinokemal in #749
- fix(media): download incoming media via derived directPath by @nazhiba in #722
- fix(device): logout should disconnect session, not delete device entry by @huboperacional in #728
- feat(app): add passkey pairing support by @aldinokemal in #754
- feat: add per-device webhook support by @mohamedhabibwork in #671
- fix(webhook): skip broadcast messages and return no rows for missing devices by @aldinokemal
- test(utils): cover location summary and extended-text fallback from #722 by @aldinokemal
- refactor(mcp): migrate send handlers to mcp-go request helpers by @aldinokemal
- fix(webhook): close per-device webhook gaps from #671 review by @aldinokemal
- fix(chatwoot): skip @newsletter JIDs before contact creation by @aldinokemal
- docs: update API and webhook documentation by @aldinokemal
- chore: update whatsmeow to latest by @aldinokemal
- chore: bump version to v8.10.0 by @aldinokemal
New Contributors
- @nazhiba made their first contribution in #722
- @huboperacional made their first contribution in #728
- @mohamedhabibwork made their first contribution in #671
Full Changelog: v8.9.0...v8.10.0