Skip to content

v8.10.0

Latest

Choose a tag to compare

@aldinokemal aldinokemal released this 03 Jul 01:27

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/passkey to poll a pending WebAuthn challenge or pairing code and its status (none / awaiting_response / awaiting_confirmation)
  • Adds POST /app/passkey/response to submit the signed WebAuthn assertion, and POST /app/passkey/confirm to confirm the pairing code when the phone's 5-minute handoff window has lapsed
  • Broadcasts PASSKEY_REQUEST / PASSKEY_CONFIRMATION / PASSKEY_ERROR over 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}/webhook and GET /devices/{device_id}/webhook so each device can override the global webhook URL, falling back to WHATSAPP_WEBHOOK when 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 /devices now accepts webhook_secret, webhook_events, and webhook_insecure_skip_verify (previously silently dropped)

Newsletter Message History (#749)

  • Adds GET /newsletter/messages?newsletter_id=...&count=...&before=..., backed by whatsmeow's GetNewsletterMessages, returning server_id, message_id, type, timestamp, views_count, reaction_counts, and extracted text
  • count defaults to 50 (max 100); before pages 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.Download reads only DirectPath, never the stored URL, so every reconstructed media message failed to download even though a URL was on file
  • Derives DirectPath from 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 FormatLocationSummary and 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_OUT websocket event keeps the current UI selection

Non-Multipart POST /send/file Panic (#748)

  • SendFile unconditionally panicked when no multipart file part was present, unlike the sibling SendImage/SendVideo/SendAudio/SendSticker handlers, which all guard the lookup
  • This made the existing file_url JSON-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.IsNewsletterJID guard to both the live webhook-forward path and the history importer

Broadcast Messages Leaking to Webhooks with Chatwoot Enabled

  • status@broadcast messages 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; SetDeviceWebhookConfig also now returns sql.ErrNoRows instead of silently no-oping when the target device doesn't exist

🔧 Technical Improvements

Dependency Updates

  • go.mau.fi/whatsmeow: refreshed to v0.0.0-20260630180629-b572e5bcb92b
  • github.com/vektah/gqlparser/v2: updated to v2.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

  • AppVersion is now v8.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

Full Changelog: v8.9.0...v8.10.0