@ikatec/digisac-api-sdk 4.15.0 → 4.16.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 (189) hide show
  1. package/README.md +3 -1
  2. package/dist/apis/absence/AbsenceApi.cjs +2 -2
  3. package/dist/apis/absence/AbsenceApi.cjs.map +1 -1
  4. package/dist/apis/absence/AbsenceApi.d.ts +2 -2
  5. package/dist/apis/absence/AbsenceApi.mjs +2 -2
  6. package/dist/apis/absence/AbsenceApi.mjs.map +1 -1
  7. package/dist/apis/absence/types.d.ts +1 -1
  8. package/dist/apis/answers/AnswersApi.cjs +23 -2
  9. package/dist/apis/answers/AnswersApi.cjs.map +1 -1
  10. package/dist/apis/answers/AnswersApi.d.ts +16 -2
  11. package/dist/apis/answers/AnswersApi.d.ts.map +1 -1
  12. package/dist/apis/answers/AnswersApi.mjs +23 -2
  13. package/dist/apis/answers/AnswersApi.mjs.map +1 -1
  14. package/dist/apis/answers/types.d.ts +1 -2
  15. package/dist/apis/answers/types.d.ts.map +1 -1
  16. package/dist/apis/bots/BotsApi.cjs +16 -7
  17. package/dist/apis/bots/BotsApi.cjs.map +1 -1
  18. package/dist/apis/bots/BotsApi.d.ts +13 -7
  19. package/dist/apis/bots/BotsApi.d.ts.map +1 -1
  20. package/dist/apis/bots/BotsApi.mjs +16 -7
  21. package/dist/apis/bots/BotsApi.mjs.map +1 -1
  22. package/dist/apis/bots/types.d.ts +12 -2
  23. package/dist/apis/bots/types.d.ts.map +1 -1
  24. package/dist/apis/campaigns/CampaignsApi.cjs +25 -1
  25. package/dist/apis/campaigns/CampaignsApi.cjs.map +1 -1
  26. package/dist/apis/campaigns/CampaignsApi.d.ts +16 -1
  27. package/dist/apis/campaigns/CampaignsApi.d.ts.map +1 -1
  28. package/dist/apis/campaigns/CampaignsApi.mjs +25 -1
  29. package/dist/apis/campaigns/CampaignsApi.mjs.map +1 -1
  30. package/dist/apis/campaigns/types.d.ts +98 -6
  31. package/dist/apis/campaigns/types.d.ts.map +1 -1
  32. package/dist/apis/cards/types.d.ts +5 -5
  33. package/dist/apis/categories/CategoriesApi.cjs +1 -2
  34. package/dist/apis/categories/CategoriesApi.cjs.map +1 -1
  35. package/dist/apis/categories/CategoriesApi.d.ts +1 -2
  36. package/dist/apis/categories/CategoriesApi.d.ts.map +1 -1
  37. package/dist/apis/categories/CategoriesApi.mjs +1 -2
  38. package/dist/apis/categories/CategoriesApi.mjs.map +1 -1
  39. package/dist/apis/clientFeedback/ClientFeedbackApi.cjs +2 -3
  40. package/dist/apis/clientFeedback/ClientFeedbackApi.cjs.map +1 -1
  41. package/dist/apis/clientFeedback/ClientFeedbackApi.d.ts +2 -3
  42. package/dist/apis/clientFeedback/ClientFeedbackApi.d.ts.map +1 -1
  43. package/dist/apis/clientFeedback/ClientFeedbackApi.mjs +2 -3
  44. package/dist/apis/clientFeedback/ClientFeedbackApi.mjs.map +1 -1
  45. package/dist/apis/contacts/ContactsApi.cjs +10 -6
  46. package/dist/apis/contacts/ContactsApi.cjs.map +1 -1
  47. package/dist/apis/contacts/ContactsApi.d.ts +19 -3
  48. package/dist/apis/contacts/ContactsApi.d.ts.map +1 -1
  49. package/dist/apis/contacts/ContactsApi.mjs +10 -6
  50. package/dist/apis/contacts/ContactsApi.mjs.map +1 -1
  51. package/dist/apis/contacts/types.d.ts +25 -0
  52. package/dist/apis/contacts/types.d.ts.map +1 -1
  53. package/dist/apis/customFields/types.d.ts +4 -4
  54. package/dist/apis/dashboard/DashboardApi.cjs +3 -3
  55. package/dist/apis/dashboard/DashboardApi.cjs.map +1 -1
  56. package/dist/apis/dashboard/DashboardApi.d.ts +3 -3
  57. package/dist/apis/dashboard/DashboardApi.mjs +3 -3
  58. package/dist/apis/dashboard/DashboardApi.mjs.map +1 -1
  59. package/dist/apis/dashboard/types.d.ts +11 -4
  60. package/dist/apis/dashboard/types.d.ts.map +1 -1
  61. package/dist/apis/departments/DepartmentsApi.cjs +5 -5
  62. package/dist/apis/departments/DepartmentsApi.cjs.map +1 -1
  63. package/dist/apis/departments/DepartmentsApi.d.ts +5 -5
  64. package/dist/apis/departments/DepartmentsApi.mjs +5 -5
  65. package/dist/apis/departments/DepartmentsApi.mjs.map +1 -1
  66. package/dist/apis/departments/types.d.ts +6 -0
  67. package/dist/apis/departments/types.d.ts.map +1 -1
  68. package/dist/apis/distribution/DistributionApi.cjs +3 -4
  69. package/dist/apis/distribution/DistributionApi.cjs.map +1 -1
  70. package/dist/apis/distribution/DistributionApi.d.ts +3 -4
  71. package/dist/apis/distribution/DistributionApi.d.ts.map +1 -1
  72. package/dist/apis/distribution/DistributionApi.mjs +3 -4
  73. package/dist/apis/distribution/DistributionApi.mjs.map +1 -1
  74. package/dist/apis/kanbanCards/KanbanCardsApi.cjs +32 -0
  75. package/dist/apis/kanbanCards/KanbanCardsApi.cjs.map +1 -1
  76. package/dist/apis/kanbanCards/KanbanCardsApi.d.ts +27 -1
  77. package/dist/apis/kanbanCards/KanbanCardsApi.d.ts.map +1 -1
  78. package/dist/apis/kanbanCards/KanbanCardsApi.mjs +32 -0
  79. package/dist/apis/kanbanCards/KanbanCardsApi.mjs.map +1 -1
  80. package/dist/apis/kanbanCards/types.d.ts +1 -1
  81. package/dist/apis/kanbanCards/types.d.ts.map +1 -1
  82. package/dist/apis/kanbanColumns/KanbanColumnsApi.cjs +19 -0
  83. package/dist/apis/kanbanColumns/KanbanColumnsApi.cjs.map +1 -1
  84. package/dist/apis/kanbanColumns/KanbanColumnsApi.d.ts +16 -1
  85. package/dist/apis/kanbanColumns/KanbanColumnsApi.d.ts.map +1 -1
  86. package/dist/apis/kanbanColumns/KanbanColumnsApi.mjs +19 -0
  87. package/dist/apis/kanbanColumns/KanbanColumnsApi.mjs.map +1 -1
  88. package/dist/apis/kanbanColumns/types.d.ts +4 -0
  89. package/dist/apis/kanbanColumns/types.d.ts.map +1 -1
  90. package/dist/apis/messages/MessagesApi.cjs +13 -4
  91. package/dist/apis/messages/MessagesApi.cjs.map +1 -1
  92. package/dist/apis/messages/MessagesApi.d.ts +13 -4
  93. package/dist/apis/messages/MessagesApi.d.ts.map +1 -1
  94. package/dist/apis/messages/MessagesApi.mjs +13 -4
  95. package/dist/apis/messages/MessagesApi.mjs.map +1 -1
  96. package/dist/apis/messages/types.d.ts +5 -0
  97. package/dist/apis/messages/types.d.ts.map +1 -1
  98. package/dist/apis/pipeline/types.d.ts +7 -8
  99. package/dist/apis/pipeline/types.d.ts.map +1 -1
  100. package/dist/apis/quickReplies/types.d.ts +4 -1
  101. package/dist/apis/quickReplies/types.d.ts.map +1 -1
  102. package/dist/apis/schedule/types.d.ts +41 -10
  103. package/dist/apis/schedule/types.d.ts.map +1 -1
  104. package/dist/apis/terms/TermsApi.cjs +2 -2
  105. package/dist/apis/terms/TermsApi.cjs.map +1 -1
  106. package/dist/apis/terms/TermsApi.d.ts +2 -2
  107. package/dist/apis/terms/TermsApi.mjs +2 -2
  108. package/dist/apis/terms/TermsApi.mjs.map +1 -1
  109. package/dist/apis/tickets/TicketsApi.cjs +18 -8
  110. package/dist/apis/tickets/TicketsApi.cjs.map +1 -1
  111. package/dist/apis/tickets/TicketsApi.d.ts +15 -8
  112. package/dist/apis/tickets/TicketsApi.d.ts.map +1 -1
  113. package/dist/apis/tickets/TicketsApi.mjs +18 -8
  114. package/dist/apis/tickets/TicketsApi.mjs.map +1 -1
  115. package/dist/apis/tickets/types.d.ts +4 -1
  116. package/dist/apis/tickets/types.d.ts.map +1 -1
  117. package/dist/apis/timetable/TimetableApi.cjs +6 -0
  118. package/dist/apis/timetable/TimetableApi.cjs.map +1 -1
  119. package/dist/apis/timetable/TimetableApi.d.ts +6 -0
  120. package/dist/apis/timetable/TimetableApi.d.ts.map +1 -1
  121. package/dist/apis/timetable/TimetableApi.mjs +6 -0
  122. package/dist/apis/timetable/TimetableApi.mjs.map +1 -1
  123. package/dist/apis/timetable/types.d.ts +8 -0
  124. package/dist/apis/timetable/types.d.ts.map +1 -1
  125. package/dist/apis/users/UsersApi.cjs +11 -3
  126. package/dist/apis/users/UsersApi.cjs.map +1 -1
  127. package/dist/apis/users/UsersApi.d.ts +10 -4
  128. package/dist/apis/users/UsersApi.d.ts.map +1 -1
  129. package/dist/apis/users/UsersApi.mjs +11 -3
  130. package/dist/apis/users/UsersApi.mjs.map +1 -1
  131. package/dist/apis/users/types.d.ts +26 -0
  132. package/dist/apis/users/types.d.ts.map +1 -1
  133. package/dist/apis/webhooks/types.d.ts +51 -6
  134. package/dist/apis/webhooks/types.d.ts.map +1 -1
  135. package/dist/core/errors.cjs +4 -1
  136. package/dist/core/errors.cjs.map +1 -1
  137. package/dist/core/errors.d.ts +4 -1
  138. package/dist/core/errors.d.ts.map +1 -1
  139. package/dist/core/errors.mjs +4 -1
  140. package/dist/core/errors.mjs.map +1 -1
  141. package/package.json +1 -1
  142. package/src/apis/absence/AbsenceApi.ts +2 -2
  143. package/src/apis/absence/types.ts +1 -1
  144. package/src/apis/answers/AnswersApi.test.ts +32 -0
  145. package/src/apis/answers/AnswersApi.ts +38 -2
  146. package/src/apis/answers/types.ts +1 -2
  147. package/src/apis/bots/BotsApi.test.ts +16 -0
  148. package/src/apis/bots/BotsApi.ts +25 -7
  149. package/src/apis/bots/types.ts +12 -2
  150. package/src/apis/campaigns/CampaignsApi.test.ts +48 -0
  151. package/src/apis/campaigns/CampaignsApi.ts +31 -2
  152. package/src/apis/campaigns/types.ts +101 -3
  153. package/src/apis/cards/types.ts +5 -5
  154. package/src/apis/categories/CategoriesApi.ts +1 -2
  155. package/src/apis/clientFeedback/ClientFeedbackApi.ts +2 -3
  156. package/src/apis/contacts/ContactsApi.test.ts +36 -2
  157. package/src/apis/contacts/ContactsApi.ts +41 -3
  158. package/src/apis/contacts/types.ts +28 -0
  159. package/src/apis/creditMovements/CreditMovementsApi.test.ts +1 -1
  160. package/src/apis/customFields/types.ts +4 -4
  161. package/src/apis/dashboard/DashboardApi.test-d.ts +9 -0
  162. package/src/apis/dashboard/DashboardApi.ts +3 -3
  163. package/src/apis/dashboard/types.ts +11 -4
  164. package/src/apis/departments/DepartmentsApi.ts +5 -5
  165. package/src/apis/departments/types.ts +13 -0
  166. package/src/apis/distribution/DistributionApi.ts +3 -4
  167. package/src/apis/kanbanCards/KanbanCardsApi.test.ts +21 -0
  168. package/src/apis/kanbanCards/KanbanCardsApi.ts +47 -1
  169. package/src/apis/kanbanCards/types.ts +1 -1
  170. package/src/apis/kanbanColumns/KanbanColumnsApi.test.ts +26 -0
  171. package/src/apis/kanbanColumns/KanbanColumnsApi.ts +31 -0
  172. package/src/apis/kanbanColumns/types.ts +5 -0
  173. package/src/apis/messages/MessagesApi.ts +13 -4
  174. package/src/apis/messages/types.ts +5 -0
  175. package/src/apis/payloads.test-d.ts +206 -4
  176. package/src/apis/pipeline/types.ts +7 -8
  177. package/src/apis/queryFormat.test.ts +13 -0
  178. package/src/apis/quickReplies/types.ts +4 -1
  179. package/src/apis/schedule/types.ts +42 -10
  180. package/src/apis/terms/TermsApi.ts +2 -2
  181. package/src/apis/tickets/TicketsApi.ts +28 -8
  182. package/src/apis/tickets/types.ts +4 -1
  183. package/src/apis/timetable/TimetableApi.ts +6 -0
  184. package/src/apis/timetable/types.ts +9 -0
  185. package/src/apis/users/UsersApi.test.ts +17 -0
  186. package/src/apis/users/UsersApi.ts +21 -3
  187. package/src/apis/users/types.ts +28 -0
  188. package/src/apis/webhooks/types.ts +53 -6
  189. package/src/core/errors.ts +4 -1
@@ -3,6 +3,7 @@ import { BaseCrudApi } from '../../core/BaseCrudApi'
3
3
  import type {
4
4
  KanbanColumn,
5
5
  CreateKanbanColumnPayload,
6
+ DeleteKanbanColumnPayload,
6
7
  ReorderKanbanColumnPayload,
7
8
  UpdateKanbanColumnPayload,
8
9
  } from './types'
@@ -16,6 +17,36 @@ export class KanbanColumnsApi extends BaseCrudApi<
16
17
  super(client, '/kanban-columns')
17
18
  }
18
19
 
20
+ /**
21
+ * Deletes a column and its cards (their tickets are kept as they are). The `'initial'` and
22
+ * `'final'` columns cannot be deleted (500). Resolves to the deleted column. To keep the cards,
23
+ * use {@link deleteMovingCards}.
24
+ * @permissions kanban.columns.destroy
25
+ */
26
+ override deleteById(id: string, headers?: Record<string, string>): Promise<KanbanColumn> {
27
+ return super.deleteById(id, headers)
28
+ }
29
+
30
+ /**
31
+ * Deletes a column after moving its cards to the top of another column of the board, in their
32
+ * order. The cards move as `KanbanCardsApi.reorder` moves them: to the `'final'` column,
33
+ * their open tickets are closed. The `'initial'` and `'final'` columns cannot be deleted (500).
34
+ * Resolves to the deleted column.
35
+ * @permissions kanban.columns.destroy
36
+ */
37
+ deleteMovingCards(
38
+ id: string,
39
+ body: DeleteKanbanColumnPayload,
40
+ headers?: Record<string, string>,
41
+ ): Promise<KanbanColumn> {
42
+ return this.client.request<KanbanColumn, DeleteKanbanColumnPayload>(
43
+ 'DELETE',
44
+ `${this.basePath}/${id}`,
45
+ body,
46
+ headers,
47
+ )
48
+ }
49
+
19
50
  /**
20
51
  * Moves a column between two neighbours of the same board. Both the column and a neighbour
21
52
  * must be draggable; swapped neighbours (`before` after `after`) fail with 500. Resolves to the
@@ -50,3 +50,8 @@ export type ReorderKanbanColumnPayload = {
50
50
  /** The column that ends up on the right. */
51
51
  afterColumnId?: string
52
52
  }
53
+
54
+ export type DeleteKanbanColumnPayload = {
55
+ /** The column of the same board that receives the cards of the deleted one. */
56
+ cardsDestinationColumnId: string
57
+ }
@@ -24,10 +24,19 @@ export class MessagesApi extends BaseCrudApi<Message, CreateMessagePayload, Upda
24
24
  }
25
25
 
26
26
  /**
27
- * Edits the text (or the file) of a message sent by the account, up to 15 minutes after it was
28
- * sent (403 `Cannot edit message` after that). `contactId` is required (without it the route
29
- * answers 500), and `text` or `file` (400 without both). Sent as `PATCH /messages/:id`.
30
- * @permissions messages.update
27
+ * Edits the text of a message sent by the account, up to 15 minutes after it was sent. Sent as
28
+ * `PATCH /messages/:id`. `contactId` is required: without it the route answers 500, and an
29
+ * unknown or blocked contact answers 400 `The given data was invalid.` (the error comes in
30
+ * `contactId`). So is `text`: `text: ''` alone answers 400 (`At least one field (text or file)
31
+ * must be provided`), and a `text` with only spaces answers 400 `Text cannot be empty`. Only the
32
+ * text is edited: `file` is not sent to the connection. A message received, or sent more than
33
+ * 15 minutes ago, answers 403 `Cannot edit message`; an unknown message answers 404
34
+ * `Message not found`. The message passes to the user who edited it.
35
+ *
36
+ * The message is answered once the edit is sent to the connection, before the connection
37
+ * confirms it: read it again until `text` changes (`data.edited` is set to `true` when the
38
+ * connection reports the edit). On WhatsApp Business and Telegram connections the route answers
39
+ * the result of the edit job, not the message: read it again with `getById`.
31
40
  */
32
41
  override updateById(
33
42
  id: string,
@@ -62,6 +62,11 @@ export type MessageData = {
62
62
  subject?: unknown
63
63
  resourceId?: string
64
64
  hasReaction?: boolean
65
+ /**
66
+ * `true` once the connection reports that the text was edited (see `MessagesApi.updateById`; on
67
+ * WhatsApp, an edit made by the contact included).
68
+ */
69
+ edited?: boolean
65
70
  whatsappMessageId?: string
66
71
  startBlockedAt?: string
67
72
  endBlockedAt?: string
@@ -13,6 +13,7 @@ import type {
13
13
  CampaignContactsPage,
14
14
  CampaignMessage,
15
15
  CampaignStats,
16
+ CampaignTemplateParameter,
16
17
  CampaignTimelineEvent,
17
18
  } from './campaigns/types'
18
19
  import { CardsApi } from './cards/CardsApi'
@@ -36,7 +37,7 @@ import { QuestionsApi } from './questions/QuestionsApi'
36
37
  import { QuickRepliesApi } from './quickReplies/QuickRepliesApi'
37
38
  import { RolesApi } from './roles/RolesApi'
38
39
  import { ScheduleApi } from './schedule/ScheduleApi'
39
- import type { ScheduleRecord } from './schedule/types'
40
+ import type { Schedule, ScheduleRecord } from './schedule/types'
40
41
  import type {
41
42
  CreateServicePayload,
42
43
  Service,
@@ -48,6 +49,7 @@ import { TicketTopicsApi } from './ticketTopics/TicketTopicsApi'
48
49
  import { TicketsApi } from './tickets/TicketsApi'
49
50
  import type { Ticket, TicketTransfer, TicketsCount, TicketsCounts } from './tickets/types'
50
51
  import { TimetableApi } from './timetable/TimetableApi'
52
+ import type { OutOfOfficeHoursErrorExtra, TimetableWorkSlot } from './timetable/types'
51
53
  import { UsersApi } from './users/UsersApi'
52
54
 
53
55
  import { AcceptanceTermsApi } from './acceptanceTerms/AcceptanceTermsApi'
@@ -59,12 +61,14 @@ import type {
59
61
  CustomFieldValue,
60
62
  FormattedCustomField,
61
63
  SummarizeTicketResult,
64
+ TransferTicketKanbanCardResult,
65
+ TransferTicketPayload,
62
66
  } from './contacts/types'
63
67
  import { AuthHistoryApi } from './authHistory/AuthHistoryApi'
64
68
  import type { AuthHistoryEvent } from './authHistory/types'
65
69
  import { CustomFieldsApi } from './customFields/CustomFieldsApi'
66
70
  import { DepartmentsApi } from './departments/DepartmentsApi'
67
- import type { Department } from './departments/types'
71
+ import type { ArchiveDepartmentErrorExtra, Department } from './departments/types'
68
72
  import type { Distribution } from './distribution/types'
69
73
  import type { ContactBlockList } from './contactBlockLists/types'
70
74
  import { DistributionApi } from './distribution/DistributionApi'
@@ -93,8 +97,11 @@ import type { Sticker } from './stickers/types'
93
97
  import { OrganizationsApi } from './organizations/OrganizationsApi'
94
98
  import { PeopleApi } from './people/PeopleApi'
95
99
  import { ServicesApi } from './services/ServicesApi'
96
- import type { UpdateUserPayload, User } from './users/types'
100
+ import type { BulkUpdateUsersLinksResult, UpdateUserPayload, User } from './users/types'
97
101
  import { WebhooksApi } from './webhooks/WebhooksApi'
102
+ import type { KanbanColumn } from './kanbanColumns/types'
103
+ import type { Message } from './messages/types'
104
+ import type { Webhook, WebhookMessageFilters, WebhookType } from './webhooks/types'
98
105
 
99
106
  declare const client: ApiClient
100
107
 
@@ -313,7 +320,7 @@ expectError(pipelines.deleteStatus('st-1', { action: 'move-to-another' }))
313
320
  expectError(pipelines.createAutomation({ pipelineId: 'p-1', type: 'email' }))
314
321
  expectError(pipelines.deleteStage('s-1', { typeAction: 'archive' }))
315
322
 
316
- // ── cards: getCards is not scoped by the backend and only answers the attributes asked ─
323
+ // ── cards: getCards takes where.accountId and only answers the attributes asked ─
317
324
 
318
325
  const cards = new CardsApi(client)
319
326
  cards.getCards({
@@ -807,3 +814,198 @@ expectType<Promise<string>>(new FilesApi(client).duplicateFile({ fileId: 'file-1
807
814
  expectError(new FilesApi(client).duplicateFile({ urlToUpload: 'https://storage' }))
808
815
  expectType<Promise<void>>(new AuthHistoryApi(client).registerLogout())
809
816
  expectAssignable<AuthHistoryEvent>('2fa_disabled')
817
+
818
+ // ── QARC-948 (4.16.0): the open subtasks ─────────────────────────────
819
+
820
+ // campaigns: one page of one campaign, and the fields the create reads
821
+ expectType<Promise<Campaign | null>>(new CampaignsApi(client).getOne({ status: 'ready' }))
822
+ expectAssignable<Parameters<CampaignsApi['create']>[0]>({
823
+ title: 'Campanha',
824
+ serviceId: 's-1',
825
+ text: 'Olá',
826
+ messages: [{ text: 'Olá', base64Url: 'data:image/png;base64,AAAA' }],
827
+ fileId: 'f-1',
828
+ nameField: 'Nome',
829
+ numberField: 'Número',
830
+ usernameField: 'Usuário',
831
+ hsmFileId: 'f-2',
832
+ })
833
+
834
+ // campaigns: the update reads its own fields and updates the messages by id
835
+ expectAssignable<Parameters<CampaignsApi['updateById']>[1]>({
836
+ title: 'Campanha',
837
+ messages: [{ id: 'm-1', text: 'Olá' }, { text: 'Nova' }],
838
+ })
839
+ expectAssignable<Parameters<CampaignsApi['updateById']>[1]>({
840
+ config: { minInterval: '1', maxInterval: '5' },
841
+ messages: [
842
+ { id: 'm-1', text: 'Olá', file: { id: 'f-1' } },
843
+ {
844
+ id: 'm-2',
845
+ base64Url: 'data:image/png;base64,AAAA',
846
+ fileName: 'b.png',
847
+ },
848
+ ],
849
+ })
850
+ expectError(new CampaignsApi(client).updateById('cmp-1', { text: 'Olá' }))
851
+ expectError(new CampaignsApi(client).updateById('cmp-1', { usernameField: 'Usuário' }))
852
+ expectError(new CampaignsApi(client).updateById('cmp-1', { hsmFileId: 'f-2' }))
853
+ expectAssignable<CampaignTemplateParameter>({
854
+ type: 'header',
855
+ parameters: [{ type: 'image', image: { link: 'https://example.invalid/a.png' } }],
856
+ })
857
+
858
+ // messages: the edit flag of the connection
859
+ declare const editedMessage: Message
860
+ expectType<boolean | undefined>(editedMessage.data.edited)
861
+
862
+ // schedule: the template parameters
863
+ expectAssignable<Parameters<ScheduleApi['create']>[0]>({
864
+ scheduledAt: '2026-10-20T12:00:00.000Z',
865
+ contactId: 'c-1',
866
+ departmentId: 'd-1',
867
+ notes: '',
868
+ hsmId: 'h-1',
869
+ extraOptions: { parameters: [{ type: 'body', parameters: [{ type: 'text', text: 'Ana' }] }] },
870
+ })
871
+ expectError(
872
+ new ScheduleApi(client).create({
873
+ scheduledAt: '2026-10-20T12:00:00.000Z',
874
+ contactId: 'c-1',
875
+ departmentId: 'd-1',
876
+ notes: '',
877
+ extraOptions: { parameters: 'Ana' },
878
+ }),
879
+ )
880
+
881
+ declare const storedSchedule: Schedule
882
+ expectType<CampaignTemplateParameter[] | undefined>(storedSchedule.extraOptions?.parameters)
883
+
884
+ // kanban: deleting a column moving its cards
885
+ expectType<Promise<KanbanColumn>>(
886
+ new KanbanColumnsApi(client).deleteMovingCards('col-1', { cardsDestinationColumnId: 'col-2' }),
887
+ )
888
+ expectError(new KanbanColumnsApi(client).deleteMovingCards('col-1', {}))
889
+ expectType<Promise<KanbanColumn>>(new KanbanColumnsApi(client).deleteById('col-1'))
890
+
891
+ // contacts: the result of the transfer and the close of the ticket
892
+ const ticketContacts = new ContactsApi(client)
893
+ expectType<Promise<TransferTicketKanbanCardResult>>(
894
+ ticketContacts.transferTicket('c-1', { departmentId: 'd-1', includeKanbanCardId: true }),
895
+ )
896
+ expectType<Promise<true>>(ticketContacts.transferTicket('c-1', { departmentId: 'd-1' }))
897
+ declare const transferPayload: TransferTicketPayload
898
+ expectType<Promise<true | TransferTicketKanbanCardResult>>(
899
+ ticketContacts.transferTicket('c-1', transferPayload),
900
+ )
901
+ declare const transferResult: TransferTicketKanbanCardResult
902
+ expectType<string | null>(transferResult.kanbanCardId)
903
+ expectType<Promise<true>>(ticketContacts.closeTicket('c-1'))
904
+ expectType<Promise<true>>(
905
+ ticketContacts.closeTicket('c-1', { ticketTopicIds: ['tt-1'], aiSummaryRating: '5' }),
906
+ )
907
+ expectError(ticketContacts.closeTicket('c-1', { aiSummaryRating: '6' }))
908
+
909
+ // webhooks: the type, the connections and the message filters
910
+ declare const webhook: Webhook
911
+ expectType<WebhookType>(webhook.type)
912
+ expectType<WebhookMessageFilters | null | undefined>(webhook.messageFilters)
913
+ expectType<number | null | undefined>(webhook.avgLatencyMs)
914
+ expectAssignable<Parameters<WebhooksApi['create']>[0]>({
915
+ name: 'Webhook',
916
+ url: 'https://example.invalid/hook',
917
+ type: 'by_service',
918
+ events: ['message.created'],
919
+ services: ['s-1'],
920
+ messageFilters: { bot: false, system: false },
921
+ })
922
+ expectAssignable<Parameters<WebhooksApi['create']>[0]>({
923
+ name: 'Webhook',
924
+ url: 'https://example.invalid/hook',
925
+ type: 'general',
926
+ events: ['message.created'],
927
+ messageFilters: null,
928
+ })
929
+ expectError(
930
+ new WebhooksApi(client).create({
931
+ name: 'Webhook',
932
+ url: 'https://example.invalid/hook',
933
+ type: 'other',
934
+ events: [],
935
+ }),
936
+ )
937
+ expectError(
938
+ new WebhooksApi(client).create({
939
+ name: 'Webhook',
940
+ url: 'https://example.invalid/hook',
941
+ type: 'general',
942
+ events: [],
943
+ messageFilters: { comments: false },
944
+ }),
945
+ )
946
+ expectError(new WebhooksApi(client).updateById('w-1', { active: false }))
947
+ const hookUrl = 'https://example.invalid/hook'
948
+ const hooks = new WebhooksApi(client)
949
+ expectError(hooks.updateById('w-1', { url: hookUrl, type: 'general', events: [] }))
950
+ expectError(hooks.updateById('w-1', { name: 'Webhook', type: 'general', events: [] }))
951
+ expectError(hooks.updateById('w-1', { name: 'Webhook', url: hookUrl, events: [] }))
952
+ expectError(hooks.updateById('w-1', { name: 'Webhook', url: hookUrl, type: 'general' }))
953
+ expectError(hooks.updateById('w-1', { name: 'Webhook', url: hookUrl, type: 'other', events: [] }))
954
+ expectAssignable<WebhookType>('whatsapp_low_level')
955
+ expectAssignable<WebhookMessageFilters>({ received: true, sent: false, bot: true, system: false })
956
+ expectAssignable<Parameters<WebhooksApi['updateById']>[1]>({
957
+ name: 'Webhook',
958
+ url: 'https://example.invalid/hook',
959
+ type: 'by_service',
960
+ events: ['message.created'],
961
+ services: ['s-1'],
962
+ messageFilters: { received: false },
963
+ })
964
+ expectAssignable<Parameters<WebhooksApi['updateById']>[1]>({
965
+ name: 'Webhook',
966
+ url: 'https://example.invalid/hook',
967
+ type: 'general',
968
+ events: ['message.created'],
969
+ messageFilters: null,
970
+ })
971
+
972
+ // users, bots and answers
973
+ expectType<Promise<BulkUpdateUsersLinksResult>>(
974
+ new UsersApi(client).bulkUpdateLinks({ ids: ['u-1'], timetableId: null }),
975
+ )
976
+ expectError(new UsersApi(client).bulkUpdateLinks({ timetableId: 't-1' }))
977
+ expectType<Promise<ArrayBuffer>>(new BotsApi(client).exportErrors('b-1'))
978
+ expectType<Promise<Response>>(new AnswersApi(client).exportTxtRaw())
979
+ expectType<Promise<Response>>(new AnswersApi(client).exportCsvRaw())
980
+
981
+ // QARC-948, second review: the remaining fields of the new types
982
+ expectAssignable<CampaignTemplateParameter>({
983
+ type: 'header',
984
+ parameters: [
985
+ { type: 'video', video: { link: 'https://example.invalid/a.mp4' } },
986
+ { type: 'document', document: { link: 'https://example.invalid/a.pdf' } },
987
+ ],
988
+ })
989
+ expectAssignable<Parameters<ContactsApi['closeTicket']>[1]>({ comments: 'Resolvido' })
990
+ expectAssignable<TransferTicketPayload>({ departmentId: 'd-1', includeKanbanCardId: true })
991
+ expectError(
992
+ new ScheduleApi(client).updateById('sch-1', {
993
+ scheduledAt: '2026-10-20T12:00:00.000Z',
994
+ contactId: 'c-1',
995
+ departmentId: 'd-1',
996
+ extraOptions: { parameters: 'Ana' },
997
+ }),
998
+ )
999
+ expectAssignable<Parameters<UsersApi['bulkUpdateLinks']>[0]>({
1000
+ ids: ['u-1'],
1001
+ departmentIds: ['d-1'],
1002
+ roleIds: ['r-1'],
1003
+ })
1004
+ declare const linksResult: BulkUpdateUsersLinksResult
1005
+ expectType<number>(linksResult.failed)
1006
+ expectType<string[]>(linksResult.missingIds)
1007
+ declare const outOfOffice: OutOfOfficeHoursErrorExtra
1008
+ expectType<TimetableWorkSlot[]>(outOfOffice.workPlan)
1009
+ declare const archiveRefusal: ArchiveDepartmentErrorExtra
1010
+ expectAssignable<ArchiveDepartmentErrorExtra['reasons'][number]>('ONLY_ONE')
1011
+ expectType<number | undefined>(archiveRefusal.openTicketsCount)
@@ -129,8 +129,7 @@ export type CreatePipelineStagePayload = {
129
129
 
130
130
  export type UpdatePipelineStagePayload = CreatePipelineStagePayload & {
131
131
  /**
132
- * The stage id. Send it: the duplicate-name check compares against the `id` of the body,
133
- * so without it keeping the current name answers `'STAGE_ALREADY_EXIST'`.
132
+ * The stage id. Send it: without it, keeping the current name answers `'STAGE_ALREADY_EXIST'`.
134
133
  */
135
134
  id?: string
136
135
  }
@@ -145,10 +144,10 @@ export type DeletePipelineStagePayload = {
145
144
  typeAction?: 'move'
146
145
  idNewStage?: string
147
146
  /**
148
- * Author of the card movements written by `'move'` — the backend reads it from the body, not
149
- * from the token (the UI sends the logged user). Without it, moving a stage that has cards
150
- * fails with 500 (`CardMovement.userId cannot be null`) after the cards were already moved,
151
- * and the stage is kept.
147
+ * The user that moves the cards with `'move'`: send the logged user (`{ id }` of
148
+ * `MeApi.getMe`). Without it, moving a stage that has cards fails with 500
149
+ * (`CardMovement.userId cannot be null`) after the cards were already moved, and the stage is
150
+ * kept.
152
151
  */
153
152
  user?: { id: string }
154
153
  }
@@ -163,7 +162,7 @@ export type PipelineStageStatusWithCount = PipelineStageStatus & { cardsCount: n
163
162
 
164
163
  /**
165
164
  * What happens to the cards of a deleted status: `'keep-without-status'` clears their status,
166
- * `'move-to-another'` sets `newStatusId` (not validated by the backend).
165
+ * `'move-to-another'` moves them to the status `newStatusId`.
167
166
  */
168
167
  export type DeletePipelineStatusPayload =
169
168
  | { action: 'keep-without-status' }
@@ -192,7 +191,7 @@ export type PipelineAutomation = {
192
191
 
193
192
  export type CreatePipelineAutomationPayload = {
194
193
  pipelineId: string
195
- /** The backend does not validate it (any string is stored); `'notification'` is the only one used. */
194
+ /** `'notification'` is the only one used. */
196
195
  type: PipelineAutomationType
197
196
  config?: PipelineAutomationConfig
198
197
  isArchived?: boolean
@@ -65,6 +65,19 @@ const cases: Case[] = [
65
65
  return (f ? api.withQueryFormat(f) : api).getMany(campaignsQuery)
66
66
  },
67
67
  },
68
+ {
69
+ name: 'CampaignsApi.getOne (one page of one campaign)',
70
+ path: '/campaigns',
71
+ query: { ...campaignsQuery, page: 1, perPage: 1 },
72
+ call: (client, f) => {
73
+ const api = new CampaignsApi(client)
74
+ return (f ? api.withQueryFormat(f) : api).getOne({
75
+ ...campaignsQuery,
76
+ paginate: false,
77
+ limit: 5,
78
+ })
79
+ },
80
+ },
68
81
  {
69
82
  name: 'CampaignsApi.getContacts',
70
83
  path: '/campaigns/c1/contacts',
@@ -49,7 +49,10 @@ export type UpdateQuickReplyPayload = {
49
49
  files: QuickReplyFilePayload[]
50
50
  }
51
51
 
52
- /** The query of `loadOnDemand`, passed to the database as is. */
52
+ /**
53
+ * The query of `loadOnDemand`: the `where`, `include`, `order`, `attributes`, `limit` and `offset`
54
+ * of a list query.
55
+ */
53
56
  export type QuickRepliesLoadOnDemandQuery = Pick<
54
57
  ListQuery<QuickReply>,
55
58
  'where' | 'include' | 'order' | 'attributes' | 'limit' | 'offset'
@@ -1,29 +1,52 @@
1
+ import type { CampaignTemplateParameter } from '../campaigns/types'
1
2
  import type { Contact } from '../contacts/types'
2
3
  import type { Department } from '../departments/types'
3
4
  import type { File } from '../files/types'
4
5
  import type { User } from '../users/types'
5
6
 
6
- /** `scheduled` until the worker runs it; `error` and `not_sent` come with the `reason`. */
7
+ /**
8
+ * - `scheduled`: waiting for the worker.
9
+ * - `done`: sent, or skipped with `reason: null` (contact blocked, connection off, open ticket
10
+ * without `sendWithOpenTicket`, user without access to the connection). It is stored
11
+ * before the message is sent, so a template schedule can still turn `error` afterwards.
12
+ * Archiving the connection also sets its `scheduled` schedules as `done`, and archiving the
13
+ * department every schedule of it (keeping the `reason` of the ones that had failed).
14
+ * - `not_sent`: only for a template schedule (`hsmId`), with `HSM_IS_BLOCKED` or
15
+ * `SERVICE_IS_BLOCKED`.
16
+ * - `error`: `DDD_BLOCKED` for any schedule; the other reasons only for a template schedule sent
17
+ * with `extraOptions` (a plain schedule is `done` instead).
18
+ */
7
19
  export type ScheduleStatus = 'scheduled' | 'done' | 'error' | 'not_sent'
8
20
 
21
+ /** The template parameters of a WhatsApp Business schedule (`hsmId`), sent with the message. */
22
+ export type ScheduleExtraOptions = {
23
+ /** The parameters of the header, body and buttons of the template, as a campaign takes them. */
24
+ parameters?: CampaignTemplateParameter[]
25
+ [key: string]: unknown
26
+ }
27
+
9
28
  export type Schedule = {
10
29
  id: string
11
30
  status: ScheduleStatus
12
31
  /**
13
- * Why it was not sent: `ALREADY_TICKET_OPENED`, `DDD_BLOCKED`, `SERVICE_IS_NOT_ENABLED`,
14
- * `CONTACT_IS_BLOCKED`, `CONTACT_NOT_EXISTS`, `HSM_LIMIT_EXCEEDED`, `HSM_IS_BLOCKED`,
15
- * `SERVICE_IS_BLOCKED`, `INVALID_PAYLOAD`, a WhatsApp Business error code or
16
- * `SCHEDULE_UNKNOWN_REASON`.
32
+ * Why an `error` or `not_sent` schedule was not sent (see {@link ScheduleStatus}):
33
+ * `ALREADY_TICKET_OPENED`, `DDD_BLOCKED`, `SERVICE_IS_NOT_ENABLED`, `CONTACT_IS_BLOCKED`,
34
+ * `CONTACT_NOT_EXISTS`, `HSM_LIMIT_EXCEEDED`, `HSM_IS_BLOCKED`, `SERVICE_IS_BLOCKED`,
35
+ * `INVALID_PAYLOAD`, a WhatsApp Business error code or `SCHEDULE_UNKNOWN_REASON`. Usually `null`
36
+ * for a `done` schedule (see the archiving of the department in {@link ScheduleStatus}).
17
37
  */
18
38
  reason: string | null
19
- /** For a WhatsApp Business template (`hsmId`), the message the server built from it. */
39
+ /**
40
+ * For a WhatsApp Business template (`hsmId`) sent with `extraOptions`, the message the server
41
+ * built from it; otherwise the `message` sent.
42
+ */
20
43
  message: string | null
21
44
  notes: string
22
45
  openTicket: boolean | null
23
46
  notificateUser: boolean | null
24
47
  /** Sends the message even when the contact already has an open ticket. */
25
48
  sendWithOpenTicket: boolean | null
26
- extraOptions: Record<string, unknown> | null
49
+ extraOptions: ScheduleExtraOptions | null
27
50
  hsmId: string | null
28
51
  hsmFileId: string | null
29
52
  scheduledAt: string
@@ -73,7 +96,11 @@ export type CreateSchedulePayload = {
73
96
  scheduledAt: string
74
97
  contactId: string
75
98
  departmentId: string
76
- /** Up to 1024 characters. Optional for a WhatsApp Business template, built from `hsmId`. */
99
+ /**
100
+ * Up to 1024 characters. Optional for a WhatsApp Business template sent with `extraOptions` (the
101
+ * server builds it from the template); without both, the schedule turns `done` and no message is
102
+ * sent.
103
+ */
77
104
  message?: string
78
105
  /**
79
106
  * Up to 1024 characters. Required by the route only with `openTicket: true`, but the column is
@@ -85,8 +112,13 @@ export type CreateSchedulePayload = {
85
112
  sendWithOpenTicket?: boolean
86
113
  userId?: string
87
114
  hsmId?: string
115
+ /** The header file of the template (`hsmId`), uploaded with `attachedType: 'hsm.file'`. */
88
116
  hsmFileId?: string
89
- extraOptions?: Record<string, unknown>
117
+ /**
118
+ * Send it with `hsmId` (`{}` is enough for a template without parameters): without it the
119
+ * schedule sends `message` as plain text, not the template.
120
+ */
121
+ extraOptions?: ScheduleExtraOptions
90
122
  /** New attachments only: the create drops `{ id }` items. */
91
123
  files?: ScheduleNewFilePayload[]
92
124
  }
@@ -107,7 +139,7 @@ export type UpdateSchedulePayload = {
107
139
  sendWithOpenTicket?: boolean
108
140
  hsmId?: string | null
109
141
  hsmFileId?: string | null
110
- extraOptions?: Record<string, unknown> | null
142
+ extraOptions?: ScheduleExtraOptions | null
111
143
  /** Replaces the attachments: `{ id }` keeps one, `{ base64, ... }` adds one; omitted or `[]` removes all. */
112
144
  files?: ScheduleFilePayload[]
113
145
  }
@@ -6,8 +6,8 @@ import type { Term } from './types'
6
6
  * Platform terms of use. Terms are published by Agnus (billing) and accepted by the account users,
7
7
  * so the `/terms` route has no create/list/update/delete — only the routes below.
8
8
  *
9
- * `GET /terms/:id/export-pdf` is not exposed: it answers a binary PDF, and `ApiClient` only
10
- * handles JSON/text bodies.
9
+ * `GET /terms/:id/export-pdf` (a binary PDF) has no method: read it with `client.requestRaw` (see
10
+ * "Raw responses" in the README).
11
11
  */
12
12
  export class TermsApi extends BaseApi implements HasGetById<Term> {
13
13
  public readonly basePath = '/terms'
@@ -1,5 +1,6 @@
1
1
  import type { ApiClient } from '../../core/ApiClient'
2
2
  import { BaseCrudApi } from '../../core/BaseCrudApi'
3
+ import type { GetByIdQuery } from '../../core/types'
3
4
  import type {
4
5
  Ticket,
5
6
  CreateTicketPayload,
@@ -15,23 +16,42 @@ import type {
15
16
  /**
16
17
  * Tickets. The backend only serves them for reading (`getMany`, `getOne`, `getById`, the counts,
17
18
  * the first waiting time and the exports) plus `closeMany`: a ticket is opened and transferred by
18
- * `ContactsApi.transferTicket`. The reads check no permission (any authenticated user): the
19
- * `@permissions` of the inherited `getMany`, `getOne` and `getById` do not apply here. `getById`
20
- * of an unknown id resolves `null`. For a user who is not an admin, `getMany` leaves out the
21
- * tickets of the contacts of the connections restricted to that user; the counts and `getById`
22
- * do not.
19
+ * `ContactsApi.transferTicket`, and the ticket of one contact is closed by
20
+ * `ContactsApi.closeTicket`. `getById` of an unknown id resolves `null`. For a user who is not an
21
+ * admin, `getMany` leaves out the tickets of the contacts of the connections restricted to that
22
+ * user.
23
23
  */
24
24
  export class TicketsApi extends BaseCrudApi<Ticket, CreateTicketPayload, UpdateTicketPayload> {
25
25
  constructor(client: ApiClient) {
26
26
  super(client, '/tickets')
27
27
  }
28
28
 
29
+ /** Returns the first ticket matching the query, or `null` when none match. */
30
+ override getOne(
31
+ query?: TicketsListQuery,
32
+ headers?: Record<string, string>,
33
+ ): Promise<Ticket | null> {
34
+ return super.getOne(query, headers)
35
+ }
36
+
37
+ /** Returns a ticket by ID; an unknown id resolves `null`. */
38
+ override getById(
39
+ id: string,
40
+ query?: GetByIdQuery<Ticket>,
41
+ headers?: Record<string, string>,
42
+ ): Promise<Ticket> {
43
+ return super.getById(id, query, headers)
44
+ }
45
+
29
46
  /** @deprecated Not served: `POST /tickets` answers 404 `Route not found.`. Open a ticket through `ContactsApi.transferTicket`. */
30
47
  override create(body: CreateTicketPayload, headers?: Record<string, string>): Promise<Ticket> {
31
48
  return super.create(body, headers)
32
49
  }
33
50
 
34
- /** @deprecated Not served: `PUT /tickets/{id}` answers 404 `Route not found.`. Transfer through `ContactsApi.transferTicket`, close through `closeMany`. */
51
+ /**
52
+ * @deprecated Not served: `PUT /tickets/{id}` answers 404 `Route not found.`. Transfer through
53
+ * `ContactsApi.transferTicket`, close through `ContactsApi.closeTicket` or `closeMany`.
54
+ */
35
55
  override updateById(
36
56
  id: string,
37
57
  body: UpdateTicketPayload,
@@ -46,8 +66,8 @@ export class TicketsApi extends BaseCrudApi<Ticket, CreateTicketPayload, UpdateT
46
66
  }
47
67
 
48
68
  /**
49
- * Closes multiple tickets in a single request. This is the only ticket-close
50
- * endpoint exposed by the API — there is no per-ticket close/update route.
69
+ * Closes multiple tickets in a single request. `ContactsApi.closeTicket` closes the ticket of one
70
+ * contact by the contact id, and also takes the rating of the AI summary.
51
71
  *
52
72
  * Pass `{ ids }` to close specific tickets, or `{ allContactsSelected: true, query }`
53
73
  * to close every OPEN ticket matching `query` (the backend forces `isOpen: true`): an empty
@@ -142,7 +142,10 @@ export type CreateTicketPayload = {
142
142
  origin?: TicketOrigin
143
143
  }
144
144
 
145
- /** @deprecated Not served: the backend has no `PUT /tickets/{id}`. Transfer through `ContactsApi.transferTicket`, close through `TicketsApi.closeMany`. */
145
+ /**
146
+ * @deprecated Not served: the backend has no `PUT /tickets/{id}`. Transfer through
147
+ * `ContactsApi.transferTicket`, close through `ContactsApi.closeTicket` or `TicketsApi.closeMany`.
148
+ */
146
149
  export type UpdateTicketPayload = {
147
150
  departmentId?: string
148
151
  userId?: string | null
@@ -3,6 +3,12 @@ import type { ListQuery } from '../../core/types'
3
3
  import { BaseCrudApi } from '../../core/BaseCrudApi'
4
4
  import type { Timetable, CreateTimetablePayload, UpdateTimetablePayload } from './types'
5
5
 
6
+ /**
7
+ * Timetables (work hours) of the users. Out of the timetable of the user, most authenticated routes
8
+ * answer 403 `Is out of office hours`, with the `workPlan` of the timetable in the `extra` of the
9
+ * error body (see `OutOfOfficeHoursErrorExtra`). Logging in (`POST /oauth/token`) and setting
10
+ * the status to `offline` still work.
11
+ */
6
12
  export class TimetableApi extends BaseCrudApi<
7
13
  Timetable,
8
14
  CreateTimetablePayload,
@@ -32,3 +32,12 @@ export type CreateTimetablePayload = {
32
32
 
33
33
  /** The backend requires the three fields on every update (400 `required` otherwise). */
34
34
  export type UpdateTimetablePayload = CreateTimetablePayload
35
+
36
+ /**
37
+ * The `extra` of the 403 `Is out of office hours` error body: the timetable of the user. The error
38
+ * is a `PermissionDeniedError` with that `message`; read it as
39
+ * `(error.body as { extra?: OutOfOfficeHoursErrorExtra }).extra?.workPlan`.
40
+ */
41
+ export type OutOfOfficeHoursErrorExtra = {
42
+ workPlan: TimetableWorkSlot[]
43
+ }