Groups

Manage group membership and admin roles from the dashboard — and how the resulting groupId connects to POST /api/v1/messages/send for group replies.

PrivacyFlow supports group conversations across Signal, SimpleX, and Session. Group lifecycle (create, member add/remove, promote/demote admins, invite-link) happens in the dashboard’s ManageGroupModal. Group messaging (replies that land in the same thread) happens via the public API’s POST /api/v1/messages/send with a groupId field. This page is the dashboard side; see send for the API side.

Open the Manage Group modal

  1. Sign in to the dashboard.
  2. Open Apps → choose the app whose group you want to manage.
  3. Open Manage Group (either from the app’s row action or from inside the app’s settings).
  4. The modal opens with per-messenger tabs (Signal / SimpleX / Session, depending on what the app is connected to).

Warning

Screenshot placeholder — ManageGroupModal showing a messenger tab strip, a members list with role badges, and a “Copy invite link” button.

Per-messenger tabs

Each messenger has its own group model. The modal presents them as tabs so you don’t confuse a SimpleX group id with a Signal group id — they’re different identifiers and only the active tab’s group is in scope for the actions you take.

Member operations

From the members list:

ActionWhere
Add memberAdds a contactId to the group. The recipient must already be a PrivacyFlow contact (i.e., they’ve initiated a conversation with your app).
Remove memberRemoves a contactId from the group.
Promote to adminElevates an existing member.
Demote adminRemoves admin privileges from a member.

Each operation maps to a backend call:

OperationBackend path
List membersGET /dashboard/group/members
Add memberPOST /dashboard/group/members/add
Remove memberPOST /dashboard/group/members/remove
Promote adminPOST /dashboard/group/promote-admin
Demote adminPOST /dashboard/group/demote-admin

All go through the dashboard’s BFF proxy — see automation overview. The browser session cookie becomes an X-Session-Token header on the outbound call.

Each group has an invite link you can copy and share. Clicking Copy Invite Link in the modal copies the link to your clipboard; the recipient clicks it (or scans the SimpleX/Session QR for those messengers) and joins the group.

ActionBackend path
Get invite linkGET /dashboard/group/invite-link

The link is messenger-specific — a Signal invite link won’t work on SimpleX.

How this connects to the API

Once the group exists and has members, messaging happens through the public API, not the dashboard. The connection between the two is the groupId.

When a member messages the group, PrivacyFlow routes the inbound to your poll queue with isGroupMessage: true and a groupId field. Your client — the MCP server, Agent Zero channel, or n8n node — sees the groupId and should pass it back unchanged on send:

{
  "messages": [
    {
      "appId": "app_123",
      "contactId": "<sender's contactId>",
      "messenger": "session",
      "message": "Got it — assigning an agent.",
      "groupId": "group_abc123"
    }
  ]
}

Without the groupId (or with the wrong one) the reply goes as a DM to the sender, not to the group thread. Each client surfaces this:

  • n8n node warns about it in the trigger UI.
  • Agent Zero channel propagates groupId automatically through pf_routing.
  • MCP server expects the LLM to lift groupId from the polled JSON and include it on send.

Tip

Group creation and member management are operator actions, not user-facing. End users message the group the same way they’d message any Signal/SimpleX/Session group; PrivacyFlow handles the plumbing. You only need the ManageGroupModal when you’re standing up a new group or rotating admins.

Underlying API calls

UI actionAPI route
Open ManageGroupModal → loads member listGET /dashboard/api/dashboard/group/members?appMessengerId=<id>
”Copy invite link” buttonGET /dashboard/api/dashboard/group/invite-link?appMessengerId=<id>
Add member → SavePOST /dashboard/api/dashboard/group/members/add with { appMessengerId, contactId }
Remove memberPOST /dashboard/api/dashboard/group/members/remove with { appMessengerId, contactId }
Promote to adminPOST /dashboard/api/dashboard/group/promote-admin with { appMessengerId, contactId }
Demote adminPOST /dashboard/api/dashboard/group/demote-admin with { appMessengerId, contactId }

appMessengerId is the join-record id for the specific (app × messenger) group you’re managing — get it from the app object or the modal’s open context. See the account API reference for the full route surface.

Last updated: