6.5 WhatsAppSavedReplyController
Route: api/v{version:apiVersion}/whatsapp/saved-replies · Class attributes: [Authorize] ·
9 endpoints — reusable canned-response text, personal or shared across the tenant's agents.
Note: WhatsAppSavedReply uses bilingual Title/FTitle fields — an intentional exception to the
platform's usual Name/FName convention (see .claude/rules/database.md in Shumoul.Saas.Api).
GET GetSavedReplies
Purpose: list saved replies visible to the current user. Permission: WhatsAppInbox.SavedReplies.View
Request (query): ?search=refund&includePersonal=true&includeShared=true
Response data: [{ "id": "s1...", "title": "رد الاسترجاع", "fTitle": "Refund Reply", "body": "تم استرجاع مبلغكم...", "shortcut": "/refund", "category": "Billing", "isShared": true, "isActive": true, "createdByUserId": "..." }]
Backend: WhatsAppSavedReplyService.GetSavedRepliesAsync. Calls Meta API: No.
Angular/Flutter: the composer's /-shortcut autocomplete and a saved-replies picker panel.
GET GetDetails/{id}
Purpose: full detail view. Permission: WhatsAppInbox.SavedReplies.View
Response (Result<WhatsAppSavedReplyDetailsDto>): adds createdByUserName, lastModifiedByUserName,
lastModifiedOn to the fields above. Backend: WhatsAppSavedReplyService.GetSavedReplyDetailsAsync.
Calls Meta API: No.
GET GetEdit/{id}
Purpose: load a saved reply into an edit form. Permission: WhatsAppInbox.SavedReplies.Edit
Response (Result<WhatsAppSavedReplyEditDto>): { "id": "s1...", "title": "...", "fTitle": "...", "body": "...", "shortcut": "/refund", "category": "Billing", "isShared": true, "isActive": true }
Backend: WhatsAppSavedReplyService.GetSavedReplyForEditAsync (AutoMapper Map<EditDto>). Calls Meta API: No.
POST Create
Purpose: create a saved reply. Permission: WhatsAppInbox.SavedReplies.Create
Request (WhatsAppSavedReplyEditDto): same shape as GetEdit's response, without Id.
Response: Result<Guid>. Backend: WhatsAppSavedReplyService.CreateSavedReplyAsync. Calls Meta API: No.
PUT Update/{id}
Purpose: update a saved reply. Permission: WhatsAppInbox.SavedReplies.Edit
Request: same shape, Id set. Response: Result<Guid>.
Backend: WhatsAppSavedReplyService.UpdateSavedReplyAsync. Calls Meta API: No.
DELETE Delete/{id}
Purpose: soft-delete. Permission: WhatsAppInbox.SavedReplies.Delete · Response: Result<Guid>.
Backend: WhatsAppSavedReplyService.DeleteSavedReplyAsync. Calls Meta API: No.
PUT Restore/{id}
Purpose: restore a soft-deleted saved reply. Permission: WhatsAppInbox.SavedReplies.Delete
Response: Result<Guid>. Backend: WhatsAppSavedReplyService.RestoreSavedReplyAsync. Calls Meta API: No.
PUT Activate/{id} · PUT Deactivate/{id}
Purpose: toggle IsActive. Permission: WhatsAppInbox.SavedReplies.Edit · Response: Result<Guid>.
Backend: WhatsAppSavedReplyService.ChangeStatusAsync(id, true|false). Calls Meta API: No.
Angular/Flutter: an inactive saved reply is hidden from the composer's autocomplete but still visible in
the management list.
