@ecodrix/erix-api 1.0.1 → 1.0.4

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (41) hide show
  1. package/dist/cli.js +38 -0
  2. package/dist/index.d.cts +1979 -0
  3. package/dist/index.d.ts +1173 -313
  4. package/dist/ts/browser/index.global.js +14 -14
  5. package/dist/ts/browser/index.global.js.map +1 -1
  6. package/dist/ts/cjs/index.cjs +1 -1
  7. package/dist/ts/cjs/index.cjs.map +1 -1
  8. package/dist/ts/cjs/index.d.cts +1173 -313
  9. package/dist/ts/esm/index.d.ts +1173 -313
  10. package/dist/ts/esm/index.js +1 -1
  11. package/dist/ts/esm/index.js.map +1 -1
  12. package/package.json +18 -13
  13. package/src/cli.ts +305 -0
  14. package/src/core.ts +28 -12
  15. package/src/index.ts +22 -8
  16. package/src/resource.ts +21 -1
  17. package/src/resources/crm/activities.ts +89 -0
  18. package/src/resources/crm/analytics.ts +89 -0
  19. package/src/resources/crm/automationDashboard.ts +24 -0
  20. package/src/resources/crm/automations.ts +151 -0
  21. package/src/resources/crm/index.ts +25 -1
  22. package/src/resources/crm/leads.ts +178 -45
  23. package/src/resources/crm/payments.ts +16 -0
  24. package/src/resources/crm/pipelines.ts +119 -0
  25. package/src/resources/crm/scoring.ts +33 -0
  26. package/src/resources/crm/sequences.ts +28 -0
  27. package/src/resources/email.ts +2 -5
  28. package/src/resources/events.ts +52 -2
  29. package/src/resources/health.ts +63 -0
  30. package/src/resources/marketing.ts +111 -0
  31. package/src/resources/media.ts +1 -4
  32. package/src/resources/meet.ts +12 -2
  33. package/src/resources/notifications.ts +30 -0
  34. package/src/resources/queue.ts +39 -0
  35. package/src/resources/storage.ts +72 -0
  36. package/src/resources/webhooks.ts +3 -8
  37. package/src/resources/whatsapp/broadcasts.ts +31 -0
  38. package/src/resources/whatsapp/conversations.ts +39 -9
  39. package/src/resources/whatsapp/index.ts +20 -2
  40. package/src/resources/whatsapp/messages.ts +24 -0
  41. package/src/resources/whatsapp/templates.ts +109 -0
package/src/cli.ts ADDED
@@ -0,0 +1,305 @@
1
+ import repl from "node:repl";
2
+ import { Command } from "commander";
3
+ import dotenv from "dotenv";
4
+ import pc from "picocolors";
5
+ import { Ecodrix } from "./core";
6
+
7
+ // Setup environment
8
+ dotenv.config();
9
+
10
+ // Build-time constants injected by tsup
11
+ declare const process: any;
12
+ const VERSION = process.env.SDK_VERSION || "1.0.2";
13
+ const NAME = process.env.SDK_NAME || "@ecodrix/erix-api";
14
+ const DESCRIPTION = process.env.SDK_DESCRIPTION || "Official ECODrIx SDK CLI";
15
+
16
+ const program = new Command();
17
+
18
+ program.name("erix").description(DESCRIPTION).version(VERSION);
19
+
20
+ /**
21
+ * Helper to initialize the Ecodrix client from environment or flags.
22
+ */
23
+ function getClient(options: any): Ecodrix {
24
+ const apiKey = options.key || process.env.ECOD_API_KEY;
25
+ const clientCode = options.client || process.env.ECOD_CLIENT_CODE;
26
+
27
+ if (!apiKey) {
28
+ console.error(pc.red("Error: API Key is missing."));
29
+ console.log(pc.yellow("Set ECOD_API_KEY environment variable or use --key <key>"));
30
+ process.exit(1);
31
+ }
32
+
33
+ return new Ecodrix({
34
+ apiKey,
35
+ clientCode,
36
+ baseUrl: options.baseUrl || process.env.ECOD_BASE_URL,
37
+ });
38
+ }
39
+
40
+ program
41
+ .option("-k, --key <key>", "ECODrIx API Key")
42
+ .option("-c, --client <code...", "Tenant Client Code")
43
+ .option("--base-url <url>", "API Base URL override");
44
+
45
+ // --- WHOAMI ---
46
+ program
47
+ .command("whoami")
48
+ .description("Verify current authentication and tenant status")
49
+ .action(async (options, command) => {
50
+ const globalOptions = command.parent.opts();
51
+ const ecod = getClient(globalOptions);
52
+
53
+ console.log(pc.cyan("Checking connection to ECODrIx Platform..."));
54
+ try {
55
+ const me = (await ecod.request("GET", "/api/saas/me/profile")) as any;
56
+ console.log(pc.green("✔ Authenticated successfully!"));
57
+ console.log(`${pc.bold("User ID:")} ${me.id}`);
58
+ console.log(`${pc.bold("Organisation:")} ${me.organisation?.name || "N/A"}`);
59
+ if (globalOptions.client) {
60
+ console.log(`${pc.bold("Tenant Code:")} ${pc.magenta(globalOptions.client)}`);
61
+ }
62
+ } catch (error: any) {
63
+ console.error(pc.red("✖ Authentication failed"));
64
+ console.error(pc.dim(error.message));
65
+ process.exit(1);
66
+ }
67
+ });
68
+
69
+ // --- WHATSAPP ---
70
+ const whatsapp = program.command("whatsapp").description("WhatsApp Business API operations");
71
+
72
+ whatsapp
73
+ .command("send-template")
74
+ .description("Send a WhatsApp template message")
75
+ .argument("<phone>", "Recipient phone number")
76
+ .argument("<template>", "Template name")
77
+ .option("-v, --vars <json>", "Template variables as JSON string", "[]")
78
+ .action(async (phone, template, options, command) => {
79
+ const globalOptions = command.parent.parent.opts();
80
+ const ecod = getClient(globalOptions);
81
+
82
+ try {
83
+ const vars = JSON.parse(options.vars);
84
+ console.log(pc.cyan(`Sending template '${template}' to ${phone}...`));
85
+
86
+ const result = (await ecod.whatsapp.messages.sendTemplate({
87
+ to: phone,
88
+ templateName: template,
89
+ language: "en_US",
90
+ variables: vars,
91
+ })) as any;
92
+
93
+ console.log(pc.green("✔ Message sent successfully!"));
94
+ console.log(pc.dim(`ID: ${result?.id || "N/A"}`));
95
+ } catch (error: any) {
96
+ console.error(pc.red("✖ Failed to send message"));
97
+ console.error(pc.dim(error.message));
98
+ }
99
+ });
100
+
101
+ // --- CRM ---
102
+ const crm = program.command("crm").description("CRM and Lead management");
103
+
104
+ crm
105
+ .command("leads")
106
+ .description("List recent leads")
107
+ .option("-l, --limit <number>", "Number of leads to fetch", "10")
108
+ .option("-s, --status <status>", "Filter by lead status")
109
+ .option("-p, --pipeline <id>", "Filter by pipeline ID")
110
+ .option("-q, --search <query>", "Search by name or email")
111
+ .action(async (options, command) => {
112
+ const globalOptions = command.parent.parent.opts();
113
+ const ecod = getClient(globalOptions);
114
+
115
+ try {
116
+ const limit = Number.parseInt(options.limit);
117
+ console.log(pc.cyan(`Fetching last ${limit} leads...`));
118
+
119
+ const queryParams: any = { limit };
120
+ if (options.status) queryParams.status = options.status;
121
+ if (options.pipeline) queryParams.pipelineId = options.pipeline;
122
+ if (options.search) queryParams.search = options.search;
123
+
124
+ const response: any = await ecod.crm.leads.list(queryParams);
125
+ const leads = Array.isArray(response.data)
126
+ ? response.data
127
+ : Array.isArray(response)
128
+ ? response
129
+ : [];
130
+
131
+ if (leads.length === 0) {
132
+ console.log(pc.yellow("No leads found."));
133
+ return;
134
+ }
135
+
136
+ console.table(
137
+ leads.map((l: any) => ({
138
+ ID: l.id || l._id,
139
+ Name: `${l.firstName} ${l.lastName || ""}`.trim(),
140
+ Phone: l.phone,
141
+ Status: l.status,
142
+ Score: l.score || 0,
143
+ Created: new Date(l.createdAt).toLocaleDateString(),
144
+ })),
145
+ );
146
+ } catch (error: any) {
147
+ console.error(pc.red("✖ Failed to fetch leads"));
148
+ console.error(pc.dim(error.message));
149
+ }
150
+ });
151
+
152
+ crm
153
+ .command("pipelines")
154
+ .description("List all CRM pipelines")
155
+ .action(async (options, command) => {
156
+ const globalOptions = command.parent.parent.opts();
157
+ const ecod = getClient(globalOptions);
158
+
159
+ try {
160
+ console.log(pc.cyan("Fetching pipelines..."));
161
+ const response: any = await ecod.crm.pipelines.list();
162
+ const pipelines = response.data || response || [];
163
+
164
+ if (pipelines.length === 0) {
165
+ console.log(pc.yellow("No pipelines found."));
166
+ return;
167
+ }
168
+
169
+ console.table(
170
+ pipelines.map((p: any) => ({
171
+ ID: p.id || p._id,
172
+ Name: p.name,
173
+ Default: p.isDefault ? "Yes" : "No",
174
+ Stages: p.stages?.length || 0,
175
+ })),
176
+ );
177
+ } catch (error: any) {
178
+ console.error(pc.red("✖ Failed to fetch pipelines"));
179
+ console.error(pc.dim(error.message));
180
+ }
181
+ });
182
+
183
+ // --- ANALYTICS ---
184
+ const analytics = program.command("analytics").description("Business Intelligence Analytics");
185
+
186
+ analytics
187
+ .command("overview")
188
+ .description("Get high-level CRM KPIs")
189
+ .option("-r, --range <range>", "Date range (e.g., 24h, 7d, 30d, 365d)", "30d")
190
+ .action(async (options, command) => {
191
+ const globalOptions = command.parent.parent.opts();
192
+ const ecod = getClient(globalOptions);
193
+
194
+ try {
195
+ console.log(pc.cyan(`Fetching overview metrics for last ${options.range}...`));
196
+ const response: any = await ecod.crm.analytics.overview({ range: options.range });
197
+ const data = response.data || response;
198
+
199
+ console.log(`\n${pc.bold("OVERVIEW KPIs:")}`);
200
+ console.log(`Total Leads: ${pc.green(data.totalLeads || 0)}`);
201
+ console.log(`Open Value: ${pc.yellow(`$${(data.openValue || 0).toLocaleString()}`)}`);
202
+ console.log(`Won Revenue: ${pc.green(`$${(data.wonRevenue || 0).toLocaleString()}`)}`);
203
+ console.log(`Avg Score: ${pc.blue(data.avgScore?.toFixed(1) || 0)}`);
204
+ console.log(`Conversion: ${pc.magenta(`${(data.conversionRate || 0).toFixed(2)}%`)}\n`);
205
+ } catch (error: any) {
206
+ console.error(pc.red("✖ Failed to fetch analytics overview"));
207
+ console.error(pc.dim(error.message));
208
+ }
209
+ });
210
+
211
+ // --- WEBHOOKS ---
212
+ const webhooks = program.command("webhooks").description("Webhook utility tools");
213
+
214
+ webhooks
215
+ .command("verify")
216
+ .description("Verify a cryptographic webhook signature")
217
+ .argument("<payload>", "The raw request body string")
218
+ .argument("<signature>", "The 'x-ecodrix-signature' header value")
219
+ .argument("<secret>", "Your webhook signing secret")
220
+ .action(async (payload, signature, secret, options, command) => {
221
+ const globalOptions = command.parent.parent.opts();
222
+ const ecod = getClient(globalOptions);
223
+
224
+ try {
225
+ await ecod.webhooks.constructEvent(payload, signature, secret);
226
+ console.log(pc.green("✔ Signature is VALID"));
227
+ } catch (error: any) {
228
+ console.error(pc.red("✖ Error during verification"));
229
+ console.error(pc.dim(error.message));
230
+ }
231
+ });
232
+
233
+ // --- SHELL (REPL) ---
234
+ program
235
+ .command("shell")
236
+ .alias("repl")
237
+ .description("Start an interactive SDK shell")
238
+ .action(async (options, command) => {
239
+ const globalOptions = command.parent.opts();
240
+ const ecod = getClient(globalOptions);
241
+
242
+ console.log(pc.magenta(pc.bold("\nWelcome to the Erix Interactive Shell")));
243
+ console.log(pc.dim(`SDK Version: ${VERSION}`));
244
+ console.log(pc.dim("The 'ecod' client is pre-initialized and ready.\n"));
245
+
246
+ const r = repl.start({
247
+ prompt: pc.cyan("erix > "),
248
+ useColors: true,
249
+ });
250
+
251
+ // Load resources into REPL context for immediate access
252
+ r.context.ecod = ecod;
253
+ r.context.whatsapp = ecod.whatsapp;
254
+ r.context.crm = ecod.crm;
255
+ r.context.meet = ecod.meet;
256
+ r.context.media = ecod.media;
257
+
258
+ r.on("exit", () => {
259
+ console.log(pc.yellow("\nGoodbye!"));
260
+ process.exit(0);
261
+ });
262
+ });
263
+
264
+ // --- COMPLETION ---
265
+ program
266
+ .command("completion")
267
+ .description("Generate Bash auto-completion script")
268
+ .action(() => {
269
+ const script = `
270
+ # Erix Bash Completion
271
+ _erix_completions() {
272
+ local cur opts
273
+ COMPREPLY=()
274
+ cur="\${COMP_WORDS[COMP_CWORD]}"
275
+ opts="whoami whatsapp crm analytics webhooks shell completion"
276
+
277
+ if [[ \${COMP_CWORD} -eq 1 ]] ; then
278
+ COMPREPLY=( $(compgen -W "\${opts}" -- \${cur}) )
279
+ return 0
280
+ fi
281
+
282
+ # Simple sub-command completion
283
+ case "\${COMP_WORDS[1]}" in
284
+ whatsapp)
285
+ COMPREPLY=( $(compgen -W "send-template" -- \${cur}) )
286
+ ;;
287
+ crm)
288
+ COMPREPLY=( $(compgen -W "leads pipelines" -- \${cur}) )
289
+ ;;
290
+ analytics)
291
+ COMPREPLY=( $(compgen -W "overview" -- \${cur}) )
292
+ ;;
293
+ webhooks)
294
+ COMPREPLY=( $(compgen -W "verify" -- \${cur}) )
295
+ ;;
296
+ esac
297
+ }
298
+ complete -F _erix_completions erix
299
+ `;
300
+ console.log(script.trim());
301
+ console.error(pc.yellow('\n# To enable, run: eval "$(erix completion)"'));
302
+ console.error(pc.dim("# Or add it to your ~/.bashrc: erix completion >> ~/.bashrc"));
303
+ });
304
+
305
+ program.parse();
package/src/core.ts CHANGED
@@ -1,15 +1,19 @@
1
1
  import axios, { type AxiosInstance, type Method } from "axios";
2
2
  import axiosRetry from "axios-retry";
3
- import { AuthenticationError, APIError } from "./error";
4
- import { WhatsApp } from "./resources/whatsapp";
3
+ import { type Socket, io } from "socket.io-client";
4
+ import { APIError, AuthenticationError } from "./error";
5
5
  import { CRM } from "./resources/crm";
6
+ import { EmailResource } from "./resources/email";
7
+ import { EventsResource } from "./resources/events";
8
+ import { Health } from "./resources/health";
9
+ import { Marketing } from "./resources/marketing";
6
10
  import { MediaResource } from "./resources/media";
7
11
  import { Meetings } from "./resources/meet";
8
12
  import { Notifications } from "./resources/notifications";
9
- import { EmailResource } from "./resources/email";
10
- import { EventsResource } from "./resources/events";
13
+ import { Queue } from "./resources/queue";
14
+ import { Storage } from "./resources/storage";
11
15
  import { Webhooks } from "./resources/webhooks";
12
- import { io, type Socket } from "socket.io-client";
16
+ import { WhatsApp } from "./resources/whatsapp";
13
17
 
14
18
  declare const process: any;
15
19
 
@@ -94,6 +98,18 @@ export class Ecodrix {
94
98
  /** Cryptographic webhook signature verification. */
95
99
  public readonly webhooks: Webhooks;
96
100
 
101
+ /** Tenant Cloud Storage mapping. */
102
+ public readonly storage: Storage;
103
+
104
+ /** Email and SMS Marketing Campaigns. */
105
+ public readonly marketing: Marketing;
106
+
107
+ /** Platform and tenant health diagnostics. */
108
+ public readonly health: Health;
109
+
110
+ /** Background job queue management. */
111
+ public readonly queue: Queue;
112
+
97
113
  constructor(options: EcodrixOptions) {
98
114
  if (!options.apiKey) {
99
115
  throw new AuthenticationError("API Key is required");
@@ -102,8 +118,7 @@ export class Ecodrix {
102
118
  const baseUrl = options.baseUrl || "https://api.ecodrix.com";
103
119
  const socketUrl = options.socketUrl || baseUrl;
104
120
 
105
- const isBrowser =
106
- typeof window !== "undefined" && typeof window.document !== "undefined";
121
+ const isBrowser = typeof window !== "undefined" && typeof window.document !== "undefined";
107
122
  const runtime = isBrowser
108
123
  ? "browser"
109
124
  : typeof process !== "undefined"
@@ -136,8 +151,7 @@ export class Ecodrix {
136
151
  retryDelay: axiosRetry.exponentialDelay,
137
152
  retryCondition: (error) => {
138
153
  return (
139
- axiosRetry.isNetworkOrIdempotentRequestError(error) ||
140
- error.response?.status === 429
154
+ axiosRetry.isNetworkOrIdempotentRequestError(error) || error.response?.status === 429
141
155
  );
142
156
  },
143
157
  });
@@ -151,6 +165,10 @@ export class Ecodrix {
151
165
  this.email = new EmailResource(this.client);
152
166
  this.events = new EventsResource(this.client);
153
167
  this.webhooks = new Webhooks();
168
+ this.storage = new Storage(this.client);
169
+ this.marketing = new Marketing(this.client);
170
+ this.health = new Health(this.client);
171
+ this.queue = new Queue(this.client);
154
172
 
155
173
  // Establish persistent Socket.io connection
156
174
  this.socket = io(socketUrl, {
@@ -249,9 +267,7 @@ export class Ecodrix {
249
267
  } catch (error: any) {
250
268
  if (error.response) {
251
269
  throw new APIError(
252
- error.response.data?.message ||
253
- error.response.data?.error ||
254
- "Raw Execution Failed",
270
+ error.response.data?.message || error.response.data?.error || "Raw Execution Failed",
255
271
  error.response.status,
256
272
  error.response.data?.code,
257
273
  );
package/src/index.ts CHANGED
@@ -1,17 +1,31 @@
1
1
  export { Ecodrix, type EcodrixOptions } from "./core";
2
2
  export * from "./error";
3
-
4
- // Resource Type Exports
5
- export * from "./resources/whatsapp/messages";
6
- export * from "./resources/whatsapp/conversations";
7
- export * from "./resources/whatsapp/index";
3
+ export * from "./resources/crm/activities";
4
+ export * from "./resources/crm/analytics";
5
+ export * from "./resources/crm/automationDashboard";
6
+ export * from "./resources/crm/automations";
7
+ export * from "./resources/crm/index";
8
8
  export * from "./resources/crm/leads";
9
- export * from "./resources/meet";
10
- export * from "./resources/media";
11
- export * from "./resources/notifications";
9
+ export * from "./resources/crm/payments";
10
+ export * from "./resources/crm/pipelines";
11
+ export * from "./resources/crm/scoring";
12
+ export * from "./resources/crm/sequences";
12
13
  export * from "./resources/email";
13
14
  export * from "./resources/events";
15
+ export * from "./resources/health";
16
+ export * from "./resources/marketing";
17
+ export * from "./resources/media";
18
+ export * from "./resources/meet";
19
+ export * from "./resources/notifications";
20
+ export * from "./resources/queue";
21
+ export * from "./resources/storage";
14
22
  export * from "./resources/webhooks";
23
+ export * from "./resources/whatsapp/broadcasts";
24
+ export * from "./resources/whatsapp/conversations";
25
+ // Resource Type Exports
26
+ export * from "./resources/whatsapp/index";
27
+ export * from "./resources/whatsapp/messages";
28
+ export * from "./resources/whatsapp/templates";
15
29
 
16
30
  // Export the main client also as default for better ergonomics
17
31
  import { Ecodrix } from "./core";
package/src/resource.ts CHANGED
@@ -37,6 +37,26 @@ export abstract class APIResource {
37
37
  }
38
38
  }
39
39
 
40
+ protected async patch<T>(url: string, data?: any, options?: RequestOptions): Promise<T> {
41
+ try {
42
+ const config = this.buildConfig(options);
43
+ const response = await this.client.patch(url, data, config);
44
+ return response.data;
45
+ } catch (error: any) {
46
+ this.handleError(error);
47
+ }
48
+ }
49
+
50
+ protected async put<T>(url: string, data?: any, options?: RequestOptions): Promise<T> {
51
+ try {
52
+ const config = this.buildConfig(options);
53
+ const response = await this.client.put(url, data, config);
54
+ return response.data;
55
+ } catch (error: any) {
56
+ this.handleError(error);
57
+ }
58
+ }
59
+
40
60
  protected async deleteRequest<T>(url: string, options?: RequestOptions): Promise<T> {
41
61
  try {
42
62
  const config = this.buildConfig(options);
@@ -65,7 +85,7 @@ export abstract class APIResource {
65
85
  throw new APIError(
66
86
  error.response.data?.message || error.response.data?.error || "API Request Failed",
67
87
  error.response.status,
68
- error.response.data?.code
88
+ error.response.data?.code,
69
89
  );
70
90
  }
71
91
  throw new APIError(error.message || "Network Error");
@@ -0,0 +1,89 @@
1
+ import { APIResource } from "../../resource";
2
+
3
+ export interface LogActivityParams {
4
+ leadId: string;
5
+ type: "note" | "call" | "email" | "meeting" | "whatsapp" | "system";
6
+ title: string;
7
+ body?: string;
8
+ metadata?: Record<string, any>;
9
+ }
10
+
11
+ export interface LogCallParams {
12
+ durationMinutes: number;
13
+ summary: string;
14
+ outcome: "answered" | "no_answer" | "busy" | "voicemail" | "wrong_number";
15
+ }
16
+
17
+ export class Notes extends APIResource {
18
+ /**
19
+ * List all notes for a specific lead.
20
+ */
21
+ async list<T = any>(leadId: string) {
22
+ return this.get<T>(`/api/saas/crm/leads/${leadId}/notes`);
23
+ }
24
+
25
+ /**
26
+ * Add a note to a lead.
27
+ */
28
+ async create<T = any>(leadId: string, params: { content: string }) {
29
+ return this.post<T>(`/api/saas/crm/leads/${leadId}/notes`, params);
30
+ }
31
+
32
+ /**
33
+ * Update an existing note.
34
+ */
35
+ async update<T = any>(noteId: string, content: string) {
36
+ return this.patch<T>(`/api/saas/crm/notes/${noteId}`, { content });
37
+ }
38
+
39
+ /**
40
+ * Pin or unpin a note to the top of the feed.
41
+ */
42
+ async pin<T = any>(noteId: string, isPinned = true) {
43
+ return this.patch<T>(`/api/saas/crm/notes/${noteId}/pin`, { isPinned });
44
+ }
45
+
46
+ /**
47
+ * Delete a note.
48
+ */
49
+ async delete(noteId: string) {
50
+ return this.deleteRequest(`/api/saas/crm/notes/${noteId}`);
51
+ }
52
+ }
53
+
54
+ export class Activities extends APIResource {
55
+ public notes: Notes;
56
+
57
+ constructor(client: any) {
58
+ super(client);
59
+ this.notes = new Notes(client);
60
+ }
61
+
62
+ /**
63
+ * Retrieve the complete chronological timeline for a lead.
64
+ */
65
+ async timeline<T = any>(leadId: string, params?: { page?: number; limit?: number }) {
66
+ return this.get<T>(`/api/saas/crm/leads/${leadId}/timeline`, { params } as any);
67
+ }
68
+
69
+ /**
70
+ * List specific activities (filtered by type).
71
+ */
72
+ async list<T = any>(leadId: string, params?: { type?: string; page?: number; limit?: number }) {
73
+ return this.get<T>("/api/saas/crm/activities", { params: { leadId, ...params } } as any);
74
+ }
75
+
76
+ /**
77
+ * Generic method to log a business activity/event.
78
+ */
79
+ async log<T = any>(params: LogActivityParams) {
80
+ return this.post<T>("/api/saas/crm/activities", params);
81
+ }
82
+
83
+ /**
84
+ * Specific method to log communication outcomes.
85
+ */
86
+ async logCall<T = any>(leadId: string, params: LogCallParams) {
87
+ return this.post<T>(`/api/saas/crm/leads/${leadId}/calls`, params);
88
+ }
89
+ }
@@ -0,0 +1,89 @@
1
+ import { APIResource } from "../../resource";
2
+
3
+ export type AnalyticsRange = "24h" | "7d" | "30d" | "60d" | "90d" | "365d";
4
+
5
+ export interface AnalyticsParams {
6
+ range?: AnalyticsRange;
7
+ from?: string;
8
+ to?: string;
9
+ pipelineId?: string;
10
+ }
11
+
12
+ export class Analytics extends APIResource {
13
+ /**
14
+ * KPIs: total leads, pipeline value, won revenue, avg score, conversion rate.
15
+ */
16
+ async overview<T = any>(params?: AnalyticsParams) {
17
+ return this.get<T>("/api/saas/crm/analytics/overview", { params } as any);
18
+ }
19
+
20
+ /**
21
+ * Stage-by-stage lead counts and conversion percentages.
22
+ */
23
+ async funnel<T = any>(pipelineId: string) {
24
+ return this.get<T>("/api/saas/crm/analytics/funnel", { params: { pipelineId } } as any);
25
+ }
26
+
27
+ /**
28
+ * Revenue forecast: deal value × stage probability.
29
+ */
30
+ async forecast<T = any>(pipelineId?: string) {
31
+ return this.get<T>("/api/saas/crm/analytics/forecast", { params: { pipelineId } } as any);
32
+ }
33
+
34
+ /**
35
+ * Lead source breakdown: count, conversion rate, total value per source.
36
+ */
37
+ async sources<T = any>(params?: AnalyticsParams) {
38
+ return this.get<T>("/api/saas/crm/analytics/sources", { params } as any);
39
+ }
40
+
41
+ /**
42
+ * Team leaderboard: won deals, revenue, activity count, conversion rate per member.
43
+ */
44
+ async team<T = any>(params?: AnalyticsParams) {
45
+ return this.get<T>("/api/saas/crm/analytics/team", { params } as any);
46
+ }
47
+
48
+ /**
49
+ * Daily activity counts by type. For activity calendar.
50
+ */
51
+ async heatmap<T = any>(params?: AnalyticsParams) {
52
+ return this.get<T>("/api/saas/crm/analytics/heatmap", { params } as any);
53
+ }
54
+
55
+ /**
56
+ * Score distribution: how many leads in each score bucket.
57
+ */
58
+ async scores<T = any>() {
59
+ return this.get<T>("/api/saas/crm/analytics/scores");
60
+ }
61
+
62
+ /**
63
+ * Avg time leads spend in each stage. Helps find bottlenecks.
64
+ */
65
+ async stageTime<T = any>(pipelineId: string) {
66
+ return this.get<T>("/api/saas/crm/analytics/stage-time", { params: { pipelineId } } as any);
67
+ }
68
+
69
+ /**
70
+ * Tiered Growth Report matching business sophistication.
71
+ */
72
+ async tiered<T = any>(params?: AnalyticsParams) {
73
+ return this.get<T>("/api/saas/crm/analytics/tiered", { params } as any);
74
+ }
75
+
76
+ /**
77
+ * Consolidated analytics including CRM overview and WhatsApp.
78
+ */
79
+ async summary<T = any>(params?: AnalyticsParams) {
80
+ return this.get<T>("/api/saas/crm/analytics/summary", { params } as any);
81
+ }
82
+
83
+ /**
84
+ * WhatsApp volume and delivery analytics.
85
+ */
86
+ async whatsapp<T = any>(params?: AnalyticsParams) {
87
+ return this.get<T>("/api/saas/crm/analytics/whatsapp", { params } as any);
88
+ }
89
+ }
@@ -0,0 +1,24 @@
1
+ import { APIResource } from "../../resource";
2
+
3
+ export class AutomationDashboard extends APIResource {
4
+ /**
5
+ * Retrieve summary statistics for automation health.
6
+ */
7
+ async stats<T = any>() {
8
+ return this.get<T>("/api/saas/crm/automation/stats");
9
+ }
10
+
11
+ /**
12
+ * List recent EventLog entries (automation logs).
13
+ */
14
+ async logs<T = any>(params?: { limit?: number; status?: string }) {
15
+ return this.get<T>("/api/saas/crm/automation/logs", { params } as any);
16
+ }
17
+
18
+ /**
19
+ * Re-emit a failed event log to process its automations again.
20
+ */
21
+ async retryFailedEvent<T = any>(logId: string) {
22
+ return this.post<T>(`/api/saas/crm/automation/logs/${logId}/retry`, {});
23
+ }
24
+ }