@ecodrix/erix-api 1.0.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,1096 @@
1
+ import { AxiosInstance, AxiosRequestConfig, Method } from 'axios';
2
+
3
+ interface RequestOptions extends AxiosRequestConfig {
4
+ /**
5
+ * If true, will not add the x-client-code header.
6
+ */
7
+ ignoreClientCode?: boolean;
8
+ /**
9
+ * Safe execution idempotency key.
10
+ * If provided, the backend will safely ignore duplicate requests retried with the same key.
11
+ */
12
+ idempotencyKey?: string;
13
+ }
14
+ declare abstract class APIResource {
15
+ protected readonly client: AxiosInstance;
16
+ constructor(client: AxiosInstance);
17
+ protected post<T>(url: string, data?: any, options?: RequestOptions): Promise<T>;
18
+ protected get<T>(url: string, options?: RequestOptions): Promise<T>;
19
+ protected deleteRequest<T>(url: string, options?: RequestOptions): Promise<T>;
20
+ private buildConfig;
21
+ private handleError;
22
+ }
23
+
24
+ /**
25
+ * Parameters for sending a free-form WhatsApp message.
26
+ */
27
+ interface SendMessageParams {
28
+ /**
29
+ * Recipient's phone number in E.164 format.
30
+ * @example "+919876543210"
31
+ */
32
+ to: string;
33
+ /** Plain text body of the message. */
34
+ text?: string;
35
+ /** Public URL of the media asset to send. */
36
+ mediaUrl?: string;
37
+ /** MIME category of the media. */
38
+ mediaType?: "image" | "video" | "audio" | "document";
39
+ /** The `messageId` of the message to reply to (quoted replies). */
40
+ replyToId?: string;
41
+ /** Filename shown to the recipient (required for `document` type). */
42
+ filename?: string;
43
+ /** Arbitrary metadata stored with the message record. */
44
+ metadata?: Record<string, any>;
45
+ }
46
+ /**
47
+ * Parameters for sending a pre-approved WhatsApp Business template.
48
+ */
49
+ interface SendTemplateParams {
50
+ /**
51
+ * Recipient's phone number in E.164 format.
52
+ * @example "+919876543210"
53
+ */
54
+ to: string;
55
+ /** The exact template name as approved in Meta Business Manager. */
56
+ templateName: string;
57
+ /**
58
+ * BCP-47 language code for the template.
59
+ * @default "en_US"
60
+ */
61
+ language?: string;
62
+ /**
63
+ * Ordered array of variable substitutions for template placeholders.
64
+ * @example ["Alice", "10 April 2026", "10:00 AM"]
65
+ */
66
+ variables?: string[];
67
+ /** Optional header media URL (for templates with media headers). */
68
+ mediaUrl?: string;
69
+ /** Media type for the header (e.g. "image", "document"). */
70
+ mediaType?: string;
71
+ }
72
+ /**
73
+ * WhatsApp outbound messaging resource.
74
+ *
75
+ * Access via `ecod.whatsapp.messages`.
76
+ *
77
+ * @example
78
+ * ```typescript
79
+ * await ecod.whatsapp.messages.send({
80
+ * to: "+919876543210",
81
+ * text: "Your appointment is confirmed!",
82
+ * });
83
+ * ```
84
+ */
85
+ declare class Messages extends APIResource {
86
+ /**
87
+ * Send a free-text or media message to a WhatsApp number.
88
+ *
89
+ * For text-only messages, supply `text`. For media, supply `mediaUrl`
90
+ * and `mediaType`. Both can be combined.
91
+ *
92
+ * @param params - Message parameters.
93
+ * @returns The created message record.
94
+ *
95
+ * @example Text message
96
+ * ```typescript
97
+ * await ecod.whatsapp.messages.send({
98
+ * to: "+919876543210",
99
+ * text: "Hello!",
100
+ * });
101
+ * ```
102
+ *
103
+ * @example Media message
104
+ * ```typescript
105
+ * await ecod.whatsapp.messages.send({
106
+ * to: "+919876543210",
107
+ * mediaUrl: "https://cdn.ecodrix.com/invoice.pdf",
108
+ * mediaType: "document",
109
+ * filename: "invoice.pdf",
110
+ * });
111
+ * ```
112
+ */
113
+ send(params: SendMessageParams): Promise<unknown>;
114
+ /**
115
+ * Send a pre-approved WhatsApp Business template message.
116
+ *
117
+ * Templates must be approved in Meta Business Manager before use.
118
+ * Variable placeholders in the template body are filled left-to-right
119
+ * from the `variables` array.
120
+ *
121
+ * @param params - Template message parameters.
122
+ * @returns The created message record.
123
+ *
124
+ * @example
125
+ * ```typescript
126
+ * await ecod.whatsapp.messages.sendTemplate({
127
+ * to: "+919876543210",
128
+ * templateName: "appointment_reminder",
129
+ * language: "en_US",
130
+ * variables: ["Alice", "10 April", "10:00 AM"],
131
+ * });
132
+ * ```
133
+ */
134
+ sendTemplate(params: SendTemplateParams): Promise<unknown>;
135
+ /**
136
+ * Mark all messages in a conversation as read (double-tick).
137
+ *
138
+ * @param conversationId - The conversation to mark as read.
139
+ *
140
+ * @example
141
+ * ```typescript
142
+ * await ecod.whatsapp.messages.markRead("conv_64abc...");
143
+ * ```
144
+ */
145
+ markRead(conversationId: string): Promise<unknown>;
146
+ }
147
+
148
+ interface ListParams {
149
+ limit?: number;
150
+ before?: string;
151
+ }
152
+ declare class Conversations extends APIResource {
153
+ /**
154
+ * List conversations for the tenant.
155
+ */
156
+ list(params?: ListParams): Promise<any>;
157
+ /**
158
+ * Retrieve details of a specific conversation.
159
+ */
160
+ retrieve(conversationId: string): Promise<any>;
161
+ /**
162
+ * Get messages for a specific conversation.
163
+ */
164
+ messages(conversationId: string, params?: ListParams): Promise<any>;
165
+ /**
166
+ * Link a conversation to a lead.
167
+ */
168
+ linkLead(conversationId: string, leadId: string): Promise<unknown>;
169
+ /**
170
+ * Delete a conversation.
171
+ */
172
+ delete(conversationId: string): Promise<any>;
173
+ }
174
+
175
+ interface SendTemplatePayload {
176
+ /** Phone number in E.164 format. */
177
+ phone: string;
178
+ /** Name of the pre-approved WhatsApp template. */
179
+ templateName: string;
180
+ /** Language code (defaults to "en"). */
181
+ languageCode?: string;
182
+ /** Key-value pairs matching variables in your template (e.g., {{1}}, {{2}}). */
183
+ variables?: Record<string, string>;
184
+ /** Explicitly resolved variables if bypassing the internal resolution engine. */
185
+ resolvedVariables?: any[];
186
+ }
187
+ declare class WhatsApp extends APIResource {
188
+ messages: Messages;
189
+ conversations: Conversations;
190
+ constructor(client: AxiosInstance);
191
+ /**
192
+ * Dispatch a WhatsApp template message directly to a specific phone number.
193
+ * Bypasses the automation queue for immediate high-priority delivery.
194
+ *
195
+ * @param payload - The template dispatch payload.
196
+ * @returns Information about the dispatched message.
197
+ */
198
+ sendTemplate(payload: SendTemplatePayload): Promise<{
199
+ success: boolean;
200
+ messageId?: string;
201
+ templateName?: string;
202
+ resolvedVariables?: any[];
203
+ }>;
204
+ }
205
+
206
+ /**
207
+ * Parameters for creating a new CRM Lead.
208
+ */
209
+ interface CreateLeadParams {
210
+ /** Lead's first name. Required. */
211
+ firstName: string;
212
+ /** Lead's last name. */
213
+ lastName?: string;
214
+ /** Lead's email address. */
215
+ email?: string;
216
+ /** Lead's phone number in E.164 format (e.g. "+919876543210"). */
217
+ phone?: string;
218
+ /**
219
+ * Acquisition channel.
220
+ * @example "website" | "whatsapp" | "direct" | "referral"
221
+ */
222
+ source?: string;
223
+ /** Arbitrary key-value metadata (UTM params, order IDs, etc.). */
224
+ metadata?: Record<string, any>;
225
+ }
226
+ /**
227
+ * CRM Lead resource — full lifecycle management.
228
+ *
229
+ * Access via `ecod.crm.leads`.
230
+ *
231
+ * @example
232
+ * ```typescript
233
+ * const { data: lead } = await ecod.crm.leads.create({
234
+ * firstName: "Alice",
235
+ * phone: "+919876543210",
236
+ * source: "website",
237
+ * });
238
+ * ```
239
+ */
240
+ declare class Leads extends APIResource {
241
+ /**
242
+ * Create a new lead in the CRM pipeline.
243
+ *
244
+ * @param params - Lead creation parameters. `firstName` is required.
245
+ * @returns The newly created Lead document.
246
+ *
247
+ * @example
248
+ * ```typescript
249
+ * const { data } = await ecod.crm.leads.create({
250
+ * firstName: "Alice",
251
+ * phone: "+919876543210",
252
+ * });
253
+ * ```
254
+ */
255
+ create<T = any>(params: CreateLeadParams): Promise<T>;
256
+ /**
257
+ * Bulk ingest leads efficiently in parallel using automatic chunking.
258
+ * Prevents rate limit exhaustion by executing `chunkSize` requests at a time.
259
+ *
260
+ * @param leads - Array of leads to create.
261
+ * @param chunkSize - Number of leads to send concurrently (default: 50)
262
+ * @returns Array of created lead results.
263
+ */
264
+ createMany(leads: CreateLeadParams[], chunkSize?: number): Promise<any[]>;
265
+ /**
266
+ * List leads with optional filtering and pagination.
267
+ *
268
+ * @param params - Filter options (status, source, pipelineId, page, limit, etc.)
269
+ * @returns Paginated list of Lead documents.
270
+ *
271
+ * @example
272
+ * ```typescript
273
+ * const { data } = await ecod.crm.leads.list({ status: "new", limit: 25 });
274
+ * ```
275
+ */
276
+ list<T = any>(params?: Record<string, any>): Promise<T>;
277
+ /**
278
+ * Auto-paginating iterator for leads.
279
+ * Seamlessly fetches leads page by page as you iterate.
280
+ *
281
+ * @example
282
+ * ```typescript
283
+ * for await (const lead of ecod.crm.leads.listAutoPaging({ status: "won" })) {
284
+ * console.log(lead.firstName);
285
+ * }
286
+ * ```
287
+ */
288
+ listAutoPaging(params?: Record<string, any>): AsyncGenerator<any, void, unknown>;
289
+ /**
290
+ * Retrieve a single lead by its unique ID.
291
+ *
292
+ * @param leadId - The MongoDB ObjectId of the lead.
293
+ * @returns The Lead document, or a 404 error if not found.
294
+ *
295
+ * @example
296
+ * ```typescript
297
+ * const { data } = await ecod.crm.leads.retrieve("64abc...");
298
+ * ```
299
+ */
300
+ retrieve(leadId: string): Promise<unknown>;
301
+ /**
302
+ * Update the fields of an existing lead.
303
+ *
304
+ * @param leadId - The ID of the lead to update.
305
+ * @param params - Partial lead fields to update.
306
+ * @returns The updated Lead document.
307
+ *
308
+ * @example
309
+ * ```typescript
310
+ * await ecod.crm.leads.update("64abc...", { email: "new@email.com" });
311
+ * ```
312
+ */
313
+ update(leadId: string, params: Partial<CreateLeadParams>): Promise<unknown>;
314
+ /**
315
+ * Archive (soft-delete) a lead. The record is retained in the database
316
+ * for audit purposes but is excluded from all standard list views.
317
+ *
318
+ * @param leadId - The ID of the lead to archive.
319
+ *
320
+ * @example
321
+ * ```typescript
322
+ * await ecod.crm.leads.delete("64abc...");
323
+ * ```
324
+ */
325
+ delete(leadId: string): Promise<unknown>;
326
+ }
327
+
328
+ declare class CRM {
329
+ leads: Leads;
330
+ constructor(client: AxiosInstance);
331
+ }
332
+
333
+ /**
334
+ * Options for the `upload()` elite helper.
335
+ */
336
+ interface UploadOptions {
337
+ /**
338
+ * The destination folder key in R2.
339
+ * @example "customer_documents" | "avatars" | "invoices"
340
+ */
341
+ folder: string;
342
+ /**
343
+ * The desired filename, including extension.
344
+ * @example "contract.pdf" | "profile.jpg"
345
+ */
346
+ filename: string;
347
+ /**
348
+ * The MIME type of the file.
349
+ * @example "application/pdf" | "image/jpeg" | "video/mp4"
350
+ */
351
+ contentType: string;
352
+ }
353
+ /**
354
+ * Cloudflare R2-backed media resource.
355
+ *
356
+ * Access via `ecod.media`.
357
+ *
358
+ * The `upload()` method is the recommended approach. It acts as a client-side
359
+ * orchestrator: it fetches a presigned URL from the backend, uploads directly
360
+ * to R2 (bypassing the API server), then confirms the upload — all in one call.
361
+ *
362
+ * @example
363
+ * ```typescript
364
+ * const { data } = await ecod.media.upload(fileBuffer, {
365
+ * folder: "invoices",
366
+ * filename: "invoice-001.pdf",
367
+ * contentType: "application/pdf",
368
+ * });
369
+ * console.log(data.url); // → https://cdn.ecodrix.com/invoices/invoice-001.pdf
370
+ * ```
371
+ */
372
+ declare class MediaResource extends APIResource {
373
+ /**
374
+ * Get current storage usage metrics for the tenant.
375
+ *
376
+ * @returns `{ usedMB, limitMB, fileCount }`
377
+ *
378
+ * @example
379
+ * ```typescript
380
+ * const { data } = await ecod.media.getUsage();
381
+ * console.log(`${data.usedMB} / ${data.limitMB} MB used`);
382
+ * ```
383
+ */
384
+ getUsage(): Promise<unknown>;
385
+ /**
386
+ * Create a new top-level folder in the tenant's R2 bucket.
387
+ *
388
+ * @param name - Folder name (alphanumeric, hyphens, underscores).
389
+ *
390
+ * @example
391
+ * ```typescript
392
+ * await ecod.media.createFolder("patient_records");
393
+ * ```
394
+ */
395
+ createFolder(name: string): Promise<unknown>;
396
+ /**
397
+ * List files within a specific folder, with optional date filtering.
398
+ *
399
+ * @param folder - The folder key to list.
400
+ * @param params - Optional `year` and `month` filters (e.g. `{ year: "2026", month: "04" }`).
401
+ * @returns Array of file metadata objects.
402
+ *
403
+ * @example
404
+ * ```typescript
405
+ * const { data: files } = await ecod.media.list("invoices", { year: "2026" });
406
+ * ```
407
+ */
408
+ list(folder: string, params?: {
409
+ year?: string;
410
+ month?: string;
411
+ }): Promise<unknown>;
412
+ /**
413
+ * Delete a file from R2 by its storage key.
414
+ *
415
+ * @param key - The full storage key of the file (e.g. `"invoices/contract.pdf"`).
416
+ *
417
+ * @example
418
+ * ```typescript
419
+ * await ecod.media.delete("invoices/old-contract.pdf");
420
+ * ```
421
+ */
422
+ delete(key: string): Promise<unknown>;
423
+ /**
424
+ * Request a temporary presigned download URL for a private file.
425
+ *
426
+ * @param key - The full storage key of the file.
427
+ * @returns `{ url }` — a time-limited download URL.
428
+ *
429
+ * @example
430
+ * ```typescript
431
+ * const { data } = await ecod.media.getDownloadUrl("invoices/contract.pdf");
432
+ * // → { url: "https://cdn.ecodrix.com/...?token=..." }
433
+ * ```
434
+ */
435
+ getDownloadUrl(key: string): Promise<unknown>;
436
+ /**
437
+ * **Elite Upload Helper** — uploads a file to Cloudflare R2 in a single call.
438
+ *
439
+ * This orchestrates 3 steps transparently:
440
+ * 1. Fetch a presigned `PUT` URL from the ECODrIx backend.
441
+ * 2. Upload the file _directly_ to R2 (no API proxy, maximum throughput).
442
+ * 3. Confirm the upload with the backend so it is indexed and tracked.
443
+ *
444
+ * Works with Node.js `Buffer`, browser `File`/`Blob`, or any stream-like
445
+ * object that Axios can PUT.
446
+ *
447
+ * @param file - The file data to upload.
448
+ * @param options - Folder, filename, and content type.
449
+ * @returns Confirmed file metadata including `key` and `url`.
450
+ *
451
+ * @example Node.js
452
+ * ```typescript
453
+ * import { readFileSync } from "fs";
454
+ * const buf = readFileSync("./invoice.pdf");
455
+ * const { data } = await ecod.media.upload(buf, {
456
+ * folder: "invoices",
457
+ * filename: "invoice-001.pdf",
458
+ * contentType: "application/pdf",
459
+ * });
460
+ * ```
461
+ *
462
+ * @example Browser
463
+ * ```typescript
464
+ * const file = inputElement.files[0];
465
+ * const { data } = await ecod.media.upload(file, {
466
+ * folder: "avatars",
467
+ * filename: file.name,
468
+ * contentType: file.type,
469
+ * });
470
+ * ```
471
+ */
472
+ upload(file: any, options: UploadOptions): Promise<any>;
473
+ }
474
+
475
+ /**
476
+ * Parameters for scheduling a new Google Meet appointment.
477
+ */
478
+ interface CreateMeetingParams {
479
+ /** The CRM Lead ID this meeting belongs to. */
480
+ leadId: string;
481
+ /** Full name of the external participant. */
482
+ participantName: string;
483
+ /** Phone number of the participant in E.164 format. */
484
+ participantPhone: string;
485
+ /**
486
+ * Meeting start time.
487
+ * @example new Date("2026-04-10T10:00:00.000Z")
488
+ */
489
+ startTime: Date | string;
490
+ /**
491
+ * Meeting end time.
492
+ * @example new Date("2026-04-10T10:30:00.000Z")
493
+ */
494
+ endTime: Date | string;
495
+ /** Arbitrary metadata to attach to the meeting record. */
496
+ metadata?: Record<string, any>;
497
+ }
498
+ /**
499
+ * Parameters for updating an existing meeting.
500
+ */
501
+ interface UpdateMeetingParams {
502
+ /**
503
+ * Update the meeting status.
504
+ * @example "scheduled" | "completed" | "cancelled"
505
+ */
506
+ status?: string;
507
+ /** Update the payment status for paid consultations. */
508
+ paymentStatus?: string;
509
+ /** New start time for rescheduling. */
510
+ startTime?: Date | string;
511
+ /** New end time for rescheduling. */
512
+ endTime?: Date | string;
513
+ /** Duration in minutes. */
514
+ duration?: number;
515
+ }
516
+ /**
517
+ * Google Meet appointment scheduling resource.
518
+ *
519
+ * Access via `ecod.meet`.
520
+ *
521
+ * @example
522
+ * ```typescript
523
+ * const { data } = await ecod.meet.create({
524
+ * leadId: "64abc...",
525
+ * participantName: "Alice",
526
+ * participantPhone: "+919876543210",
527
+ * startTime: "2026-04-10T10:00:00Z",
528
+ * endTime: "2026-04-10T10:30:00Z",
529
+ * });
530
+ * console.log(data.meetLink); // → https://meet.google.com/abc-defg-hij
531
+ * ```
532
+ */
533
+ declare class Meetings extends APIResource {
534
+ /**
535
+ * Schedule a new Google Meet with a lead.
536
+ *
537
+ * The backend automatically creates a Google Calendar event and generates
538
+ * a Meet link, then sends confirmation notifications via WhatsApp.
539
+ *
540
+ * @param data - Meeting details.
541
+ * @returns The created Meeting document including `meetLink`.
542
+ *
543
+ * @example
544
+ * ```typescript
545
+ * const { data } = await ecod.meet.create({
546
+ * leadId: "64abc...",
547
+ * participantName: "Alice",
548
+ * participantPhone: "+91...",
549
+ * startTime: "2026-04-10T10:00:00Z",
550
+ * endTime: "2026-04-10T10:30:00Z",
551
+ * });
552
+ * ```
553
+ */
554
+ create(data: CreateMeetingParams): Promise<any>;
555
+ /**
556
+ * List all meetings for the tenant, with optional filters.
557
+ *
558
+ * @param params - `leadId` to filter by lead; `status` to filter by state.
559
+ * @returns Array of Meeting documents.
560
+ *
561
+ * @example
562
+ * ```typescript
563
+ * const { data } = await ecod.meet.list({ status: "scheduled" });
564
+ * ```
565
+ */
566
+ list(params?: {
567
+ leadId?: string;
568
+ status?: string;
569
+ }): Promise<any>;
570
+ /**
571
+ * Retrieve the full details for a specific meeting.
572
+ *
573
+ * @param meetingId - The unique meeting ID.
574
+ * @returns The Meeting document.
575
+ *
576
+ * @example
577
+ * ```typescript
578
+ * const { data } = await ecod.meet.retrieve("meeting_id");
579
+ * ```
580
+ */
581
+ retrieve(meetingId: string): Promise<any>;
582
+ /**
583
+ * Update or reschedule an existing meeting.
584
+ *
585
+ * Partial updates are supported — only supply the fields you wish to change.
586
+ *
587
+ * @param meetingId - The meeting to update.
588
+ * @param data - Fields to update.
589
+ * @returns The updated Meeting document.
590
+ *
591
+ * @example
592
+ * ```typescript
593
+ * // Reschedule
594
+ * await ecod.meet.update("meeting_id", {
595
+ * startTime: "2026-04-11T11:00:00Z",
596
+ * endTime: "2026-04-11T11:30:00Z",
597
+ * });
598
+ * ```
599
+ */
600
+ update(meetingId: string, data: UpdateMeetingParams): Promise<any>;
601
+ /**
602
+ * Cancel a meeting. This sets the meeting status to `"cancelled"`.
603
+ *
604
+ * @param meetingId - The meeting to cancel.
605
+ *
606
+ * @example
607
+ * ```typescript
608
+ * await ecod.meet.delete("meeting_id");
609
+ * ```
610
+ */
611
+ delete(meetingId: string): Promise<any>;
612
+ }
613
+
614
+ /**
615
+ * Filters for querying event and automation execution logs.
616
+ */
617
+ interface LogFilter {
618
+ /** Page number for pagination (1-indexed). */
619
+ page?: number;
620
+ /** Maximum number of records to return per page. */
621
+ limit?: number;
622
+ /**
623
+ * Filter by automation trigger name.
624
+ * @example "lead_created" | "appointment_booked"
625
+ */
626
+ trigger?: string;
627
+ /**
628
+ * Filter by execution status.
629
+ * @example "success" | "failed" | "pending"
630
+ */
631
+ status?: string;
632
+ /** Filter logs associated with a specific phone number. */
633
+ phone?: string;
634
+ /** Start of the date range (inclusive). ISO 8601 or Date object. */
635
+ startDate?: string | Date;
636
+ /** End of the date range (inclusive). ISO 8601 or Date object. */
637
+ endDate?: string | Date;
638
+ }
639
+ /**
640
+ * Automation event log and provider callback resource.
641
+ *
642
+ * Access via `ecod.notifications`.
643
+ *
644
+ * This resource is **read-only**. It exposes platform audit trails — useful
645
+ * for debugging automation failures, monitoring webhook callbacks, and
646
+ * building internal ops dashboards.
647
+ *
648
+ * @example
649
+ * ```typescript
650
+ * // Find failed automations in April
651
+ * const { data } = await ecod.notifications.listLogs({
652
+ * status: "failed",
653
+ * startDate: "2026-04-01",
654
+ * endDate: "2026-04-30",
655
+ * });
656
+ * ```
657
+ */
658
+ declare class Notifications extends APIResource {
659
+ /**
660
+ * List automation execution logs with optional filtering.
661
+ *
662
+ * Each log entry represents one automation run triggered by a platform event.
663
+ * Filter by `status: "failed"` to build a failure alerting pipeline.
664
+ *
665
+ * @param params - Optional filter criteria.
666
+ * @returns Paginated list of event log objects.
667
+ *
668
+ * @example
669
+ * ```typescript
670
+ * const { data: failed } = await ecod.notifications.listLogs({
671
+ * status: "failed",
672
+ * trigger: "lead_created",
673
+ * limit: 50,
674
+ * });
675
+ * ```
676
+ */
677
+ listLogs(params?: LogFilter): Promise<unknown>;
678
+ /**
679
+ * Retrieve the full details for a single automation event log entry.
680
+ *
681
+ * @param logId - The unique log ID.
682
+ * @returns A single event log document including the payload and error trace.
683
+ *
684
+ * @example
685
+ * ```typescript
686
+ * const { data } = await ecod.notifications.retrieveLog("log_64abc...");
687
+ * console.log(data.error); // → "Provider timeout after 30s"
688
+ * ```
689
+ */
690
+ retrieveLog(logId: string): Promise<unknown>;
691
+ /**
692
+ * Get a summary statistics object for automation event execution.
693
+ *
694
+ * @param params - Optional date range for the summary window.
695
+ * @returns `{ total, success, failed, pending }` counts.
696
+ *
697
+ * @example
698
+ * ```typescript
699
+ * const { data: stats } = await ecod.notifications.getStats({
700
+ * startDate: "2026-04-01",
701
+ * endDate: "2026-04-30",
702
+ * });
703
+ * console.log(`Failed: ${stats.failed} / ${stats.total}`);
704
+ * ```
705
+ */
706
+ getStats(params?: {
707
+ startDate?: string;
708
+ endDate?: string;
709
+ }): Promise<unknown>;
710
+ /**
711
+ * List external provider webhook callback logs.
712
+ *
713
+ * These are inbound HTTP callbacks from third-party providers
714
+ * (payment gateways, email services, etc.) stored for audit purposes.
715
+ *
716
+ * @param params - Pagination and date filter options.
717
+ * @returns Paginated list of callback log records.
718
+ *
719
+ * @example
720
+ * ```typescript
721
+ * const { data } = await ecod.notifications.listCallbacks({ limit: 20 });
722
+ * ```
723
+ */
724
+ listCallbacks(params?: Omit<LogFilter, "trigger" | "phone">): Promise<unknown>;
725
+ }
726
+
727
+ /**
728
+ * Payload to send a high-throughput email campaign.
729
+ */
730
+ interface SendCampaignPayload {
731
+ /** Array of recipient email addresses. */
732
+ recipients: string[];
733
+ /** Subject line of the email. */
734
+ subject: string;
735
+ /** HTML body of the email. */
736
+ html: string;
737
+ }
738
+ /**
739
+ * Interface representing the result of a campaign dispatch.
740
+ */
741
+ interface CampaignResult {
742
+ success: boolean;
743
+ message?: string;
744
+ [key: string]: any;
745
+ }
746
+ declare class EmailResource extends APIResource {
747
+ /**
748
+ * Send an HTML email campaign to a list of recipients.
749
+ *
750
+ * @param payload - The campaign details (recipients, subject, html).
751
+ * @returns The dispatch result.
752
+ */
753
+ sendEmailCampaign(payload: SendCampaignPayload): Promise<CampaignResult>;
754
+ /**
755
+ * Send a system verification/test email to validate SMTP configuration.
756
+ *
757
+ * @param to - The recipient's email address.
758
+ * @returns The dispatch result.
759
+ */
760
+ sendTestEmail(to: string): Promise<CampaignResult>;
761
+ }
762
+
763
+ /**
764
+ * Event definition representing an entry point capable of triggering automations.
765
+ */
766
+ interface EventDefinition {
767
+ name: string;
768
+ displayName: string;
769
+ description?: string;
770
+ pipelineId?: string;
771
+ stageId?: string;
772
+ defaultSource?: string;
773
+ [key: string]: any;
774
+ }
775
+ /**
776
+ * Payload to register/assign a new custom event definition.
777
+ */
778
+ interface AssignEventPayload {
779
+ /** The internal machine-readable name of the event (e.g. "webinar_joined") */
780
+ name: string;
781
+ /** Human-readable display name */
782
+ displayName: string;
783
+ /** Event description */
784
+ description?: string;
785
+ /** ID of the pipeline to associate with matching leads */
786
+ pipelineId?: string;
787
+ /** ID of the stage within the pipeline */
788
+ stageId?: string;
789
+ /** Default source tag for leads created via this event */
790
+ defaultSource?: string;
791
+ }
792
+ /**
793
+ * Payload to programmatically trigger an event/workflow.
794
+ */
795
+ interface TriggerPayload {
796
+ /** The name of the event to fire (e.g., "webinar_joined") */
797
+ trigger: string;
798
+ /** Phone number of the lead (E.164 format) */
799
+ phone: string;
800
+ /** Email of the lead */
801
+ email?: string;
802
+ /** Key-value pairs for string templates */
803
+ variables?: Record<string, string>;
804
+ /** Deep payload data mapping to the event */
805
+ data?: any;
806
+ /** URL to receive an acknowledgment callback when processing completes */
807
+ callbackUrl?: string;
808
+ /** Secret metadata passed back to the callback URL */
809
+ callbackMetadata?: any;
810
+ /** Auto-create lead if phone does not exist in CRM */
811
+ createLeadIfMissing?: boolean;
812
+ /** Pre-fill data if creating a new lead */
813
+ leadData?: {
814
+ firstName?: string;
815
+ lastName?: string;
816
+ source?: string;
817
+ };
818
+ /** Delay execution of matched workflows (in seconds) */
819
+ delaySeconds?: number;
820
+ /** Delay execution of matched workflows (in minutes) */
821
+ delayMinutes?: number;
822
+ /** Explicit ISO timestamp to trigger the workflow run */
823
+ runAt?: string;
824
+ }
825
+ /**
826
+ * Response returned when triggering an event.
827
+ */
828
+ interface TriggerResponse {
829
+ success: boolean;
830
+ data?: {
831
+ eventLogId: string;
832
+ trigger: string;
833
+ leadId: string;
834
+ rulesMatched: number;
835
+ };
836
+ message?: string;
837
+ code?: string;
838
+ }
839
+ declare class EventsResource extends APIResource {
840
+ /**
841
+ * Retrieve all valid events (system + custom) that can be used as Automation Rule triggers.
842
+ */
843
+ list(): Promise<{
844
+ success: boolean;
845
+ data: EventDefinition[];
846
+ }>;
847
+ /**
848
+ * Register a new custom event entry point into the CRM automation engine.
849
+ * Useful when introducing new granular triggers.
850
+ */
851
+ assign(payload: AssignEventPayload): Promise<{
852
+ success: boolean;
853
+ data: EventDefinition;
854
+ }>;
855
+ /**
856
+ * Deactivate a custom event assignment by name.
857
+ */
858
+ unassign(name: string): Promise<{
859
+ success: boolean;
860
+ data: any;
861
+ }>;
862
+ /**
863
+ * Deactivate multiple custom event assignments simultaneously.
864
+ */
865
+ unassignBulk(names: string[]): Promise<{
866
+ success: boolean;
867
+ message: string;
868
+ }>;
869
+ /**
870
+ * Programmatically fire an event into the CRM automation engine.
871
+ * Emits to the internal EventBus to match with active Workflow Automation Rules.
872
+ */
873
+ trigger(payload: TriggerPayload): Promise<TriggerResponse>;
874
+ }
875
+
876
+ /**
877
+ * Typed error hierarchy for the @ecodrix/erix-api SDK.
878
+ *
879
+ * All errors thrown by the SDK extend `EcodrixError`, so a single
880
+ * `catch` block can handle them all, while still allowing granular
881
+ * differentiation between auth failures, rate limits, and generic API errors.
882
+ *
883
+ * @example
884
+ * ```typescript
885
+ * import { APIError, AuthenticationError, RateLimitError } from "@ecodrix/erix-api";
886
+ *
887
+ * try {
888
+ * await ecod.crm.leads.retrieve("invalid_id");
889
+ * } catch (err) {
890
+ * if (err instanceof AuthenticationError) {
891
+ * console.error("Invalid API key or client code.");
892
+ * } else if (err instanceof RateLimitError) {
893
+ * console.warn("Slow down — rate limit hit.");
894
+ * } else if (err instanceof APIError) {
895
+ * console.error(`API error ${err.status}: ${err.message}`);
896
+ * }
897
+ * }
898
+ * ```
899
+ */
900
+ /** Base class for all ECODrIx SDK errors. */
901
+ declare class EcodrixError extends Error {
902
+ constructor(message: string);
903
+ }
904
+ /**
905
+ * Represents an error returned by the ECODrIx API.
906
+ * Carries the HTTP `status` code and an optional `code` string.
907
+ */
908
+ declare class APIError extends EcodrixError {
909
+ /** HTTP status code returned by the API (e.g. 400, 404, 500). */
910
+ status?: number;
911
+ /** Machine-readable error code (e.g. `"NOT_FOUND"`, `"VALIDATION_ERROR"`). */
912
+ code?: string;
913
+ constructor(message: string, status?: number, code?: string);
914
+ }
915
+ /**
916
+ * Thrown when the API key or client code is missing, invalid, or expired.
917
+ * HTTP 401.
918
+ */
919
+ declare class AuthenticationError extends APIError {
920
+ constructor(message?: string);
921
+ }
922
+ /**
923
+ * Thrown when the rate limit for the API key has been exceeded.
924
+ * HTTP 429. Implement exponential backoff before retrying.
925
+ */
926
+ declare class RateLimitError extends APIError {
927
+ constructor(message?: string);
928
+ }
929
+
930
+ declare class WebhookSignatureError extends APIError {
931
+ constructor(message: string);
932
+ }
933
+ /**
934
+ * Validates and constructs webhook events sent by the ECODrIx platform.
935
+ * Ensures the payload has not been tampered with.
936
+ *
937
+ * @example
938
+ * ```typescript
939
+ * import { ecod } from "./services/ecodrix";
940
+ *
941
+ * app.post("/api/webhooks", async (req, res) => {
942
+ * try {
943
+ * const event = await ecod.webhooks.constructEvent(
944
+ * req.rawBody,
945
+ * req.headers["x-ecodrix-signature"],
946
+ * process.env.ECOD_WEBHOOK_SECRET
947
+ * );
948
+ * console.log("Verified event:", event.type);
949
+ * res.send({ received: true });
950
+ * } catch (err) {
951
+ * res.status(400).send(`Webhook Error: ${err.message}`);
952
+ * }
953
+ * });
954
+ * ```
955
+ */
956
+ declare class Webhooks {
957
+ /**
958
+ * Cryptographically validates a webhook payload.
959
+ * Note: This method dynamically imports Node's `crypto` module, meaning it will only execute gracefully in a Server environment.
960
+ *
961
+ * @param payload - The raw request body as a string or Buffer.
962
+ * @param signature - The `x-ecodrix-signature` header value.
963
+ * @param secret - The webhook signing secret for your tenant.
964
+ * @returns The parsed JSON object of the event if the signature is valid.
965
+ * @throws WebhookSignatureError if the validation fails.
966
+ */
967
+ constructEvent(payload: string | Buffer, signature: string | string[] | undefined, secret: string): Promise<any>;
968
+ }
969
+
970
+ /**
971
+ * Configuration options for the Ecodrix client.
972
+ */
973
+ interface EcodrixOptions {
974
+ /**
975
+ * Your ECODrIx Platform API key.
976
+ * Obtain this from the ECODrIx dashboard under Settings → API Keys.
977
+ * @example "ecod_live_sk_..."
978
+ */
979
+ apiKey: string;
980
+ /**
981
+ * Your tenant ID (Client Code).
982
+ * This scopes all API requests to your specific organisation.
983
+ * Required for most operations.
984
+ * @example "ERIX_CLNT_JHBJHF"
985
+ */
986
+ clientCode?: string;
987
+ /**
988
+ * Override the base URL of the ECODrIx API.
989
+ * Useful for pointing to a local development or staging server.
990
+ * @default "https://api.ecodrix.com"
991
+ */
992
+ baseUrl?: string;
993
+ /**
994
+ * Override the Socket.io server URL for real-time events.
995
+ * Defaults to the same value as `baseUrl`.
996
+ * @default "https://api.ecodrix.com"
997
+ */
998
+ socketUrl?: string;
999
+ }
1000
+ /**
1001
+ * The primary entry point for the ECODrIx SDK.
1002
+ *
1003
+ * Initialise once with your credentials and use the namespaced resources
1004
+ * to interact with every part of the platform.
1005
+ *
1006
+ * @example
1007
+ * ```typescript
1008
+ * import { Ecodrix } from "@ecodrix/erix-api";
1009
+ *
1010
+ * const ecod = new Ecodrix({
1011
+ * apiKey: process.env.ECOD_API_KEY!,
1012
+ * clientCode: "ERIX_CLNT_JHBJHF",
1013
+ * });
1014
+ *
1015
+ * await ecod.whatsapp.messages.send({ to: "+91...", text: "Hello!" });
1016
+ * const lead = await ecod.crm.leads.create({ firstName: "Alice", phone: "+91..." });
1017
+ * ```
1018
+ */
1019
+ declare class Ecodrix {
1020
+ private readonly client;
1021
+ private readonly socket;
1022
+ /** WhatsApp messaging and conversation management. */
1023
+ readonly whatsapp: WhatsApp;
1024
+ /** CRM resources — Leads and related sub-resources. */
1025
+ readonly crm: CRM;
1026
+ /** Cloudflare R2-backed media storage. */
1027
+ readonly media: MediaResource;
1028
+ /** Google Meet appointment scheduling. */
1029
+ readonly meet: Meetings;
1030
+ /** Automation execution logs and provider webhook callbacks. */
1031
+ readonly notifications: Notifications;
1032
+ /** Outbound email marketing engine. */
1033
+ readonly email: EmailResource;
1034
+ /** Lead events and workflow automation triggers. */
1035
+ readonly events: EventsResource;
1036
+ /** Cryptographic webhook signature verification. */
1037
+ readonly webhooks: Webhooks;
1038
+ constructor(options: EcodrixOptions);
1039
+ private setupSocket;
1040
+ /**
1041
+ * Subscribe to a real-time event emitted by the ECODrIx platform.
1042
+ *
1043
+ * The SDK maintains a persistent Socket.io connection. Events are
1044
+ * scoped to your `clientCode` — you will only receive events for
1045
+ * your own tenant.
1046
+ *
1047
+ * **Standard events:**
1048
+ * - `whatsapp.message_received` — inbound WhatsApp message
1049
+ * - `whatsapp.message_sent` — outbound message delivered
1050
+ * - `crm.lead_created` — new CRM lead ingested
1051
+ * - `crm.lead_updated` — lead details or stage changed
1052
+ * - `meet.scheduled` — Google Meet appointment booked
1053
+ * - `storage.upload_confirmed` — file upload completed
1054
+ * - `automation.failed` — automation execution error
1055
+ *
1056
+ * @param event - The event name to subscribe to.
1057
+ * @param callback - The handler function invoked when the event fires.
1058
+ * @returns `this` for method chaining.
1059
+ *
1060
+ * @example
1061
+ * ```typescript
1062
+ * ecod
1063
+ * .on("whatsapp.message_received", (msg) => console.log(msg.body))
1064
+ * .on("automation.failed", (err) => alertTeam(err));
1065
+ * ```
1066
+ */
1067
+ on(event: string, callback: (...args: any[]) => void): this;
1068
+ /**
1069
+ * Gracefully disconnect the real-time Socket.io connection.
1070
+ * Call this when shutting down your server or when the client is
1071
+ * no longer needed to free up resources.
1072
+ *
1073
+ * @example
1074
+ * ```typescript
1075
+ * process.on("SIGTERM", () => ecod.disconnect());
1076
+ * ```
1077
+ */
1078
+ disconnect(): void;
1079
+ /**
1080
+ * Raw Execution Escape-Hatch.
1081
+ * Send an authenticated HTTP request directly to the ECODrIx backend from ANY external project.
1082
+ *
1083
+ * This is extremely powerful giving you full unrestricted access to make calls
1084
+ * against new, experimental, or completely custom backend APIs while still benefitting
1085
+ * from the SDK's built-in authentication and automatic `axios-retry` logic.
1086
+ *
1087
+ * @example
1088
+ * ```typescript
1089
+ * const { data } = await ecod.request("POST", "/api/saas/experimental-feature", { flag: true });
1090
+ * console.log(data);
1091
+ * ```
1092
+ */
1093
+ request<T = any>(method: Method, path: string, data?: any, params?: any): Promise<T>;
1094
+ }
1095
+
1096
+ export { APIError, type AssignEventPayload, AuthenticationError, type CampaignResult, Conversations, type CreateLeadParams, type CreateMeetingParams, Ecodrix, EcodrixError, type EcodrixOptions, EmailResource, type EventDefinition, EventsResource, Leads, type ListParams, type LogFilter, MediaResource, Meetings, Messages, Notifications, RateLimitError, type SendCampaignPayload, type SendMessageParams, type SendTemplateParams, type SendTemplatePayload, type TriggerPayload, type TriggerResponse, type UpdateMeetingParams, type UploadOptions, WebhookSignatureError, Webhooks, WhatsApp, Ecodrix as default };