DocHub
REST endpoints for library CRUD, send, and the dual-approach purge algorithm

API Endpoints

All endpoints are mounted at /api/library.

CRUD Endpoints

Method Route Description
GET /api/library List all photos (id, filename, thumbnail_name, md5_hash, caption, created_at, file_size_bytes, width, height)
POST /api/library/upload Upload photo (multipart, field: photo). Computes MD5, checks for duplicate, generates thumbnail
POST /api/library/save-from-message Save from conversation. Body: { chatId, messageId }. Downloads media from WhatsApp message
GET /api/library/:id/file Serve full-size photo
GET /api/library/:id/thumb Serve thumbnail
PATCH /api/library/:id Update caption. Body: { caption }
DELETE /api/library/:id Delete photo, thumbnail, and DB record

Send Endpoint

Method Route Description
POST /api/library/:id/send Send photo to chat. Body: { chatId, caption? }

Send flow:

  1. Load photo record from DB
  2. Read file from disk
  3. Create MessageMedia from file path
  4. Call client.sendMessage(chatId, media) via whatsapp-web.js
  5. Record in photo_library_sends: library_photo_id, message_wa_id, chat_wa_id
  6. Return the sent message ID

Purge System

The purge removes a photo from every conversation it was sent to, using “delete for me” (recipients keep their copy).

Purge Preview

Method Route Description
POST /api/library/:id/purge-preview Dry run — returns affected chats and message counts

Returns: { chats: [{ chatId, messageCount }], totalMessages }

Purge Execution

Method Route Description
POST /api/library/:id/purge Delete from all conversations

Dual-Approach Algorithm

The purge uses two methods to find all instances:

  1. Tracked sends — query photo_library_sends for all messages sent from this library photo
  2. Hash scan fallback — query media_files table for matching md5_hash to catch photos saved before the library existed or sent manually

For each found message:

  1. Load the WhatsApp message via client.getMessageById(msg_wa_id)
  2. Call msg.delete(false) — “delete for me” (does NOT delete for recipient)
  3. Delete from messages table in DB
  4. Delete from media_files table if present
  5. Clean up photo_library_sends records

Returns: { deletedMessages, failedMessages, affectedChats }

Frontend Integration

PhotoLibraryPage (/library)

  • Responsive grid of photo thumbnails
  • Click photo → full-size lightbox viewer
  • Per-photo actions: Download, Send, Purge, Delete
  • Upload button with drag-and-drop support
  • Toast notifications for all operations

Send Modal (within PhotoLibraryPage)

  • Search-enabled contact picker
  • Shows contact avatars and names from the chat list
  • Sends via libraryAPI.send(photoId, chatId)

Purge Flow (within PhotoLibraryPage)

  1. Click Purge → calls purge-preview
  2. Modal shows affected chats and message counts
  3. Confirm → calls purge endpoint
  4. Result toast: “Deleted X messages from Y chats”

LibraryPickerModal (from MessageComposer)

  • Triggered by Library icon button in the message composer
  • 4-column thumbnail grid
  • Click to select → sends to current chat