late-sdk 0.0.67 → 0.0.69

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 (101) hide show
  1. checksums.yaml +4 -4
  2. data/README.md +63 -0
  3. data/docs/AddBroadcastRecipientsRequest.md +20 -0
  4. data/docs/BroadcastsApi.md +699 -0
  5. data/docs/BulkCreateContactsRequest.md +24 -0
  6. data/docs/BulkCreateContactsRequestContactsInner.md +28 -0
  7. data/docs/CommentAutomationsApi.md +428 -0
  8. data/docs/ContactsApi.md +500 -0
  9. data/docs/CreateBroadcastRequest.md +32 -0
  10. data/docs/CreateBroadcastRequestMessage.md +20 -0
  11. data/docs/CreateBroadcastRequestMessageAttachmentsInner.md +22 -0
  12. data/docs/CreateBroadcastRequestSegmentFilters.md +20 -0
  13. data/docs/CreateBroadcastRequestTemplate.md +22 -0
  14. data/docs/CreateCommentAutomationRequest.md +36 -0
  15. data/docs/CreateContactRequest.md +38 -0
  16. data/docs/CreateCustomFieldRequest.md +26 -0
  17. data/docs/CreateSequenceRequest.md +32 -0
  18. data/docs/CreateSequenceRequestStepsInner.md +24 -0
  19. data/docs/CreateSequenceRequestStepsInnerMessage.md +18 -0
  20. data/docs/CustomFieldsApi.md +419 -0
  21. data/docs/EnrollContactsRequest.md +20 -0
  22. data/docs/ListCommentAutomations200Response.md +20 -0
  23. data/docs/ListCommentAutomations200ResponseAutomationsInner.md +42 -0
  24. data/docs/ListCommentAutomations200ResponseAutomationsInnerStats.md +24 -0
  25. data/docs/ScheduleBroadcastRequest.md +18 -0
  26. data/docs/SequencesApi.md +697 -0
  27. data/docs/SetContactFieldValueRequest.md +18 -0
  28. data/docs/TwitterPlatformData.md +3 -1
  29. data/docs/TwitterPlatformDataPoll.md +20 -0
  30. data/docs/UpdateCommentAutomationRequest.md +28 -0
  31. data/docs/UpdateContactRequest.md +32 -0
  32. data/docs/UpdateCustomFieldRequest.md +20 -0
  33. data/docs/WhatsAppApi.md +25 -25
  34. data/lib/late-sdk/api/broadcasts_api.rb +689 -0
  35. data/lib/late-sdk/api/comment_automations_api.rb +420 -0
  36. data/lib/late-sdk/api/contacts_api.rb +503 -0
  37. data/lib/late-sdk/api/custom_fields_api.rb +424 -0
  38. data/lib/late-sdk/api/sequences_api.rb +681 -0
  39. data/lib/late-sdk/api/whats_app_api.rb +50 -50
  40. data/lib/late-sdk/models/add_broadcast_recipients_request.rb +160 -0
  41. data/lib/late-sdk/models/bulk_create_contacts_request.rb +253 -0
  42. data/lib/late-sdk/models/bulk_create_contacts_request_contacts_inner.rb +228 -0
  43. data/lib/late-sdk/models/create_broadcast_request.rb +302 -0
  44. data/lib/late-sdk/models/create_broadcast_request_message.rb +158 -0
  45. data/lib/late-sdk/models/create_broadcast_request_message_attachments_inner.rb +165 -0
  46. data/lib/late-sdk/models/create_broadcast_request_segment_filters.rb +158 -0
  47. data/lib/late-sdk/models/create_broadcast_request_template.rb +168 -0
  48. data/lib/late-sdk/models/create_comment_automation_request.rb +359 -0
  49. data/lib/late-sdk/models/create_contact_request.rb +276 -0
  50. data/lib/late-sdk/models/create_custom_field_request.rb +262 -0
  51. data/lib/late-sdk/models/create_sequence_request.rb +308 -0
  52. data/lib/late-sdk/models/create_sequence_request_steps_inner.rb +208 -0
  53. data/lib/late-sdk/models/create_sequence_request_steps_inner_message.rb +147 -0
  54. data/lib/late-sdk/models/enroll_contacts_request.rb +178 -0
  55. data/lib/late-sdk/models/list_comment_automations200_response.rb +158 -0
  56. data/lib/late-sdk/models/list_comment_automations200_response_automations_inner.rb +303 -0
  57. data/lib/late-sdk/models/list_comment_automations200_response_automations_inner_stats.rb +174 -0
  58. data/lib/late-sdk/models/schedule_broadcast_request.rb +164 -0
  59. data/lib/late-sdk/models/set_contact_field_value_request.rb +150 -0
  60. data/lib/late-sdk/models/twitter_platform_data.rb +13 -4
  61. data/lib/late-sdk/models/twitter_platform_data_poll.rb +231 -0
  62. data/lib/late-sdk/models/update_comment_automation_request.rb +228 -0
  63. data/lib/late-sdk/models/update_contact_request.rb +212 -0
  64. data/lib/late-sdk/models/update_custom_field_request.rb +158 -0
  65. data/lib/late-sdk/version.rb +1 -1
  66. data/lib/late-sdk.rb +29 -0
  67. data/openapi.yaml +830 -13
  68. data/spec/api/broadcasts_api_spec.rb +154 -0
  69. data/spec/api/comment_automations_api_spec.rb +108 -0
  70. data/spec/api/contacts_api_spec.rb +122 -0
  71. data/spec/api/custom_fields_api_spec.rb +105 -0
  72. data/spec/api/sequences_api_spec.rb +153 -0
  73. data/spec/api/whats_app_api_spec.rb +25 -25
  74. data/spec/models/add_broadcast_recipients_request_spec.rb +42 -0
  75. data/spec/models/bulk_create_contacts_request_contacts_inner_spec.rb +66 -0
  76. data/spec/models/bulk_create_contacts_request_spec.rb +54 -0
  77. data/spec/models/create_broadcast_request_message_attachments_inner_spec.rb +48 -0
  78. data/spec/models/create_broadcast_request_message_spec.rb +42 -0
  79. data/spec/models/create_broadcast_request_segment_filters_spec.rb +42 -0
  80. data/spec/models/create_broadcast_request_spec.rb +82 -0
  81. data/spec/models/create_broadcast_request_template_spec.rb +48 -0
  82. data/spec/models/create_comment_automation_request_spec.rb +94 -0
  83. data/spec/models/create_contact_request_spec.rb +96 -0
  84. data/spec/models/create_custom_field_request_spec.rb +64 -0
  85. data/spec/models/create_sequence_request_spec.rb +82 -0
  86. data/spec/models/create_sequence_request_steps_inner_message_spec.rb +36 -0
  87. data/spec/models/create_sequence_request_steps_inner_spec.rb +54 -0
  88. data/spec/models/enroll_contacts_request_spec.rb +42 -0
  89. data/spec/models/list_comment_automations200_response_automations_inner_spec.rb +116 -0
  90. data/spec/models/list_comment_automations200_response_automations_inner_stats_spec.rb +54 -0
  91. data/spec/models/list_comment_automations200_response_spec.rb +42 -0
  92. data/spec/models/schedule_broadcast_request_spec.rb +36 -0
  93. data/spec/models/set_contact_field_value_request_spec.rb +36 -0
  94. data/spec/models/twitter_platform_data_poll_spec.rb +42 -0
  95. data/spec/models/twitter_platform_data_spec.rb +6 -0
  96. data/spec/models/update_comment_automation_request_spec.rb +70 -0
  97. data/spec/models/update_contact_request_spec.rb +78 -0
  98. data/spec/models/update_custom_field_request_spec.rb +42 -0
  99. data/zernio-sdk-0.0.69.gem +0 -0
  100. metadata +118 -2
  101. data/zernio-sdk-0.0.67.gem +0 -0
data/openapi.yaml CHANGED
@@ -210,6 +210,27 @@ tags:
210
210
  - name: Account Settings
211
211
  description: |
212
212
  Platform-specific account settings: Facebook persistent menu, Instagram ice breakers, and Telegram bot commands.
213
+ - name: Contacts
214
+ description: |
215
+ Cross-platform contact management (CRM). Contacts are unified identities linked to platform-specific
216
+ channels (phone, IGSID, etc.). Created automatically when messages arrive, or manually via API.
217
+ - name: Custom Fields
218
+ description: |
219
+ Custom field definitions for contacts. Define fields (text, number, date, boolean, select) that can be
220
+ set on any contact for segmentation and personalization.
221
+ - name: Broadcasts
222
+ description: |
223
+ Platform-agnostic broadcast campaigns. Send bulk messages to contacts via any inbox platform.
224
+ WhatsApp broadcasts use templates; other platforms use generic messages.
225
+ - name: Sequences
226
+ description: |
227
+ Drip campaign sequences. Send a series of messages to enrolled contacts with configurable delays
228
+ between steps. Supports auto-exit on reply or unsubscribe.
229
+ - name: Comment Automations
230
+ description: |
231
+ Comment-to-DM growth automations. Set up keyword triggers on Instagram/Facebook posts so
232
+ commenters automatically receive a DM. Supports dedup, optional public comment reply, and
233
+ auto-creates contacts.
213
234
  - name: Webhooks
214
235
  description: |
215
236
  Configure webhooks for real-time notifications. Events: post.scheduled, post.published, post.failed, post.partial, post.recycled, account.connected, account.disconnected, message.received, comment.received.
@@ -219,7 +240,9 @@ tags:
219
240
  Publishing logs for transparency and debugging. Each log includes the platform API endpoint, HTTP status code, request/response bodies, duration, and retry attempts. Logs are automatically deleted after 7 days.
220
241
  - name: WhatsApp
221
242
  description: |
222
- WhatsApp Business API for sending messages, managing contacts, templates, broadcasts, and conversations.
243
+ WhatsApp Business API. Contact, broadcast, and group endpoints are **deprecated** in favor of the
244
+ cross-platform `/v1/contacts`, `/v1/broadcasts`, and `/v1/sequences` endpoints.
245
+ Template, business profile, and phone number endpoints remain active (no cross-platform equivalent).
223
246
  All endpoints require an accountId parameter identifying the WhatsApp-connected social account.
224
247
  - name: WhatsApp Phone Numbers
225
248
  description: |
@@ -1349,6 +1372,27 @@ components:
1349
1372
  mediaItems:
1350
1373
  type: array
1351
1374
  items: { $ref: '#/components/schemas/MediaItem' }
1375
+ poll:
1376
+ type: object
1377
+ description: Create a poll with this tweet. Mutually exclusive with media attachments and threads.
1378
+ properties:
1379
+ options:
1380
+ type: array
1381
+ minItems: 2
1382
+ maxItems: 4
1383
+ items:
1384
+ type: string
1385
+ minLength: 1
1386
+ maxLength: 25
1387
+ description: Poll options (2-4 choices, max 25 characters each)
1388
+ duration_minutes:
1389
+ type: integer
1390
+ minimum: 5
1391
+ maximum: 10080
1392
+ description: Poll duration in minutes (5 min to 7 days)
1393
+ required:
1394
+ - options
1395
+ - duration_minutes
1352
1396
 
1353
1397
  ThreadsPlatformData:
1354
1398
  type: object
@@ -12344,15 +12388,21 @@ paths:
12344
12388
  '403':
12345
12389
  description: Inbox addon required
12346
12390
  # ──────────────────────────────────────────────────────────────────────────
12347
- # BULK SEND
12391
+ # WHATSAPP-SPECIFIC ENDPOINTS
12392
+ # Contacts, broadcasts, groups: DEPRECATED (use cross-platform endpoints)
12393
+ # Templates, business profile, phone numbers: ACTIVE (no equivalent)
12348
12394
  # ──────────────────────────────────────────────────────────────────────────
12349
12395
 
12396
+ # ── BULK SEND ──────────────────────────────────────────────────────────
12397
+
12350
12398
  /v1/whatsapp/bulk:
12351
12399
  post:
12352
12400
  operationId: sendWhatsAppBulk
12401
+ deprecated: true
12353
12402
  tags: [WhatsApp]
12354
12403
  summary: Bulk send template messages
12355
12404
  description: |
12405
+ **Deprecated.** Use `POST /v1/broadcasts` to create a broadcast, `POST /v1/broadcasts/{id}/recipients` to add recipients, then `POST /v1/broadcasts/{id}/send` to send.
12356
12406
  Send a template message to multiple recipients in a single request. Maximum 100 recipients per request.
12357
12407
  Only template messages are supported for bulk sending (not free-form text).
12358
12408
 
@@ -12452,9 +12502,11 @@ paths:
12452
12502
  /v1/whatsapp/contacts:
12453
12503
  get:
12454
12504
  operationId: getWhatsAppContacts
12505
+ deprecated: true
12455
12506
  tags: [WhatsApp]
12456
12507
  summary: List contacts
12457
12508
  description: |
12509
+ **Deprecated.** Use `GET /v1/contacts?profileId={profileId}` instead.
12458
12510
  List WhatsApp contacts for an account. Supports filtering by tags, groups, opt-in status,
12459
12511
  and text search. Returns contacts sorted by name with available filter options.
12460
12512
  security:
@@ -12560,9 +12612,11 @@ paths:
12560
12612
  '404': { description: WhatsApp account not found }
12561
12613
  post:
12562
12614
  operationId: createWhatsAppContact
12615
+ deprecated: true
12563
12616
  tags: [WhatsApp]
12564
12617
  summary: Create contact
12565
12618
  description: |
12619
+ **Deprecated.** Use `POST /v1/contacts` instead.
12566
12620
  Create a new WhatsApp contact. Phone number must be unique per account
12567
12621
  and in E.164 format (e.g., +1234567890).
12568
12622
  security:
@@ -12652,9 +12706,12 @@ paths:
12652
12706
  /v1/whatsapp/contacts/{contactId}:
12653
12707
  get:
12654
12708
  operationId: getWhatsAppContact
12709
+ deprecated: true
12655
12710
  tags: [WhatsApp]
12656
12711
  summary: Get contact
12657
- description: Retrieve a single WhatsApp contact by ID with full details.
12712
+ description: |
12713
+ **Deprecated.** Use `GET /v1/contacts/{id}` instead.
12714
+ Retrieve a single WhatsApp contact by ID with full details.
12658
12715
  security:
12659
12716
  - bearerAuth: []
12660
12717
  parameters:
@@ -12704,9 +12761,11 @@ paths:
12704
12761
  '404': { $ref: '#/components/responses/NotFound' }
12705
12762
  put:
12706
12763
  operationId: updateWhatsAppContact
12764
+ deprecated: true
12707
12765
  tags: [WhatsApp]
12708
12766
  summary: Update contact
12709
12767
  description: |
12768
+ **Deprecated.** Use `PATCH /v1/contacts/{id}` instead.
12710
12769
  Update an existing WhatsApp contact. All fields are optional; only provided fields will be updated.
12711
12770
  Custom fields are merged with existing values. Set a custom field to null to remove it.
12712
12771
  security:
@@ -12791,9 +12850,12 @@ paths:
12791
12850
  '404': { $ref: '#/components/responses/NotFound' }
12792
12851
  delete:
12793
12852
  operationId: deleteWhatsAppContact
12853
+ deprecated: true
12794
12854
  tags: [WhatsApp]
12795
12855
  summary: Delete contact
12796
- description: Permanently delete a WhatsApp contact.
12856
+ description: |
12857
+ **Deprecated.** Use `DELETE /v1/contacts/{id}` instead.
12858
+ Permanently delete a WhatsApp contact.
12797
12859
  security:
12798
12860
  - bearerAuth: []
12799
12861
  parameters:
@@ -12822,9 +12884,11 @@ paths:
12822
12884
  /v1/whatsapp/contacts/import:
12823
12885
  post:
12824
12886
  operationId: importWhatsAppContacts
12887
+ deprecated: true
12825
12888
  tags: [WhatsApp]
12826
12889
  summary: Bulk import contacts
12827
12890
  description: |
12891
+ **Deprecated.** Use `POST /v1/contacts/bulk` instead.
12828
12892
  Import up to 1000 contacts at once. Each contact requires a phone number and name.
12829
12893
  Duplicates are skipped by default. Supports default tags and groups applied to all imported contacts.
12830
12894
  security:
@@ -12928,9 +12992,11 @@ paths:
12928
12992
  /v1/whatsapp/contacts/bulk:
12929
12993
  post:
12930
12994
  operationId: bulkUpdateWhatsAppContacts
12995
+ deprecated: true
12931
12996
  tags: [WhatsApp]
12932
12997
  summary: Bulk update contacts
12933
12998
  description: |
12999
+ **Deprecated.** Use `PATCH /v1/contacts/{id}` for individual updates instead.
12934
13000
  Perform bulk operations on multiple contacts (max 500 per request). Supported actions:
12935
13001
  addTags, removeTags, addGroups, removeGroups, optIn, optOut, block, unblock.
12936
13002
  security:
@@ -12990,9 +13056,12 @@ paths:
12990
13056
  '401': { $ref: '#/components/responses/Unauthorized' }
12991
13057
  delete:
12992
13058
  operationId: bulkDeleteWhatsAppContacts
13059
+ deprecated: true
12993
13060
  tags: [WhatsApp]
12994
13061
  summary: Bulk delete contacts
12995
- description: Permanently delete multiple contacts at once (max 500 per request).
13062
+ description: |
13063
+ **Deprecated.** Use `DELETE /v1/contacts/{id}` for individual deletes instead.
13064
+ Permanently delete multiple contacts at once (max 500 per request).
12996
13065
  security:
12997
13066
  - bearerAuth: []
12998
13067
  requestBody:
@@ -13031,9 +13100,11 @@ paths:
13031
13100
  /v1/whatsapp/groups:
13032
13101
  get:
13033
13102
  operationId: getWhatsAppGroups
13103
+ deprecated: true
13034
13104
  tags: [WhatsApp]
13035
13105
  summary: List contact groups
13036
13106
  description: |
13107
+ **Deprecated.** Use contact tags via `GET /v1/contacts` for grouping instead. WhatsApp groups have no cross-platform equivalent.
13037
13108
  List all contact groups for a WhatsApp account with contact counts.
13038
13109
  Groups are derived from the groups field on contacts, not stored as separate documents.
13039
13110
  security:
@@ -13073,9 +13144,12 @@ paths:
13073
13144
  '404': { description: WhatsApp account not found }
13074
13145
  post:
13075
13146
  operationId: renameWhatsAppGroup
13147
+ deprecated: true
13076
13148
  tags: [WhatsApp]
13077
13149
  summary: Rename group
13078
- description: Rename a contact group. This updates the group name on all contacts that belong to the group.
13150
+ description: |
13151
+ **Deprecated.** Use contact tags via `PATCH /v1/contacts/{id}` instead.
13152
+ Rename a contact group. This updates the group name on all contacts that belong to the group.
13079
13153
  security:
13080
13154
  - bearerAuth: []
13081
13155
  requestBody:
@@ -13118,9 +13192,12 @@ paths:
13118
13192
  '404': { description: WhatsApp account not found }
13119
13193
  delete:
13120
13194
  operationId: deleteWhatsAppGroup
13195
+ deprecated: true
13121
13196
  tags: [WhatsApp]
13122
13197
  summary: Delete group
13123
- description: Delete a contact group. This removes the group from all contacts but does not delete the contacts themselves.
13198
+ description: |
13199
+ **Deprecated.** Use contact tags via `PATCH /v1/contacts/{id}` instead.
13200
+ Delete a contact group. This removes the group from all contacts but does not delete the contacts themselves.
13124
13201
  security:
13125
13202
  - bearerAuth: []
13126
13203
  requestBody:
@@ -13329,7 +13406,8 @@ paths:
13329
13406
  operationId: getWhatsAppTemplate
13330
13407
  tags: [WhatsApp]
13331
13408
  summary: Get template
13332
- description: Retrieve a single message template by name.
13409
+ description: |
13410
+ Retrieve a single message template by name.
13333
13411
  security:
13334
13412
  - bearerAuth: []
13335
13413
  parameters:
@@ -13430,7 +13508,8 @@ paths:
13430
13508
  operationId: deleteWhatsAppTemplate
13431
13509
  tags: [WhatsApp]
13432
13510
  summary: Delete template
13433
- description: Permanently delete a message template by name.
13511
+ description: |
13512
+ Permanently delete a message template by name.
13434
13513
  security:
13435
13514
  - bearerAuth: []
13436
13515
  parameters:
@@ -13470,9 +13549,11 @@ paths:
13470
13549
  /v1/whatsapp/broadcasts:
13471
13550
  get:
13472
13551
  operationId: getWhatsAppBroadcasts
13552
+ deprecated: true
13473
13553
  tags: [WhatsApp]
13474
13554
  summary: List broadcasts
13475
13555
  description: |
13556
+ **Deprecated.** Use `GET /v1/broadcasts?profileId={profileId}` instead.
13476
13557
  List all WhatsApp broadcasts for an account. Returns broadcasts sorted by creation date
13477
13558
  (newest first) without the full recipients list for performance.
13478
13559
  security:
@@ -13549,9 +13630,11 @@ paths:
13549
13630
  '404': { description: WhatsApp account not found }
13550
13631
  post:
13551
13632
  operationId: createWhatsAppBroadcast
13633
+ deprecated: true
13552
13634
  tags: [WhatsApp]
13553
13635
  summary: Create broadcast
13554
13636
  description: |
13637
+ **Deprecated.** Use `POST /v1/broadcasts` instead.
13555
13638
  Create a new draft broadcast. Optionally include initial recipients.
13556
13639
  After creation, add recipients and then send or schedule the broadcast.
13557
13640
  security:
@@ -13647,9 +13730,12 @@ paths:
13647
13730
  /v1/whatsapp/broadcasts/{broadcastId}:
13648
13731
  get:
13649
13732
  operationId: getWhatsAppBroadcast
13733
+ deprecated: true
13650
13734
  tags: [WhatsApp]
13651
13735
  summary: Get broadcast
13652
- description: Retrieve detailed information about a single broadcast including delivery statistics.
13736
+ description: |
13737
+ **Deprecated.** Use `GET /v1/broadcasts/{id}` instead.
13738
+ Retrieve detailed information about a single broadcast including delivery statistics.
13653
13739
  security:
13654
13740
  - bearerAuth: []
13655
13741
  parameters:
@@ -13690,9 +13776,12 @@ paths:
13690
13776
  '404': { $ref: '#/components/responses/NotFound' }
13691
13777
  delete:
13692
13778
  operationId: deleteWhatsAppBroadcast
13779
+ deprecated: true
13693
13780
  tags: [WhatsApp]
13694
13781
  summary: Delete broadcast
13695
- description: Delete a broadcast. Only draft or cancelled broadcasts can be deleted.
13782
+ description: |
13783
+ **Deprecated.** Use `DELETE /v1/broadcasts/{id}` instead.
13784
+ Delete a broadcast. Only draft or cancelled broadcasts can be deleted.
13696
13785
  security:
13697
13786
  - bearerAuth: []
13698
13787
  parameters:
@@ -13722,9 +13811,11 @@ paths:
13722
13811
  /v1/whatsapp/broadcasts/{broadcastId}/send:
13723
13812
  post:
13724
13813
  operationId: sendWhatsAppBroadcast
13814
+ deprecated: true
13725
13815
  tags: [WhatsApp]
13726
13816
  summary: Send broadcast
13727
13817
  description: |
13818
+ **Deprecated.** Use `POST /v1/broadcasts/{id}/send` instead.
13728
13819
  Start sending a broadcast immediately. The broadcast must be in draft or scheduled status
13729
13820
  and have at least one recipient. Messages are sent sequentially with rate limiting.
13730
13821
  security:
@@ -13762,9 +13853,11 @@ paths:
13762
13853
  /v1/whatsapp/broadcasts/{broadcastId}/schedule:
13763
13854
  post:
13764
13855
  operationId: scheduleWhatsAppBroadcast
13856
+ deprecated: true
13765
13857
  tags: [WhatsApp]
13766
13858
  summary: Schedule broadcast
13767
13859
  description: |
13860
+ **Deprecated.** Use `POST /v1/broadcasts/{id}/schedule` instead.
13768
13861
  Schedule a draft broadcast for future sending. The scheduled time must be in the future
13769
13862
  and no more than 30 days in advance. The broadcast must be in draft status and have recipients.
13770
13863
  security:
@@ -13811,9 +13904,11 @@ paths:
13811
13904
  '404': { $ref: '#/components/responses/NotFound' }
13812
13905
  delete:
13813
13906
  operationId: cancelWhatsAppBroadcastSchedule
13907
+ deprecated: true
13814
13908
  tags: [WhatsApp]
13815
13909
  summary: Cancel scheduled broadcast
13816
13910
  description: |
13911
+ **Deprecated.** Use `POST /v1/broadcasts/{id}/cancel` instead.
13817
13912
  Cancel a scheduled broadcast and return it to draft status. Only broadcasts in
13818
13913
  scheduled status can be cancelled.
13819
13914
  security:
@@ -13853,9 +13948,11 @@ paths:
13853
13948
  /v1/whatsapp/broadcasts/{broadcastId}/recipients:
13854
13949
  get:
13855
13950
  operationId: getWhatsAppBroadcastRecipients
13951
+ deprecated: true
13856
13952
  tags: [WhatsApp]
13857
13953
  summary: List recipients
13858
13954
  description: |
13955
+ **Deprecated.** Use `GET /v1/broadcasts/{id}/recipients` instead.
13859
13956
  List recipients of a broadcast with their delivery status. Supports filtering
13860
13957
  by delivery status and pagination.
13861
13958
  security:
@@ -13931,9 +14028,11 @@ paths:
13931
14028
  '404': { $ref: '#/components/responses/NotFound' }
13932
14029
  patch:
13933
14030
  operationId: addWhatsAppBroadcastRecipients
14031
+ deprecated: true
13934
14032
  tags: [WhatsApp]
13935
14033
  summary: Add recipients
13936
14034
  description: |
14035
+ **Deprecated.** Use `POST /v1/broadcasts/{id}/recipients` instead.
13937
14036
  Add recipients to a draft broadcast. Maximum 1000 recipients per request.
13938
14037
  Duplicate phone numbers are automatically skipped.
13939
14038
  security:
@@ -13995,9 +14094,12 @@ paths:
13995
14094
  '404': { $ref: '#/components/responses/NotFound' }
13996
14095
  delete:
13997
14096
  operationId: removeWhatsAppBroadcastRecipients
14097
+ deprecated: true
13998
14098
  tags: [WhatsApp]
13999
14099
  summary: Remove recipients
14000
- description: Remove recipients from a draft broadcast by phone number.
14100
+ description: |
14101
+ **Deprecated.** Use `POST /v1/broadcasts/{id}/recipients` with removal flag instead.
14102
+ Remove recipients from a draft broadcast by phone number.
14001
14103
  security:
14002
14104
  - bearerAuth: []
14003
14105
  parameters:
@@ -14046,7 +14148,8 @@ paths:
14046
14148
  operationId: getWhatsAppBusinessProfile
14047
14149
  tags: [WhatsApp]
14048
14150
  summary: Get business profile
14049
- description: Retrieve the WhatsApp Business profile for the account (about, address, description, email, websites, etc.).
14151
+ description: |
14152
+ Retrieve the WhatsApp Business profile for the account (about, address, description, email, websites, etc.).
14050
14153
  security:
14051
14154
  - bearerAuth: []
14052
14155
  parameters:
@@ -14462,3 +14565,717 @@ paths:
14462
14565
  '401': { $ref: '#/components/responses/Unauthorized' }
14463
14566
  '404': { $ref: '#/components/responses/NotFound' }
14464
14567
 
14568
+ # ─── Contacts ─────────────────────────────────────────────────────
14569
+
14570
+ /v1/contacts:
14571
+ get:
14572
+ operationId: listContacts
14573
+ summary: List contacts
14574
+ description: List and search contacts for a profile. Supports filtering by tags, platform, subscription status, and full-text search.
14575
+ tags: [Contacts]
14576
+ parameters:
14577
+ - { name: profileId, in: query, required: true, schema: { type: string } }
14578
+ - { name: search, in: query, schema: { type: string } }
14579
+ - { name: tag, in: query, schema: { type: string } }
14580
+ - { name: platform, in: query, schema: { type: string, enum: [instagram, facebook, telegram, twitter, bluesky, reddit, whatsapp] } }
14581
+ - { name: isSubscribed, in: query, schema: { type: string, enum: ['true', 'false'] } }
14582
+ - { name: limit, in: query, schema: { type: integer, default: 50, maximum: 200 } }
14583
+ - { name: skip, in: query, schema: { type: integer, default: 0 } }
14584
+ responses:
14585
+ '200': { description: Contacts list with pagination and filter metadata }
14586
+ '401': { $ref: '#/components/responses/Unauthorized' }
14587
+ post:
14588
+ operationId: createContact
14589
+ summary: Create a contact
14590
+ description: Create a new contact. Optionally create a platform channel in the same request by providing accountId, platform, and platformIdentifier.
14591
+ tags: [Contacts]
14592
+ requestBody:
14593
+ required: true
14594
+ content:
14595
+ application/json:
14596
+ schema:
14597
+ type: object
14598
+ required: [profileId, name]
14599
+ properties:
14600
+ profileId: { type: string }
14601
+ name: { type: string }
14602
+ email: { type: string }
14603
+ company: { type: string }
14604
+ tags: { type: array, items: { type: string } }
14605
+ isSubscribed: { type: boolean, default: true }
14606
+ notes: { type: string }
14607
+ accountId: { type: string, description: Optional. Creates a channel if provided with platform + platformIdentifier }
14608
+ platform: { type: string }
14609
+ platformIdentifier: { type: string }
14610
+ displayIdentifier: { type: string }
14611
+ responses:
14612
+ '200': { description: Contact created }
14613
+ '401': { $ref: '#/components/responses/Unauthorized' }
14614
+ '409': { description: Duplicate contact }
14615
+
14616
+ /v1/contacts/{contactId}:
14617
+ get:
14618
+ operationId: getContact
14619
+ summary: Get contact with channels
14620
+ tags: [Contacts]
14621
+ parameters:
14622
+ - { name: contactId, in: path, required: true, schema: { type: string } }
14623
+ responses:
14624
+ '200': { description: Contact with channels }
14625
+ '401': { $ref: '#/components/responses/Unauthorized' }
14626
+ '404': { $ref: '#/components/responses/NotFound' }
14627
+ patch:
14628
+ operationId: updateContact
14629
+ summary: Update a contact
14630
+ tags: [Contacts]
14631
+ parameters:
14632
+ - { name: contactId, in: path, required: true, schema: { type: string } }
14633
+ requestBody:
14634
+ content:
14635
+ application/json:
14636
+ schema:
14637
+ type: object
14638
+ properties:
14639
+ name: { type: string }
14640
+ email: { type: string }
14641
+ company: { type: string }
14642
+ avatarUrl: { type: string }
14643
+ tags: { type: array, items: { type: string } }
14644
+ isSubscribed: { type: boolean }
14645
+ isBlocked: { type: boolean }
14646
+ notes: { type: string }
14647
+ responses:
14648
+ '200': { description: Contact updated }
14649
+ '401': { $ref: '#/components/responses/Unauthorized' }
14650
+ '404': { $ref: '#/components/responses/NotFound' }
14651
+ delete:
14652
+ operationId: deleteContact
14653
+ summary: Delete a contact
14654
+ tags: [Contacts]
14655
+ parameters:
14656
+ - { name: contactId, in: path, required: true, schema: { type: string } }
14657
+ responses:
14658
+ '200': { description: Contact deleted }
14659
+ '401': { $ref: '#/components/responses/Unauthorized' }
14660
+ '404': { $ref: '#/components/responses/NotFound' }
14661
+
14662
+ /v1/contacts/{contactId}/channels:
14663
+ get:
14664
+ operationId: getContactChannels
14665
+ summary: List channels for a contact
14666
+ tags: [Contacts]
14667
+ parameters:
14668
+ - { name: contactId, in: path, required: true, schema: { type: string } }
14669
+ responses:
14670
+ '200': { description: List of contact channels }
14671
+ '401': { $ref: '#/components/responses/Unauthorized' }
14672
+ '404': { $ref: '#/components/responses/NotFound' }
14673
+
14674
+ /v1/contacts/bulk:
14675
+ post:
14676
+ operationId: bulkCreateContacts
14677
+ summary: Bulk create contacts
14678
+ description: Import up to 1000 contacts at a time. Skips duplicates.
14679
+ tags: [Contacts]
14680
+ requestBody:
14681
+ required: true
14682
+ content:
14683
+ application/json:
14684
+ schema:
14685
+ type: object
14686
+ required: [profileId, accountId, platform, contacts]
14687
+ properties:
14688
+ profileId: { type: string }
14689
+ accountId: { type: string }
14690
+ platform: { type: string }
14691
+ contacts:
14692
+ type: array
14693
+ maxItems: 1000
14694
+ items:
14695
+ type: object
14696
+ required: [name, platformIdentifier]
14697
+ properties:
14698
+ name: { type: string }
14699
+ platformIdentifier: { type: string }
14700
+ displayIdentifier: { type: string }
14701
+ email: { type: string }
14702
+ company: { type: string }
14703
+ tags: { type: array, items: { type: string } }
14704
+ responses:
14705
+ '200': { description: Bulk import results }
14706
+ '401': { $ref: '#/components/responses/Unauthorized' }
14707
+
14708
+ /v1/contacts/{contactId}/fields/{slug}:
14709
+ put:
14710
+ operationId: setContactFieldValue
14711
+ summary: Set a custom field value
14712
+ tags: [Custom Fields]
14713
+ parameters:
14714
+ - { name: contactId, in: path, required: true, schema: { type: string } }
14715
+ - { name: slug, in: path, required: true, schema: { type: string } }
14716
+ requestBody:
14717
+ required: true
14718
+ content:
14719
+ application/json:
14720
+ schema:
14721
+ type: object
14722
+ required: [value]
14723
+ properties:
14724
+ value: { description: Field value (type depends on field definition) }
14725
+ responses:
14726
+ '200': { description: Field value set }
14727
+ '401': { $ref: '#/components/responses/Unauthorized' }
14728
+ '404': { $ref: '#/components/responses/NotFound' }
14729
+ delete:
14730
+ operationId: clearContactFieldValue
14731
+ summary: Clear a custom field value
14732
+ tags: [Custom Fields]
14733
+ parameters:
14734
+ - { name: contactId, in: path, required: true, schema: { type: string } }
14735
+ - { name: slug, in: path, required: true, schema: { type: string } }
14736
+ responses:
14737
+ '200': { description: Field value cleared }
14738
+ '401': { $ref: '#/components/responses/Unauthorized' }
14739
+ '404': { $ref: '#/components/responses/NotFound' }
14740
+
14741
+ # ─── Custom Fields ────────────────────────────────────────────────
14742
+
14743
+ /v1/custom-fields:
14744
+ get:
14745
+ operationId: listCustomFields
14746
+ summary: List custom field definitions
14747
+ tags: [Custom Fields]
14748
+ parameters:
14749
+ - { name: profileId, in: query, required: true, schema: { type: string } }
14750
+ responses:
14751
+ '200': { description: List of custom field definitions }
14752
+ '401': { $ref: '#/components/responses/Unauthorized' }
14753
+ post:
14754
+ operationId: createCustomField
14755
+ summary: Create a custom field definition
14756
+ tags: [Custom Fields]
14757
+ requestBody:
14758
+ required: true
14759
+ content:
14760
+ application/json:
14761
+ schema:
14762
+ type: object
14763
+ required: [profileId, name, type]
14764
+ properties:
14765
+ profileId: { type: string }
14766
+ name: { type: string }
14767
+ slug: { type: string, description: Auto-generated from name if not provided }
14768
+ type: { type: string, enum: [text, number, date, boolean, select] }
14769
+ options: { type: array, items: { type: string }, description: Required for select type }
14770
+ responses:
14771
+ '200': { description: Custom field created }
14772
+ '401': { $ref: '#/components/responses/Unauthorized' }
14773
+ '409': { description: Duplicate slug }
14774
+
14775
+ /v1/custom-fields/{fieldId}:
14776
+ patch:
14777
+ operationId: updateCustomField
14778
+ summary: Update a custom field definition
14779
+ tags: [Custom Fields]
14780
+ parameters:
14781
+ - { name: fieldId, in: path, required: true, schema: { type: string } }
14782
+ requestBody:
14783
+ content:
14784
+ application/json:
14785
+ schema:
14786
+ type: object
14787
+ properties:
14788
+ name: { type: string }
14789
+ options: { type: array, items: { type: string } }
14790
+ responses:
14791
+ '200': { description: Custom field updated }
14792
+ '401': { $ref: '#/components/responses/Unauthorized' }
14793
+ '404': { $ref: '#/components/responses/NotFound' }
14794
+ delete:
14795
+ operationId: deleteCustomField
14796
+ summary: Delete a custom field definition
14797
+ tags: [Custom Fields]
14798
+ parameters:
14799
+ - { name: fieldId, in: path, required: true, schema: { type: string } }
14800
+ responses:
14801
+ '200': { description: Custom field deleted }
14802
+ '401': { $ref: '#/components/responses/Unauthorized' }
14803
+ '404': { $ref: '#/components/responses/NotFound' }
14804
+
14805
+ # ─── Broadcasts ───────────────────────────────────────────────────
14806
+
14807
+ /v1/broadcasts:
14808
+ get:
14809
+ operationId: listBroadcasts
14810
+ summary: List broadcasts
14811
+ tags: [Broadcasts]
14812
+ parameters:
14813
+ - { name: profileId, in: query, required: true, schema: { type: string } }
14814
+ - { name: status, in: query, schema: { type: string, enum: [draft, scheduled, sending, completed, failed, cancelled] } }
14815
+ - { name: platform, in: query, schema: { type: string } }
14816
+ - { name: limit, in: query, schema: { type: integer, default: 50 } }
14817
+ - { name: skip, in: query, schema: { type: integer, default: 0 } }
14818
+ responses:
14819
+ '200': { description: Broadcasts list }
14820
+ '401': { $ref: '#/components/responses/Unauthorized' }
14821
+ post:
14822
+ operationId: createBroadcast
14823
+ summary: Create a broadcast draft
14824
+ tags: [Broadcasts]
14825
+ requestBody:
14826
+ required: true
14827
+ content:
14828
+ application/json:
14829
+ schema:
14830
+ type: object
14831
+ required: [profileId, accountId, platform, name]
14832
+ properties:
14833
+ profileId: { type: string }
14834
+ accountId: { type: string }
14835
+ platform: { type: string, enum: [instagram, facebook, telegram, twitter, bluesky, reddit, whatsapp] }
14836
+ name: { type: string }
14837
+ description: { type: string }
14838
+ message:
14839
+ type: object
14840
+ properties:
14841
+ text: { type: string }
14842
+ attachments: { type: array, items: { type: object, properties: { type: { type: string }, url: { type: string }, filename: { type: string } } } }
14843
+ template:
14844
+ type: object
14845
+ description: WhatsApp template (required when platform is whatsapp)
14846
+ properties:
14847
+ name: { type: string }
14848
+ language: { type: string }
14849
+ components: { type: array }
14850
+ segmentFilters:
14851
+ type: object
14852
+ properties:
14853
+ tags: { type: array, items: { type: string } }
14854
+ isSubscribed: { type: boolean }
14855
+ responses:
14856
+ '200': { description: Broadcast created }
14857
+ '401': { $ref: '#/components/responses/Unauthorized' }
14858
+
14859
+ /v1/broadcasts/{broadcastId}:
14860
+ get:
14861
+ operationId: getBroadcast
14862
+ summary: Get broadcast details
14863
+ tags: [Broadcasts]
14864
+ parameters:
14865
+ - { name: broadcastId, in: path, required: true, schema: { type: string } }
14866
+ responses:
14867
+ '200': { description: Broadcast details with stats }
14868
+ '401': { $ref: '#/components/responses/Unauthorized' }
14869
+ '404': { $ref: '#/components/responses/NotFound' }
14870
+ patch:
14871
+ operationId: updateBroadcast
14872
+ summary: Update a broadcast
14873
+ tags: [Broadcasts]
14874
+ parameters:
14875
+ - { name: broadcastId, in: path, required: true, schema: { type: string } }
14876
+ responses:
14877
+ '200': { description: Broadcast updated }
14878
+ '401': { $ref: '#/components/responses/Unauthorized' }
14879
+ '404': { $ref: '#/components/responses/NotFound' }
14880
+ delete:
14881
+ operationId: deleteBroadcast
14882
+ summary: Delete a broadcast (draft only)
14883
+ tags: [Broadcasts]
14884
+ parameters:
14885
+ - { name: broadcastId, in: path, required: true, schema: { type: string } }
14886
+ responses:
14887
+ '200': { description: Broadcast deleted }
14888
+ '401': { $ref: '#/components/responses/Unauthorized' }
14889
+ '404': { $ref: '#/components/responses/NotFound' }
14890
+
14891
+ /v1/broadcasts/{broadcastId}/send:
14892
+ post:
14893
+ operationId: sendBroadcast
14894
+ summary: Trigger immediate send
14895
+ tags: [Broadcasts]
14896
+ parameters:
14897
+ - { name: broadcastId, in: path, required: true, schema: { type: string } }
14898
+ responses:
14899
+ '200': { description: Broadcast sending started }
14900
+ '400': { description: Invalid status or no recipients }
14901
+ '401': { $ref: '#/components/responses/Unauthorized' }
14902
+ '404': { $ref: '#/components/responses/NotFound' }
14903
+
14904
+ /v1/broadcasts/{broadcastId}/schedule:
14905
+ post:
14906
+ operationId: scheduleBroadcast
14907
+ summary: Schedule broadcast for later
14908
+ tags: [Broadcasts]
14909
+ parameters:
14910
+ - { name: broadcastId, in: path, required: true, schema: { type: string } }
14911
+ requestBody:
14912
+ required: true
14913
+ content:
14914
+ application/json:
14915
+ schema:
14916
+ type: object
14917
+ required: [scheduledAt]
14918
+ properties:
14919
+ scheduledAt: { type: string, format: date-time }
14920
+ responses:
14921
+ '200': { description: Broadcast scheduled }
14922
+ '400': { description: Invalid date or status }
14923
+ '401': { $ref: '#/components/responses/Unauthorized' }
14924
+ '404': { $ref: '#/components/responses/NotFound' }
14925
+
14926
+ /v1/broadcasts/{broadcastId}/cancel:
14927
+ post:
14928
+ operationId: cancelBroadcast
14929
+ summary: Cancel a broadcast
14930
+ tags: [Broadcasts]
14931
+ parameters:
14932
+ - { name: broadcastId, in: path, required: true, schema: { type: string } }
14933
+ responses:
14934
+ '200': { description: Broadcast cancelled }
14935
+ '400': { description: Cannot cancel in current status }
14936
+ '401': { $ref: '#/components/responses/Unauthorized' }
14937
+ '404': { $ref: '#/components/responses/NotFound' }
14938
+
14939
+ /v1/broadcasts/{broadcastId}/recipients:
14940
+ get:
14941
+ operationId: listBroadcastRecipients
14942
+ summary: List broadcast recipients
14943
+ tags: [Broadcasts]
14944
+ parameters:
14945
+ - { name: broadcastId, in: path, required: true, schema: { type: string } }
14946
+ - { name: status, in: query, schema: { type: string, enum: [pending, sent, delivered, read, failed] } }
14947
+ - { name: limit, in: query, schema: { type: integer, default: 50 } }
14948
+ - { name: skip, in: query, schema: { type: integer, default: 0 } }
14949
+ responses:
14950
+ '200': { description: Recipients list with delivery status }
14951
+ '401': { $ref: '#/components/responses/Unauthorized' }
14952
+ '404': { $ref: '#/components/responses/NotFound' }
14953
+ post:
14954
+ operationId: addBroadcastRecipients
14955
+ summary: Add recipients to a broadcast
14956
+ tags: [Broadcasts]
14957
+ parameters:
14958
+ - { name: broadcastId, in: path, required: true, schema: { type: string } }
14959
+ requestBody:
14960
+ required: true
14961
+ content:
14962
+ application/json:
14963
+ schema:
14964
+ type: object
14965
+ properties:
14966
+ contactIds: { type: array, items: { type: string }, description: Specific contact IDs to add }
14967
+ useSegment: { type: boolean, description: Auto-populate from broadcast segment filters }
14968
+ responses:
14969
+ '200': { description: Recipients added }
14970
+ '401': { $ref: '#/components/responses/Unauthorized' }
14971
+ '404': { $ref: '#/components/responses/NotFound' }
14972
+
14973
+ # ─── Sequences ────────────────────────────────────────────────────
14974
+
14975
+ /v1/sequences:
14976
+ get:
14977
+ operationId: listSequences
14978
+ summary: List sequences
14979
+ tags: [Sequences]
14980
+ parameters:
14981
+ - { name: profileId, in: query, required: true, schema: { type: string } }
14982
+ - { name: status, in: query, schema: { type: string, enum: [draft, active, paused] } }
14983
+ - { name: limit, in: query, schema: { type: integer, default: 50 } }
14984
+ - { name: skip, in: query, schema: { type: integer, default: 0 } }
14985
+ responses:
14986
+ '200': { description: Sequences list }
14987
+ '401': { $ref: '#/components/responses/Unauthorized' }
14988
+ post:
14989
+ operationId: createSequence
14990
+ summary: Create a sequence
14991
+ tags: [Sequences]
14992
+ requestBody:
14993
+ required: true
14994
+ content:
14995
+ application/json:
14996
+ schema:
14997
+ type: object
14998
+ required: [profileId, accountId, platform, name]
14999
+ properties:
15000
+ profileId: { type: string }
15001
+ accountId: { type: string }
15002
+ platform: { type: string, enum: [instagram, facebook, telegram, twitter, bluesky, reddit, whatsapp] }
15003
+ name: { type: string }
15004
+ description: { type: string }
15005
+ steps:
15006
+ type: array
15007
+ items:
15008
+ type: object
15009
+ required: [order, delayMinutes]
15010
+ properties:
15011
+ order: { type: integer }
15012
+ delayMinutes: { type: integer }
15013
+ message: { type: object, properties: { text: { type: string } } }
15014
+ template: { type: object, properties: { name: { type: string }, language: { type: string } } }
15015
+ exitOnReply: { type: boolean, default: true }
15016
+ exitOnUnsubscribe: { type: boolean, default: true }
15017
+ responses:
15018
+ '200': { description: Sequence created }
15019
+ '401': { $ref: '#/components/responses/Unauthorized' }
15020
+
15021
+ /v1/sequences/{sequenceId}:
15022
+ get:
15023
+ operationId: getSequence
15024
+ summary: Get sequence with steps
15025
+ tags: [Sequences]
15026
+ parameters:
15027
+ - { name: sequenceId, in: path, required: true, schema: { type: string } }
15028
+ responses:
15029
+ '200': { description: Sequence details with steps }
15030
+ '401': { $ref: '#/components/responses/Unauthorized' }
15031
+ '404': { $ref: '#/components/responses/NotFound' }
15032
+ patch:
15033
+ operationId: updateSequence
15034
+ summary: Update a sequence
15035
+ tags: [Sequences]
15036
+ parameters:
15037
+ - { name: sequenceId, in: path, required: true, schema: { type: string } }
15038
+ responses:
15039
+ '200': { description: Sequence updated }
15040
+ '401': { $ref: '#/components/responses/Unauthorized' }
15041
+ '404': { $ref: '#/components/responses/NotFound' }
15042
+ delete:
15043
+ operationId: deleteSequence
15044
+ summary: Delete a sequence
15045
+ tags: [Sequences]
15046
+ parameters:
15047
+ - { name: sequenceId, in: path, required: true, schema: { type: string } }
15048
+ responses:
15049
+ '200': { description: Sequence deleted }
15050
+ '401': { $ref: '#/components/responses/Unauthorized' }
15051
+ '404': { $ref: '#/components/responses/NotFound' }
15052
+
15053
+ /v1/sequences/{sequenceId}/activate:
15054
+ post:
15055
+ operationId: activateSequence
15056
+ summary: Activate a sequence
15057
+ tags: [Sequences]
15058
+ parameters:
15059
+ - { name: sequenceId, in: path, required: true, schema: { type: string } }
15060
+ responses:
15061
+ '200': { description: Sequence activated }
15062
+ '400': { description: Invalid status or no steps }
15063
+ '401': { $ref: '#/components/responses/Unauthorized' }
15064
+ '404': { $ref: '#/components/responses/NotFound' }
15065
+
15066
+ /v1/sequences/{sequenceId}/pause:
15067
+ post:
15068
+ operationId: pauseSequence
15069
+ summary: Pause a sequence
15070
+ tags: [Sequences]
15071
+ parameters:
15072
+ - { name: sequenceId, in: path, required: true, schema: { type: string } }
15073
+ responses:
15074
+ '200': { description: Sequence paused }
15075
+ '400': { description: Sequence is not active }
15076
+ '401': { $ref: '#/components/responses/Unauthorized' }
15077
+ '404': { $ref: '#/components/responses/NotFound' }
15078
+
15079
+ /v1/sequences/{sequenceId}/enroll:
15080
+ post:
15081
+ operationId: enrollContacts
15082
+ summary: Enroll contacts in a sequence
15083
+ tags: [Sequences]
15084
+ parameters:
15085
+ - { name: sequenceId, in: path, required: true, schema: { type: string } }
15086
+ requestBody:
15087
+ required: true
15088
+ content:
15089
+ application/json:
15090
+ schema:
15091
+ type: object
15092
+ required: [contactIds]
15093
+ properties:
15094
+ contactIds: { type: array, items: { type: string } }
15095
+ channelIds: { type: array, items: { type: string }, description: Optional. Auto-detected if not provided. }
15096
+ responses:
15097
+ '200': { description: Enrollment results }
15098
+ '401': { $ref: '#/components/responses/Unauthorized' }
15099
+ '404': { $ref: '#/components/responses/NotFound' }
15100
+
15101
+ /v1/sequences/{sequenceId}/enroll/{contactId}:
15102
+ delete:
15103
+ operationId: unenrollContact
15104
+ summary: Unenroll a contact from a sequence
15105
+ tags: [Sequences]
15106
+ parameters:
15107
+ - { name: sequenceId, in: path, required: true, schema: { type: string } }
15108
+ - { name: contactId, in: path, required: true, schema: { type: string } }
15109
+ responses:
15110
+ '200': { description: Contact unenrolled }
15111
+ '401': { $ref: '#/components/responses/Unauthorized' }
15112
+ '404': { $ref: '#/components/responses/NotFound' }
15113
+
15114
+ /v1/sequences/{sequenceId}/enrollments:
15115
+ get:
15116
+ operationId: listSequenceEnrollments
15117
+ summary: List enrollments for a sequence
15118
+ tags: [Sequences]
15119
+ parameters:
15120
+ - { name: sequenceId, in: path, required: true, schema: { type: string } }
15121
+ - { name: status, in: query, schema: { type: string, enum: [active, completed, exited, paused] } }
15122
+ - { name: limit, in: query, schema: { type: integer, default: 50 } }
15123
+ - { name: skip, in: query, schema: { type: integer, default: 0 } }
15124
+ responses:
15125
+ '200': { description: Enrollments list with progress }
15126
+ '401': { $ref: '#/components/responses/Unauthorized' }
15127
+ '404': { $ref: '#/components/responses/NotFound' }
15128
+
15129
+ # ──────────────────────────────────────────────────────────────────────────
15130
+ # COMMENT AUTOMATIONS (Comment-to-DM)
15131
+ # ──────────────────────────────────────────────────────────────────────────
15132
+
15133
+ /v1/comment-automations:
15134
+ get:
15135
+ operationId: listCommentAutomations
15136
+ tags: [Comment Automations]
15137
+ summary: List comment-to-DM automations
15138
+ description: List all comment-to-DM automations for a profile. Returns automations with their stats.
15139
+ security:
15140
+ - bearerAuth: []
15141
+ parameters:
15142
+ - { name: profileId, in: query, required: true, schema: { type: string }, description: Profile ID }
15143
+ responses:
15144
+ '200':
15145
+ description: Automations list
15146
+ content:
15147
+ application/json:
15148
+ schema:
15149
+ type: object
15150
+ properties:
15151
+ success: { type: boolean }
15152
+ automations:
15153
+ type: array
15154
+ items:
15155
+ type: object
15156
+ properties:
15157
+ id: { type: string }
15158
+ name: { type: string }
15159
+ platform: { type: string, enum: [instagram, facebook] }
15160
+ accountId: { type: string }
15161
+ platformPostId: { type: string }
15162
+ postTitle: { type: string }
15163
+ keywords: { type: array, items: { type: string } }
15164
+ matchMode: { type: string, enum: [exact, contains] }
15165
+ dmMessage: { type: string }
15166
+ commentReply: { type: string }
15167
+ isActive: { type: boolean }
15168
+ stats:
15169
+ type: object
15170
+ properties:
15171
+ triggered: { type: integer }
15172
+ dmsSent: { type: integer }
15173
+ dmsFailed: { type: integer }
15174
+ uniqueContacts: { type: integer }
15175
+ createdAt: { type: string, format: date-time }
15176
+ '401': { $ref: '#/components/responses/Unauthorized' }
15177
+ post:
15178
+ operationId: createCommentAutomation
15179
+ tags: [Comment Automations]
15180
+ summary: Create a comment-to-DM automation
15181
+ description: |
15182
+ Create a keyword-triggered DM automation on an Instagram or Facebook post.
15183
+ When someone comments a matching keyword, they automatically receive a DM.
15184
+ Only one active automation per post is allowed.
15185
+ security:
15186
+ - bearerAuth: []
15187
+ requestBody:
15188
+ required: true
15189
+ content:
15190
+ application/json:
15191
+ schema:
15192
+ type: object
15193
+ required: [profileId, accountId, platformPostId, name, dmMessage]
15194
+ properties:
15195
+ profileId: { type: string }
15196
+ accountId: { type: string, description: Instagram or Facebook account ID }
15197
+ platformPostId: { type: string, description: Platform media/post ID }
15198
+ postId: { type: string, description: Zernio post ID (optional) }
15199
+ postTitle: { type: string, description: Post content snippet for display }
15200
+ name: { type: string, description: Automation label }
15201
+ keywords:
15202
+ type: array
15203
+ items: { type: string }
15204
+ description: Trigger keywords (empty = any comment triggers)
15205
+ matchMode: { type: string, enum: [exact, contains], default: contains }
15206
+ dmMessage: { type: string, description: DM text to send to commenter }
15207
+ commentReply: { type: string, description: Optional public reply to the comment }
15208
+ responses:
15209
+ '200': { description: Automation created }
15210
+ '400': { description: Validation error }
15211
+ '401': { $ref: '#/components/responses/Unauthorized' }
15212
+ '409': { description: Active automation already exists for this post }
15213
+
15214
+ /v1/comment-automations/{automationId}:
15215
+ get:
15216
+ operationId: getCommentAutomation
15217
+ tags: [Comment Automations]
15218
+ summary: Get automation details with recent logs
15219
+ security:
15220
+ - bearerAuth: []
15221
+ parameters:
15222
+ - { name: automationId, in: path, required: true, schema: { type: string } }
15223
+ responses:
15224
+ '200': { description: Automation details with stats and recent trigger logs }
15225
+ '401': { $ref: '#/components/responses/Unauthorized' }
15226
+ '404': { $ref: '#/components/responses/NotFound' }
15227
+ patch:
15228
+ operationId: updateCommentAutomation
15229
+ tags: [Comment Automations]
15230
+ summary: Update automation settings
15231
+ security:
15232
+ - bearerAuth: []
15233
+ parameters:
15234
+ - { name: automationId, in: path, required: true, schema: { type: string } }
15235
+ requestBody:
15236
+ content:
15237
+ application/json:
15238
+ schema:
15239
+ type: object
15240
+ properties:
15241
+ name: { type: string }
15242
+ keywords: { type: array, items: { type: string } }
15243
+ matchMode: { type: string, enum: [exact, contains] }
15244
+ dmMessage: { type: string }
15245
+ commentReply: { type: string }
15246
+ isActive: { type: boolean }
15247
+ responses:
15248
+ '200': { description: Automation updated }
15249
+ '401': { $ref: '#/components/responses/Unauthorized' }
15250
+ '404': { $ref: '#/components/responses/NotFound' }
15251
+ delete:
15252
+ operationId: deleteCommentAutomation
15253
+ tags: [Comment Automations]
15254
+ summary: Delete automation and all logs
15255
+ security:
15256
+ - bearerAuth: []
15257
+ parameters:
15258
+ - { name: automationId, in: path, required: true, schema: { type: string } }
15259
+ responses:
15260
+ '200': { description: Automation deleted }
15261
+ '401': { $ref: '#/components/responses/Unauthorized' }
15262
+ '404': { $ref: '#/components/responses/NotFound' }
15263
+
15264
+ /v1/comment-automations/{automationId}/logs:
15265
+ get:
15266
+ operationId: listCommentAutomationLogs
15267
+ tags: [Comment Automations]
15268
+ summary: List trigger logs for an automation
15269
+ description: Paginated list of every comment that triggered this automation, with send status and commenter info.
15270
+ security:
15271
+ - bearerAuth: []
15272
+ parameters:
15273
+ - { name: automationId, in: path, required: true, schema: { type: string } }
15274
+ - { name: status, in: query, schema: { type: string, enum: [sent, failed, skipped] }, description: Filter by result status }
15275
+ - { name: limit, in: query, schema: { type: integer, default: 50 } }
15276
+ - { name: skip, in: query, schema: { type: integer, default: 0 } }
15277
+ responses:
15278
+ '200': { description: Trigger logs with pagination }
15279
+ '401': { $ref: '#/components/responses/Unauthorized' }
15280
+ '404': { $ref: '#/components/responses/NotFound' }
15281
+