@ikatec/digisac-api-sdk 4.7.0 → 4.8.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.
@@ -1,16 +1,20 @@
1
+ import type { ListQuery } from '../../core';
2
+ import type { Account } from '../accounts';
1
3
  import type { Department } from '../departments';
2
4
  import type { File } from '../files';
3
- import type { Message } from '../messages';
4
5
  import type { Service } from '../services';
5
6
  import type { Tag } from '../tags';
6
7
  import type { User } from '../users';
7
8
  import type { WhatsappBusinessTemplate } from '../whatsappBusinessTemplates';
8
9
  export type CampaignStatus = 'ready' | 'queued' | 'processing' | 'paused' | 'waiting_connection' | 'canceled' | 'done' | 'insufficient_credits' | 'hsm_limit_exceeded' | 'import_error' | 'error' | 'importing_contacts' | 'preventive_break';
9
10
  export type CampaignConfig = {
10
- /** Minimum interval in ms between sends. */
11
- minInterval: number;
12
- /** Maximum interval in ms between sends. */
13
- maxInterval: number;
11
+ /**
12
+ * Minimum interval in ms between sends. Absent until set (a new campaign answers `config: {}`);
13
+ * `setIntervalById` stores a number, `updateById` stores what it is sent (a string stays a string).
14
+ */
15
+ minInterval?: number | string;
16
+ /** Maximum interval in ms between sends. Same rules as `minInterval`. */
17
+ maxInterval?: number | string;
14
18
  /** Column name in the import file used as the contact name. */
15
19
  nameField?: string;
16
20
  /** Column name in the import file used as the phone number. */
@@ -34,11 +38,22 @@ export type Campaign = {
34
38
  totalContacts: number | null;
35
39
  totalContactsImported: number | null;
36
40
  totalValidContacts: number | null;
37
- sentContacts: number | null;
38
- viewedContacts: number | null;
39
- contactCount: number | null;
41
+ /** @deprecated Never answered: the campaign has no such column. */
42
+ sentContacts?: number | null;
43
+ /** @deprecated Never answered: the campaign has no such column. */
44
+ viewedContacts?: number | null;
45
+ /** @deprecated Never answered: read `getContactCount`. */
46
+ contactCount?: number | null;
40
47
  mustOpenTicket: boolean;
41
- marketingIntegration: boolean;
48
+ /** @deprecated Never answered: the campaign transformer leaves the column out. */
49
+ marketingIntegration?: boolean;
50
+ /** Always `null`: the campaign has no such column (answered by the transformer). */
51
+ userId?: null;
52
+ /** Only in `getMany`: messages sent and viewed (ack 3). */
53
+ stats?: {
54
+ sent: number;
55
+ viewed: number;
56
+ };
42
57
  accountId: string;
43
58
  serviceId: string;
44
59
  defaultDepartmentId: string | null;
@@ -54,9 +69,26 @@ export type Campaign = {
54
69
  createdBy?: User | null;
55
70
  sentBy?: User | null;
56
71
  tags?: Tag[];
57
- messages?: Message[];
72
+ messages?: CampaignMessage[];
58
73
  importFile?: File | null;
59
74
  };
75
+ /** A message of the campaign (`campaign_messages`), as the `messages` include answers it. */
76
+ export type CampaignMessage = {
77
+ id: string;
78
+ text: string | null;
79
+ extraOptions: Record<string, unknown> | null;
80
+ hsmId: string | null;
81
+ hsmFileId: string | null;
82
+ accountId: string;
83
+ campaignId: string;
84
+ createdAt: string;
85
+ updatedAt: string;
86
+ deletedAt: string | null;
87
+ account?: Account;
88
+ file?: File | null;
89
+ hsmFile?: File | null;
90
+ hsm?: WhatsappBusinessTemplate | null;
91
+ };
60
92
  export type CampaignRelationships = 'service' | 'defaultDepartment' | 'defaultUser' | 'createdBy' | 'sentBy' | 'tags' | 'messages' | 'importFile';
61
93
  export type CampaignTemplateParameterItem = {
62
94
  type: string;
@@ -102,6 +134,80 @@ export type CreateCampaignPayload = {
102
134
  marketingIntegration?: boolean;
103
135
  };
104
136
  export type UpdateCampaignPayload = Partial<CreateCampaignPayload>;
137
+ /** The visible states the `status` filter of `getMany` takes (`'scheduled'` is derived from `isScheduled` + `sendsAt`). */
138
+ export type CampaignListStatus = CampaignStatus | 'scheduled';
139
+ /**
140
+ * `getMany` query: the `ListQuery` of a campaign plus the flat filters of the Campaigns screen.
141
+ * A flat `status` takes precedence over `where.status`. An invalid `status` or date answers 400
142
+ * `{ error: 'Invalid status' | 'Invalid date', code: 'FILTER_STATUS_INVALID' | 'FILTER_DATE_INVALID' }`.
143
+ */
144
+ export type CampaignListQuery = ListQuery<Campaign> & {
145
+ serviceId?: string;
146
+ status?: CampaignListStatus;
147
+ /**
148
+ * Quality of the HSM template of the messages. `'HIGH'`, `'MEDIUM'` and `'LOW'` only filter when
149
+ * `include` has `messages` (the filter rewrites that include); without it they are ignored.
150
+ * `'UNKNOWN'` keeps the campaigns without a rated template.
151
+ */
152
+ templateHealth?: 'UNKNOWN' | 'HIGH' | 'MEDIUM' | 'LOW';
153
+ /** Searches the title (accent-insensitive). */
154
+ q?: string;
155
+ /**
156
+ * UTC ISO date-times ending in `Z` (a date alone answers 400 `FILTER_DATE_INVALID`); the days are
157
+ * taken in the timezone of the account. `sentAt*` filter `startedAt`.
158
+ */
159
+ sentAtFrom?: string;
160
+ sentAtTo?: string;
161
+ createdAtFrom?: string;
162
+ createdAtTo?: string;
163
+ };
164
+ /** The sending status of a contact of the campaign (`not_sent` in the filter also matches `pending`). */
165
+ export type CampaignContactStatus = 'pending' | 'not_sent' | 'sent' | 'received' | 'read' | 'answered' | 'quality_hold' | 'quality_dropped';
166
+ export type CampaignContactsQuery = {
167
+ page?: number;
168
+ perPage?: number;
169
+ /** Searches the name, the number and the username of the contact. */
170
+ search?: string;
171
+ contactStatus?: CampaignContactStatus[];
172
+ failReason?: string;
173
+ sortBy?: 'contactName' | 'contactNumber' | 'contactUsername' | 'status' | 'sentAt' | 'failReason';
174
+ sortDir?: 'ASC' | 'DESC';
175
+ };
176
+ export type CampaignContact = {
177
+ id: string;
178
+ sentAt: string | null;
179
+ failed: boolean;
180
+ failReason: string | null;
181
+ parameters: unknown;
182
+ contactName: string;
183
+ /** `null` for a contact known only by its username. */
184
+ contactNumber: string | null;
185
+ contactUsername: string | null;
186
+ contactId: string;
187
+ status: CampaignContactStatus;
188
+ };
189
+ export type CampaignContactsPage = {
190
+ data: CampaignContact[];
191
+ total: number;
192
+ limit: number;
193
+ skip: number;
194
+ currentPage: number;
195
+ lastPage: number;
196
+ from: number;
197
+ to: number;
198
+ };
199
+ export type CampaignTimelineEvent = {
200
+ /** `created`, `scheduled`, `started`, `finished` or `status-<status>`. */
201
+ id: string;
202
+ type: 'created' | 'scheduled' | 'started' | 'finished' | CampaignStatus;
203
+ timestamp: string;
204
+ /** The name of the user who created or sent the campaign, or `'Sistema'`. */
205
+ actor: string;
206
+ triggerType: 'manual' | 'automatic';
207
+ };
208
+ export type ExportCampaignImportErrorsQuery = {
209
+ delimiter?: ',' | ';' | ':';
210
+ };
105
211
  export type CampaignStatsInfo = {
106
212
  totalValidContacts: number;
107
213
  totalContacts: number;
@@ -109,34 +215,67 @@ export type CampaignStatsInfo = {
109
215
  firedSuccessCount: number;
110
216
  firedFailedCount: number;
111
217
  totalMessagesCount: number;
218
+ sentMessagesCount: number;
112
219
  totalFiredCount: number;
113
220
  firedBlockedByMessageRuleCount: number;
114
221
  };
222
+ /** Messages of the campaign by ack: `error`, `sending` (0), `sentToServer` (1), `received` (2), `viewed` (3), `played` (4). */
115
223
  export type CampaignStatsMessages = {
116
224
  error: number;
225
+ sending: number;
226
+ sentToServer: number;
117
227
  received: number;
118
228
  viewed: number;
229
+ played: number;
119
230
  answered: number;
120
231
  };
121
232
  export type CampaignStats = {
122
233
  campaignInfo: CampaignStatsInfo;
123
234
  messageInfo: CampaignStatsMessages;
235
+ /** @deprecated Kept by the backend for backward compatibility: read `campaignInfo.totalMessagesCount`. */
236
+ total: number;
237
+ /** @deprecated Read `campaignInfo.sentMessagesCount`. */
238
+ sent: number;
239
+ /** @deprecated Read `campaignInfo.firedFailedCount`. */
240
+ failed: number;
241
+ /** @deprecated Read `messageInfo.sending`. */
242
+ sending: number;
243
+ /** @deprecated Read `messageInfo.sentToServer`. */
244
+ sentToServer: number;
245
+ /** @deprecated Read `messageInfo.received`. */
246
+ received: number;
247
+ /** @deprecated Read `messageInfo.viewed`. */
248
+ viewed: number;
249
+ /** @deprecated Read `messageInfo.played`. */
250
+ played: number;
251
+ /** @deprecated Read `messageInfo.answered`. */
252
+ answered: number;
253
+ /** @deprecated Same as `messageInfo.sentToServer`. */
254
+ sentAndNotReceived: number;
124
255
  };
256
+ /** Whole numbers, `0` or more (numeric strings are accepted). */
125
257
  export type SetIntervalPayload = {
126
- minInterval: string;
127
- maxInterval: string;
258
+ minInterval: number | string;
259
+ maxInterval: number | string;
128
260
  };
129
261
  export type ExportCampaignResultPayload = {
130
- campaignId: string;
262
+ where: {
263
+ campaignId: string;
264
+ [key: string]: unknown;
265
+ };
266
+ /** `'semiColon'` separates the columns with `;` (default `,`). */
267
+ type?: 'semiColon';
131
268
  };
132
269
  export type ExportTemplateCsvPayload = {
133
270
  hsmId: string;
134
271
  };
135
272
  export type AutoPauseModePayload = {
136
- mode: string;
273
+ mode: 'low-health' | 'medium-health' | 'disabled';
137
274
  };
138
275
  export type HsmLimit = {
139
276
  hsmLimit: number;
140
277
  hsmUsedLimit: number;
278
+ /** The HSM messages still available (`0` when none or the plan has no WhatsApp Business); `true` when the limit is disabled. */
279
+ hasLimit: number | boolean;
141
280
  };
142
281
  //# sourceMappingURL=types.d.ts.map
@@ -1 +1 @@
1
- {"version":3,"file":"types.d.ts","sourceRoot":"","sources":["../../../src/apis/campaigns/types.ts"],"names":[],"mappings":"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"}
1
+ {"version":3,"file":"types.d.ts","sourceRoot":"","sources":["../../../src/apis/campaigns/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.7.0",
3
+ "version": "4.8.0",
4
4
  "type": "module",
5
5
  "main": "./dist/index.cjs",
6
6
  "module": "./dist/index.mjs",
@@ -3,6 +3,8 @@ import { CampaignsApi } from './CampaignsApi'
3
3
  import type { ApiClient } from '../../core/ApiClient'
4
4
  import type {
5
5
  Campaign,
6
+ CampaignContactsPage,
7
+ CampaignTimelineEvent,
6
8
  CreateCampaignPayload,
7
9
  CampaignStats,
8
10
  SetIntervalPayload,
@@ -43,11 +45,7 @@ const campaign: Campaign = {
43
45
  totalContacts: null,
44
46
  totalContactsImported: null,
45
47
  totalValidContacts: null,
46
- sentContacts: null,
47
- viewedContacts: null,
48
- contactCount: null,
49
48
  mustOpenTicket: false,
50
- marketingIntegration: false,
51
49
  accountId: 'acc-1',
52
50
  serviceId: 'svc-1',
53
51
  defaultDepartmentId: null,
@@ -188,32 +186,44 @@ describe('CampaignsApi', () => {
188
186
 
189
187
  describe('sendById', () => {
190
188
  it('calls client.post with /campaigns/:id/send', async () => {
191
- vi.mocked(client.post).mockResolvedValue(campaign)
189
+ vi.mocked(client.post).mockResolvedValue({ ...campaign, status: 'processing' })
192
190
  const result = await api.sendById('cmp-1')
193
- expect(client.post).toHaveBeenCalledWith('/campaigns/cmp-1/send')
194
- expect(result).toEqual(campaign)
191
+ expect(client.post).toHaveBeenCalledWith('/campaigns/cmp-1/send', undefined, undefined)
192
+ expect(result).toEqual({ ...campaign, status: 'processing' })
195
193
  })
196
194
  })
197
195
 
198
- // ── pauseById ────────────────────────────────────────────────────
196
+ // ── pauseById / resumeById / retryById ───────────────────────────
199
197
 
200
198
  describe('pauseById', () => {
201
- it('calls client.post with /campaigns/:id/pause', async () => {
202
- vi.mocked(client.post).mockResolvedValue(campaign)
199
+ it('calls client.post with /campaigns/:id/pause and resolves the boolean', async () => {
200
+ vi.mocked(client.post).mockResolvedValue(true)
203
201
  const result = await api.pauseById('cmp-1')
204
- expect(client.post).toHaveBeenCalledWith('/campaigns/cmp-1/pause')
205
- expect(result).toEqual(campaign)
202
+ expect(client.post).toHaveBeenCalledWith('/campaigns/cmp-1/pause', undefined, undefined)
203
+ expect(result).toBe(true)
206
204
  })
207
205
  })
208
206
 
209
- // ── resumeById ───────────────────────────────────────────────────
210
-
211
207
  describe('resumeById', () => {
212
- it('calls client.post with /campaigns/:id/resume', async () => {
213
- vi.mocked(client.post).mockResolvedValue(campaign)
208
+ it('calls client.post with /campaigns/:id/resume and resolves the boolean', async () => {
209
+ vi.mocked(client.post).mockResolvedValue(true)
214
210
  const result = await api.resumeById('cmp-1')
215
- expect(client.post).toHaveBeenCalledWith('/campaigns/cmp-1/resume')
216
- expect(result).toEqual(campaign)
211
+ expect(client.post).toHaveBeenCalledWith('/campaigns/cmp-1/resume', undefined, undefined)
212
+ expect(result).toBe(true)
213
+ })
214
+ })
215
+
216
+ describe('retryById', () => {
217
+ it('calls client.post with /campaigns/:id/retry', async () => {
218
+ vi.mocked(client.post).mockResolvedValue('OK')
219
+ const result = await api.retryById('cmp-1')
220
+ expect(client.post).toHaveBeenCalledWith('/campaigns/cmp-1/retry', undefined, undefined)
221
+ expect(result).toBe('OK')
222
+ })
223
+
224
+ it('resolves false for an unknown campaign', async () => {
225
+ vi.mocked(client.post).mockResolvedValue(false)
226
+ await expect(api.retryById('unknown')).resolves.toBe(false)
217
227
  })
218
228
  })
219
229
 
@@ -223,7 +233,7 @@ describe('CampaignsApi', () => {
223
233
  it('calls client.post with /campaigns/:id/duplicate', async () => {
224
234
  vi.mocked(client.post).mockResolvedValue(campaign)
225
235
  const result = await api.duplicateById('cmp-1')
226
- expect(client.post).toHaveBeenCalledWith('/campaigns/cmp-1/duplicate')
236
+ expect(client.post).toHaveBeenCalledWith('/campaigns/cmp-1/duplicate', undefined, undefined)
227
237
  expect(result).toEqual(campaign)
228
238
  })
229
239
  })
@@ -233,6 +243,16 @@ describe('CampaignsApi', () => {
233
243
  describe('getStatsById', () => {
234
244
  it('calls client.get with /campaigns/:id/stats', async () => {
235
245
  const stats: CampaignStats = {
246
+ total: 100,
247
+ sent: 100,
248
+ failed: 10,
249
+ sending: 0,
250
+ sentToServer: 5,
251
+ received: 85,
252
+ viewed: 70,
253
+ played: 0,
254
+ answered: 30,
255
+ sentAndNotReceived: 5,
236
256
  campaignInfo: {
237
257
  totalValidContacts: 100,
238
258
  totalContacts: 110,
@@ -240,74 +260,184 @@ describe('CampaignsApi', () => {
240
260
  firedSuccessCount: 90,
241
261
  firedFailedCount: 10,
242
262
  totalMessagesCount: 100,
263
+ sentMessagesCount: 100,
243
264
  totalFiredCount: 100,
244
265
  firedBlockedByMessageRuleCount: 0,
245
266
  },
246
- messageInfo: { error: 5, received: 85, viewed: 70, answered: 30 },
267
+ messageInfo: {
268
+ error: 5,
269
+ sending: 0,
270
+ sentToServer: 5,
271
+ received: 85,
272
+ viewed: 70,
273
+ played: 0,
274
+ answered: 30,
275
+ },
247
276
  }
248
277
  vi.mocked(client.get).mockResolvedValue(stats)
249
278
  const result = await api.getStatsById('cmp-1')
250
- expect(client.get).toHaveBeenCalledWith('/campaigns/cmp-1/stats')
279
+ expect(client.get).toHaveBeenCalledWith('/campaigns/cmp-1/stats', undefined)
251
280
  expect(result).toEqual(stats)
252
281
  })
253
282
  })
254
283
 
284
+ // ── getTimeline ──────────────────────────────────────────────────
285
+
286
+ describe('getTimeline', () => {
287
+ it('calls client.get with /campaigns/:id/timeline', async () => {
288
+ const events: CampaignTimelineEvent[] = [
289
+ {
290
+ id: 'finished',
291
+ type: 'finished',
292
+ timestamp: '2026-10-14T15:02:40.770Z',
293
+ actor: 'Sistema',
294
+ triggerType: 'automatic',
295
+ },
296
+ {
297
+ id: 'created',
298
+ type: 'created',
299
+ timestamp: '2026-10-14T15:02:33.795Z',
300
+ actor: 'Ana',
301
+ triggerType: 'manual',
302
+ },
303
+ ]
304
+ vi.mocked(client.get).mockResolvedValue(events)
305
+ const result = await api.getTimeline('cmp-1')
306
+ expect(client.get).toHaveBeenCalledWith('/campaigns/cmp-1/timeline', undefined)
307
+ expect(result).toEqual(events)
308
+ })
309
+ })
310
+
311
+ // ── getContacts ──────────────────────────────────────────────────
312
+
313
+ describe('getContacts', () => {
314
+ const page: CampaignContactsPage = {
315
+ data: [],
316
+ total: 0,
317
+ limit: 15,
318
+ skip: 0,
319
+ currentPage: 1,
320
+ lastPage: 1,
321
+ from: 0,
322
+ to: 0,
323
+ }
324
+
325
+ it('calls client.get with /campaigns/:id/contacts when no query is provided', async () => {
326
+ vi.mocked(client.get).mockResolvedValue(page)
327
+ const result = await api.getContacts('cmp-1')
328
+ expect(client.get).toHaveBeenCalledWith('/campaigns/cmp-1/contacts', undefined)
329
+ expect(result).toEqual(page)
330
+ })
331
+
332
+ it('serializes the query', async () => {
333
+ vi.mocked(client.get).mockResolvedValue(page)
334
+ await api.getContacts('cmp-1', { page: 2, contactStatus: ['not_sent'], sortBy: 'sentAt' })
335
+ const url = vi.mocked(client.get).mock.calls[0]?.[0] as string
336
+ expect(url.startsWith('/campaigns/cmp-1/contacts?')).toBe(true)
337
+ expect(decodeURIComponent(url)).toContain('"contactStatus":["not_sent"]')
338
+ })
339
+ })
340
+
255
341
  // ── setIntervalById ──────────────────────────────────────────────
256
342
 
257
343
  describe('setIntervalById', () => {
258
344
  it('calls client.post with /campaigns/:id/interval and body', async () => {
259
- vi.mocked(client.post).mockResolvedValue(campaign)
260
- const data: SetIntervalPayload = { minInterval: '1000', maxInterval: '5000' }
345
+ vi.mocked(client.post).mockResolvedValue(true)
346
+ const data: SetIntervalPayload = { minInterval: 5, maxInterval: 10 }
261
347
  const result = await api.setIntervalById('cmp-1', data)
262
- expect(client.post).toHaveBeenCalledWith('/campaigns/cmp-1/interval', data)
263
- expect(result).toEqual(campaign)
348
+ expect(client.post).toHaveBeenCalledWith('/campaigns/cmp-1/interval', data, undefined)
349
+ expect(result).toBe(true)
264
350
  })
265
351
  })
266
352
 
267
- // ── getContactCount ──────────────────────────────────────────────
353
+ // ── getContactCount / countReadyByService ────────────────────────
268
354
 
269
355
  describe('getContactCount', () => {
270
356
  it('calls client.get with /campaigns/:id/contactCount', async () => {
271
357
  vi.mocked(client.get).mockResolvedValue(42)
272
358
  const result = await api.getContactCount('cmp-1')
273
- expect(client.get).toHaveBeenCalledWith('/campaigns/cmp-1/contactCount')
359
+ expect(client.get).toHaveBeenCalledWith('/campaigns/cmp-1/contactCount', undefined)
274
360
  expect(result).toBe(42)
275
361
  })
276
362
  })
277
363
 
364
+ describe('countReadyByService', () => {
365
+ it('calls client.get with /campaigns/count-ready/:serviceId', async () => {
366
+ vi.mocked(client.get).mockResolvedValue(4)
367
+ const result = await api.countReadyByService('svc-1')
368
+ expect(client.get).toHaveBeenCalledWith('/campaigns/count-ready/svc-1', undefined)
369
+ expect(result).toBe(4)
370
+ })
371
+ })
372
+
278
373
  // ── setAutoPauseMode ─────────────────────────────────────────────
279
374
 
280
375
  describe('setAutoPauseMode', () => {
281
376
  it('calls client.put with /campaigns/autoPauseMode and body', async () => {
282
- vi.mocked(client.put).mockResolvedValue({ ok: true })
283
- const data: AutoPauseModePayload = { mode: 'auto' }
377
+ vi.mocked(client.put).mockResolvedValue('OK')
378
+ const data: AutoPauseModePayload = { mode: 'medium-health' }
284
379
  const result = await api.setAutoPauseMode(data)
285
- expect(client.put).toHaveBeenCalledWith('/campaigns/autoPauseMode', data)
286
- expect(result).toEqual({ ok: true })
380
+ expect(client.put).toHaveBeenCalledWith('/campaigns/autoPauseMode', data, undefined)
381
+ expect(result).toBe('OK')
287
382
  })
288
383
  })
289
384
 
290
- // ── exportCampaignResult ─────────────────────────────────────────
385
+ // ── exports ──────────────────────────────────────────────────────
291
386
 
292
387
  describe('exportCampaignResult', () => {
293
- it('calls client.post with /campaigns/export/csv and body', async () => {
294
- vi.mocked(client.post).mockResolvedValue({ ok: true })
295
- const data: ExportCampaignResultPayload = { campaignId: 'cmp-1' }
388
+ it('calls client.post with /campaigns/export/csv and the where of the campaign', async () => {
389
+ vi.mocked(client.post).mockResolvedValue('Nome do contato;Número do contato\n')
390
+ const data: ExportCampaignResultPayload = {
391
+ where: { campaignId: 'cmp-1' },
392
+ type: 'semiColon',
393
+ }
296
394
  const result = await api.exportCampaignResult(data)
297
- expect(client.post).toHaveBeenCalledWith('/campaigns/export/csv', data)
298
- expect(result).toEqual({ ok: true })
395
+ expect(client.post).toHaveBeenCalledWith('/campaigns/export/csv', data, undefined)
396
+ expect(result).toBe('Nome do contato;Número do contato\n')
299
397
  })
300
398
  })
301
399
 
302
- // ── exportTemplateCsv ────────────────────────────────────────────
303
-
304
400
  describe('exportTemplateCsv', () => {
305
401
  it('calls client.post with /campaigns/exportTemplate and body', async () => {
306
- vi.mocked(client.post).mockResolvedValue({ ok: true })
402
+ vi.mocked(client.post).mockResolvedValue('Nome;Telefone;Username\n')
307
403
  const data: ExportTemplateCsvPayload = { hsmId: 'hsm-1' }
308
404
  const result = await api.exportTemplateCsv(data)
309
- expect(client.post).toHaveBeenCalledWith('/campaigns/exportTemplate', data)
310
- expect(result).toEqual({ ok: true })
405
+ expect(client.post).toHaveBeenCalledWith('/campaigns/exportTemplate', data, undefined)
406
+ expect(result).toBe('Nome;Telefone;Username\n')
407
+ })
408
+ })
409
+
410
+ describe('exportImportErrors', () => {
411
+ it('calls client.get with /campaigns/:id/import-errors', async () => {
412
+ vi.mocked(client.get).mockResolvedValue('Linha,Nome,Número,Username,Motivo\n')
413
+ const result = await api.exportImportErrors('cmp-1')
414
+ expect(client.get).toHaveBeenCalledWith('/campaigns/cmp-1/import-errors', undefined)
415
+ expect(result).toBe('Linha,Nome,Número,Username,Motivo\n')
416
+ })
417
+
418
+ it('sends the delimiter in the query string', async () => {
419
+ vi.mocked(client.get).mockResolvedValue('Linha;Nome;Número;Username;Motivo\n')
420
+ await api.exportImportErrors('cmp-1', { delimiter: ';' })
421
+ expect(client.get).toHaveBeenCalledWith(
422
+ '/campaigns/cmp-1/import-errors?delimiter=%3B',
423
+ undefined,
424
+ )
425
+ })
426
+ })
427
+
428
+ // ── deleteMany ───────────────────────────────────────────────────
429
+
430
+ describe('deleteMany', () => {
431
+ it('calls client.request with DELETE /campaigns/delete-many and the ids', async () => {
432
+ vi.mocked(client.request).mockResolvedValue(true)
433
+ const result = await api.deleteMany(['cmp-1', 'cmp-2'])
434
+ expect(client.request).toHaveBeenCalledWith(
435
+ 'DELETE',
436
+ '/campaigns/delete-many',
437
+ { ids: ['cmp-1', 'cmp-2'] },
438
+ undefined,
439
+ )
440
+ expect(result).toBe(true)
311
441
  })
312
442
  })
313
443
 
@@ -315,10 +445,13 @@ describe('CampaignsApi', () => {
315
445
 
316
446
  describe('getHsmLimit', () => {
317
447
  it('calls client.get with /whatsapp-business-templates/:accountId/hsmLimit', async () => {
318
- const limit: HsmLimit = { hsmLimit: 1000, hsmUsedLimit: 150 }
448
+ const limit: HsmLimit = { hsmLimit: 1000, hsmUsedLimit: 150, hasLimit: 850 }
319
449
  vi.mocked(client.get).mockResolvedValue(limit)
320
450
  const result = await api.getHsmLimit('acc-1')
321
- expect(client.get).toHaveBeenCalledWith('/whatsapp-business-templates/acc-1/hsmLimit')
451
+ expect(client.get).toHaveBeenCalledWith(
452
+ '/whatsapp-business-templates/acc-1/hsmLimit',
453
+ undefined,
454
+ )
322
455
  expect(result).toEqual(limit)
323
456
  })
324
457
  })