@moltflow/skills 2.0.0 → 2.1.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
package/CHANGELOG.md CHANGED
@@ -4,6 +4,26 @@ All notable changes to the **MoltFlow Skills** package are documented here.
4
4
 
5
5
  ---
6
6
 
7
+ ## [2.1.0] - 2026-02-12 — "Import & Delete"
8
+
9
+ > Import contacts from WhatsApp groups, delete your account with full cascade, and GDPR scripts for everything.
10
+
11
+ ### Added
12
+
13
+ - **WhatsApp Group Import** — `GET /custom-groups/wa-groups` lists all WA groups across sessions; `POST /custom-groups/from-wa-groups` creates a custom group by resolving and deduplicating participants from selected WA groups
14
+ - **Account Deletion** — `DELETE /users/me` with password confirmation cascades through 32+ tables (GDPR Article 17)
15
+ - `outreach.py` — added `list_wa_groups()` and `create_group_from_wa_groups()` functions
16
+ - `gdpr.py` — added `delete_account(password)` function
17
+ - Scripts table — added `gdpr.py` and `group_monitor.py` to main SKILL.md documentation
18
+ - moltflow-outreach sub-skill — documented WA group import endpoints and examples
19
+
20
+ ### Changed
21
+
22
+ - Custom Groups endpoint table expanded from 10 to 12 endpoints (both main SKILL.md and moltflow-outreach)
23
+ - Version bumped to 2.1.0 across package.json, main SKILL.md, and moltflow-outreach
24
+
25
+ ---
26
+
7
27
  ## [2.0.0] - 2026-02-12 — "The Full Platform"
8
28
 
9
29
  > Every feature, every endpoint, every workflow — v2 is the complete MoltFlow experience.
package/SKILL.md CHANGED
@@ -1,14 +1,15 @@
1
1
  ---
2
- name: "WhatsApp Automation & A2A"
3
- version: "2.0.0"
4
- description: "MoltFlow — complete WhatsApp automation platform: bulk messaging, scheduled messages, custom groups, lead detection & CRM, AI replies with style cloning, knowledge base (RAG), voice transcription, group monitoring, labels, anti-spam, content safeguards, review collection, webhooks, GDPR compliance, and agent-to-agent protocol (JSON-RPC, encryption). 90+ API endpoints."
2
+ name: "MoltFlow — WhatsApp AI Automation Platform and More"
3
+ version: "2.1.0"
4
+ description: "MoltFlow — complete WhatsApp automation platform: bulk messaging, scheduled messages, custom groups, lead detection & CRM, AI replies with style cloning, knowledge base (RAG), voice transcription, group monitoring, labels, anti-spam, content safeguards, review collection, webhooks, GDPR compliance (data export, contact erasure, account deletion), and agent-to-agent protocol (JSON-RPC, encryption). 90+ API endpoints."
5
5
  source: "MoltFlow Team"
6
6
  risk: safe
7
+ homepage: "https://molt.waiflow.app"
7
8
  requiredEnv:
8
9
  - MOLTFLOW_API_KEY
9
10
  primaryEnv: MOLTFLOW_API_KEY
10
- disableModelInvocation: true
11
- metadata: {"openclaw":{"emoji":"📱","homepage":"https://waiflow.app","requires":{"env":["MOLTFLOW_API_KEY"]},"primaryEnv":"MOLTFLOW_API_KEY"}}
11
+ disable-model-invocation: true
12
+ metadata: {"openclaw":{"emoji":"📱","homepage":"https://molt.waiflow.app","requires":{"env":["MOLTFLOW_API_KEY"]},"primaryEnv":"MOLTFLOW_API_KEY"}}
12
13
  ---
13
14
 
14
15
  # WhatsApp Automation & A2A
@@ -24,7 +25,7 @@ MoltFlow is a complete WhatsApp automation platform with 90+ API endpoints cover
24
25
  | **Messaging** | Send text, media, polls, stickers, GIFs, voice notes, locations, vCards. Reply, react, edit, unsend. Read receipts & typing simulation. |
25
26
  | **Bulk Messaging** | Broadcast to custom groups with ban-safe throttling (random 30s–2min delays). Real-time progress via SSE. Pause/resume/cancel. |
26
27
  | **Scheduled Messages** | One-time, daily, weekly, monthly, or custom cron. Timezone-aware. Pause, resume, edit. Execution history tracking. |
27
- | **Custom Groups** | Build targeted contact lists. Import from WhatsApp groups or add manually. Feed into Bulk Send or Scheduled Messages. CSV/JSON export. |
28
+ | **Custom Groups** | Build targeted contact lists. Import members from WhatsApp groups or add manually. Feed into Bulk Send or Scheduled Messages. CSV/JSON export. |
28
29
  | **Lead Detection & CRM** | Auto-detect purchase intent in monitored groups. Lead pipeline with status tracking (new → contacted → qualified → converted). Bulk status update, bulk add-to-group, CSV/JSON export. Reciprocity check (anti-spam). |
29
30
  | **Group Monitoring** | Monitor 50+ groups simultaneously. Keyword/mention detection. Auto-respond with AI. Per-group prompts. Skip admins & existing contacts. |
30
31
  | **Labels** | Create, sync to WhatsApp Business, import from WhatsApp. Color-coded contact organization. |
@@ -37,7 +38,7 @@ MoltFlow is a complete WhatsApp automation platform with 90+ API endpoints cover
37
38
  | **Content Safeguards** | Block API keys, credit cards, SSNs, PII, prompt injection. Custom regex rules. Test content against full policy stack. |
38
39
  | **Webhooks** | 10+ event types (message.received, lead.detected, session.connected, etc.). HMAC-SHA256 signed. Delivery history. Test payloads. |
39
40
  | **A2A Protocol** | JSON-RPC 2.0 agent-to-agent communication. X25519-AES256GCM encryption. Agent discovery, trust levels, encrypted messaging. |
40
- | **GDPR Compliance** | Auto-expiring messages (90-day). Data minimization (500-char preview). Contact erasure. Data export. AI consent enforcement. DPA available. Named sub-processors (Art. 28). |
41
+ | **GDPR Compliance** | Auto-expiring messages (90-day). Data minimization (500-char preview). Contact erasure. Data export. Account deletion (32+ table cascade). AI consent enforcement. DPA available. Named sub-processors (Art. 28). |
41
42
  | **Billing & Usage** | Stripe-powered. Free/Starter/Pro/Business plans. Usage tracking, daily breakdown. Billing portal. **Yearly plans save up to 17%.** |
42
43
 
43
44
  ## When to use
@@ -121,6 +122,8 @@ Env vars:
121
122
  - `MOLTFLOW_API_KEY` (required) — API key from waiflow.app dashboard
122
123
  - `MOLTFLOW_API_URL` (optional) — defaults to `https://apiv2.waiflow.app`
123
124
 
125
+ **Security note:** Use the principle of least privilege. If you only need messaging and monitoring features, create a non-admin API key. Admin-level keys grant access to tenant management, user operations, and GDPR erasure endpoints. Only supply an admin key if you explicitly need those capabilities.
126
+
124
127
  Authentication: `X-API-Key: $MOLTFLOW_API_KEY` header or `Authorization: Bearer $TOKEN` (JWT from login).
125
128
 
126
129
  Base URL: `https://apiv2.waiflow.app/api/v2`
@@ -780,6 +783,16 @@ curl -X POST -H "X-API-Key: $MOLTFLOW_API_KEY" \
780
783
  # Export as CSV
781
784
  curl -H "X-API-Key: $MOLTFLOW_API_KEY" \
782
785
  https://apiv2.waiflow.app/api/v2/custom-groups/{group_id}/export/csv
786
+
787
+ # List WhatsApp groups available for import
788
+ curl -H "X-API-Key: $MOLTFLOW_API_KEY" \
789
+ https://apiv2.waiflow.app/api/v2/custom-groups/wa-groups
790
+
791
+ # Create group by importing members from WhatsApp groups
792
+ curl -X POST -H "X-API-Key: $MOLTFLOW_API_KEY" \
793
+ -H "Content-Type: application/json" \
794
+ -d '{"name": "Imported Leads", "wa_groups": [{"wa_group_id": "123@g.us", "session_id": "session-uuid"}]}' \
795
+ https://apiv2.waiflow.app/api/v2/custom-groups/from-wa-groups
783
796
  ```
784
797
 
785
798
  | Endpoint | Method | Description |
@@ -787,6 +800,8 @@ curl -H "X-API-Key: $MOLTFLOW_API_KEY" \
787
800
  | `/custom-groups` | GET | List all custom groups |
788
801
  | `/custom-groups` | POST | Create group (with optional initial members) |
789
802
  | `/custom-groups/contacts` | GET | List all unique contacts across sessions |
803
+ | `/custom-groups/wa-groups` | GET | List WhatsApp groups for import |
804
+ | `/custom-groups/from-wa-groups` | POST | Create group by importing WA group members |
790
805
  | `/custom-groups/{id}` | GET | Group details with members |
791
806
  | `/custom-groups/{id}` | PATCH | Update group name |
792
807
  | `/custom-groups/{id}` | DELETE | Delete group and members |
@@ -1067,6 +1082,8 @@ The `scripts/` directory contains standalone Python examples (requires `requests
1067
1082
  | `reviews.py` | Create collectors, export testimonials |
1068
1083
  | `outreach.py` | Bulk send, scheduled messages, custom groups |
1069
1084
  | `leads.py` | Lead pipeline, bulk ops, CSV/JSON export |
1085
+ | `gdpr.py` | Contact erasure, data export, account deletion |
1086
+ | `group_monitor.py` | WhatsApp group monitoring & lead detection |
1070
1087
 
1071
1088
  Run any script: `MOLTFLOW_API_KEY=your-key python scripts/quickstart.py`
1072
1089
 
package/moltflow/SKILL.md CHANGED
@@ -7,7 +7,7 @@ risk: safe
7
7
  requiredEnv:
8
8
  - MOLTFLOW_API_KEY
9
9
  primaryEnv: MOLTFLOW_API_KEY
10
- disableModelInvocation: true
10
+ disable-model-invocation: true
11
11
  ---
12
12
 
13
13
  > **MoltFlow** -- WhatsApp Business automation for teams. Connect, monitor, and automate WhatsApp at scale.
@@ -7,7 +7,7 @@ risk: safe
7
7
  requiredEnv:
8
8
  - MOLTFLOW_API_KEY
9
9
  primaryEnv: MOLTFLOW_API_KEY
10
- disableModelInvocation: true
10
+ disable-model-invocation: true
11
11
  ---
12
12
 
13
13
  > **MoltFlow** -- WhatsApp Business automation for teams. Connect, monitor, and automate WhatsApp at scale.
@@ -7,7 +7,7 @@ risk: safe
7
7
  requiredEnv:
8
8
  - MOLTFLOW_API_KEY
9
9
  primaryEnv: MOLTFLOW_API_KEY
10
- disableModelInvocation: true
10
+ disable-model-invocation: true
11
11
  ---
12
12
 
13
13
  > **MoltFlow** — WhatsApp Business automation for teams. Connect, monitor, and automate WhatsApp at scale.
@@ -7,7 +7,7 @@ risk: safe
7
7
  requiredEnv:
8
8
  - MOLTFLOW_API_KEY
9
9
  primaryEnv: MOLTFLOW_API_KEY
10
- disableModelInvocation: true
10
+ disable-model-invocation: true
11
11
  ---
12
12
 
13
13
  > **MoltFlow** -- WhatsApp Business automation for teams. Connect, monitor, and automate WhatsApp at scale.
@@ -7,7 +7,7 @@ risk: safe
7
7
  requiredEnv:
8
8
  - MOLTFLOW_API_KEY
9
9
  primaryEnv: MOLTFLOW_API_KEY
10
- disableModelInvocation: true
10
+ disable-model-invocation: true
11
11
  ---
12
12
 
13
13
  > **MoltFlow** -- WhatsApp Business automation for teams. Connect, monitor, and automate WhatsApp at scale.
@@ -2,12 +2,12 @@
2
2
  name: moltflow-outreach
3
3
  description: "Bulk messaging, scheduled messages, and custom groups for WhatsApp outreach. Use when: bulk send, broadcast, schedule message, cron, custom group, contact list, ban-safe messaging."
4
4
  source: "MoltFlow Team"
5
- version: "2.0.0"
5
+ version: "2.1.0"
6
6
  risk: safe
7
7
  requiredEnv:
8
8
  - MOLTFLOW_API_KEY
9
9
  primaryEnv: MOLTFLOW_API_KEY
10
- disableModelInvocation: true
10
+ disable-model-invocation: true
11
11
  ---
12
12
 
13
13
  > **MoltFlow** -- WhatsApp Business automation for teams. Connect, monitor, and automate WhatsApp at scale.
@@ -57,6 +57,8 @@ Build targeted contact lists for Bulk Send and Scheduled Messages. Custom Groups
57
57
  | GET | `/custom-groups` | List all custom groups |
58
58
  | POST | `/custom-groups` | Create group (with optional initial members) |
59
59
  | GET | `/custom-groups/contacts` | List all unique contacts across sessions |
60
+ | GET | `/custom-groups/wa-groups` | List WhatsApp groups for import |
61
+ | POST | `/custom-groups/from-wa-groups` | Create group by importing WA group members |
60
62
  | GET | `/custom-groups/{id}` | Group details with members |
61
63
  | PATCH | `/custom-groups/{id}` | Update group name |
62
64
  | DELETE | `/custom-groups/{id}` | Delete group and members |
@@ -81,6 +83,28 @@ Build targeted contact lists for Bulk Send and Scheduled Messages. Custom Groups
81
83
 
82
84
  Members is an array of objects with `phone` (required) and `name` (optional). Omit `members` to create an empty group.
83
85
 
86
+ ### Create Group from WhatsApp Groups
87
+
88
+ **POST** `/custom-groups/from-wa-groups`
89
+
90
+ ```json
91
+ {
92
+ "name": "Imported Leads",
93
+ "wa_groups": [
94
+ {"wa_group_id": "120363012345@g.us", "session_id": "session-uuid-..."},
95
+ {"wa_group_id": "120363067890@g.us", "session_id": "session-uuid-..."}
96
+ ]
97
+ }
98
+ ```
99
+
100
+ Resolves participants from each WhatsApp group, deduplicates by phone number, and creates the custom group with all unique members.
101
+
102
+ ### List WhatsApp Groups
103
+
104
+ **GET** `/custom-groups/wa-groups`
105
+
106
+ Returns all WhatsApp groups across your connected sessions with participant counts. Use this to discover groups available for import.
107
+
84
108
  **Response** `201 Created`:
85
109
 
86
110
  ```json
@@ -7,7 +7,7 @@ risk: safe
7
7
  requiredEnv:
8
8
  - MOLTFLOW_API_KEY
9
9
  primaryEnv: MOLTFLOW_API_KEY
10
- disableModelInvocation: true
10
+ disable-model-invocation: true
11
11
  ---
12
12
 
13
13
  > **MoltFlow** — WhatsApp Business automation for teams. Connect, monitor, and automate WhatsApp at scale.
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@moltflow/skills",
3
- "version": "2.0.0",
3
+ "version": "2.1.0",
4
4
  "description": "MoltFlow — complete WhatsApp automation platform: bulk messaging, scheduled messages, custom groups, lead detection & CRM, AI replies with style cloning, knowledge base (RAG), voice transcription, group monitoring, labels, anti-spam, content safeguards, review collection, webhooks, GDPR compliance, and agent-to-agent protocol. 90+ API endpoints.",
5
5
  "license": "MIT",
6
6
  "private": false,
@@ -0,0 +1,81 @@
1
+ #!/usr/bin/env python3
2
+ """
3
+ MoltFlow GDPR - Contact Erasure & Data Export
4
+ """
5
+ import os
6
+ import json
7
+ import requests
8
+
9
+ API_KEY = os.environ.get("MOLTFLOW_API_KEY")
10
+ BASE_URL = os.environ.get("MOLTFLOW_API_URL", "https://apiv2.waiflow.app")
11
+
12
+ if not API_KEY:
13
+ print("Error: MOLTFLOW_API_KEY environment variable not set")
14
+ exit(1)
15
+
16
+ headers = {"X-API-Key": API_KEY, "Content-Type": "application/json"}
17
+
18
+
19
+ def erase_contact(phone: str, reason: str = "gdpr_request"):
20
+ """Erase all data for a contact phone number (GDPR Article 17).
21
+
22
+ Deletes messages, reviews, anonymizes chats and group memberships.
23
+ phone: e.g. "972501234567" or "972501234567@c.us"
24
+ """
25
+ r = requests.post(
26
+ f"{BASE_URL}/api/v2/gdpr/contact-erasure",
27
+ headers=headers,
28
+ json={"phone": phone, "reason": reason},
29
+ )
30
+ r.raise_for_status()
31
+ return r.json()
32
+
33
+
34
+ def export_my_data():
35
+ """Export all account data as JSON (GDPR Article 20 - Data Portability).
36
+
37
+ Returns profile, sessions, chats, messages, groups, labels, webhooks, etc.
38
+ """
39
+ r = requests.get(f"{BASE_URL}/api/v2/users/me/export", headers=headers)
40
+ r.raise_for_status()
41
+ return r.json()
42
+
43
+
44
+ def save_export(filepath: str = None):
45
+ """Export account data and save to a JSON file."""
46
+ data = export_my_data()
47
+ if not filepath:
48
+ from datetime import datetime
49
+ filepath = f"moltflow-data-export-{datetime.utcnow().strftime('%Y%m%d')}.json"
50
+ with open(filepath, "w", encoding="utf-8") as f:
51
+ json.dump(data, f, indent=2, ensure_ascii=False)
52
+ return filepath
53
+
54
+
55
+ def delete_account(password: str):
56
+ """Delete your account and all associated data (GDPR Article 17).
57
+
58
+ Requires password confirmation. Permanently removes all tenant-scoped
59
+ data (32+ tables) including sessions, messages, groups, labels, etc.
60
+ """
61
+ r = requests.delete(
62
+ f"{BASE_URL}/api/v2/users/me",
63
+ headers=headers,
64
+ json={"current_password": password},
65
+ )
66
+ r.raise_for_status()
67
+ return {"status": "deleted"}
68
+
69
+
70
+ if __name__ == "__main__":
71
+ print("MoltFlow GDPR Tools")
72
+ print("=" * 40)
73
+ print("\nAvailable operations:")
74
+ print(" erase_contact(phone, reason) - Erase all data for a contact")
75
+ print(" export_my_data() - Export all account data as JSON")
76
+ print(" save_export(filepath) - Export and save to file")
77
+ print(" delete_account(password) - Delete account and all data")
78
+ print("\nExample:")
79
+ print(' from gdpr import erase_contact')
80
+ print(' result = erase_contact("972501234567")')
81
+ print(f" print(result)")
@@ -0,0 +1,123 @@
1
+ #!/usr/bin/env python3
2
+ """
3
+ MoltFlow Group Monitor - WhatsApp Group Monitoring & Lead Detection
4
+ """
5
+ import os
6
+ import requests
7
+
8
+ API_KEY = os.environ.get("MOLTFLOW_API_KEY")
9
+ BASE_URL = os.environ.get("MOLTFLOW_API_URL", "https://apiv2.waiflow.app")
10
+
11
+ if not API_KEY:
12
+ print("Error: MOLTFLOW_API_KEY environment variable not set")
13
+ exit(1)
14
+
15
+ headers = {"X-API-Key": API_KEY, "Content-Type": "application/json"}
16
+
17
+
18
+ def list_monitored_groups():
19
+ """List all monitored WhatsApp groups."""
20
+ r = requests.get(f"{BASE_URL}/api/v2/groups", headers=headers)
21
+ r.raise_for_status()
22
+ return r.json()
23
+
24
+
25
+ def list_available_groups(session_id: str):
26
+ """List available WhatsApp groups for a session (not yet monitored)."""
27
+ r = requests.get(
28
+ f"{BASE_URL}/api/v2/groups/available/{session_id}",
29
+ headers=headers,
30
+ )
31
+ r.raise_for_status()
32
+ return r.json()
33
+
34
+
35
+ def add_monitored_group(
36
+ session_id: str,
37
+ wa_group_id: str,
38
+ name: str = None,
39
+ monitor_mode: str = "first_message",
40
+ monitor_keywords: list = None,
41
+ monitor_prompt: str = None,
42
+ auto_respond: bool = False,
43
+ response_template: str = None,
44
+ auto_label_leads: bool = False,
45
+ lead_label_id: str = None,
46
+ webhook_url: str = None,
47
+ ):
48
+ """Add a WhatsApp group to monitoring.
49
+
50
+ monitor_mode: first_message, keyword, ai_prompt
51
+ monitor_keywords: list of keyword strings (for keyword mode)
52
+ monitor_prompt: AI prompt (for ai_prompt mode)
53
+ auto_respond: send automatic response to detected leads
54
+ auto_label_leads: auto-apply a label to detected leads
55
+ """
56
+ data = {
57
+ "session_id": session_id,
58
+ "wa_group_id": wa_group_id,
59
+ "monitor_mode": monitor_mode,
60
+ "auto_respond": auto_respond,
61
+ "auto_label_leads": auto_label_leads,
62
+ }
63
+ if name:
64
+ data["name"] = name
65
+ if monitor_keywords:
66
+ data["monitor_keywords"] = monitor_keywords
67
+ if monitor_prompt:
68
+ data["monitor_prompt"] = monitor_prompt
69
+ if response_template:
70
+ data["response_template"] = response_template
71
+ if lead_label_id:
72
+ data["lead_label_id"] = lead_label_id
73
+ if webhook_url:
74
+ data["webhook_url"] = webhook_url
75
+ r = requests.post(f"{BASE_URL}/api/v2/groups", headers=headers, json=data)
76
+ r.raise_for_status()
77
+ return r.json()
78
+
79
+
80
+ def get_monitored_group(group_id: str):
81
+ """Get monitored group details."""
82
+ r = requests.get(f"{BASE_URL}/api/v2/groups/{group_id}", headers=headers)
83
+ r.raise_for_status()
84
+ return r.json()
85
+
86
+
87
+ def update_monitored_group(group_id: str, **kwargs):
88
+ """Update monitoring settings.
89
+
90
+ Accepts: name, monitor_mode, monitor_keywords, monitor_prompt,
91
+ auto_respond, response_template, auto_label_leads,
92
+ lead_label_id, webhook_url, is_active
93
+ """
94
+ r = requests.patch(
95
+ f"{BASE_URL}/api/v2/groups/{group_id}",
96
+ headers=headers,
97
+ json={k: v for k, v in kwargs.items() if v is not None},
98
+ )
99
+ r.raise_for_status()
100
+ return r.json()
101
+
102
+
103
+ def delete_monitored_group(group_id: str):
104
+ """Stop monitoring a group and remove it."""
105
+ r = requests.delete(f"{BASE_URL}/api/v2/groups/{group_id}", headers=headers)
106
+ r.raise_for_status()
107
+ return r.json()
108
+
109
+
110
+ if __name__ == "__main__":
111
+ print("MoltFlow Group Monitor")
112
+ print("=" * 40)
113
+
114
+ data = list_monitored_groups()
115
+ groups = data.get("items", [])
116
+ print(f"\nMonitored Groups: {data.get('total', len(groups))}")
117
+
118
+ for g in groups:
119
+ status = "active" if g.get("is_active") else "paused"
120
+ mode = g.get("monitor_mode", "unknown")
121
+ leads = g.get("leads_detected", 0)
122
+ msgs = g.get("messages_processed", 0)
123
+ print(f" - {g['name']} [{status}] mode={mode} leads={leads} msgs={msgs}")
@@ -62,6 +62,71 @@ def export_group_csv(group_id: str):
62
62
  return r.text
63
63
 
64
64
 
65
+ def get_custom_group(group_id: str):
66
+ """Get custom group details."""
67
+ r = requests.get(f"{BASE_URL}/api/v2/custom-groups/{group_id}", headers=headers)
68
+ r.raise_for_status()
69
+ return r.json()
70
+
71
+
72
+ def update_custom_group(group_id: str, name: str):
73
+ """Update custom group name."""
74
+ r = requests.patch(
75
+ f"{BASE_URL}/api/v2/custom-groups/{group_id}",
76
+ headers=headers,
77
+ json={"name": name},
78
+ )
79
+ r.raise_for_status()
80
+ return r.json()
81
+
82
+
83
+ def delete_custom_group(group_id: str):
84
+ """Delete a custom group."""
85
+ r = requests.delete(f"{BASE_URL}/api/v2/custom-groups/{group_id}", headers=headers)
86
+ r.raise_for_status()
87
+ return r.json()
88
+
89
+
90
+ def remove_members(group_id: str, member_ids: list):
91
+ """Remove members from a custom group. member_ids = list of member UUID strings."""
92
+ r = requests.post(
93
+ f"{BASE_URL}/api/v2/custom-groups/{group_id}/members/remove",
94
+ headers=headers,
95
+ json={"member_ids": member_ids},
96
+ )
97
+ r.raise_for_status()
98
+ return r.json()
99
+
100
+
101
+ def list_contacts():
102
+ """List all available contacts for group building."""
103
+ r = requests.get(f"{BASE_URL}/api/v2/custom-groups/contacts", headers=headers)
104
+ r.raise_for_status()
105
+ return r.json()
106
+
107
+
108
+ def list_wa_groups():
109
+ """List WhatsApp groups across all working sessions (for import into custom groups)."""
110
+ r = requests.get(f"{BASE_URL}/api/v2/custom-groups/wa-groups", headers=headers)
111
+ r.raise_for_status()
112
+ return r.json()
113
+
114
+
115
+ def create_group_from_wa_groups(name: str, wa_groups: list):
116
+ """Create a custom group by importing members from WhatsApp groups.
117
+
118
+ wa_groups: list of {"wa_group_id": str, "session_id": str} dicts.
119
+ Members are resolved from each WA group's participant list and deduplicated.
120
+ """
121
+ r = requests.post(
122
+ f"{BASE_URL}/api/v2/custom-groups/from-wa-groups",
123
+ headers=headers,
124
+ json={"name": name, "wa_groups": wa_groups},
125
+ )
126
+ r.raise_for_status()
127
+ return r.json()
128
+
129
+
65
130
  def export_group_json(group_id: str):
66
131
  """Export group members as JSON."""
67
132
  r = requests.get(
@@ -130,6 +195,13 @@ def cancel_bulk_job(job_id: str):
130
195
  return r.json()
131
196
 
132
197
 
198
+ def get_bulk_progress(job_id: str):
199
+ """Get real-time progress of a bulk send job."""
200
+ r = requests.get(f"{BASE_URL}/api/v2/bulk-send/{job_id}/progress", headers=headers)
201
+ r.raise_for_status()
202
+ return r.json()
203
+
204
+
133
205
  # ============================================================================
134
206
  # Scheduled Messages
135
207
  # ============================================================================
@@ -208,6 +280,38 @@ def cancel_scheduled(message_id: str):
208
280
  return r.json()
209
281
 
210
282
 
283
+ def get_scheduled_message(message_id: str):
284
+ """Get scheduled message details."""
285
+ r = requests.get(f"{BASE_URL}/api/v2/scheduled-messages/{message_id}", headers=headers)
286
+ r.raise_for_status()
287
+ return r.json()
288
+
289
+
290
+ def update_scheduled_message(message_id: str, **kwargs):
291
+ """Update a scheduled message. Accepts: name, message_content, scheduled_time, cron_expression, timezone."""
292
+ r = requests.patch(
293
+ f"{BASE_URL}/api/v2/scheduled-messages/{message_id}",
294
+ headers=headers,
295
+ json={k: v for k, v in kwargs.items() if v is not None},
296
+ )
297
+ r.raise_for_status()
298
+ return r.json()
299
+
300
+
301
+ def delete_scheduled(message_id: str):
302
+ """Delete a scheduled message."""
303
+ r = requests.delete(f"{BASE_URL}/api/v2/scheduled-messages/{message_id}", headers=headers)
304
+ r.raise_for_status()
305
+ return r.json()
306
+
307
+
308
+ def get_scheduled_history(message_id: str):
309
+ """Get execution history for a scheduled message."""
310
+ r = requests.get(f"{BASE_URL}/api/v2/scheduled-messages/{message_id}/history", headers=headers)
311
+ r.raise_for_status()
312
+ return r.json()
313
+
314
+
211
315
  if __name__ == "__main__":
212
316
  print("MoltFlow Outreach")
213
317
  print("=" * 40)