@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.
@@ -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 };