@ikatec/digisac-api-sdk 4.3.0 → 4.4.1

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 (65) hide show
  1. package/dist/apis/contacts/ContactsApi.cjs +70 -0
  2. package/dist/apis/contacts/ContactsApi.cjs.map +1 -1
  3. package/dist/apis/contacts/ContactsApi.d.ts +51 -1
  4. package/dist/apis/contacts/ContactsApi.d.ts.map +1 -1
  5. package/dist/apis/contacts/ContactsApi.mjs +70 -0
  6. package/dist/apis/contacts/ContactsApi.mjs.map +1 -1
  7. package/dist/apis/contacts/types.d.ts +141 -1
  8. package/dist/apis/contacts/types.d.ts.map +1 -1
  9. package/dist/apis/messages/MessagesApi.cjs +4 -1
  10. package/dist/apis/messages/MessagesApi.cjs.map +1 -1
  11. package/dist/apis/messages/MessagesApi.d.ts +5 -2
  12. package/dist/apis/messages/MessagesApi.d.ts.map +1 -1
  13. package/dist/apis/messages/MessagesApi.mjs +4 -1
  14. package/dist/apis/messages/MessagesApi.mjs.map +1 -1
  15. package/dist/apis/messages/types.d.ts +13 -0
  16. package/dist/apis/messages/types.d.ts.map +1 -1
  17. package/dist/apis/services/ServicesApi.cjs +8 -0
  18. package/dist/apis/services/ServicesApi.cjs.map +1 -1
  19. package/dist/apis/services/ServicesApi.d.ts +7 -1
  20. package/dist/apis/services/ServicesApi.d.ts.map +1 -1
  21. package/dist/apis/services/ServicesApi.mjs +8 -0
  22. package/dist/apis/services/ServicesApi.mjs.map +1 -1
  23. package/dist/apis/services/types.d.ts +7 -0
  24. package/dist/apis/services/types.d.ts.map +1 -1
  25. package/dist/apis/tags/TagsApi.cjs +24 -0
  26. package/dist/apis/tags/TagsApi.cjs.map +1 -1
  27. package/dist/apis/tags/TagsApi.d.ts +20 -1
  28. package/dist/apis/tags/TagsApi.d.ts.map +1 -1
  29. package/dist/apis/tags/TagsApi.mjs +24 -0
  30. package/dist/apis/tags/TagsApi.mjs.map +1 -1
  31. package/dist/apis/tags/types.d.ts +13 -0
  32. package/dist/apis/tags/types.d.ts.map +1 -1
  33. package/dist/apis/users/UsersApi.cjs +77 -0
  34. package/dist/apis/users/UsersApi.cjs.map +1 -1
  35. package/dist/apis/users/UsersApi.d.ts +59 -1
  36. package/dist/apis/users/UsersApi.d.ts.map +1 -1
  37. package/dist/apis/users/UsersApi.mjs +77 -0
  38. package/dist/apis/users/UsersApi.mjs.map +1 -1
  39. package/dist/apis/users/types.d.ts +123 -3
  40. package/dist/apis/users/types.d.ts.map +1 -1
  41. package/package.json +1 -1
  42. package/src/apis/acceptanceTerms/AcceptanceTermsApi.test.ts +1 -1
  43. package/src/apis/authHistory/AuthHistoryApi.test.ts +1 -1
  44. package/src/apis/campaigns/CampaignsApi.test.ts +1 -1
  45. package/src/apis/contacts/ContactsApi.test.ts +182 -5
  46. package/src/apis/contacts/ContactsApi.ts +128 -0
  47. package/src/apis/contacts/types.ts +154 -1
  48. package/src/apis/me/MeApi.test.ts +3 -3
  49. package/src/apis/messages/MessagesApi.test.ts +14 -3
  50. package/src/apis/messages/MessagesApi.ts +6 -3
  51. package/src/apis/messages/types.ts +13 -0
  52. package/src/apis/payloads.test-d.ts +26 -0
  53. package/src/apis/queryFormat.test.ts +27 -3
  54. package/src/apis/serviceAccessManagement/ServiceAccessManagementApi.test.ts +2 -2
  55. package/src/apis/services/ServicesApi.test.ts +49 -0
  56. package/src/apis/services/ServicesApi.ts +10 -1
  57. package/src/apis/services/types.ts +9 -0
  58. package/src/apis/stickerUsers/StickerUsersApi.test.ts +1 -1
  59. package/src/apis/tags/TagsApi.test.ts +84 -0
  60. package/src/apis/tags/TagsApi.ts +59 -1
  61. package/src/apis/tags/types.ts +15 -0
  62. package/src/apis/terms/TermsApi.test.ts +1 -1
  63. package/src/apis/users/UsersApi.test.ts +228 -0
  64. package/src/apis/users/UsersApi.ts +152 -1
  65. package/src/apis/users/types.ts +144 -3
@@ -6,21 +6,37 @@ export type UserPreferences = {
6
6
  audioSpeed?: number;
7
7
  isShowTagsChat?: boolean;
8
8
  };
9
+ export type UserData = {
10
+ /** Push token of the mobile app; cleared (`null`) when the user is archived. */
11
+ expoPushToken?: string | null;
12
+ [key: string]: unknown;
13
+ };
14
+ /** A connection the user is restricted to (`GET /users/:id` of a non-admin user). */
15
+ export type UserRestrictedService = {
16
+ id: string;
17
+ name: string;
18
+ };
19
+ /**
20
+ * A user as the API answers it (`userTransformer`). `isSuperAdmin`, `active` and `offlineAt` exist in
21
+ * the database but are never answered.
22
+ */
9
23
  export type User = {
10
24
  id: string;
11
25
  name: string;
12
26
  email: string;
13
27
  phoneNumber: string | null;
14
28
  branch: string | null;
15
- isSuperAdmin: boolean;
16
29
  isClientUser: boolean;
17
- active: boolean;
18
30
  language: string;
19
31
  isFirstLogin: boolean;
20
32
  status: UserStatus;
21
33
  clientsStatus: Record<string, string> | null;
22
- offlineAt: string | null;
23
34
  isActiveInternalChat: boolean;
35
+ /** Token of the internal chat; `null` right after the creation, regenerated on every write of the user. */
36
+ internalChatToken: string | null;
37
+ /** Set by the backend from an internal flag of the user. */
38
+ noteReference: boolean;
39
+ data: UserData;
24
40
  passwordExpiresAt: string | null;
25
41
  otpAuthActive: boolean | null;
26
42
  preferences: UserPreferences;
@@ -33,6 +49,8 @@ export type User = {
33
49
  timetable?: Timetable | null;
34
50
  roles?: Role[];
35
51
  departments?: Department[];
52
+ /** Only in `GET /users/:id`, for a user without an admin role. */
53
+ restrictedServices?: UserRestrictedService[];
36
54
  };
37
55
  export type UserRelationships = 'timetable' | 'roles' | 'departments';
38
56
  export type CreateUserPayload = {
@@ -62,4 +80,106 @@ export type UpdateUserPayload = {
62
80
  language?: string;
63
81
  archivedAt?: string | null;
64
82
  };
83
+ /** Body for `POST /users/:id/archive`. */
84
+ export type ArchiveUserPayload = {
85
+ /** `true` archives the user; `false` restores it. */
86
+ archive: boolean;
87
+ };
88
+ /** Body for `POST /users/bulk-status` and `POST /users/bulk-status/preview` (1 to 100 IDs). */
89
+ export type BulkUsersStatusPayload = {
90
+ ids: string[];
91
+ archive: boolean;
92
+ };
93
+ export type BulkUsersStatusScenario = 'emptySelection' | 'noneEligible' | 'allEligible' | 'partiallyBlocked' | 'onlySelfBlocked' | 'planLimitExceeded';
94
+ /** Read-only preview of a bulk status change: nothing is written. */
95
+ export type BulkUsersStatusPreview = {
96
+ scenario: BulkUsersStatusScenario;
97
+ totalSelected: number;
98
+ /** Users already in the target status. */
99
+ noop: number;
100
+ eligible: number;
101
+ /** Users that cannot change (e.g. referenced by a bot, or the acting user). */
102
+ blocked: number;
103
+ blockedSelf: boolean;
104
+ /** Free plan slots when unarchiving; `null` when archiving. */
105
+ planSlotsAvailable: number | null;
106
+ };
107
+ export type BulkUsersStatusResult = {
108
+ changed: number;
109
+ noop: number;
110
+ blocked: number;
111
+ failed: number;
112
+ changedIds: string[];
113
+ /** IDs of the batch that no longer exist in the account. */
114
+ missingIds: string[];
115
+ };
116
+ /** Body for `POST /users/export`. */
117
+ export type ExportUsersPayload = {
118
+ filter: 'all' | 'active' | 'archived';
119
+ };
120
+ /** A file previously uploaded through `FilesApi`. */
121
+ export type UserImportFile = {
122
+ id: string;
123
+ name: string;
124
+ mimetype: string;
125
+ url?: string;
126
+ urlToUpload?: string;
127
+ };
128
+ /** Body for `POST /users/import/validate`. */
129
+ export type ValidateUserImportPayload = {
130
+ file: UserImportFile;
131
+ };
132
+ export type UserImportRowsSummary = {
133
+ total: number;
134
+ valid: number;
135
+ invalid: number;
136
+ hasInvalid: boolean;
137
+ };
138
+ export type ValidateUserImportResult = {
139
+ licenses: {
140
+ requestedRows: number;
141
+ available: number;
142
+ exceeded: boolean;
143
+ };
144
+ columns: {
145
+ required: {
146
+ name: string;
147
+ found: boolean;
148
+ }[];
149
+ missingRequired: string[];
150
+ optionalFound: string[];
151
+ };
152
+ rows: UserImportRowsSummary;
153
+ /** Same rows validated with the optional columns applied. */
154
+ rowsWithOptionalColumns: UserImportRowsSummary;
155
+ };
156
+ /** Body for `POST /users/import`. */
157
+ export type ImportUsersPayload = {
158
+ file: UserImportFile;
159
+ useOptionalColumns?: boolean;
160
+ };
161
+ /** The import runs in the background (the route answers `202 Accepted`). */
162
+ export type ImportUsersResult = {
163
+ importId: string;
164
+ };
165
+ export type EnableUserAccessResult = {
166
+ success: boolean;
167
+ message: string;
168
+ };
169
+ /** Body for `PATCH /users/pin`: toggles the pin of a contact for the logged user (max. 3). */
170
+ export type TogglePinContactPayload = {
171
+ contactId: string;
172
+ };
173
+ /** Link row returned by `PATCH /users/pin` when the contact gets pinned. */
174
+ export type UserPinnedContactLink = {
175
+ userId: string;
176
+ contactId: string;
177
+ createdAt: string;
178
+ updatedAt: string;
179
+ };
180
+ /**
181
+ * Result of `PATCH /users/pin`: the created link rows when the contact gets pinned, or the
182
+ * number of removed links when it gets unpinned.
183
+ */
184
+ export type TogglePinContactResult = UserPinnedContactLink[] | number;
65
185
  //# sourceMappingURL=types.d.ts.map
@@ -1 +1 @@
1
- {"version":3,"file":"types.d.ts","sourceRoot":"","sources":["../../../src/apis/users/types.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,UAAU,EAAE,MAAM,sBAAsB,CAAA;AACtD,OAAO,KAAK,EAAE,IAAI,EAAE,MAAM,gBAAgB,CAAA;AAC1C,OAAO,KAAK,EAAE,SAAS,EAAE,MAAM,oBAAoB,CAAA;AAEnD,MAAM,MAAM,UAAU,GAAG,QAAQ,GAAG,SAAS,GAAG,MAAM,CAAA;AAEtD,MAAM,MAAM,eAAe,GAAG;IAC5B,UAAU,CAAC,EAAE,MAAM,CAAA;IACnB,cAAc,CAAC,EAAE,OAAO,CAAA;CACzB,CAAA;AAED,MAAM,MAAM,IAAI,GAAG;IACjB,EAAE,EAAE,MAAM,CAAA;IACV,IAAI,EAAE,MAAM,CAAA;IACZ,KAAK,EAAE,MAAM,CAAA;IACb,WAAW,EAAE,MAAM,GAAG,IAAI,CAAA;IAC1B,MAAM,EAAE,MAAM,GAAG,IAAI,CAAA;IACrB,YAAY,EAAE,OAAO,CAAA;IACrB,YAAY,EAAE,OAAO,CAAA;IACrB,MAAM,EAAE,OAAO,CAAA;IACf,QAAQ,EAAE,MAAM,CAAA;IAChB,YAAY,EAAE,OAAO,CAAA;IACrB,MAAM,EAAE,UAAU,CAAA;IAClB,aAAa,EAAE,MAAM,CAAC,MAAM,EAAE,MAAM,CAAC,GAAG,IAAI,CAAA;IAC5C,SAAS,EAAE,MAAM,GAAG,IAAI,CAAA;IACxB,oBAAoB,EAAE,OAAO,CAAA;IAC7B,iBAAiB,EAAE,MAAM,GAAG,IAAI,CAAA;IAChC,aAAa,EAAE,OAAO,GAAG,IAAI,CAAA;IAC7B,WAAW,EAAE,eAAe,CAAA;IAC5B,UAAU,EAAE,MAAM,GAAG,IAAI,CAAA;IACzB,SAAS,EAAE,MAAM,CAAA;IACjB,WAAW,EAAE,MAAM,GAAG,IAAI,CAAA;IAC1B,SAAS,EAAE,MAAM,CAAA;IACjB,SAAS,EAAE,MAAM,CAAA;IACjB,SAAS,EAAE,MAAM,GAAG,IAAI,CAAA;IAExB,SAAS,CAAC,EAAE,SAAS,GAAG,IAAI,CAAA;IAC5B,KAAK,CAAC,EAAE,IAAI,EAAE,CAAA;IACd,WAAW,CAAC,EAAE,UAAU,EAAE,CAAA;CAC3B,CAAA;AAED,MAAM,MAAM,iBAAiB,GAAG,WAAW,GAAG,OAAO,GAAG,aAAa,CAAA;AAErE,MAAM,MAAM,iBAAiB,GAAG;IAC9B,IAAI,EAAE,MAAM,CAAA;IACZ,KAAK,EAAE,MAAM,CAAA;IACb,QAAQ,EAAE,MAAM,CAAA;IAChB,oBAAoB,EAAE,MAAM,CAAA;IAC5B,WAAW,CAAC,EAAE,MAAM,CAAA;IACpB,MAAM,CAAC,EAAE,MAAM,CAAA;IACf,YAAY,CAAC,EAAE,OAAO,CAAA;IACtB,KAAK,CAAC,EAAE,MAAM,EAAE,CAAA;IAChB,WAAW,CAAC,EAAE,MAAM,EAAE,CAAA;IACtB,QAAQ,CAAC,EAAE,MAAM,EAAE,CAAA;IACnB,UAAU,CAAC,EAAE,MAAM,CAAA;CACpB,CAAA;AAED,MAAM,MAAM,iBAAiB,GAAG;IAC9B,IAAI,CAAC,EAAE,MAAM,CAAA;IACb,KAAK,CAAC,EAAE,MAAM,CAAA;IACd,WAAW,CAAC,EAAE,MAAM,GAAG,IAAI,CAAA;IAC3B,MAAM,CAAC,EAAE,MAAM,GAAG,IAAI,CAAA;IACtB,YAAY,CAAC,EAAE,OAAO,CAAA;IACtB,KAAK,CAAC,EAAE,MAAM,EAAE,CAAA;IAChB,WAAW,CAAC,EAAE,MAAM,EAAE,CAAA;IACtB,QAAQ,CAAC,EAAE,MAAM,EAAE,CAAA;IACnB,WAAW,CAAC,EAAE,MAAM,GAAG,IAAI,CAAA;IAC3B,WAAW,CAAC,EAAE,eAAe,CAAA;IAC7B,QAAQ,CAAC,EAAE,MAAM,CAAA;IACjB,UAAU,CAAC,EAAE,MAAM,GAAG,IAAI,CAAA;CAC3B,CAAA"}
1
+ {"version":3,"file":"types.d.ts","sourceRoot":"","sources":["../../../src/apis/users/types.ts"],"names":[],"mappings":"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"}
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@ikatec/digisac-api-sdk",
3
- "version": "4.3.0",
3
+ "version": "4.4.1",
4
4
  "type": "module",
5
5
  "main": "./dist/index.cjs",
6
6
  "module": "./dist/index.mjs",
@@ -87,7 +87,7 @@ describe('AcceptanceTermsApi', () => {
87
87
  it('includes the file relationship', async () => {
88
88
  vi.mocked(client.get).mockResolvedValue({ ...term, file: null })
89
89
  const result = await api.getById('at-1', { include: ['file'] })
90
- const url = vi.mocked(client.get).mock.calls[0][0] as string
90
+ const url = vi.mocked(client.get).mock.calls[0]?.[0] as string
91
91
  expect(url).toContain('/acceptance-terms/at-1?')
92
92
  expect(url).toContain('include')
93
93
  expect(result.file).toBeNull()
@@ -66,7 +66,7 @@ describe('AuthHistoryApi', () => {
66
66
  it('serializes query parameters', async () => {
67
67
  vi.mocked(client.get).mockResolvedValue(paginated)
68
68
  await api.getMany({ page: 2, perPage: 5 })
69
- const url = vi.mocked(client.get).mock.calls[0][0] as string
69
+ const url = vi.mocked(client.get).mock.calls[0]?.[0] as string
70
70
  expect(url).toContain('/auth-history?')
71
71
  expect(decodeURIComponent(url)).toContain('"page":2')
72
72
  })
@@ -94,7 +94,7 @@ describe('CampaignsApi', () => {
94
94
  it('serializes query parameters', async () => {
95
95
  vi.mocked(client.get).mockResolvedValue(paginated)
96
96
  await api.getMany({ page: 2, perPage: 5 })
97
- const url = vi.mocked(client.get).mock.calls[0][0] as string
97
+ const url = vi.mocked(client.get).mock.calls[0]?.[0] as string
98
98
  expect(url).toContain('/campaigns?')
99
99
  expect(decodeURIComponent(url)).toContain('"page":2')
100
100
  })
@@ -2,12 +2,20 @@ import { beforeEach, describe, expect, it, vi } from 'vitest'
2
2
  import { ContactsApi } from './ContactsApi'
3
3
  import type { ApiClient } from '../../core/ApiClient'
4
4
  import type {
5
+ BlockContactPayload,
6
+ BulkTransferTicketsPayload,
7
+ BulkTransferTicketsResult,
5
8
  Contact,
9
+ ContactMediaPage,
10
+ ContactsSelection,
6
11
  CreateContactPayload,
12
+ CreateManyContactsItem,
13
+ ExportCsvPayload,
7
14
  ExportTemplatePayload,
8
15
  CountContactsQuery,
9
16
  ExistsContactsParams,
10
17
  CountMediaResult,
18
+ ImportContactsPayload,
11
19
  } from './types'
12
20
  import type { Paginated } from '../../core/types'
13
21
 
@@ -101,7 +109,7 @@ describe('ContactsApi', () => {
101
109
  it('serializes query parameters', async () => {
102
110
  vi.mocked(client.get).mockResolvedValue(paginated)
103
111
  await api.getMany({ page: 2, perPage: 5 })
104
- const url = vi.mocked(client.get).mock.calls[0][0] as string
112
+ const url = vi.mocked(client.get).mock.calls[0]?.[0] as string
105
113
  expect(url).toContain('/contacts?')
106
114
  expect(decodeURIComponent(url)).toContain('"page":2')
107
115
  })
@@ -225,7 +233,7 @@ describe('ContactsApi', () => {
225
233
  vi.mocked(client.get).mockResolvedValue({ count: 10 })
226
234
  const query: CountContactsQuery = { where: { name: 'Alice' } }
227
235
  await api.count(query)
228
- const url = vi.mocked(client.get).mock.calls[0][0] as string
236
+ const url = vi.mocked(client.get).mock.calls[0]?.[0] as string
229
237
  expect(url).toContain('/contacts/count?')
230
238
  expect(url).toContain('where')
231
239
  })
@@ -270,7 +278,7 @@ describe('ContactsApi', () => {
270
278
  it('serializes query parameters', async () => {
271
279
  vi.mocked(client.get).mockResolvedValue(paginated)
272
280
  await api.forward({ page: 1, perPage: 10 })
273
- const url = vi.mocked(client.get).mock.calls[0][0] as string
281
+ const url = vi.mocked(client.get).mock.calls[0]?.[0] as string
274
282
  expect(url).toContain('/contacts/forward?')
275
283
  })
276
284
 
@@ -289,7 +297,7 @@ describe('ContactsApi', () => {
289
297
  vi.mocked(client.get).mockResolvedValue({ '1234567890': true })
290
298
  const params: ExistsContactsParams = { serviceId: 'svc-1', numbers: ['1234567890'] }
291
299
  const result = await api.exists(params)
292
- const url = vi.mocked(client.get).mock.calls[0][0] as string
300
+ const url = vi.mocked(client.get).mock.calls[0]?.[0] as string
293
301
  expect(url).toContain('/contacts/exists?')
294
302
  expect(url).toContain('serviceId=svc-1')
295
303
  expect(result).toEqual({ '1234567890': true })
@@ -299,7 +307,7 @@ describe('ContactsApi', () => {
299
307
  vi.mocked(client.get).mockResolvedValue({})
300
308
  const headers = { 'X-Custom': 'h' }
301
309
  await api.exists({ serviceId: 'svc-1', numbers: [] }, headers)
302
- expect(vi.mocked(client.get).mock.calls[0][1]).toEqual(headers)
310
+ expect(vi.mocked(client.get).mock.calls[0]?.[1]).toEqual(headers)
303
311
  })
304
312
  })
305
313
 
@@ -365,6 +373,175 @@ describe('ContactsApi', () => {
365
373
  })
366
374
  })
367
375
 
376
+ // ── createMany ───────────────────────────────────────────────────
377
+
378
+ describe('createMany', () => {
379
+ const items: CreateManyContactsItem[] = [
380
+ { serviceId: 'svc-1', name: 'Alice', number: '5511999990001' },
381
+ { serviceId: 'svc-1', name: 'Bob', number: '5511999990002', tagIds: ['t1'] },
382
+ ]
383
+
384
+ it('calls client.post with /contacts/many and the array body', async () => {
385
+ vi.mocked(client.post).mockResolvedValue([contact])
386
+ const result = await api.createMany(items)
387
+ expect(client.post).toHaveBeenCalledWith('/contacts/many', items, undefined)
388
+ expect(result).toEqual([contact])
389
+ })
390
+
391
+ it('serializes the query and forwards custom headers', async () => {
392
+ const headers = { 'X-Custom': 'value' }
393
+ await api.createMany(items, { include: ['tags'] }, headers)
394
+ const [url, body, sentHeaders] = vi.mocked(client.post).mock.calls[0] ?? []
395
+ expect(decodeURIComponent(url as string)).toBe('/contacts/many?query={"include":["tags"]}')
396
+ expect(body).toBe(items)
397
+ expect(sentHeaders).toBe(headers)
398
+ })
399
+ })
400
+
401
+ // ── deleteMany ───────────────────────────────────────────────────
402
+
403
+ describe('deleteMany', () => {
404
+ it('calls client.request with DELETE /contacts/many and the selection', async () => {
405
+ vi.mocked(client.request).mockResolvedValue(true)
406
+ const body: ContactsSelection = { where: { id: { $in: ['c1', 'c2'] } } }
407
+ const result = await api.deleteMany(body)
408
+ expect(client.request).toHaveBeenCalledWith('DELETE', '/contacts/many', body, undefined)
409
+ expect(result).toBe(true)
410
+ })
411
+
412
+ it('forwards custom headers', async () => {
413
+ const headers = { 'X-Custom': 'value' }
414
+ await api.deleteMany({ where: { id: 'c1' } }, headers)
415
+ expect(client.request).toHaveBeenCalledWith(
416
+ 'DELETE',
417
+ '/contacts/many',
418
+ { where: { id: 'c1' } },
419
+ headers,
420
+ )
421
+ })
422
+ })
423
+
424
+ // ── exportCsv ────────────────────────────────────────────────────
425
+
426
+ describe('exportCsv', () => {
427
+ it('calls client.post with /contacts/export/csv and resolves to the CSV text', async () => {
428
+ const csv = 'Nome,DDI,Número\nAlice,55,11999990001\n'
429
+ vi.mocked(client.post).mockResolvedValue(csv)
430
+ const body: ExportCsvPayload = {
431
+ serviceType: 'whatsapp',
432
+ type: 'comma',
433
+ where: { id: 'cnt-1' },
434
+ }
435
+ const result = await api.exportCsv(body)
436
+ expect(client.post).toHaveBeenCalledWith('/contacts/export/csv', body, undefined)
437
+ expect(result).toBe(csv)
438
+ })
439
+ })
440
+
441
+ // ── importCsv ────────────────────────────────────────────────────
442
+
443
+ describe('importCsv', () => {
444
+ it('calls client.post with /contacts/import-contacts and body', async () => {
445
+ const body: ImportContactsPayload = {
446
+ service: { id: 'svc-1', accountId: 'acc-1', type: 'whatsapp' },
447
+ file: { id: 'f1', name: 'contacts.csv', mimetype: 'text/csv', urlToUpload: 'https://s3' },
448
+ csvHeaderLine: ['Nome', 'DDI', 'Número'],
449
+ type: 'comma',
450
+ tagsIds: ['t1'],
451
+ }
452
+ vi.mocked(client.post).mockResolvedValue('OK')
453
+ const headers = { 'X-Custom': 'value' }
454
+ const result = await api.importCsv(body, headers)
455
+ expect(client.post).toHaveBeenCalledWith('/contacts/import-contacts', body, headers)
456
+ expect(result).toBe('OK')
457
+ })
458
+ })
459
+
460
+ // ── sync ─────────────────────────────────────────────────────────
461
+
462
+ describe('sync', () => {
463
+ it('calls client.post with /contacts/:id/sync and an empty body by default', async () => {
464
+ vi.mocked(client.post).mockResolvedValue('OK')
465
+ const result = await api.sync('c1')
466
+ expect(client.post).toHaveBeenCalledWith('/contacts/c1/sync', {}, undefined)
467
+ expect(result).toBe('OK')
468
+ })
469
+
470
+ it('sends forceSync and forwards custom headers', async () => {
471
+ const headers = { 'X-Custom': 'value' }
472
+ await api.sync('c1', { forceSync: true }, headers)
473
+ expect(client.post).toHaveBeenCalledWith('/contacts/c1/sync', { forceSync: true }, headers)
474
+ })
475
+ })
476
+
477
+ // ── block ────────────────────────────────────────────────────────
478
+
479
+ describe('block', () => {
480
+ it('calls client.post with /contacts/:id/block and body', async () => {
481
+ vi.mocked(client.post).mockResolvedValue({ ...contact, block: true })
482
+ const body: BlockContactPayload = { block: true, description: 'spam' }
483
+ const result = await api.block('c1', body)
484
+ expect(client.post).toHaveBeenCalledWith('/contacts/c1/block', body, undefined)
485
+ expect(result.block).toBe(true)
486
+ })
487
+ })
488
+
489
+ // ── markRead ─────────────────────────────────────────────────────
490
+
491
+ describe('markRead', () => {
492
+ it('calls client.post with /contacts/:id/mark-read and no body', async () => {
493
+ vi.mocked(client.post).mockResolvedValue('OK')
494
+ const headers = { 'X-Custom': 'value' }
495
+ const result = await api.markRead('c1', headers)
496
+ expect(client.post).toHaveBeenCalledWith('/contacts/c1/mark-read', undefined, headers)
497
+ expect(result).toBe('OK')
498
+ })
499
+ })
500
+
501
+ // ── getMedia ─────────────────────────────────────────────────────
502
+
503
+ describe('getMedia', () => {
504
+ const page: ContactMediaPage = { data: [], limit: 50, hasNextPage: false, nextCursor: null }
505
+
506
+ it('calls client.get with /contacts/:id/media when no query is provided', async () => {
507
+ vi.mocked(client.get).mockResolvedValue(page)
508
+ const result = await api.getMedia('c1')
509
+ expect(client.get).toHaveBeenCalledWith('/contacts/c1/media', undefined)
510
+ expect(result).toEqual(page)
511
+ })
512
+
513
+ it('serializes the type, cursor and perPage', async () => {
514
+ await api.getMedia('c1', {
515
+ where: { type: 'document', cursor: '2026-01-01T00:00:00Z' },
516
+ perPage: 10,
517
+ })
518
+ const url = decodeURIComponent(vi.mocked(client.get).mock.calls[0]?.[0] as string)
519
+ expect(url).toBe(
520
+ '/contacts/c1/media?query={"where":{"type":"document","cursor":"2026-01-01T00:00:00Z"},"perPage":10}',
521
+ )
522
+ })
523
+ })
524
+
525
+ // ── bulkTransferTickets ──────────────────────────────────────────
526
+
527
+ describe('bulkTransferTickets', () => {
528
+ it('calls client.post with /contacts/ticket/bulk-transfer and body', async () => {
529
+ const response: BulkTransferTicketsResult = {
530
+ message: 'Transferência realizada com sucesso',
531
+ ticketsSelectedId: ['t1'],
532
+ }
533
+ vi.mocked(client.post).mockResolvedValue(response)
534
+ const body: BulkTransferTicketsPayload = {
535
+ departmentId: 'd1',
536
+ userId: null,
537
+ ticketsSelectedId: ['t1'],
538
+ }
539
+ const result = await api.bulkTransferTickets(body)
540
+ expect(client.post).toHaveBeenCalledWith('/contacts/ticket/bulk-transfer', body, undefined)
541
+ expect(result).toEqual(response)
542
+ })
543
+ })
544
+
368
545
  // ── Error propagation ────────────────────────────────────────────
369
546
 
370
547
  describe('error propagation', () => {
@@ -3,12 +3,22 @@ import type { ApiClient } from '../../core/ApiClient'
3
3
  import { BaseCrudApi } from '../../core/BaseCrudApi'
4
4
  import type { ListQuery, Paginated } from '../../core/types'
5
5
  import type {
6
+ BlockContactPayload,
7
+ BulkTransferTicketsPayload,
8
+ BulkTransferTicketsResult,
6
9
  Contact,
10
+ ContactMediaPage,
11
+ ContactMediaQuery,
12
+ ContactsSelection,
7
13
  CountContactsQuery,
8
14
  CountMediaResult,
9
15
  CreateContactPayload,
16
+ CreateManyContactsItem,
10
17
  ExistsContactsParams,
18
+ ExportCsvPayload,
11
19
  ExportTemplatePayload,
20
+ ImportContactsPayload,
21
+ SyncContactPayload,
12
22
  TransferTicketPayload,
13
23
  UpdateContactPayload,
14
24
  } from './types'
@@ -120,4 +130,122 @@ export class ContactsApi extends BaseCrudApi<Contact, CreateContactPayload, Upda
120
130
  headers,
121
131
  )
122
132
  }
133
+
134
+ /**
135
+ * Creates or updates several contacts in one call. Existing contacts (same service and
136
+ * number or e-mail) are updated; the others are created. Returns the resulting contacts.
137
+ * @permissions contacts.view OR contacts.update OR contacts.create
138
+ */
139
+ createMany(
140
+ body: CreateManyContactsItem[],
141
+ query?: ListQuery<Contact>,
142
+ headers?: Record<string, string>,
143
+ ): Promise<Contact[]> {
144
+ const queryString = this.toQueryString(query)
145
+ return this.client.post<Contact[], CreateManyContactsItem[]>(
146
+ `${this.basePath}/many${queryString}`,
147
+ body,
148
+ headers,
149
+ )
150
+ }
151
+
152
+ /**
153
+ * Deletes every contact of the account that matches the selection.
154
+ * @permissions contacts.view OR contacts.destroy
155
+ */
156
+ deleteMany(body: ContactsSelection, headers?: Record<string, string>): Promise<boolean> {
157
+ return this.client.request<boolean, ContactsSelection>(
158
+ 'DELETE',
159
+ `${this.basePath}/many`,
160
+ body,
161
+ headers,
162
+ )
163
+ }
164
+
165
+ /**
166
+ * Exports the contacts that match the filter as CSV. Resolves to the CSV text.
167
+ * @permissions contacts.view AND contacts.export
168
+ */
169
+ exportCsv(body: ExportCsvPayload, headers?: Record<string, string>): Promise<string> {
170
+ return this.client.post<string, ExportCsvPayload>(`${this.basePath}/export/csv`, body, headers)
171
+ }
172
+
173
+ /**
174
+ * Starts the import of a CSV file previously uploaded through `FilesApi`. The import runs
175
+ * in the background; the header line is validated against the service type template.
176
+ * Resolves to `'OK'`.
177
+ * @permissions contacts.view OR contacts.update OR contacts.create
178
+ */
179
+ importCsv(body: ImportContactsPayload, headers?: Record<string, string>): Promise<string> {
180
+ return this.client.post<string, ImportContactsPayload>(
181
+ `${this.basePath}/import-contacts`,
182
+ body,
183
+ headers,
184
+ )
185
+ }
186
+
187
+ /**
188
+ * Marks the contact as read and, when needed, syncs it with the messaging service.
189
+ * Resolves to `'OK'`.
190
+ * @permissions contacts.view OR contacts.update
191
+ */
192
+ sync(id: string, body?: SyncContactPayload, headers?: Record<string, string>): Promise<string> {
193
+ return this.client.post<string, SyncContactPayload>(
194
+ `${this.basePath}/${id}/sync`,
195
+ body ?? {},
196
+ headers,
197
+ )
198
+ }
199
+
200
+ /**
201
+ * Blocks or unblocks a contact. Blocking closes the contact's open ticket. Requires the
202
+ * block list to be active on the account.
203
+ * @permissions contacts.block
204
+ */
205
+ block(id: string, body: BlockContactPayload, headers?: Record<string, string>): Promise<Contact> {
206
+ return this.client.post<Contact, BlockContactPayload>(
207
+ `${this.basePath}/${id}/block`,
208
+ body,
209
+ headers,
210
+ )
211
+ }
212
+
213
+ /**
214
+ * Resets the contact's unread counter. Resolves to `'OK'`.
215
+ * @permissions contacts.view OR contacts.update
216
+ */
217
+ markRead(id: string, headers?: Record<string, string>): Promise<string> {
218
+ return this.client.post<string>(`${this.basePath}/${id}/mark-read`, undefined, headers)
219
+ }
220
+
221
+ /**
222
+ * Returns the files and links exchanged with a contact, cursor-paginated.
223
+ * @permissions contacts.view
224
+ */
225
+ getMedia(
226
+ contactId: string,
227
+ query?: ContactMediaQuery,
228
+ headers?: Record<string, string>,
229
+ ): Promise<ContactMediaPage> {
230
+ const queryString = this.toQueryString(query)
231
+ return this.client.get<ContactMediaPage>(
232
+ `${this.basePath}/${contactId}/media${queryString}`,
233
+ headers,
234
+ )
235
+ }
236
+
237
+ /**
238
+ * Transfers several tickets at once to a department and/or user.
239
+ * @permissions tickets.transfer.all.bulk
240
+ */
241
+ bulkTransferTickets(
242
+ body: BulkTransferTicketsPayload,
243
+ headers?: Record<string, string>,
244
+ ): Promise<BulkTransferTicketsResult> {
245
+ return this.client.post<BulkTransferTicketsResult, BulkTransferTicketsPayload>(
246
+ `${this.basePath}/ticket/bulk-transfer`,
247
+ body,
248
+ headers,
249
+ )
250
+ }
123
251
  }