@cakemail-org/cakemail-cli 1.5.0 → 2.0.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.
Files changed (234) hide show
  1. package/.claude/settings.local.json +12 -0
  2. package/.env.example +40 -0
  3. package/.env.test.example +45 -0
  4. package/CHANGELOG.md +1031 -0
  5. package/README.md +319 -15
  6. package/audit-formats.js +128 -0
  7. package/cakemail.rb +20 -0
  8. package/dist/cli.js +27 -10
  9. package/dist/cli.js.map +1 -1
  10. package/dist/client.d.ts +2 -0
  11. package/dist/client.d.ts.map +1 -1
  12. package/dist/client.js +16 -6
  13. package/dist/client.js.map +1 -1
  14. package/dist/commands/account.js +1 -1
  15. package/dist/commands/account.js.map +1 -1
  16. package/dist/commands/attributes.js +1 -1
  17. package/dist/commands/attributes.js.map +1 -1
  18. package/dist/commands/campaigns.d.ts.map +1 -1
  19. package/dist/commands/campaigns.js +103 -8
  20. package/dist/commands/campaigns.js.map +1 -1
  21. package/dist/commands/config.d.ts.map +1 -1
  22. package/dist/commands/config.js +63 -4
  23. package/dist/commands/config.js.map +1 -1
  24. package/dist/commands/contacts.d.ts.map +1 -1
  25. package/dist/commands/contacts.js +91 -12
  26. package/dist/commands/contacts.js.map +1 -1
  27. package/dist/commands/emails.js +1 -1
  28. package/dist/commands/emails.js.map +1 -1
  29. package/dist/commands/interests.d.ts +5 -0
  30. package/dist/commands/interests.d.ts.map +1 -0
  31. package/dist/commands/interests.js +172 -0
  32. package/dist/commands/interests.js.map +1 -0
  33. package/dist/commands/lists.d.ts.map +1 -1
  34. package/dist/commands/lists.js +6 -8
  35. package/dist/commands/lists.js.map +1 -1
  36. package/dist/commands/logs.d.ts +5 -0
  37. package/dist/commands/logs.d.ts.map +1 -0
  38. package/dist/commands/logs.js +237 -0
  39. package/dist/commands/logs.js.map +1 -0
  40. package/dist/commands/reports.js +1 -1
  41. package/dist/commands/reports.js.map +1 -1
  42. package/dist/commands/segments.js +1 -1
  43. package/dist/commands/segments.js.map +1 -1
  44. package/dist/commands/senders.d.ts.map +1 -1
  45. package/dist/commands/senders.js +11 -8
  46. package/dist/commands/senders.js.map +1 -1
  47. package/dist/commands/suppressed.js +1 -1
  48. package/dist/commands/suppressed.js.map +1 -1
  49. package/dist/commands/tags.d.ts +5 -0
  50. package/dist/commands/tags.d.ts.map +1 -0
  51. package/dist/commands/tags.js +124 -0
  52. package/dist/commands/tags.js.map +1 -0
  53. package/dist/commands/templates.js +1 -1
  54. package/dist/commands/templates.js.map +1 -1
  55. package/dist/commands/transactional-templates.d.ts +5 -0
  56. package/dist/commands/transactional-templates.d.ts.map +1 -0
  57. package/dist/commands/transactional-templates.js +354 -0
  58. package/dist/commands/transactional-templates.js.map +1 -0
  59. package/dist/commands/webhooks.js +1 -1
  60. package/dist/commands/webhooks.js.map +1 -1
  61. package/dist/utils/auth.d.ts +8 -1
  62. package/dist/utils/auth.d.ts.map +1 -1
  63. package/dist/utils/auth.js +39 -11
  64. package/dist/utils/auth.js.map +1 -1
  65. package/dist/utils/config-file.d.ts +7 -0
  66. package/dist/utils/config-file.d.ts.map +1 -1
  67. package/dist/utils/config-file.js +15 -0
  68. package/dist/utils/config-file.js.map +1 -1
  69. package/dist/utils/config.d.ts +2 -0
  70. package/dist/utils/config.d.ts.map +1 -1
  71. package/dist/utils/config.js +12 -4
  72. package/dist/utils/config.js.map +1 -1
  73. package/dist/utils/errors.js +1 -1
  74. package/dist/utils/errors.js.map +1 -1
  75. package/dist/utils/list-defaults.d.ts +33 -0
  76. package/dist/utils/list-defaults.d.ts.map +1 -0
  77. package/dist/utils/list-defaults.js +52 -0
  78. package/dist/utils/list-defaults.js.map +1 -0
  79. package/dist/utils/output.d.ts.map +1 -1
  80. package/dist/utils/output.js +36 -13
  81. package/dist/utils/output.js.map +1 -1
  82. package/dist/utils/progress.d.ts.map +1 -1
  83. package/dist/utils/progress.js +32 -4
  84. package/dist/utils/progress.js.map +1 -1
  85. package/dist/utils/spinner.d.ts +17 -0
  86. package/dist/utils/spinner.d.ts.map +1 -0
  87. package/dist/utils/spinner.js +43 -0
  88. package/dist/utils/spinner.js.map +1 -0
  89. package/docs/DOCUMENTATION-STANDARD.md +1068 -0
  90. package/docs/README.md +161 -0
  91. package/docs/developer/ARCHITECTURE.md +516 -0
  92. package/docs/developer/AUTH.md +204 -0
  93. package/docs/developer/CONTRIBUTING.md +227 -0
  94. package/docs/developer/DOCUMENTATION_SUMMARY.md +346 -0
  95. package/docs/developer/PROJECT_INDEX.md +365 -0
  96. package/docs/planning/API_COVERAGE.md +1045 -0
  97. package/docs/planning/BACKLOG.md +1159 -0
  98. package/docs/planning/PROFILE_SYSTEM_TASKS.md +287 -0
  99. package/docs/planning/UX_IMPLEMENTATION_PLAN.md +691 -0
  100. package/docs/planning/archive/RELEASE_CHECKLIST_v1.3.0.md +332 -0
  101. package/docs/planning/archive/RELEASE_v1.3.0.md +428 -0
  102. package/docs/planning/archive/cakemail-cli-ux-improvements.md +438 -0
  103. package/docs/planning/cakemail-profile-system-plan.md +1121 -0
  104. package/docs/testing/AI_USER_SIMULATION_DESIGN.md +1342 -0
  105. package/docs/testing/KENOGAMI_BIDIRECTIONAL_FLOW.md +1517 -0
  106. package/docs/testing/KENOGAMI_TRUTH_RECONCILIATION_SYSTEM.md +1369 -0
  107. package/docs/user-manual/.obsidian/app.json +1 -0
  108. package/docs/user-manual/.obsidian/appearance.json +1 -0
  109. package/docs/user-manual/.obsidian/core-plugins.json +33 -0
  110. package/docs/user-manual/.obsidian/workspace.json +167 -0
  111. package/docs/user-manual/01-getting-started/01-installation.md +214 -0
  112. package/docs/user-manual/01-getting-started/02-quick-start.md +432 -0
  113. package/docs/user-manual/01-getting-started/03-authentication.md +448 -0
  114. package/docs/user-manual/01-getting-started/04-configuration.md +430 -0
  115. package/docs/user-manual/01-getting-started/05-output-formats.md +447 -0
  116. package/docs/user-manual/02-core-concepts/01-accounts.md +514 -0
  117. package/docs/user-manual/02-core-concepts/02-profile-system.md +771 -0
  118. package/docs/user-manual/02-core-concepts/03-smart-defaults.md +485 -0
  119. package/docs/user-manual/02-core-concepts/04-authentication-methods.md +435 -0
  120. package/docs/user-manual/02-core-concepts/05-pagination-filtering.md +600 -0
  121. package/docs/user-manual/02-core-concepts/06-error-handling.md +718 -0
  122. package/docs/user-manual/02-core-concepts/07-api-coverage.md +483 -0
  123. package/docs/user-manual/03-email-operations/01-senders.md +490 -0
  124. package/docs/user-manual/03-email-operations/02-templates.md +444 -0
  125. package/docs/user-manual/03-email-operations/03-transactional-emails.md +706 -0
  126. package/docs/user-manual/03-email-operations/04-email-tracking.md +407 -0
  127. package/docs/user-manual/04-campaign-management/01-campaigns-basics.md +394 -0
  128. package/docs/user-manual/04-campaign-management/02-campaign-scheduling.md +630 -0
  129. package/docs/user-manual/04-campaign-management/03-campaign-testing.md +997 -0
  130. package/docs/user-manual/04-campaign-management/04-campaign-lifecycle.md +709 -0
  131. package/docs/user-manual/04-campaign-management/05-campaign-links.md +934 -0
  132. package/docs/user-manual/05-contact-management/01-lists.md +836 -0
  133. package/docs/user-manual/05-contact-management/02-contacts.md +1035 -0
  134. package/docs/user-manual/05-contact-management/03-custom-attributes.md +788 -0
  135. package/docs/user-manual/05-contact-management/04-segments.md +1028 -0
  136. package/docs/user-manual/05-contact-management/05-contact-import-export.md +1031 -0
  137. package/docs/user-manual/06-analytics-reporting/01-campaign-analytics.md +867 -0
  138. package/docs/user-manual/06-analytics-reporting/02-account-reports.md +227 -0
  139. package/docs/user-manual/07-integrations/01-webhooks-integration.md +259 -0
  140. package/docs/user-manual/07-integrations/02-automation.md +326 -0
  141. package/docs/user-manual/08-advanced-usage/01-scripting-patterns.md +672 -0
  142. package/docs/user-manual/08-advanced-usage/02-bulk-operations.md +932 -0
  143. package/docs/user-manual/08-advanced-usage/03-ci-cd-integration.md +892 -0
  144. package/docs/user-manual/08-advanced-usage/04-performance-optimization.md +766 -0
  145. package/docs/user-manual/09-command-reference/01-config.md +776 -0
  146. package/docs/user-manual/09-command-reference/02-account.md +652 -0
  147. package/docs/user-manual/09-command-reference/03-lists.md +958 -0
  148. package/docs/user-manual/09-command-reference/04-contacts.md +1408 -0
  149. package/docs/user-manual/09-command-reference/05-attributes.md +617 -0
  150. package/docs/user-manual/09-command-reference/06-segments.md +894 -0
  151. package/docs/user-manual/09-command-reference/07-senders.md +803 -0
  152. package/docs/user-manual/09-command-reference/08-templates.md +818 -0
  153. package/docs/user-manual/09-command-reference/09-campaigns.md +1250 -0
  154. package/docs/user-manual/09-command-reference/10-emails.md +807 -0
  155. package/docs/user-manual/09-command-reference/11-reports.md +1135 -0
  156. package/docs/user-manual/09-command-reference/12-webhooks.md +773 -0
  157. package/docs/user-manual/09-command-reference/13-suppressed.md +797 -0
  158. package/docs/user-manual/09-command-reference/14-interests.md +630 -0
  159. package/docs/user-manual/09-command-reference/15-tags.md +584 -0
  160. package/docs/user-manual/09-command-reference/16-logs.md +656 -0
  161. package/docs/user-manual/09-command-reference/17-transactional-templates.md +850 -0
  162. package/docs/user-manual/10-troubleshooting/01-common-errors.md +457 -0
  163. package/docs/user-manual/10-troubleshooting/02-authentication-issues.md +558 -0
  164. package/docs/user-manual/10-troubleshooting/03-connection-problems.md +634 -0
  165. package/docs/user-manual/10-troubleshooting/04-debugging.md +725 -0
  166. package/docs/user-manual/11-appendix/04-faq.md +484 -0
  167. package/docs/user-manual/11-appendix/05-glossary.md +250 -0
  168. package/docs/user-manual/README.md +0 -0
  169. package/package.json +13 -47
  170. package/src/cli.ts +125 -0
  171. package/src/client.ts +16 -0
  172. package/src/commands/account.ts +267 -0
  173. package/src/commands/accounts.ts +78 -0
  174. package/src/commands/actions.ts +249 -0
  175. package/src/commands/attributes.ts +139 -0
  176. package/src/commands/campaign-blueprints.ts +106 -0
  177. package/src/commands/campaigns.ts +469 -0
  178. package/src/commands/config.ts +77 -0
  179. package/src/commands/contacts.ts +612 -0
  180. package/src/commands/custom-attributes.ts +127 -0
  181. package/src/commands/dkims.ts +117 -0
  182. package/src/commands/domains.ts +82 -0
  183. package/src/commands/email-apis.ts +569 -0
  184. package/src/commands/emails.ts +197 -0
  185. package/src/commands/forms.ts +283 -0
  186. package/src/commands/interests.ts +155 -0
  187. package/src/commands/links.ts +38 -0
  188. package/src/commands/lists.ts +406 -0
  189. package/src/commands/logos.ts +71 -0
  190. package/src/commands/logs.ts +386 -0
  191. package/src/commands/reports.ts +306 -0
  192. package/src/commands/segments.ts +158 -0
  193. package/src/commands/senders.ts +204 -0
  194. package/src/commands/sub-accounts.ts +271 -0
  195. package/src/commands/suppressed-emails.ts +234 -0
  196. package/src/commands/suppressed.ts +198 -0
  197. package/src/commands/system-emails.ts +85 -0
  198. package/src/commands/tags.ts +146 -0
  199. package/src/commands/tasks.ts +116 -0
  200. package/src/commands/templates.ts +189 -0
  201. package/src/commands/tokens.ts +83 -0
  202. package/src/commands/transactional-emails.ts +374 -0
  203. package/src/commands/transactional-templates.ts +385 -0
  204. package/src/commands/users.ts +506 -0
  205. package/src/commands/webhooks.ts +172 -0
  206. package/src/commands/workflow-blueprints.ts +123 -0
  207. package/src/commands/workflows.ts +265 -0
  208. package/src/types/profile.ts +93 -0
  209. package/src/utils/auth.ts +272 -0
  210. package/src/utils/config-file.ts +96 -0
  211. package/src/utils/config.ts +134 -0
  212. package/src/utils/confirm.ts +32 -0
  213. package/src/utils/defaults.ts +99 -0
  214. package/src/utils/errors.ts +116 -0
  215. package/src/utils/interactive.ts +91 -0
  216. package/src/utils/list-defaults.ts +74 -0
  217. package/src/utils/output.ts +190 -0
  218. package/src/utils/progress.ts +320 -0
  219. package/src/utils/spinner.ts +22 -0
  220. package/tests/IMPLEMENTATION_STATUS.md +258 -0
  221. package/tests/PTY_SETUP.md +118 -0
  222. package/tests/PTY_TESTING_GUIDE.md +507 -0
  223. package/tests/README.md +244 -0
  224. package/tests/fixtures/api-responses/campaigns.json +34 -0
  225. package/tests/fixtures/test-config.json +13 -0
  226. package/tests/helpers/cli-runner.ts +128 -0
  227. package/tests/helpers/mock-server.ts +301 -0
  228. package/tests/helpers/pty-runner.ts +181 -0
  229. package/tests/integration/campaigns-real-api.test.ts +196 -0
  230. package/tests/integration/setup-integration.ts +50 -0
  231. package/tests/pty/campaigns.test.ts +241 -0
  232. package/tests/setup.ts +34 -0
  233. package/tsconfig.json +15 -0
  234. package/vitest.config.ts +28 -0
@@ -0,0 +1,1408 @@
1
+ # Contact Commands
2
+
3
+ Manage individual contacts within lists, including CRUD operations, tagging, interests, and bulk exports.
4
+
5
+ ## Overview
6
+
7
+ Contact commands allow you to:
8
+ - List and search contacts with advanced filtering
9
+ - Add, update, and delete individual contacts
10
+ - Manage contact subscriptions and status
11
+ - Apply tags and interests to contacts (individually or in bulk)
12
+ - Export contacts with status filtering
13
+ - Manage contact custom attributes
14
+
15
+ All contact operations support **smart defaults** - list IDs are auto-detected when you have only one list, making commands simpler to use.
16
+
17
+ ## Commands
18
+
19
+ - [contacts list](#contacts-list) - List contacts in a list
20
+ - [contacts get](#contacts-get) - Get contact details
21
+ - [contacts add](#contacts-add) - Add a contact to a list
22
+ - [contacts update](#contacts-update) - Update contact information
23
+ - [contacts delete](#contacts-delete) - Delete a contact from a list
24
+ - [contacts unsubscribe](#contacts-unsubscribe) - Unsubscribe a contact
25
+ - [contacts export](#contacts-export) - Create and download contacts export
26
+ - [contacts exports](#contacts-exports) - List contact exports
27
+ - [contacts export-get](#contacts-export-get) - Get export status
28
+ - [contacts export-download](#contacts-export-download) - Download export file
29
+ - [contacts export-delete](#contacts-export-delete) - Delete an export
30
+ - [contacts tag](#contacts-tag) - Tag a single contact
31
+ - [contacts untag](#contacts-untag) - Remove tags from a contact
32
+ - [contacts tag-bulk](#contacts-tag-bulk) - Tag multiple contacts
33
+ - [contacts untag-bulk](#contacts-untag-bulk) - Remove tags from multiple contacts
34
+ - [contacts add-interests](#contacts-add-interests) - Add interests to contacts
35
+ - [contacts remove-interests](#contacts-remove-interests) - Remove interests from contacts
36
+
37
+ ---
38
+
39
+ ## contacts list
40
+
41
+ List contacts in a list with optional filtering, sorting, and pagination.
42
+
43
+ ### Usage
44
+
45
+ ```bash
46
+ cakemail contacts list [list-id] [options]
47
+ ```
48
+
49
+ ### Arguments
50
+
51
+ - `list-id` - List ID (optional - auto-detected if only one list exists)
52
+
53
+ ### Options
54
+
55
+ - `-l, --limit <number>` - Limit number of results per page
56
+ - `-p, --page <number>` - Page number (default: 1)
57
+ - `-q, --query <query>` - Search query (searches across email, name fields)
58
+ - `--sort <sort>` - Sort order (e.g., `+email`, `-subscribed_on`, `+status`)
59
+ - `--filter <filter>` - Filter expression (e.g., `status==active;email==user@example.com`)
60
+
61
+ ### Examples
62
+
63
+ **List all contacts with auto-detection:**
64
+
65
+ ```bash
66
+ $ cakemail contacts list
67
+ ```
68
+
69
+ **Output:**
70
+ ```
71
+ ✓ Auto-detected list: 123 (Newsletter Subscribers)
72
+ ┌────────┬──────────────────────┬────────────┬────────────┬──────────────┐
73
+ │ ID │ Email │ First Name │ Last Name │ Status │
74
+ ├────────┼──────────────────────┼────────────┼────────────┼──────────────┤
75
+ │ 501 │ john@example.com │ John │ Doe │ subscribed │
76
+ │ 502 │ jane@example.com │ Jane │ Smith │ subscribed │
77
+ │ 503 │ bob@example.com │ Bob │ Johnson │ unsubscribed │
78
+ └────────┴──────────────────────┴────────────┴────────────┴──────────────┘
79
+ ```
80
+
81
+ **List contacts for specific list:**
82
+
83
+ ```bash
84
+ $ cakemail contacts list 123
85
+ ```
86
+
87
+ **Filter by status:**
88
+
89
+ ```bash
90
+ $ cakemail contacts list 123 --filter "status==subscribed"
91
+ ```
92
+
93
+ **Output:**
94
+ ```
95
+ ┌────────┬──────────────────────┬────────────┬────────────┬──────────────┐
96
+ │ ID │ Email │ First Name │ Last Name │ Status │
97
+ ├────────┼──────────────────────┼────────────┼────────────┼──────────────┤
98
+ │ 501 │ john@example.com │ John │ Doe │ subscribed │
99
+ │ 502 │ jane@example.com │ Jane │ Smith │ subscribed │
100
+ └────────┴──────────────────────┴────────────┴────────────┴──────────────┘
101
+ ```
102
+
103
+ **Search with query:**
104
+
105
+ ```bash
106
+ $ cakemail contacts list 123 -q "john"
107
+ ```
108
+
109
+ **Sort by most recently subscribed:**
110
+
111
+ ```bash
112
+ $ cakemail contacts list 123 --sort "-subscribed_on" -l 10
113
+ ```
114
+
115
+ **Combine multiple filters:**
116
+
117
+ ```bash
118
+ $ cakemail contacts list 123 --filter "status==subscribed;email==*@gmail.com" -q "smith"
119
+ ```
120
+
121
+ ### Notes
122
+
123
+ - Auto-detection works when you have exactly one list in your account
124
+ - The `--filter` option uses semicolon-separated key==value pairs
125
+ - Sort accepts `+` (ascending) or `-` (descending) prefix
126
+ - Use `--limit` for pagination control
127
+ - Search query (`-q`) performs full-text search across contact fields
128
+
129
+ ### Related Commands
130
+
131
+ - [contacts get](#contacts-get) - Get detailed contact information
132
+ - [contacts add](#contacts-add) - Add new contacts
133
+ - [lists list](/en/cli/command-reference/lists#lists-list) - View all your lists
134
+
135
+ ---
136
+
137
+ ## contacts get
138
+
139
+ Get detailed information about a specific contact.
140
+
141
+ ### Usage
142
+
143
+ ```bash
144
+ cakemail contacts get <list-id> <contact-id>
145
+ ```
146
+
147
+ ### Arguments
148
+
149
+ - `list-id` - List ID (required)
150
+ - `contact-id` - Contact ID (required)
151
+
152
+ ### Examples
153
+
154
+ **Get contact details:**
155
+
156
+ ```bash
157
+ $ cakemail contacts get 123 501
158
+ ```
159
+
160
+ **Output:**
161
+ ```
162
+ {
163
+ "id": 501,
164
+ "email": "john@example.com",
165
+ "first_name": "John",
166
+ "last_name": "Doe",
167
+ "status": "subscribed",
168
+ "subscribed_on": "2024-03-15T10:30:00Z",
169
+ "custom_attributes": {
170
+ "company": "Acme Corp",
171
+ "plan": "premium"
172
+ },
173
+ "tags": ["vip", "customer"],
174
+ "interests": ["product-updates", "promotions"],
175
+ "list_id": 123
176
+ }
177
+ ```
178
+
179
+ **Get contact in JSON format for piping:**
180
+
181
+ ```bash
182
+ $ cakemail contacts get 123 501 -f json | jq '.email'
183
+ ```
184
+
185
+ **Output:**
186
+ ```
187
+ "john@example.com"
188
+ ```
189
+
190
+ ### Notes
191
+
192
+ - Returns complete contact information including custom attributes
193
+ - Shows all tags and interests associated with the contact
194
+ - Use `-f json` for structured output suitable for automation
195
+
196
+ ### Related Commands
197
+
198
+ - [contacts list](#contacts-list) - Find contact IDs
199
+ - [contacts update](#contacts-update) - Modify contact details
200
+
201
+ ---
202
+
203
+ ## contacts add
204
+
205
+ Add a new contact to a list.
206
+
207
+ ### Usage
208
+
209
+ ```bash
210
+ cakemail contacts add [list-id] [options]
211
+ ```
212
+
213
+ ### Arguments
214
+
215
+ - `list-id` - List ID (optional - auto-detected if only one list exists)
216
+
217
+ ### Options
218
+
219
+ - `-e, --email <email>` - Contact email (required)
220
+ - `-f, --first-name <name>` - First name
221
+ - `-l, --last-name <name>` - Last name
222
+ - `-d, --data <json>` - Custom attributes as JSON
223
+
224
+ ### Examples
225
+
226
+ **Add contact with auto-detection:**
227
+
228
+ ```bash
229
+ $ cakemail contacts add -e john@example.com -f John -l Doe
230
+ ```
231
+
232
+ **Output:**
233
+ ```
234
+ ✓ Auto-detected list: 123 (Newsletter Subscribers)
235
+ ✓ Contact added: 501
236
+ {
237
+ "id": 501,
238
+ "email": "john@example.com",
239
+ "first_name": "John",
240
+ "last_name": "Doe",
241
+ "status": "subscribed"
242
+ }
243
+ ```
244
+
245
+ **Add contact to specific list:**
246
+
247
+ ```bash
248
+ $ cakemail contacts add 123 -e jane@example.com -f Jane -l Smith
249
+ ```
250
+
251
+ **Add contact with custom attributes:**
252
+
253
+ ```bash
254
+ $ cakemail contacts add 123 \
255
+ -e bob@example.com \
256
+ -f Bob \
257
+ -l Johnson \
258
+ -d '{"company":"Tech Inc","role":"Developer"}'
259
+ ```
260
+
261
+ **Output:**
262
+ ```
263
+ ✓ Contact added: 502
264
+ {
265
+ "id": 502,
266
+ "email": "bob@example.com",
267
+ "first_name": "Bob",
268
+ "last_name": "Johnson",
269
+ "custom_attributes": {
270
+ "company": "Tech Inc",
271
+ "role": "Developer"
272
+ }
273
+ }
274
+ ```
275
+
276
+ **Add contact with just email (minimal):**
277
+
278
+ ```bash
279
+ $ cakemail contacts add -e minimal@example.com
280
+ ```
281
+
282
+ ### Notes
283
+
284
+ - Email validation is performed before creating the contact
285
+ - Duplicate emails in the same list are rejected
286
+ - Custom attributes must be valid JSON format
287
+ - Auto-detection works when you have exactly one list
288
+ - Contact status defaults to "subscribed"
289
+
290
+ ### Related Commands
291
+
292
+ - [contacts update](#contacts-update) - Modify contact after creation
293
+ - [contacts tag](#contacts-tag) - Add tags to contact
294
+ - [contacts add-interests](#contacts-add-interests) - Add interests
295
+
296
+ ---
297
+
298
+ ## contacts update
299
+
300
+ Update an existing contact's information.
301
+
302
+ ### Usage
303
+
304
+ ```bash
305
+ cakemail contacts update <list-id> <contact-id> [options]
306
+ ```
307
+
308
+ ### Arguments
309
+
310
+ - `list-id` - List ID (required)
311
+ - `contact-id` - Contact ID (required)
312
+
313
+ ### Options
314
+
315
+ - `-e, --email <email>` - New email address
316
+ - `-f, --first-name <name>` - New first name
317
+ - `-l, --last-name <name>` - New last name
318
+ - `-d, --data <json>` - Custom attributes as JSON (merges with existing)
319
+
320
+ ### Examples
321
+
322
+ **Update contact name:**
323
+
324
+ ```bash
325
+ $ cakemail contacts update 123 501 -f Jonathan
326
+ ```
327
+
328
+ **Output:**
329
+ ```
330
+ ✓ Contact 501 updated
331
+ {
332
+ "id": 501,
333
+ "email": "john@example.com",
334
+ "first_name": "Jonathan",
335
+ "last_name": "Doe"
336
+ }
337
+ ```
338
+
339
+ **Update email address:**
340
+
341
+ ```bash
342
+ $ cakemail contacts update 123 501 -e newemail@example.com
343
+ ```
344
+
345
+ **Update custom attributes:**
346
+
347
+ ```bash
348
+ $ cakemail contacts update 123 501 -d '{"company":"New Corp","plan":"enterprise"}'
349
+ ```
350
+
351
+ **Output:**
352
+ ```
353
+ ✓ Contact 501 updated
354
+ {
355
+ "id": 501,
356
+ "email": "john@example.com",
357
+ "custom_attributes": {
358
+ "company": "New Corp",
359
+ "plan": "enterprise"
360
+ }
361
+ }
362
+ ```
363
+
364
+ **Update multiple fields:**
365
+
366
+ ```bash
367
+ $ cakemail contacts update 123 501 \
368
+ -f John \
369
+ -l Doe-Smith \
370
+ -d '{"updated":"2024-03-15"}'
371
+ ```
372
+
373
+ ### Notes
374
+
375
+ - Only provided fields are updated (partial updates)
376
+ - Email validation is performed if email is changed
377
+ - Custom attributes are merged with existing attributes
378
+ - Changing email to an existing email in the list will fail
379
+
380
+ ### Related Commands
381
+
382
+ - [contacts get](#contacts-get) - View current contact details
383
+ - [contacts add](#contacts-add) - Add new contacts
384
+
385
+ ---
386
+
387
+ ## contacts delete
388
+
389
+ Permanently delete a contact from a list.
390
+
391
+ ### Usage
392
+
393
+ ```bash
394
+ cakemail contacts delete <list-id> <contact-id> [options]
395
+ ```
396
+
397
+ ### Arguments
398
+
399
+ - `list-id` - List ID (required)
400
+ - `contact-id` - Contact ID (required)
401
+
402
+ ### Options
403
+
404
+ - `-f, --force` - Skip confirmation prompt (use in scripts)
405
+
406
+ ### Examples
407
+
408
+ **Delete contact with confirmation:**
409
+
410
+ ```bash
411
+ $ cakemail contacts delete 123 501
412
+ ```
413
+
414
+ **Output:**
415
+ ```
416
+ ⚠ Delete contact 501?
417
+
418
+ The following will happen:
419
+ • Contact will be permanently deleted from this list
420
+ • Contact history and data will be lost
421
+
422
+ Type 'yes' to confirm: yes
423
+
424
+ ✓ Contact 501 deleted
425
+ ```
426
+
427
+ **Force delete without confirmation:**
428
+
429
+ ```bash
430
+ $ cakemail contacts delete 123 501 --force
431
+ ```
432
+
433
+ **Output:**
434
+ ```
435
+ ✓ Contact 501 deleted
436
+ ```
437
+
438
+ **Delete in script (batch mode):**
439
+
440
+ ```bash
441
+ $ cakemail contacts delete 123 501 --force --batch
442
+ ```
443
+
444
+ ### Notes
445
+
446
+ - Deletion is **permanent** and cannot be undone
447
+ - All contact history and custom attributes are lost
448
+ - Interactive confirmation is shown unless `--force` is used
449
+ - Consider using [contacts unsubscribe](#contacts-unsubscribe) instead to preserve history
450
+ - Contact is removed from this list only (if contact exists in other lists, those remain)
451
+
452
+ ### Related Commands
453
+
454
+ - [contacts unsubscribe](#contacts-unsubscribe) - Unsubscribe without deleting
455
+ - [contacts list](#contacts-list) - View contacts before deletion
456
+
457
+ ---
458
+
459
+ ## contacts unsubscribe
460
+
461
+ Unsubscribe a contact from a list (preserves contact data).
462
+
463
+ ### Usage
464
+
465
+ ```bash
466
+ cakemail contacts unsubscribe <list-id> <contact-id>
467
+ ```
468
+
469
+ ### Arguments
470
+
471
+ - `list-id` - List ID (required)
472
+ - `contact-id` - Contact ID (required)
473
+
474
+ ### Examples
475
+
476
+ **Unsubscribe a contact:**
477
+
478
+ ```bash
479
+ $ cakemail contacts unsubscribe 123 501
480
+ ```
481
+
482
+ **Output:**
483
+ ```
484
+ ✓ Contact 501 unsubscribed
485
+ ```
486
+
487
+ **Verify unsubscribe status:**
488
+
489
+ ```bash
490
+ $ cakemail contacts get 123 501 -f json | jq '.status'
491
+ ```
492
+
493
+ **Output:**
494
+ ```
495
+ "unsubscribed"
496
+ ```
497
+
498
+ ### Notes
499
+
500
+ - Changes contact status to "unsubscribed"
501
+ - Preserves all contact data and history
502
+ - Contact will not receive future campaigns sent to this list
503
+ - Preferred over [contacts delete](#contacts-delete) for compliance reasons
504
+ - Contact can be re-subscribed later if needed
505
+
506
+ ### Related Commands
507
+
508
+ - [contacts delete](#contacts-delete) - Permanently remove contact
509
+ - [contacts get](#contacts-get) - Check subscription status
510
+
511
+ ---
512
+
513
+ ## contacts export
514
+
515
+ Create and download a contacts export from a list.
516
+
517
+ ### Usage
518
+
519
+ ```bash
520
+ cakemail contacts export [list-id] [options]
521
+ ```
522
+
523
+ ### Arguments
524
+
525
+ - `list-id` - List ID (optional - auto-detected if only one list exists)
526
+
527
+ ### Options
528
+
529
+ - `--status <status>` - Filter by status (subscribed, unsubscribed, etc.)
530
+ - `--no-wait` - Create export job without waiting for completion
531
+
532
+ ### Examples
533
+
534
+ **Export all contacts with auto-detection:**
535
+
536
+ ```bash
537
+ $ cakemail contacts export
538
+ ```
539
+
540
+ **Output:**
541
+ ```
542
+ ✓ Auto-detected list: 123 (Newsletter Subscribers)
543
+ ✓ Export job created
544
+ ⠋ Waiting for export to complete...
545
+ ✓ Export ready
546
+ ✓ Export completed. Download with: cakemail contacts export-download 123 export_abc123
547
+ {
548
+ "id": "export_abc123",
549
+ "status": "ready",
550
+ "created_at": "2024-03-15T10:30:00Z",
551
+ "download_url": "https://..."
552
+ }
553
+ ```
554
+
555
+ **Export only subscribed contacts:**
556
+
557
+ ```bash
558
+ $ cakemail contacts export 123 --status subscribed
559
+ ```
560
+
561
+ **Output:**
562
+ ```
563
+ ✓ Export job created
564
+ ⠋ Waiting for export to complete...
565
+ ✓ Export ready
566
+ ✓ Export completed. Download with: cakemail contacts export-download 123 export_def456
567
+ ```
568
+
569
+ **Create export without waiting (background job):**
570
+
571
+ ```bash
572
+ $ cakemail contacts export 123 --no-wait
573
+ ```
574
+
575
+ **Output:**
576
+ ```
577
+ ✓ Export job created
578
+ ℹ Export ID: export_ghi789
579
+ ℹ Check status with: cakemail contacts export-get 123 export_ghi789
580
+ ```
581
+
582
+ **Export with specific list ID:**
583
+
584
+ ```bash
585
+ $ cakemail contacts export 123
586
+ ```
587
+
588
+ ### Notes
589
+
590
+ - Default behavior waits for export to complete (polls every 2 seconds)
591
+ - Use `--no-wait` for large lists to avoid timeout
592
+ - Export includes all contact fields and custom attributes
593
+ - Download URL expires after 24 hours
594
+ - Status filter options: `subscribed`, `unsubscribed`, `bounced`, `complained`
595
+
596
+ ### Related Commands
597
+
598
+ - [contacts export-download](#contacts-export-download) - Download completed export
599
+ - [contacts exports](#contacts-exports) - List all exports
600
+ - [contacts export-get](#contacts-export-get) - Check export status
601
+
602
+ ---
603
+
604
+ ## contacts exports
605
+
606
+ List all contact exports for a list.
607
+
608
+ ### Usage
609
+
610
+ ```bash
611
+ cakemail contacts exports [list-id] [options]
612
+ ```
613
+
614
+ ### Arguments
615
+
616
+ - `list-id` - List ID (optional - auto-detected if only one list exists)
617
+
618
+ ### Options
619
+
620
+ - `-l, --limit <number>` - Limit number of results
621
+ - `-p, --page <number>` - Page number
622
+
623
+ ### Examples
624
+
625
+ **List all exports:**
626
+
627
+ ```bash
628
+ $ cakemail contacts exports 123
629
+ ```
630
+
631
+ **Output:**
632
+ ```
633
+ ┌──────────────┬──────────┬─────────────────────┬────────────────┐
634
+ │ ID │ Status │ Created │ Records │
635
+ ├──────────────┼──────────┼─────────────────────┼────────────────┤
636
+ │ export_abc123│ ready │ 2024-03-15 10:30:00 │ 1,234 │
637
+ │ export_def456│ ready │ 2024-03-14 14:20:00 │ 1,189 │
638
+ │ export_ghi789│ processing│ 2024-03-15 10:35:00│ - │
639
+ └──────────────┴──────────┴─────────────────────┴────────────────┘
640
+ ```
641
+
642
+ **List recent exports (paginated):**
643
+
644
+ ```bash
645
+ $ cakemail contacts exports 123 -l 5 -p 1
646
+ ```
647
+
648
+ ### Notes
649
+
650
+ - Shows all exports regardless of status (ready, processing, failed)
651
+ - Exports expire after 30 days
652
+ - Use [contacts export-download](#contacts-export-download) to download ready exports
653
+
654
+ ### Related Commands
655
+
656
+ - [contacts export](#contacts-export) - Create new export
657
+ - [contacts export-get](#contacts-export-get) - Get export details
658
+
659
+ ---
660
+
661
+ ## contacts export-get
662
+
663
+ Get the status and details of a specific export.
664
+
665
+ ### Usage
666
+
667
+ ```bash
668
+ cakemail contacts export-get <list-id> <export-id>
669
+ ```
670
+
671
+ ### Arguments
672
+
673
+ - `list-id` - List ID (required)
674
+ - `export-id` - Export ID (required)
675
+
676
+ ### Examples
677
+
678
+ **Check export status:**
679
+
680
+ ```bash
681
+ $ cakemail contacts export-get 123 export_abc123
682
+ ```
683
+
684
+ **Output:**
685
+ ```
686
+ {
687
+ "id": "export_abc123",
688
+ "status": "ready",
689
+ "created_at": "2024-03-15T10:30:00Z",
690
+ "completed_at": "2024-03-15T10:31:30Z",
691
+ "total_records": 1234,
692
+ "download_url": "https://api.cakemail.com/exports/...",
693
+ "expires_at": "2024-04-14T10:31:30Z"
694
+ }
695
+ ```
696
+
697
+ **Monitor processing export:**
698
+
699
+ ```bash
700
+ $ cakemail contacts export-get 123 export_ghi789
701
+ ```
702
+
703
+ **Output:**
704
+ ```
705
+ {
706
+ "id": "export_ghi789",
707
+ "status": "processing",
708
+ "created_at": "2024-03-15T10:35:00Z",
709
+ "progress": 45
710
+ }
711
+ ```
712
+
713
+ ### Notes
714
+
715
+ - Status values: `processing`, `ready`, `failed`
716
+ - `download_url` only available when status is `ready`
717
+ - Use this to poll export status when using `--no-wait`
718
+
719
+ ### Related Commands
720
+
721
+ - [contacts export](#contacts-export) - Create export
722
+ - [contacts export-download](#contacts-export-download) - Download ready export
723
+
724
+ ---
725
+
726
+ ## contacts export-download
727
+
728
+ Download a completed contacts export file.
729
+
730
+ ### Usage
731
+
732
+ ```bash
733
+ cakemail contacts export-download <list-id> <export-id>
734
+ ```
735
+
736
+ ### Arguments
737
+
738
+ - `list-id` - List ID (required)
739
+ - `export-id` - Export ID (required)
740
+
741
+ ### Examples
742
+
743
+ **Download export file:**
744
+
745
+ ```bash
746
+ $ cakemail contacts export-download 123 export_abc123
747
+ ```
748
+
749
+ **Output:**
750
+ ```
751
+ ✓ Export downloaded
752
+ {
753
+ "filename": "contacts_export_abc123.csv",
754
+ "size": 245678,
755
+ "download_url": "https://..."
756
+ }
757
+ ```
758
+
759
+ **Download and save to specific file:**
760
+
761
+ ```bash
762
+ $ cakemail contacts export-download 123 export_abc123 -f json > contacts.json
763
+ ```
764
+
765
+ ### Notes
766
+
767
+ - Export must have status `ready` before download
768
+ - File format is CSV by default
769
+ - Download URL expires after 24 hours
770
+ - Large files may take time to download
771
+
772
+ ### Related Commands
773
+
774
+ - [contacts export](#contacts-export) - Create export
775
+ - [contacts export-get](#contacts-export-get) - Check if ready
776
+
777
+ ---
778
+
779
+ ## contacts export-delete
780
+
781
+ Delete a contacts export file.
782
+
783
+ ### Usage
784
+
785
+ ```bash
786
+ cakemail contacts export-delete <list-id> <export-id> [options]
787
+ ```
788
+
789
+ ### Arguments
790
+
791
+ - `list-id` - List ID (required)
792
+ - `export-id` - Export ID (required)
793
+
794
+ ### Options
795
+
796
+ - `-f, --force` - Skip confirmation prompt
797
+
798
+ ### Examples
799
+
800
+ **Delete export with confirmation:**
801
+
802
+ ```bash
803
+ $ cakemail contacts export-delete 123 export_abc123
804
+ ```
805
+
806
+ **Output:**
807
+ ```
808
+ ⚠ Delete contacts export export_abc123?
809
+
810
+ The following will happen:
811
+ • Export file will be permanently deleted
812
+
813
+ Type 'yes' to confirm: yes
814
+
815
+ ✓ Export export_abc123 deleted
816
+ ```
817
+
818
+ **Force delete:**
819
+
820
+ ```bash
821
+ $ cakemail contacts export-delete 123 export_abc123 --force
822
+ ```
823
+
824
+ **Output:**
825
+ ```
826
+ ✓ Export export_abc123 deleted
827
+ ```
828
+
829
+ ### Notes
830
+
831
+ - Deletion is permanent
832
+ - Export data cannot be recovered
833
+ - Exports auto-delete after 30 days
834
+
835
+ ### Related Commands
836
+
837
+ - [contacts exports](#contacts-exports) - List all exports
838
+ - [contacts export](#contacts-export) - Create new export
839
+
840
+ ---
841
+
842
+ ## contacts tag
843
+
844
+ Add tags to a single contact.
845
+
846
+ ### Usage
847
+
848
+ ```bash
849
+ cakemail contacts tag <list-id> <contact-id> [options]
850
+ ```
851
+
852
+ ### Arguments
853
+
854
+ - `list-id` - List ID (required)
855
+ - `contact-id` - Contact ID (required)
856
+
857
+ ### Options
858
+
859
+ - `-t, --tags <tags>` - Comma-separated tags (required)
860
+
861
+ ### Examples
862
+
863
+ **Tag a contact:**
864
+
865
+ ```bash
866
+ $ cakemail contacts tag 123 501 -t "vip,customer"
867
+ ```
868
+
869
+ **Output:**
870
+ ```
871
+ ✓ Contact 501 tagged
872
+ ```
873
+
874
+ **Add multiple tags:**
875
+
876
+ ```bash
877
+ $ cakemail contacts tag 123 501 -t "premium,early-adopter,newsletter-subscriber"
878
+ ```
879
+
880
+ **Verify tags were added:**
881
+
882
+ ```bash
883
+ $ cakemail contacts get 123 501 -f json | jq '.tags'
884
+ ```
885
+
886
+ **Output:**
887
+ ```
888
+ ["vip", "customer", "premium", "early-adopter", "newsletter-subscriber"]
889
+ ```
890
+
891
+ ### Notes
892
+
893
+ - Tags are global (shared across all lists)
894
+ - Tags must exist before applying (use [tags create](/en/cli/command-reference/tags#tags-create))
895
+ - Duplicate tags are ignored
896
+ - For bulk operations, use [contacts tag-bulk](#contacts-tag-bulk)
897
+
898
+ ### Related Commands
899
+
900
+ - [contacts untag](#contacts-untag) - Remove tags
901
+ - [contacts tag-bulk](#contacts-tag-bulk) - Tag multiple contacts
902
+ - [tags list](/en/cli/command-reference/tags#tags-list) - View available tags
903
+
904
+ ---
905
+
906
+ ## contacts untag
907
+
908
+ Remove tags from a single contact.
909
+
910
+ ### Usage
911
+
912
+ ```bash
913
+ cakemail contacts untag <list-id> <contact-id> [options]
914
+ ```
915
+
916
+ ### Arguments
917
+
918
+ - `list-id` - List ID (required)
919
+ - `contact-id` - Contact ID (required)
920
+
921
+ ### Options
922
+
923
+ - `-t, --tags <tags>` - Comma-separated tags to remove (required)
924
+
925
+ ### Examples
926
+
927
+ **Remove tags from contact:**
928
+
929
+ ```bash
930
+ $ cakemail contacts untag 123 501 -t "customer,trial"
931
+ ```
932
+
933
+ **Output:**
934
+ ```
935
+ ✓ Tags removed from contact 501
936
+ ```
937
+
938
+ **Remove single tag:**
939
+
940
+ ```bash
941
+ $ cakemail contacts untag 123 501 -t "vip"
942
+ ```
943
+
944
+ **Verify tags were removed:**
945
+
946
+ ```bash
947
+ $ cakemail contacts get 123 501 -f json | jq '.tags'
948
+ ```
949
+
950
+ **Output:**
951
+ ```
952
+ ["premium", "early-adopter"]
953
+ ```
954
+
955
+ ### Notes
956
+
957
+ - Only removes specified tags
958
+ - Non-existent tags are silently ignored
959
+ - For bulk operations, use [contacts untag-bulk](#contacts-untag-bulk)
960
+
961
+ ### Related Commands
962
+
963
+ - [contacts tag](#contacts-tag) - Add tags
964
+ - [contacts untag-bulk](#contacts-untag-bulk) - Remove tags from multiple contacts
965
+
966
+ ---
967
+
968
+ ## contacts tag-bulk
969
+
970
+ Add tags to multiple contacts at once.
971
+
972
+ ### Usage
973
+
974
+ ```bash
975
+ cakemail contacts tag-bulk <list-id> [options]
976
+ ```
977
+
978
+ ### Arguments
979
+
980
+ - `list-id` - List ID (required)
981
+
982
+ ### Options
983
+
984
+ - `-c, --contacts <ids>` - Comma-separated contact IDs (required)
985
+ - `-t, --tags <tags>` - Comma-separated tags (required)
986
+
987
+ ### Examples
988
+
989
+ **Tag multiple contacts:**
990
+
991
+ ```bash
992
+ $ cakemail contacts tag-bulk 123 -c "501,502,503" -t "webinar-attendee"
993
+ ```
994
+
995
+ **Output:**
996
+ ```
997
+ ⠋ Tagging 3 contacts...
998
+ ✓ Successfully tagged 3 contacts
999
+ ```
1000
+
1001
+ **Tag many contacts with multiple tags:**
1002
+
1003
+ ```bash
1004
+ $ cakemail contacts tag-bulk 123 \
1005
+ -c "501,502,503,504,505,506,507,508,509,510" \
1006
+ -t "campaign-2024-q1,engaged,priority"
1007
+ ```
1008
+
1009
+ **Output:**
1010
+ ```
1011
+ ⠋ Tagging 10 contacts...
1012
+ ✓ Successfully tagged 10 contacts
1013
+ ```
1014
+
1015
+ ### Notes
1016
+
1017
+ - More efficient than individual [contacts tag](#contacts-tag) calls
1018
+ - Tags must exist before applying
1019
+ - Progress indicator shows for large batches
1020
+ - All specified tags are added to all specified contacts
1021
+ - Maximum 1000 contacts per request
1022
+
1023
+ ### Related Commands
1024
+
1025
+ - [contacts tag](#contacts-tag) - Tag single contact
1026
+ - [contacts untag-bulk](#contacts-untag-bulk) - Remove tags from multiple contacts
1027
+
1028
+ ---
1029
+
1030
+ ## contacts untag-bulk
1031
+
1032
+ Remove tags from multiple contacts at once.
1033
+
1034
+ ### Usage
1035
+
1036
+ ```bash
1037
+ cakemail contacts untag-bulk <list-id> [options]
1038
+ ```
1039
+
1040
+ ### Arguments
1041
+
1042
+ - `list-id` - List ID (required)
1043
+
1044
+ ### Options
1045
+
1046
+ - `-c, --contacts <ids>` - Comma-separated contact IDs (required)
1047
+ - `-t, --tags <tags>` - Comma-separated tags to remove (required)
1048
+
1049
+ ### Examples
1050
+
1051
+ **Remove tags from multiple contacts:**
1052
+
1053
+ ```bash
1054
+ $ cakemail contacts untag-bulk 123 -c "501,502,503" -t "trial,prospect"
1055
+ ```
1056
+
1057
+ **Output:**
1058
+ ```
1059
+ ⠋ Untagging 3 contacts...
1060
+ ✓ Successfully untagged 3 contacts
1061
+ ```
1062
+
1063
+ **Remove tag from many contacts:**
1064
+
1065
+ ```bash
1066
+ $ cakemail contacts untag-bulk 123 \
1067
+ -c "501,502,503,504,505" \
1068
+ -t "old-campaign"
1069
+ ```
1070
+
1071
+ **Output:**
1072
+ ```
1073
+ ⠋ Untagging 5 contacts...
1074
+ ✓ Successfully untagged 5 contacts
1075
+ ```
1076
+
1077
+ ### Notes
1078
+
1079
+ - More efficient than individual [contacts untag](#contacts-untag) calls
1080
+ - Non-existent tags are silently ignored
1081
+ - Progress indicator shows for large batches
1082
+ - Maximum 1000 contacts per request
1083
+
1084
+ ### Related Commands
1085
+
1086
+ - [contacts untag](#contacts-untag) - Remove tags from single contact
1087
+ - [contacts tag-bulk](#contacts-tag-bulk) - Add tags to multiple contacts
1088
+
1089
+ ---
1090
+
1091
+ ## contacts add-interests
1092
+
1093
+ Add list-specific interests to one or more contacts.
1094
+
1095
+ ### Usage
1096
+
1097
+ ```bash
1098
+ cakemail contacts add-interests <list-id> [options]
1099
+ ```
1100
+
1101
+ ### Arguments
1102
+
1103
+ - `list-id` - List ID (required)
1104
+
1105
+ ### Options
1106
+
1107
+ - `-i, --interests <interests>` - Comma-separated interest names (required)
1108
+ - `-c, --contacts <ids>` - Comma-separated contact IDs (optional)
1109
+ - `-q, --query <query>` - SQL query to select contacts (optional)
1110
+
1111
+ Note: Either `--contacts` or `--query` must be provided.
1112
+
1113
+ ### Examples
1114
+
1115
+ **Add interests to specific contacts:**
1116
+
1117
+ ```bash
1118
+ $ cakemail contacts add-interests 123 \
1119
+ -i "product-updates,promotions" \
1120
+ -c "501,502,503"
1121
+ ```
1122
+
1123
+ **Output:**
1124
+ ```
1125
+ ✓ Interests added to contacts
1126
+ ```
1127
+
1128
+ **Add interests using query:**
1129
+
1130
+ ```bash
1131
+ $ cakemail contacts add-interests 123 \
1132
+ -i "newsletter" \
1133
+ -q "status='subscribed' AND email LIKE '%@gmail.com'"
1134
+ ```
1135
+
1136
+ **Output:**
1137
+ ```
1138
+ ✓ Interests added to contacts
1139
+ ```
1140
+
1141
+ **Add single interest to one contact:**
1142
+
1143
+ ```bash
1144
+ $ cakemail contacts add-interests 123 -i "vip-access" -c "501"
1145
+ ```
1146
+
1147
+ ### Notes
1148
+
1149
+ - Interests are list-specific (unlike tags which are global)
1150
+ - Interests must exist on the list before applying
1151
+ - Use `--query` for bulk operations based on conditions
1152
+ - Query syntax is SQL-like (supports WHERE clause conditions)
1153
+ - Maximum 1000 contacts when using `--contacts`
1154
+
1155
+ ### Related Commands
1156
+
1157
+ - [contacts remove-interests](#contacts-remove-interests) - Remove interests
1158
+ - [interests list](/en/cli/command-reference/interests#interests-list) - View list interests
1159
+ - [interests create](/en/cli/command-reference/interests#interests-create) - Create new interest
1160
+
1161
+ ---
1162
+
1163
+ ## contacts remove-interests
1164
+
1165
+ Remove list-specific interests from one or more contacts.
1166
+
1167
+ ### Usage
1168
+
1169
+ ```bash
1170
+ cakemail contacts remove-interests <list-id> [options]
1171
+ ```
1172
+
1173
+ ### Arguments
1174
+
1175
+ - `list-id` - List ID (required)
1176
+
1177
+ ### Options
1178
+
1179
+ - `-i, --interests <interests>` - Comma-separated interest names (required)
1180
+ - `-c, --contacts <ids>` - Comma-separated contact IDs (optional)
1181
+ - `-q, --query <query>` - SQL query to select contacts (optional)
1182
+
1183
+ Note: Either `--contacts` or `--query` must be provided.
1184
+
1185
+ ### Examples
1186
+
1187
+ **Remove interests from specific contacts:**
1188
+
1189
+ ```bash
1190
+ $ cakemail contacts remove-interests 123 \
1191
+ -i "promotions" \
1192
+ -c "501,502,503"
1193
+ ```
1194
+
1195
+ **Output:**
1196
+ ```
1197
+ ✓ Interests removed from contacts
1198
+ ```
1199
+
1200
+ **Remove interests using query:**
1201
+
1202
+ ```bash
1203
+ $ cakemail contacts remove-interests 123 \
1204
+ -i "newsletter,updates" \
1205
+ -q "status='unsubscribed'"
1206
+ ```
1207
+
1208
+ **Output:**
1209
+ ```
1210
+ ✓ Interests removed from contacts
1211
+ ```
1212
+
1213
+ **Remove all promotional interests:**
1214
+
1215
+ ```bash
1216
+ $ cakemail contacts remove-interests 123 \
1217
+ -i "promotions,special-offers,deals" \
1218
+ -q "status='subscribed'"
1219
+ ```
1220
+
1221
+ ### Notes
1222
+
1223
+ - Interests are list-specific
1224
+ - Non-existent interests are silently ignored
1225
+ - Query syntax supports complex SQL WHERE conditions
1226
+ - Use to clean up interests during list maintenance
1227
+
1228
+ ### Related Commands
1229
+
1230
+ - [contacts add-interests](#contacts-add-interests) - Add interests
1231
+ - [interests list](/en/cli/command-reference/interests#interests-list) - View list interests
1232
+
1233
+ ---
1234
+
1235
+ ## Common Workflows
1236
+
1237
+ ### Workflow 1: Add and Tag New Contacts
1238
+
1239
+ ```bash
1240
+ # Add contact
1241
+ $ cakemail contacts add -e john@example.com -f John -l Doe
1242
+
1243
+ # Tag as customer
1244
+ $ cakemail contacts tag 123 501 -t "customer,vip"
1245
+
1246
+ # Add interests
1247
+ $ cakemail contacts add-interests 123 -i "product-updates" -c "501"
1248
+ ```
1249
+
1250
+ ### Workflow 2: Export Subscribed Contacts
1251
+
1252
+ ```bash
1253
+ # Create filtered export
1254
+ $ cakemail contacts export 123 --status subscribed
1255
+
1256
+ # Wait for completion (automatic with default behavior)
1257
+ # Download is shown in output
1258
+
1259
+ # Or check status manually
1260
+ $ cakemail contacts export-get 123 export_abc123
1261
+
1262
+ # Download when ready
1263
+ $ cakemail contacts export-download 123 export_abc123
1264
+ ```
1265
+
1266
+ ### Workflow 3: Bulk Tag Management
1267
+
1268
+ ```bash
1269
+ # List contacts to get IDs
1270
+ $ cakemail contacts list 123 --filter "status==subscribed" -f json | \
1271
+ jq -r '.data[].id' | paste -sd "," -
1272
+
1273
+ # Tag all at once
1274
+ $ cakemail contacts tag-bulk 123 -c "501,502,503,504,505" -t "campaign-2024"
1275
+
1276
+ # Verify tags
1277
+ $ cakemail contacts get 123 501 -f json | jq '.tags'
1278
+ ```
1279
+
1280
+ ### Workflow 4: Interest-Based Segmentation
1281
+
1282
+ ```bash
1283
+ # Add interests to engaged contacts
1284
+ $ cakemail contacts add-interests 123 \
1285
+ -i "premium-content" \
1286
+ -q "last_open_date > '2024-01-01'"
1287
+
1288
+ # Remove interests from inactive contacts
1289
+ $ cakemail contacts remove-interests 123 \
1290
+ -i "newsletter" \
1291
+ -q "last_open_date < '2023-01-01'"
1292
+ ```
1293
+
1294
+ ## Best Practices
1295
+
1296
+ 1. **Use Auto-Detection**: When working with a single list, omit list-id for cleaner commands
1297
+ 2. **Preserve History**: Prefer [contacts unsubscribe](#contacts-unsubscribe) over [contacts delete](#contacts-delete)
1298
+ 3. **Bulk Operations**: Use bulk commands for multiple contacts to improve performance
1299
+ 4. **Export Regularly**: Create periodic exports for backup and analysis
1300
+ 5. **Query Syntax**: Use SQL-like queries for powerful filtering with interests operations
1301
+ 6. **Tag Organization**: Use tags for global characteristics, interests for list-specific preferences
1302
+ 7. **Custom Attributes**: Store additional data as JSON for flexible contact profiles
1303
+ 8. **Validation**: Always validate email addresses before bulk imports
1304
+
1305
+ ## Troubleshooting
1306
+
1307
+ ### Error: "List ID not found"
1308
+
1309
+ Auto-detection failed. Possible causes:
1310
+ - You have no lists in your account
1311
+ - You have multiple lists (must specify list-id)
1312
+ - Invalid list-id provided
1313
+
1314
+ **Solution:**
1315
+ ```bash
1316
+ # List your lists first
1317
+ $ cakemail lists list
1318
+
1319
+ # Use specific list-id
1320
+ $ cakemail contacts list 123
1321
+ ```
1322
+
1323
+ ### Error: "Email address is invalid"
1324
+
1325
+ The provided email fails validation.
1326
+
1327
+ **Solution:**
1328
+ ```bash
1329
+ # Ensure proper email format
1330
+ $ cakemail contacts add -e "user@example.com" -f John
1331
+ ```
1332
+
1333
+ ### Error: "Contact already exists"
1334
+
1335
+ Email already exists in the list.
1336
+
1337
+ **Solution:**
1338
+ ```bash
1339
+ # Use update instead of add
1340
+ $ cakemail contacts update 123 501 -f "New Name"
1341
+
1342
+ # Or list to find existing contact
1343
+ $ cakemail contacts list 123 -q "user@example.com"
1344
+ ```
1345
+
1346
+ ### Error: "Either --contacts or --query is required"
1347
+
1348
+ Both interest operations require a target selector.
1349
+
1350
+ **Solution:**
1351
+ ```bash
1352
+ # Provide contact IDs
1353
+ $ cakemail contacts add-interests 123 -i "newsletter" -c "501,502"
1354
+
1355
+ # Or use query
1356
+ $ cakemail contacts add-interests 123 -i "newsletter" -q "status='subscribed'"
1357
+ ```
1358
+
1359
+ ### Export Takes Too Long
1360
+
1361
+ Large exports may timeout.
1362
+
1363
+ **Solution:**
1364
+ ```bash
1365
+ # Use --no-wait for large exports
1366
+ $ cakemail contacts export 123 --no-wait
1367
+
1368
+ # Check status separately
1369
+ $ cakemail contacts export-get 123 export_abc123
1370
+
1371
+ # Download when ready
1372
+ $ cakemail contacts export-download 123 export_abc123
1373
+ ```
1374
+
1375
+ ### Tags Not Found
1376
+
1377
+ Tags must be created before applying.
1378
+
1379
+ **Solution:**
1380
+ ```bash
1381
+ # Create tag first
1382
+ $ cakemail tags create -n "customer"
1383
+
1384
+ # Then apply to contacts
1385
+ $ cakemail contacts tag 123 501 -t "customer"
1386
+ ```
1387
+
1388
+ ### Interests Not Found
1389
+
1390
+ Interests must exist on the list.
1391
+
1392
+ **Solution:**
1393
+ ```bash
1394
+ # Create interest on list first
1395
+ $ cakemail interests create 123 -n "product-updates"
1396
+
1397
+ # Then add to contacts
1398
+ $ cakemail contacts add-interests 123 -i "product-updates" -c "501"
1399
+ ```
1400
+
1401
+ ---
1402
+
1403
+ **Related Documentation:**
1404
+ - [Lists Commands](/en/cli/command-reference/lists/) - Manage contact lists
1405
+ - [Tags Commands](/en/cli/command-reference/tags/) - Global contact tags
1406
+ - [Interests Commands](/en/cli/command-reference/interests/) - List-specific interests
1407
+ - [Segments Commands](/en/cli/command-reference/segments/) - Dynamic contact filtering
1408
+ - [Attributes Commands](/en/cli/command-reference/attributes/) - Custom contact fields