@dispatchtickets/sdk 0.1.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.
- package/README.md +327 -0
- package/dist/index.cjs +923 -0
- package/dist/index.cjs.map +1 -0
- package/dist/index.d.cts +1116 -0
- package/dist/index.d.ts +1116 -0
- package/dist/index.js +910 -0
- package/dist/index.js.map +1 -0
- package/package.json +46 -0
package/dist/index.d.cts
ADDED
|
@@ -0,0 +1,1116 @@
|
|
|
1
|
+
interface HttpClientConfig {
|
|
2
|
+
baseUrl: string;
|
|
3
|
+
apiKey: string;
|
|
4
|
+
timeout: number;
|
|
5
|
+
maxRetries: number;
|
|
6
|
+
debug?: boolean;
|
|
7
|
+
}
|
|
8
|
+
interface RequestOptions {
|
|
9
|
+
method: 'GET' | 'POST' | 'PATCH' | 'PUT' | 'DELETE';
|
|
10
|
+
path: string;
|
|
11
|
+
body?: unknown;
|
|
12
|
+
query?: Record<string, string | number | boolean | undefined>;
|
|
13
|
+
headers?: Record<string, string>;
|
|
14
|
+
idempotencyKey?: string;
|
|
15
|
+
}
|
|
16
|
+
/**
|
|
17
|
+
* HTTP client with retry logic and error handling
|
|
18
|
+
*/
|
|
19
|
+
declare class HttpClient {
|
|
20
|
+
private readonly config;
|
|
21
|
+
constructor(config: HttpClientConfig);
|
|
22
|
+
/**
|
|
23
|
+
* Execute an HTTP request with retry logic
|
|
24
|
+
*/
|
|
25
|
+
request<T>(options: RequestOptions): Promise<T>;
|
|
26
|
+
private buildUrl;
|
|
27
|
+
private buildHeaders;
|
|
28
|
+
private executeRequest;
|
|
29
|
+
private handleResponse;
|
|
30
|
+
private calculateBackoff;
|
|
31
|
+
private sleep;
|
|
32
|
+
}
|
|
33
|
+
|
|
34
|
+
/**
|
|
35
|
+
* Base class for all resource classes
|
|
36
|
+
*/
|
|
37
|
+
declare abstract class BaseResource {
|
|
38
|
+
protected readonly http: HttpClient;
|
|
39
|
+
constructor(http: HttpClient);
|
|
40
|
+
protected _get<T>(path: string, query?: RequestOptions['query']): Promise<T>;
|
|
41
|
+
protected _post<T>(path: string, body?: unknown, options?: {
|
|
42
|
+
idempotencyKey?: string;
|
|
43
|
+
query?: RequestOptions['query'];
|
|
44
|
+
}): Promise<T>;
|
|
45
|
+
protected _patch<T>(path: string, body?: unknown): Promise<T>;
|
|
46
|
+
protected _put<T>(path: string, body?: unknown): Promise<T>;
|
|
47
|
+
protected _delete<T>(path: string, query?: RequestOptions['query']): Promise<T>;
|
|
48
|
+
}
|
|
49
|
+
|
|
50
|
+
/**
|
|
51
|
+
* Brand (workspace) resource
|
|
52
|
+
*/
|
|
53
|
+
interface Brand {
|
|
54
|
+
id: string;
|
|
55
|
+
accountId: string;
|
|
56
|
+
name: string;
|
|
57
|
+
slug: string;
|
|
58
|
+
ticketPrefix?: string;
|
|
59
|
+
nextTicketNumber: number;
|
|
60
|
+
url?: string;
|
|
61
|
+
iconUrl?: string;
|
|
62
|
+
settings?: Record<string, unknown>;
|
|
63
|
+
metadata?: Record<string, unknown>;
|
|
64
|
+
ticketSchema?: Record<string, unknown>;
|
|
65
|
+
fieldDefinitions?: Record<string, unknown>;
|
|
66
|
+
inboundEmailEnabled: boolean;
|
|
67
|
+
autoresponseEnabled: boolean;
|
|
68
|
+
autoresponseSubject?: string;
|
|
69
|
+
autoresponseBody?: string;
|
|
70
|
+
fromName?: string;
|
|
71
|
+
fromEmail?: string;
|
|
72
|
+
createdAt: string;
|
|
73
|
+
updatedAt: string;
|
|
74
|
+
}
|
|
75
|
+
/**
|
|
76
|
+
* Input for creating a brand
|
|
77
|
+
*/
|
|
78
|
+
interface CreateBrandInput {
|
|
79
|
+
name: string;
|
|
80
|
+
slug: string;
|
|
81
|
+
ticketPrefix?: string;
|
|
82
|
+
ticketNumberStart?: number;
|
|
83
|
+
metadata?: Record<string, unknown>;
|
|
84
|
+
ticketSchema?: Record<string, unknown>;
|
|
85
|
+
}
|
|
86
|
+
/**
|
|
87
|
+
* Input for updating a brand
|
|
88
|
+
*/
|
|
89
|
+
interface UpdateBrandInput {
|
|
90
|
+
name?: string;
|
|
91
|
+
slug?: string;
|
|
92
|
+
ticketPrefix?: string;
|
|
93
|
+
url?: string;
|
|
94
|
+
iconUrl?: string;
|
|
95
|
+
fromName?: string;
|
|
96
|
+
fromEmail?: string;
|
|
97
|
+
autoresponseEnabled?: boolean;
|
|
98
|
+
autoresponseSubject?: string;
|
|
99
|
+
autoresponseBody?: string;
|
|
100
|
+
metadata?: Record<string, unknown>;
|
|
101
|
+
ticketSchema?: Record<string, unknown>;
|
|
102
|
+
}
|
|
103
|
+
/**
|
|
104
|
+
* Brand deletion preview result
|
|
105
|
+
*/
|
|
106
|
+
interface DeleteBrandPreview {
|
|
107
|
+
ticketCount: number;
|
|
108
|
+
webhookCount: number;
|
|
109
|
+
categoryCount: number;
|
|
110
|
+
tagCount: number;
|
|
111
|
+
}
|
|
112
|
+
|
|
113
|
+
/**
|
|
114
|
+
* Brands resource for managing workspaces
|
|
115
|
+
*/
|
|
116
|
+
declare class BrandsResource extends BaseResource {
|
|
117
|
+
/**
|
|
118
|
+
* Create a new brand
|
|
119
|
+
*/
|
|
120
|
+
create(data: CreateBrandInput): Promise<Brand>;
|
|
121
|
+
/**
|
|
122
|
+
* List all brands
|
|
123
|
+
*/
|
|
124
|
+
list(): Promise<Brand[]>;
|
|
125
|
+
/**
|
|
126
|
+
* Get a brand by ID
|
|
127
|
+
*/
|
|
128
|
+
get(brandId: string): Promise<Brand>;
|
|
129
|
+
/**
|
|
130
|
+
* Update a brand
|
|
131
|
+
*/
|
|
132
|
+
update(brandId: string, data: UpdateBrandInput): Promise<Brand>;
|
|
133
|
+
/**
|
|
134
|
+
* Delete a brand
|
|
135
|
+
* @param brandId - The brand ID
|
|
136
|
+
* @param confirm - Set to true to actually delete; false to preview what would be deleted
|
|
137
|
+
*/
|
|
138
|
+
delete(brandId: string, confirm?: boolean): Promise<void | DeleteBrandPreview>;
|
|
139
|
+
/**
|
|
140
|
+
* Get the ticket schema for a brand
|
|
141
|
+
*/
|
|
142
|
+
getSchema(brandId: string): Promise<Record<string, unknown>>;
|
|
143
|
+
/**
|
|
144
|
+
* Update the ticket schema for a brand
|
|
145
|
+
*/
|
|
146
|
+
updateSchema(brandId: string, schema: Record<string, unknown>): Promise<Record<string, unknown>>;
|
|
147
|
+
}
|
|
148
|
+
|
|
149
|
+
/**
|
|
150
|
+
* Pagination response wrapper
|
|
151
|
+
*/
|
|
152
|
+
interface PaginatedResponse<T> {
|
|
153
|
+
data: T[];
|
|
154
|
+
pagination: {
|
|
155
|
+
cursor?: string;
|
|
156
|
+
hasMore: boolean;
|
|
157
|
+
};
|
|
158
|
+
}
|
|
159
|
+
/**
|
|
160
|
+
* Link object for ticket/comment links
|
|
161
|
+
*/
|
|
162
|
+
interface Link {
|
|
163
|
+
url: string;
|
|
164
|
+
title?: string;
|
|
165
|
+
type?: string;
|
|
166
|
+
}
|
|
167
|
+
/**
|
|
168
|
+
* Ticket source channels
|
|
169
|
+
*/
|
|
170
|
+
type TicketSource = 'api' | 'web' | 'email' | 'slack' | 'sms' | 'discord' | 'instagram' | 'twitter' | 'whatsapp' | 'custom';
|
|
171
|
+
/**
|
|
172
|
+
* Ticket status values
|
|
173
|
+
*/
|
|
174
|
+
type TicketStatus = 'open' | 'pending' | 'resolved' | 'closed';
|
|
175
|
+
/**
|
|
176
|
+
* Ticket priority values
|
|
177
|
+
*/
|
|
178
|
+
type TicketPriority = 'low' | 'normal' | 'medium' | 'high' | 'urgent';
|
|
179
|
+
/**
|
|
180
|
+
* Comment author types
|
|
181
|
+
*/
|
|
182
|
+
type AuthorType = 'CUSTOMER' | 'AGENT' | 'SYSTEM';
|
|
183
|
+
/**
|
|
184
|
+
* Attachment status values
|
|
185
|
+
*/
|
|
186
|
+
type AttachmentStatus = 'PENDING' | 'UPLOADED' | 'FAILED';
|
|
187
|
+
/**
|
|
188
|
+
* Webhook event types
|
|
189
|
+
*/
|
|
190
|
+
type WebhookEvent = 'ticket.created' | 'ticket.updated' | 'ticket.deleted' | 'comment.created' | 'comment.updated' | 'comment.deleted' | 'attachment.created' | 'attachment.deleted';
|
|
191
|
+
/**
|
|
192
|
+
* Custom field types
|
|
193
|
+
*/
|
|
194
|
+
type FieldType = 'text' | 'number' | 'boolean' | 'date' | 'select' | 'multiselect' | 'url' | 'array' | 'object';
|
|
195
|
+
/**
|
|
196
|
+
* Entity types for custom fields
|
|
197
|
+
*/
|
|
198
|
+
type EntityType = 'ticket' | 'customer' | 'company';
|
|
199
|
+
/**
|
|
200
|
+
* Bulk action types
|
|
201
|
+
*/
|
|
202
|
+
type BulkAction = 'spam' | 'resolve' | 'close' | 'delete' | 'assign' | 'setCategory' | 'setTags';
|
|
203
|
+
/**
|
|
204
|
+
* Sort order
|
|
205
|
+
*/
|
|
206
|
+
type SortOrder = 'asc' | 'desc';
|
|
207
|
+
|
|
208
|
+
/**
|
|
209
|
+
* Category resource
|
|
210
|
+
*/
|
|
211
|
+
interface Category {
|
|
212
|
+
id: string;
|
|
213
|
+
brandId: string;
|
|
214
|
+
name: string;
|
|
215
|
+
color: string;
|
|
216
|
+
description?: string;
|
|
217
|
+
sortOrder: number;
|
|
218
|
+
createdAt: string;
|
|
219
|
+
}
|
|
220
|
+
/**
|
|
221
|
+
* Input for creating a category
|
|
222
|
+
*/
|
|
223
|
+
interface CreateCategoryInput {
|
|
224
|
+
name: string;
|
|
225
|
+
color?: string;
|
|
226
|
+
description?: string;
|
|
227
|
+
sortOrder?: number;
|
|
228
|
+
}
|
|
229
|
+
/**
|
|
230
|
+
* Input for updating a category
|
|
231
|
+
*/
|
|
232
|
+
interface UpdateCategoryInput {
|
|
233
|
+
name?: string;
|
|
234
|
+
color?: string;
|
|
235
|
+
description?: string;
|
|
236
|
+
sortOrder?: number;
|
|
237
|
+
}
|
|
238
|
+
/**
|
|
239
|
+
* Category stats
|
|
240
|
+
*/
|
|
241
|
+
interface CategoryStats {
|
|
242
|
+
[categoryId: string]: {
|
|
243
|
+
ticketCount: number;
|
|
244
|
+
};
|
|
245
|
+
}
|
|
246
|
+
|
|
247
|
+
/**
|
|
248
|
+
* Tag resource
|
|
249
|
+
*/
|
|
250
|
+
interface Tag {
|
|
251
|
+
id: string;
|
|
252
|
+
brandId: string;
|
|
253
|
+
name: string;
|
|
254
|
+
color: string;
|
|
255
|
+
createdAt: string;
|
|
256
|
+
}
|
|
257
|
+
/**
|
|
258
|
+
* Input for creating a tag
|
|
259
|
+
*/
|
|
260
|
+
interface CreateTagInput {
|
|
261
|
+
name: string;
|
|
262
|
+
color?: string;
|
|
263
|
+
}
|
|
264
|
+
/**
|
|
265
|
+
* Input for updating a tag
|
|
266
|
+
*/
|
|
267
|
+
interface UpdateTagInput {
|
|
268
|
+
name?: string;
|
|
269
|
+
color?: string;
|
|
270
|
+
}
|
|
271
|
+
/**
|
|
272
|
+
* Input for merging tags
|
|
273
|
+
*/
|
|
274
|
+
interface MergeTagsInput {
|
|
275
|
+
sourceTagIds: string[];
|
|
276
|
+
}
|
|
277
|
+
|
|
278
|
+
/**
|
|
279
|
+
* Customer resource
|
|
280
|
+
*/
|
|
281
|
+
interface Customer {
|
|
282
|
+
id: string;
|
|
283
|
+
brandId: string;
|
|
284
|
+
email: string;
|
|
285
|
+
name?: string;
|
|
286
|
+
avatarUrl?: string;
|
|
287
|
+
companyId?: string;
|
|
288
|
+
company?: Company;
|
|
289
|
+
metadata?: Record<string, unknown>;
|
|
290
|
+
createdAt: string;
|
|
291
|
+
updatedAt: string;
|
|
292
|
+
_count?: {
|
|
293
|
+
tickets: number;
|
|
294
|
+
};
|
|
295
|
+
}
|
|
296
|
+
/**
|
|
297
|
+
* Company resource
|
|
298
|
+
*/
|
|
299
|
+
interface Company {
|
|
300
|
+
id: string;
|
|
301
|
+
brandId: string;
|
|
302
|
+
name: string;
|
|
303
|
+
domain?: string;
|
|
304
|
+
metadata?: Record<string, unknown>;
|
|
305
|
+
createdAt: string;
|
|
306
|
+
updatedAt: string;
|
|
307
|
+
_count?: {
|
|
308
|
+
customers: number;
|
|
309
|
+
};
|
|
310
|
+
}
|
|
311
|
+
/**
|
|
312
|
+
* Input for creating a customer
|
|
313
|
+
*/
|
|
314
|
+
interface CreateCustomerInput {
|
|
315
|
+
email: string;
|
|
316
|
+
name?: string;
|
|
317
|
+
avatarUrl?: string;
|
|
318
|
+
companyId?: string;
|
|
319
|
+
metadata?: Record<string, unknown>;
|
|
320
|
+
}
|
|
321
|
+
/**
|
|
322
|
+
* Input for updating a customer
|
|
323
|
+
*/
|
|
324
|
+
interface UpdateCustomerInput {
|
|
325
|
+
email?: string;
|
|
326
|
+
name?: string;
|
|
327
|
+
avatarUrl?: string;
|
|
328
|
+
companyId?: string;
|
|
329
|
+
metadata?: Record<string, unknown>;
|
|
330
|
+
}
|
|
331
|
+
/**
|
|
332
|
+
* Filters for listing customers
|
|
333
|
+
*/
|
|
334
|
+
interface ListCustomersFilters {
|
|
335
|
+
limit?: number;
|
|
336
|
+
cursor?: string;
|
|
337
|
+
sort?: 'createdAt' | 'name' | 'email';
|
|
338
|
+
order?: SortOrder;
|
|
339
|
+
}
|
|
340
|
+
|
|
341
|
+
/**
|
|
342
|
+
* Ticket resource
|
|
343
|
+
*/
|
|
344
|
+
interface Ticket {
|
|
345
|
+
id: string;
|
|
346
|
+
brandId: string;
|
|
347
|
+
ticketNumber: number;
|
|
348
|
+
title: string;
|
|
349
|
+
body?: string;
|
|
350
|
+
status: TicketStatus;
|
|
351
|
+
priority: TicketPriority;
|
|
352
|
+
assigneeId?: string;
|
|
353
|
+
createdBy?: string;
|
|
354
|
+
customerId?: string;
|
|
355
|
+
customer?: Customer;
|
|
356
|
+
categoryId?: string;
|
|
357
|
+
category?: Category;
|
|
358
|
+
tags?: Tag[];
|
|
359
|
+
links?: Link[];
|
|
360
|
+
customFields?: Record<string, unknown>;
|
|
361
|
+
metadata?: Record<string, unknown>;
|
|
362
|
+
source: TicketSource;
|
|
363
|
+
sourceId?: string;
|
|
364
|
+
sourceData?: Record<string, unknown>;
|
|
365
|
+
commentCount: number;
|
|
366
|
+
attachmentCount: number;
|
|
367
|
+
isSpam: boolean;
|
|
368
|
+
createdAt: string;
|
|
369
|
+
updatedAt: string;
|
|
370
|
+
deletedAt?: string;
|
|
371
|
+
mergedIntoId?: string;
|
|
372
|
+
}
|
|
373
|
+
/**
|
|
374
|
+
* Input for creating a ticket
|
|
375
|
+
*/
|
|
376
|
+
interface CreateTicketInput {
|
|
377
|
+
title: string;
|
|
378
|
+
body?: string;
|
|
379
|
+
status?: TicketStatus;
|
|
380
|
+
priority?: TicketPriority;
|
|
381
|
+
assigneeId?: string;
|
|
382
|
+
createdBy?: string;
|
|
383
|
+
categoryId?: string;
|
|
384
|
+
tags?: string[];
|
|
385
|
+
links?: Link[];
|
|
386
|
+
customFields?: Record<string, unknown>;
|
|
387
|
+
metadata?: Record<string, unknown>;
|
|
388
|
+
source?: TicketSource;
|
|
389
|
+
sourceId?: string;
|
|
390
|
+
sourceData?: Record<string, unknown>;
|
|
391
|
+
notifyCustomer?: boolean;
|
|
392
|
+
}
|
|
393
|
+
/**
|
|
394
|
+
* Input for updating a ticket
|
|
395
|
+
*/
|
|
396
|
+
interface UpdateTicketInput {
|
|
397
|
+
title?: string;
|
|
398
|
+
body?: string;
|
|
399
|
+
status?: TicketStatus;
|
|
400
|
+
priority?: TicketPriority;
|
|
401
|
+
assigneeId?: string | null;
|
|
402
|
+
categoryId?: string | null;
|
|
403
|
+
tags?: string[];
|
|
404
|
+
links?: Link[];
|
|
405
|
+
customFields?: Record<string, unknown>;
|
|
406
|
+
metadata?: Record<string, unknown>;
|
|
407
|
+
isSpam?: boolean;
|
|
408
|
+
}
|
|
409
|
+
/**
|
|
410
|
+
* Filters for listing tickets
|
|
411
|
+
*/
|
|
412
|
+
interface ListTicketsFilters {
|
|
413
|
+
status?: TicketStatus | TicketStatus[] | 'active';
|
|
414
|
+
priority?: TicketPriority;
|
|
415
|
+
assigneeId?: string;
|
|
416
|
+
customerId?: string;
|
|
417
|
+
customerEmail?: string;
|
|
418
|
+
createdBy?: string;
|
|
419
|
+
createdAfter?: string;
|
|
420
|
+
createdBefore?: string;
|
|
421
|
+
hasAttachments?: boolean;
|
|
422
|
+
isSpam?: boolean;
|
|
423
|
+
search?: string;
|
|
424
|
+
categoryId?: string;
|
|
425
|
+
tagIds?: string[];
|
|
426
|
+
source?: TicketSource;
|
|
427
|
+
sort?: 'createdAt' | 'updatedAt' | 'priority';
|
|
428
|
+
order?: SortOrder;
|
|
429
|
+
limit?: number;
|
|
430
|
+
cursor?: string;
|
|
431
|
+
}
|
|
432
|
+
/**
|
|
433
|
+
* Options for creating a ticket
|
|
434
|
+
*/
|
|
435
|
+
interface CreateTicketOptions {
|
|
436
|
+
idempotencyKey?: string;
|
|
437
|
+
}
|
|
438
|
+
/**
|
|
439
|
+
* Input for merging tickets
|
|
440
|
+
*/
|
|
441
|
+
interface MergeTicketsInput {
|
|
442
|
+
sourceTicketIds: string[];
|
|
443
|
+
}
|
|
444
|
+
/**
|
|
445
|
+
* Result of a bulk action
|
|
446
|
+
*/
|
|
447
|
+
interface BulkActionResult {
|
|
448
|
+
success: boolean;
|
|
449
|
+
count: number;
|
|
450
|
+
}
|
|
451
|
+
|
|
452
|
+
/**
|
|
453
|
+
* Tickets resource
|
|
454
|
+
*/
|
|
455
|
+
declare class TicketsResource extends BaseResource {
|
|
456
|
+
/**
|
|
457
|
+
* Create a new ticket
|
|
458
|
+
*/
|
|
459
|
+
create(brandId: string, data: CreateTicketInput, options?: CreateTicketOptions): Promise<Ticket>;
|
|
460
|
+
/**
|
|
461
|
+
* List tickets with pagination (async iterator)
|
|
462
|
+
* Automatically fetches all pages
|
|
463
|
+
*/
|
|
464
|
+
list(brandId: string, filters?: Omit<ListTicketsFilters, 'cursor'>): AsyncIterable<Ticket>;
|
|
465
|
+
/**
|
|
466
|
+
* List a single page of tickets
|
|
467
|
+
*/
|
|
468
|
+
listPage(brandId: string, filters?: ListTicketsFilters): Promise<PaginatedResponse<Ticket>>;
|
|
469
|
+
/**
|
|
470
|
+
* Get a ticket by ID
|
|
471
|
+
*/
|
|
472
|
+
get(brandId: string, ticketId: string): Promise<Ticket>;
|
|
473
|
+
/**
|
|
474
|
+
* Update a ticket
|
|
475
|
+
*/
|
|
476
|
+
update(brandId: string, ticketId: string, data: UpdateTicketInput): Promise<Ticket>;
|
|
477
|
+
/**
|
|
478
|
+
* Delete a ticket
|
|
479
|
+
*/
|
|
480
|
+
delete(brandId: string, ticketId: string): Promise<Ticket>;
|
|
481
|
+
/**
|
|
482
|
+
* Mark a ticket as spam or not spam
|
|
483
|
+
*/
|
|
484
|
+
markAsSpam(brandId: string, ticketId: string, isSpam: boolean): Promise<Ticket>;
|
|
485
|
+
/**
|
|
486
|
+
* Merge tickets into a target ticket
|
|
487
|
+
*/
|
|
488
|
+
merge(brandId: string, targetTicketId: string, sourceTicketIds: string[]): Promise<Ticket>;
|
|
489
|
+
/**
|
|
490
|
+
* Perform a bulk action on multiple tickets
|
|
491
|
+
*/
|
|
492
|
+
bulk(brandId: string, action: BulkAction, ticketIds: string[], options?: {
|
|
493
|
+
assigneeId?: string | null;
|
|
494
|
+
categoryId?: string | null;
|
|
495
|
+
tags?: string[];
|
|
496
|
+
}): Promise<BulkActionResult>;
|
|
497
|
+
private buildListQuery;
|
|
498
|
+
}
|
|
499
|
+
|
|
500
|
+
/**
|
|
501
|
+
* Comment resource
|
|
502
|
+
*/
|
|
503
|
+
interface Comment {
|
|
504
|
+
id: string;
|
|
505
|
+
ticketId: string;
|
|
506
|
+
body: string;
|
|
507
|
+
authorId?: string;
|
|
508
|
+
authorName?: string;
|
|
509
|
+
authorType: AuthorType;
|
|
510
|
+
parentId?: string;
|
|
511
|
+
links?: Link[];
|
|
512
|
+
metadata?: Record<string, unknown>;
|
|
513
|
+
source: TicketSource;
|
|
514
|
+
sourceId?: string;
|
|
515
|
+
sourceData?: Record<string, unknown>;
|
|
516
|
+
createdAt: string;
|
|
517
|
+
updatedAt: string;
|
|
518
|
+
deletedAt?: string;
|
|
519
|
+
replies?: Comment[];
|
|
520
|
+
}
|
|
521
|
+
/**
|
|
522
|
+
* Input for creating a comment
|
|
523
|
+
*/
|
|
524
|
+
interface CreateCommentInput {
|
|
525
|
+
body: string;
|
|
526
|
+
authorId?: string;
|
|
527
|
+
authorName?: string;
|
|
528
|
+
authorType?: AuthorType;
|
|
529
|
+
parentId?: string;
|
|
530
|
+
links?: Link[];
|
|
531
|
+
metadata?: Record<string, unknown>;
|
|
532
|
+
source?: TicketSource;
|
|
533
|
+
sourceId?: string;
|
|
534
|
+
sourceData?: Record<string, unknown>;
|
|
535
|
+
setStatus?: Exclude<TicketStatus, 'closed'>;
|
|
536
|
+
connectionId?: string;
|
|
537
|
+
cc?: string[];
|
|
538
|
+
}
|
|
539
|
+
/**
|
|
540
|
+
* Input for updating a comment
|
|
541
|
+
*/
|
|
542
|
+
interface UpdateCommentInput {
|
|
543
|
+
body?: string;
|
|
544
|
+
links?: Link[];
|
|
545
|
+
metadata?: Record<string, unknown>;
|
|
546
|
+
}
|
|
547
|
+
/**
|
|
548
|
+
* Options for creating a comment
|
|
549
|
+
*/
|
|
550
|
+
interface CreateCommentOptions {
|
|
551
|
+
idempotencyKey?: string;
|
|
552
|
+
}
|
|
553
|
+
|
|
554
|
+
/**
|
|
555
|
+
* Comments resource
|
|
556
|
+
*/
|
|
557
|
+
declare class CommentsResource extends BaseResource {
|
|
558
|
+
/**
|
|
559
|
+
* Create a new comment on a ticket
|
|
560
|
+
*/
|
|
561
|
+
create(brandId: string, ticketId: string, data: CreateCommentInput, options?: CreateCommentOptions): Promise<Comment>;
|
|
562
|
+
/**
|
|
563
|
+
* List all comments on a ticket
|
|
564
|
+
*/
|
|
565
|
+
list(brandId: string, ticketId: string): Promise<Comment[]>;
|
|
566
|
+
/**
|
|
567
|
+
* Get a comment by ID
|
|
568
|
+
*/
|
|
569
|
+
get(brandId: string, ticketId: string, commentId: string): Promise<Comment>;
|
|
570
|
+
/**
|
|
571
|
+
* Update a comment
|
|
572
|
+
*/
|
|
573
|
+
update(brandId: string, ticketId: string, commentId: string, data: UpdateCommentInput): Promise<Comment>;
|
|
574
|
+
/**
|
|
575
|
+
* Delete a comment
|
|
576
|
+
*/
|
|
577
|
+
delete(brandId: string, ticketId: string, commentId: string): Promise<Comment>;
|
|
578
|
+
}
|
|
579
|
+
|
|
580
|
+
/**
|
|
581
|
+
* Attachment resource
|
|
582
|
+
*/
|
|
583
|
+
interface Attachment {
|
|
584
|
+
id: string;
|
|
585
|
+
ticketId: string;
|
|
586
|
+
commentId?: string;
|
|
587
|
+
filename: string;
|
|
588
|
+
contentType: string;
|
|
589
|
+
size: number;
|
|
590
|
+
status: AttachmentStatus;
|
|
591
|
+
uploadedBy?: string;
|
|
592
|
+
metadata?: Record<string, unknown>;
|
|
593
|
+
createdAt: string;
|
|
594
|
+
updatedAt: string;
|
|
595
|
+
}
|
|
596
|
+
/**
|
|
597
|
+
* Attachment with download URL
|
|
598
|
+
*/
|
|
599
|
+
interface AttachmentWithUrl extends Attachment {
|
|
600
|
+
downloadUrl: string;
|
|
601
|
+
}
|
|
602
|
+
/**
|
|
603
|
+
* Input for initiating an upload
|
|
604
|
+
*/
|
|
605
|
+
interface InitiateUploadInput {
|
|
606
|
+
filename: string;
|
|
607
|
+
contentType: string;
|
|
608
|
+
size: number;
|
|
609
|
+
uploadedBy?: string;
|
|
610
|
+
}
|
|
611
|
+
/**
|
|
612
|
+
* Response from initiating an upload
|
|
613
|
+
*/
|
|
614
|
+
interface InitiateUploadResponse {
|
|
615
|
+
attachmentId: string;
|
|
616
|
+
uploadUrl: string;
|
|
617
|
+
expiresIn: number;
|
|
618
|
+
}
|
|
619
|
+
|
|
620
|
+
/**
|
|
621
|
+
* Attachments resource
|
|
622
|
+
*/
|
|
623
|
+
declare class AttachmentsResource extends BaseResource {
|
|
624
|
+
/**
|
|
625
|
+
* Initiate an upload and get a presigned URL
|
|
626
|
+
*/
|
|
627
|
+
initiateUpload(brandId: string, ticketId: string, data: InitiateUploadInput): Promise<InitiateUploadResponse>;
|
|
628
|
+
/**
|
|
629
|
+
* Confirm that an upload has completed
|
|
630
|
+
*/
|
|
631
|
+
confirmUpload(brandId: string, ticketId: string, attachmentId: string): Promise<Attachment>;
|
|
632
|
+
/**
|
|
633
|
+
* List all attachments on a ticket
|
|
634
|
+
*/
|
|
635
|
+
list(brandId: string, ticketId: string): Promise<Attachment[]>;
|
|
636
|
+
/**
|
|
637
|
+
* Get an attachment with its download URL
|
|
638
|
+
*/
|
|
639
|
+
get(brandId: string, ticketId: string, attachmentId: string): Promise<AttachmentWithUrl>;
|
|
640
|
+
/**
|
|
641
|
+
* Delete an attachment
|
|
642
|
+
*/
|
|
643
|
+
delete(brandId: string, ticketId: string, attachmentId: string): Promise<void>;
|
|
644
|
+
/**
|
|
645
|
+
* Convenience method: Upload a file in one step
|
|
646
|
+
* Handles: initiate -> upload to presigned URL -> confirm
|
|
647
|
+
*/
|
|
648
|
+
upload(brandId: string, ticketId: string, file: Blob | Buffer | ArrayBuffer, filename: string, contentType: string): Promise<Attachment>;
|
|
649
|
+
}
|
|
650
|
+
|
|
651
|
+
/**
|
|
652
|
+
* Webhook resource
|
|
653
|
+
*/
|
|
654
|
+
interface Webhook {
|
|
655
|
+
id: string;
|
|
656
|
+
brandId: string;
|
|
657
|
+
url: string;
|
|
658
|
+
events: WebhookEvent[];
|
|
659
|
+
enabled: boolean;
|
|
660
|
+
failureCount: number;
|
|
661
|
+
lastTriggered?: string;
|
|
662
|
+
lastFailure?: string;
|
|
663
|
+
createdAt: string;
|
|
664
|
+
updatedAt: string;
|
|
665
|
+
}
|
|
666
|
+
/**
|
|
667
|
+
* Input for creating a webhook
|
|
668
|
+
*/
|
|
669
|
+
interface CreateWebhookInput {
|
|
670
|
+
url: string;
|
|
671
|
+
secret: string;
|
|
672
|
+
events: WebhookEvent[];
|
|
673
|
+
}
|
|
674
|
+
/**
|
|
675
|
+
* Webhook delivery record
|
|
676
|
+
*/
|
|
677
|
+
interface WebhookDelivery {
|
|
678
|
+
id: string;
|
|
679
|
+
webhookId: string;
|
|
680
|
+
event: WebhookEvent;
|
|
681
|
+
payload: Record<string, unknown>;
|
|
682
|
+
status: 'PENDING' | 'SUCCESS' | 'FAILED' | 'RETRYING';
|
|
683
|
+
attempts: number;
|
|
684
|
+
lastAttempt?: string;
|
|
685
|
+
responseCode?: number;
|
|
686
|
+
responseBody?: string;
|
|
687
|
+
error?: string;
|
|
688
|
+
createdAt: string;
|
|
689
|
+
}
|
|
690
|
+
|
|
691
|
+
/**
|
|
692
|
+
* Webhooks resource
|
|
693
|
+
*/
|
|
694
|
+
declare class WebhooksResource extends BaseResource {
|
|
695
|
+
/**
|
|
696
|
+
* Create a new webhook
|
|
697
|
+
*/
|
|
698
|
+
create(brandId: string, data: CreateWebhookInput): Promise<Webhook>;
|
|
699
|
+
/**
|
|
700
|
+
* List all webhooks for a brand
|
|
701
|
+
*/
|
|
702
|
+
list(brandId: string): Promise<Webhook[]>;
|
|
703
|
+
/**
|
|
704
|
+
* Get a webhook by ID
|
|
705
|
+
*/
|
|
706
|
+
get(brandId: string, webhookId: string): Promise<Webhook>;
|
|
707
|
+
/**
|
|
708
|
+
* Delete a webhook
|
|
709
|
+
*/
|
|
710
|
+
delete(brandId: string, webhookId: string): Promise<void>;
|
|
711
|
+
/**
|
|
712
|
+
* Get webhook delivery history
|
|
713
|
+
*/
|
|
714
|
+
getDeliveries(brandId: string, webhookId: string): Promise<WebhookDelivery[]>;
|
|
715
|
+
}
|
|
716
|
+
|
|
717
|
+
/**
|
|
718
|
+
* Categories resource
|
|
719
|
+
*/
|
|
720
|
+
declare class CategoriesResource extends BaseResource {
|
|
721
|
+
/**
|
|
722
|
+
* Create a new category
|
|
723
|
+
*/
|
|
724
|
+
create(brandId: string, data: CreateCategoryInput): Promise<Category>;
|
|
725
|
+
/**
|
|
726
|
+
* List all categories for a brand
|
|
727
|
+
*/
|
|
728
|
+
list(brandId: string): Promise<Category[]>;
|
|
729
|
+
/**
|
|
730
|
+
* Get a category by ID
|
|
731
|
+
*/
|
|
732
|
+
get(brandId: string, categoryId: string): Promise<Category>;
|
|
733
|
+
/**
|
|
734
|
+
* Update a category
|
|
735
|
+
*/
|
|
736
|
+
update(brandId: string, categoryId: string, data: UpdateCategoryInput): Promise<Category>;
|
|
737
|
+
/**
|
|
738
|
+
* Delete a category
|
|
739
|
+
*/
|
|
740
|
+
delete(brandId: string, categoryId: string): Promise<void>;
|
|
741
|
+
/**
|
|
742
|
+
* Get category statistics (ticket counts)
|
|
743
|
+
*/
|
|
744
|
+
getStats(brandId: string): Promise<CategoryStats>;
|
|
745
|
+
/**
|
|
746
|
+
* Reorder categories
|
|
747
|
+
*/
|
|
748
|
+
reorder(brandId: string, categoryIds: string[]): Promise<void>;
|
|
749
|
+
}
|
|
750
|
+
|
|
751
|
+
/**
|
|
752
|
+
* Tags resource
|
|
753
|
+
*/
|
|
754
|
+
declare class TagsResource extends BaseResource {
|
|
755
|
+
/**
|
|
756
|
+
* Create a new tag
|
|
757
|
+
*/
|
|
758
|
+
create(brandId: string, data: CreateTagInput): Promise<Tag>;
|
|
759
|
+
/**
|
|
760
|
+
* List all tags for a brand
|
|
761
|
+
*/
|
|
762
|
+
list(brandId: string): Promise<Tag[]>;
|
|
763
|
+
/**
|
|
764
|
+
* Update a tag
|
|
765
|
+
*/
|
|
766
|
+
update(brandId: string, tagId: string, data: UpdateTagInput): Promise<Tag>;
|
|
767
|
+
/**
|
|
768
|
+
* Delete a tag
|
|
769
|
+
*/
|
|
770
|
+
delete(brandId: string, tagId: string): Promise<void>;
|
|
771
|
+
/**
|
|
772
|
+
* Merge tags into a target tag
|
|
773
|
+
*/
|
|
774
|
+
merge(brandId: string, targetTagId: string, sourceTagIds: string[]): Promise<Tag>;
|
|
775
|
+
}
|
|
776
|
+
|
|
777
|
+
/**
|
|
778
|
+
* Customers resource
|
|
779
|
+
*/
|
|
780
|
+
declare class CustomersResource extends BaseResource {
|
|
781
|
+
/**
|
|
782
|
+
* Create a new customer
|
|
783
|
+
*/
|
|
784
|
+
create(brandId: string, data: CreateCustomerInput): Promise<Customer>;
|
|
785
|
+
/**
|
|
786
|
+
* List customers with pagination (async iterator)
|
|
787
|
+
*/
|
|
788
|
+
list(brandId: string, filters?: Omit<ListCustomersFilters, 'cursor'>): AsyncIterable<Customer>;
|
|
789
|
+
/**
|
|
790
|
+
* List a single page of customers
|
|
791
|
+
*/
|
|
792
|
+
listPage(brandId: string, filters?: ListCustomersFilters): Promise<PaginatedResponse<Customer>>;
|
|
793
|
+
/**
|
|
794
|
+
* Search customers (autocomplete)
|
|
795
|
+
*/
|
|
796
|
+
search(brandId: string, query: string): Promise<Customer[]>;
|
|
797
|
+
/**
|
|
798
|
+
* Get a customer by ID
|
|
799
|
+
*/
|
|
800
|
+
get(brandId: string, customerId: string): Promise<Customer>;
|
|
801
|
+
/**
|
|
802
|
+
* Update a customer
|
|
803
|
+
*/
|
|
804
|
+
update(brandId: string, customerId: string, data: UpdateCustomerInput): Promise<Customer>;
|
|
805
|
+
/**
|
|
806
|
+
* Delete a customer
|
|
807
|
+
*/
|
|
808
|
+
delete(brandId: string, customerId: string): Promise<Customer>;
|
|
809
|
+
private buildListQuery;
|
|
810
|
+
}
|
|
811
|
+
|
|
812
|
+
/**
|
|
813
|
+
* Custom field definition
|
|
814
|
+
*/
|
|
815
|
+
interface FieldDefinition {
|
|
816
|
+
key: string;
|
|
817
|
+
label: string;
|
|
818
|
+
type: FieldType;
|
|
819
|
+
required: boolean;
|
|
820
|
+
defaultValue?: unknown;
|
|
821
|
+
description?: string;
|
|
822
|
+
placeholder?: string;
|
|
823
|
+
options?: string[];
|
|
824
|
+
visible: boolean;
|
|
825
|
+
sortOrder: number;
|
|
826
|
+
source?: string;
|
|
827
|
+
createdAt?: string;
|
|
828
|
+
}
|
|
829
|
+
/**
|
|
830
|
+
* Field definitions grouped by entity type
|
|
831
|
+
*/
|
|
832
|
+
interface FieldDefinitions {
|
|
833
|
+
ticket: FieldDefinition[];
|
|
834
|
+
customer: FieldDefinition[];
|
|
835
|
+
company: FieldDefinition[];
|
|
836
|
+
}
|
|
837
|
+
/**
|
|
838
|
+
* Input for creating a field definition
|
|
839
|
+
*/
|
|
840
|
+
interface CreateFieldInput {
|
|
841
|
+
key: string;
|
|
842
|
+
label: string;
|
|
843
|
+
type: FieldType;
|
|
844
|
+
required?: boolean;
|
|
845
|
+
defaultValue?: unknown;
|
|
846
|
+
description?: string;
|
|
847
|
+
placeholder?: string;
|
|
848
|
+
options?: string[];
|
|
849
|
+
visible?: boolean;
|
|
850
|
+
sortOrder?: number;
|
|
851
|
+
source?: string;
|
|
852
|
+
}
|
|
853
|
+
/**
|
|
854
|
+
* Input for updating a field definition
|
|
855
|
+
*/
|
|
856
|
+
interface UpdateFieldInput {
|
|
857
|
+
label?: string;
|
|
858
|
+
required?: boolean;
|
|
859
|
+
defaultValue?: unknown;
|
|
860
|
+
description?: string;
|
|
861
|
+
placeholder?: string;
|
|
862
|
+
options?: string[];
|
|
863
|
+
visible?: boolean;
|
|
864
|
+
sortOrder?: number;
|
|
865
|
+
}
|
|
866
|
+
|
|
867
|
+
/**
|
|
868
|
+
* Custom fields resource
|
|
869
|
+
*/
|
|
870
|
+
declare class FieldsResource extends BaseResource {
|
|
871
|
+
/**
|
|
872
|
+
* Get all field definitions for a brand
|
|
873
|
+
*/
|
|
874
|
+
getAll(brandId: string): Promise<FieldDefinitions>;
|
|
875
|
+
/**
|
|
876
|
+
* Get field definitions for a specific entity type
|
|
877
|
+
*/
|
|
878
|
+
list(brandId: string, entityType: EntityType): Promise<FieldDefinition[]>;
|
|
879
|
+
/**
|
|
880
|
+
* Create a new field definition
|
|
881
|
+
*/
|
|
882
|
+
create(brandId: string, entityType: EntityType, data: CreateFieldInput): Promise<FieldDefinition>;
|
|
883
|
+
/**
|
|
884
|
+
* Update a field definition
|
|
885
|
+
*/
|
|
886
|
+
update(brandId: string, entityType: EntityType, key: string, data: UpdateFieldInput): Promise<FieldDefinition>;
|
|
887
|
+
/**
|
|
888
|
+
* Delete a field definition
|
|
889
|
+
*/
|
|
890
|
+
delete(brandId: string, entityType: EntityType, key: string): Promise<void>;
|
|
891
|
+
/**
|
|
892
|
+
* Reorder field definitions
|
|
893
|
+
*/
|
|
894
|
+
reorder(brandId: string, entityType: EntityType, keys: string[]): Promise<void>;
|
|
895
|
+
}
|
|
896
|
+
|
|
897
|
+
/**
|
|
898
|
+
* Configuration options for the Dispatch Tickets client
|
|
899
|
+
*/
|
|
900
|
+
interface DispatchTicketsConfig {
|
|
901
|
+
/**
|
|
902
|
+
* Your API key (required)
|
|
903
|
+
*/
|
|
904
|
+
apiKey: string;
|
|
905
|
+
/**
|
|
906
|
+
* Base URL for the API
|
|
907
|
+
* @default 'https://dispatch-tickets-api.onrender.com/v1'
|
|
908
|
+
*/
|
|
909
|
+
baseUrl?: string;
|
|
910
|
+
/**
|
|
911
|
+
* Request timeout in milliseconds
|
|
912
|
+
* @default 30000
|
|
913
|
+
*/
|
|
914
|
+
timeout?: number;
|
|
915
|
+
/**
|
|
916
|
+
* Maximum number of retries for failed requests
|
|
917
|
+
* @default 3
|
|
918
|
+
*/
|
|
919
|
+
maxRetries?: number;
|
|
920
|
+
/**
|
|
921
|
+
* Enable debug logging
|
|
922
|
+
* @default false
|
|
923
|
+
*/
|
|
924
|
+
debug?: boolean;
|
|
925
|
+
}
|
|
926
|
+
/**
|
|
927
|
+
* Dispatch Tickets SDK client
|
|
928
|
+
*
|
|
929
|
+
* @example
|
|
930
|
+
* ```typescript
|
|
931
|
+
* import { DispatchTickets } from '@dispatchtickets/sdk';
|
|
932
|
+
*
|
|
933
|
+
* const client = new DispatchTickets({
|
|
934
|
+
* apiKey: 'sk_live_...',
|
|
935
|
+
* });
|
|
936
|
+
*
|
|
937
|
+
* // List brands
|
|
938
|
+
* const brands = await client.brands.list();
|
|
939
|
+
*
|
|
940
|
+
* // Create a ticket
|
|
941
|
+
* const ticket = await client.tickets.create('ws_abc123', {
|
|
942
|
+
* title: 'Help with login',
|
|
943
|
+
* body: 'I cannot log in to my account',
|
|
944
|
+
* });
|
|
945
|
+
*
|
|
946
|
+
* // Iterate through all tickets
|
|
947
|
+
* for await (const ticket of client.tickets.list('ws_abc123', { status: 'open' })) {
|
|
948
|
+
* console.log(ticket.title);
|
|
949
|
+
* }
|
|
950
|
+
* ```
|
|
951
|
+
*/
|
|
952
|
+
declare class DispatchTickets {
|
|
953
|
+
private readonly http;
|
|
954
|
+
/**
|
|
955
|
+
* Brands (workspaces) resource
|
|
956
|
+
*/
|
|
957
|
+
readonly brands: BrandsResource;
|
|
958
|
+
/**
|
|
959
|
+
* Tickets resource
|
|
960
|
+
*/
|
|
961
|
+
readonly tickets: TicketsResource;
|
|
962
|
+
/**
|
|
963
|
+
* Comments resource
|
|
964
|
+
*/
|
|
965
|
+
readonly comments: CommentsResource;
|
|
966
|
+
/**
|
|
967
|
+
* Attachments resource
|
|
968
|
+
*/
|
|
969
|
+
readonly attachments: AttachmentsResource;
|
|
970
|
+
/**
|
|
971
|
+
* Webhooks resource
|
|
972
|
+
*/
|
|
973
|
+
readonly webhooks: WebhooksResource;
|
|
974
|
+
/**
|
|
975
|
+
* Categories resource
|
|
976
|
+
*/
|
|
977
|
+
readonly categories: CategoriesResource;
|
|
978
|
+
/**
|
|
979
|
+
* Tags resource
|
|
980
|
+
*/
|
|
981
|
+
readonly tags: TagsResource;
|
|
982
|
+
/**
|
|
983
|
+
* Customers resource
|
|
984
|
+
*/
|
|
985
|
+
readonly customers: CustomersResource;
|
|
986
|
+
/**
|
|
987
|
+
* Custom fields resource
|
|
988
|
+
*/
|
|
989
|
+
readonly fields: FieldsResource;
|
|
990
|
+
/**
|
|
991
|
+
* Static webhook utilities
|
|
992
|
+
*/
|
|
993
|
+
static readonly webhooks: {
|
|
994
|
+
verifySignature(payload: string, signature: string, secret: string): boolean;
|
|
995
|
+
generateSignature(payload: string, secret: string): string;
|
|
996
|
+
};
|
|
997
|
+
constructor(config: DispatchTicketsConfig);
|
|
998
|
+
}
|
|
999
|
+
|
|
1000
|
+
/**
|
|
1001
|
+
* Base error class for all Dispatch Tickets SDK errors
|
|
1002
|
+
*/
|
|
1003
|
+
declare class DispatchTicketsError extends Error {
|
|
1004
|
+
readonly code: string;
|
|
1005
|
+
readonly statusCode?: number;
|
|
1006
|
+
readonly details?: Record<string, unknown>;
|
|
1007
|
+
constructor(message: string, code: string, statusCode?: number, details?: Record<string, unknown>);
|
|
1008
|
+
}
|
|
1009
|
+
/**
|
|
1010
|
+
* Thrown when API key is missing or invalid
|
|
1011
|
+
*/
|
|
1012
|
+
declare class AuthenticationError extends DispatchTicketsError {
|
|
1013
|
+
constructor(message?: string);
|
|
1014
|
+
}
|
|
1015
|
+
/**
|
|
1016
|
+
* Thrown when rate limit is exceeded
|
|
1017
|
+
*/
|
|
1018
|
+
declare class RateLimitError extends DispatchTicketsError {
|
|
1019
|
+
readonly retryAfter?: number;
|
|
1020
|
+
constructor(message?: string, retryAfter?: number);
|
|
1021
|
+
}
|
|
1022
|
+
/**
|
|
1023
|
+
* Thrown when request validation fails
|
|
1024
|
+
*/
|
|
1025
|
+
declare class ValidationError extends DispatchTicketsError {
|
|
1026
|
+
readonly errors?: Array<{
|
|
1027
|
+
field: string;
|
|
1028
|
+
message: string;
|
|
1029
|
+
}>;
|
|
1030
|
+
constructor(message?: string, errors?: Array<{
|
|
1031
|
+
field: string;
|
|
1032
|
+
message: string;
|
|
1033
|
+
}>);
|
|
1034
|
+
}
|
|
1035
|
+
/**
|
|
1036
|
+
* Thrown when a resource is not found
|
|
1037
|
+
*/
|
|
1038
|
+
declare class NotFoundError extends DispatchTicketsError {
|
|
1039
|
+
readonly resourceType?: string;
|
|
1040
|
+
readonly resourceId?: string;
|
|
1041
|
+
constructor(message?: string, resourceType?: string, resourceId?: string);
|
|
1042
|
+
}
|
|
1043
|
+
/**
|
|
1044
|
+
* Thrown when there's a conflict (e.g., duplicate resource)
|
|
1045
|
+
*/
|
|
1046
|
+
declare class ConflictError extends DispatchTicketsError {
|
|
1047
|
+
constructor(message?: string);
|
|
1048
|
+
}
|
|
1049
|
+
/**
|
|
1050
|
+
* Thrown when the server returns an unexpected error
|
|
1051
|
+
*/
|
|
1052
|
+
declare class ServerError extends DispatchTicketsError {
|
|
1053
|
+
constructor(message?: string, statusCode?: number);
|
|
1054
|
+
}
|
|
1055
|
+
/**
|
|
1056
|
+
* Thrown when request times out
|
|
1057
|
+
*/
|
|
1058
|
+
declare class TimeoutError extends DispatchTicketsError {
|
|
1059
|
+
constructor(message?: string);
|
|
1060
|
+
}
|
|
1061
|
+
/**
|
|
1062
|
+
* Thrown when network connection fails
|
|
1063
|
+
*/
|
|
1064
|
+
declare class NetworkError extends DispatchTicketsError {
|
|
1065
|
+
constructor(message?: string);
|
|
1066
|
+
}
|
|
1067
|
+
|
|
1068
|
+
/**
|
|
1069
|
+
* Webhook signature verification utilities
|
|
1070
|
+
*/
|
|
1071
|
+
declare const webhookUtils: {
|
|
1072
|
+
/**
|
|
1073
|
+
* Verify a webhook signature
|
|
1074
|
+
*
|
|
1075
|
+
* @param payload - The raw request body as a string
|
|
1076
|
+
* @param signature - The X-Dispatch-Signature header value
|
|
1077
|
+
* @param secret - Your webhook secret
|
|
1078
|
+
* @returns true if the signature is valid
|
|
1079
|
+
*
|
|
1080
|
+
* @example
|
|
1081
|
+
* ```typescript
|
|
1082
|
+
* import { DispatchTickets } from '@dispatchtickets/sdk';
|
|
1083
|
+
*
|
|
1084
|
+
* app.post('/webhooks', (req, res) => {
|
|
1085
|
+
* const signature = req.headers['x-dispatch-signature'];
|
|
1086
|
+
* const isValid = DispatchTickets.webhooks.verifySignature(
|
|
1087
|
+
* req.rawBody,
|
|
1088
|
+
* signature,
|
|
1089
|
+
* process.env.WEBHOOK_SECRET
|
|
1090
|
+
* );
|
|
1091
|
+
*
|
|
1092
|
+
* if (!isValid) {
|
|
1093
|
+
* return res.status(401).send('Invalid signature');
|
|
1094
|
+
* }
|
|
1095
|
+
*
|
|
1096
|
+
* // Process webhook...
|
|
1097
|
+
* });
|
|
1098
|
+
* ```
|
|
1099
|
+
*/
|
|
1100
|
+
verifySignature(payload: string, signature: string, secret: string): boolean;
|
|
1101
|
+
/**
|
|
1102
|
+
* Generate a signature for testing purposes
|
|
1103
|
+
*
|
|
1104
|
+
* @param payload - The payload to sign
|
|
1105
|
+
* @param secret - The secret to sign with
|
|
1106
|
+
* @returns The signature in the format sha256=<hex>
|
|
1107
|
+
*/
|
|
1108
|
+
generateSignature(payload: string, secret: string): string;
|
|
1109
|
+
};
|
|
1110
|
+
|
|
1111
|
+
/**
|
|
1112
|
+
* Collect all items from an async iterable into an array
|
|
1113
|
+
*/
|
|
1114
|
+
declare function collectAll<T>(iterable: AsyncIterable<T>): Promise<T[]>;
|
|
1115
|
+
|
|
1116
|
+
export { type Attachment, type AttachmentStatus, type AttachmentWithUrl, AuthenticationError, type AuthorType, type Brand, type BulkAction, type BulkActionResult, type Category, type CategoryStats, type Comment, type Company, ConflictError, type CreateBrandInput, type CreateCategoryInput, type CreateCommentInput, type CreateCommentOptions, type CreateCustomerInput, type CreateFieldInput, type CreateTagInput, type CreateTicketInput, type CreateTicketOptions, type CreateWebhookInput, type Customer, type DeleteBrandPreview, DispatchTickets, type DispatchTicketsConfig, DispatchTicketsError, type EntityType, type FieldDefinition, type FieldDefinitions, type FieldType, type InitiateUploadInput, type InitiateUploadResponse, type Link, type ListCustomersFilters, type ListTicketsFilters, type MergeTagsInput, type MergeTicketsInput, NetworkError, NotFoundError, type PaginatedResponse, RateLimitError, ServerError, type SortOrder, type Tag, type Ticket, type TicketPriority, type TicketSource, type TicketStatus, TimeoutError, type UpdateBrandInput, type UpdateCategoryInput, type UpdateCommentInput, type UpdateCustomerInput, type UpdateFieldInput, type UpdateTagInput, type UpdateTicketInput, ValidationError, type Webhook, type WebhookDelivery, type WebhookEvent, collectAll, webhookUtils };
|