@ecodrix/erix-api 1.3.1 → 1.3.2

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
@@ -1 +1 @@
1
- {"version":3,"sources":["../../../src/core.ts","../../../src/error.ts","../../../src/resource.ts","../../../src/resources/crm/activities.ts","../../../src/resources/crm/analytics.ts","../../../src/resources/crm/automationDashboard.ts","../../../src/resources/crm/automations.ts","../../../src/resources/crm/leads.ts","../../../src/resources/crm/payments.ts","../../../src/resources/crm/pipelines.ts","../../../src/resources/crm/scoring.ts","../../../src/resources/crm/sequences.ts","../../../src/resources/crm/index.ts","../../../src/resources/email.ts","../../../src/resources/events.ts","../../../src/resources/health.ts","../../../src/resources/logs.ts","../../../src/resources/marketing.ts","../../../src/resources/media.ts","../../../src/resources/meet.ts","../../../src/resources/notifications.ts","../../../src/resources/queue.ts","../../../src/resources/storage.ts","../../../src/resources/webhooks.ts","../../../src/resources/whatsapp/broadcasts.ts","../../../src/resources/whatsapp/conversations.ts","../../../src/resources/whatsapp/messages.ts","../../../src/resources/whatsapp/templates.ts","../../../src/resources/whatsapp/index.ts","../../../src/resources/agency.ts","../../../src/resources/services.ts","../../../src/resources/settings.ts","../../../src/resources/cors.ts","../../../src/index.ts"],"sourcesContent":["import axios, { type AxiosInstance, type Method } from \"axios\";\nimport axiosRetry from \"axios-retry\";\nimport { type Socket, io } from \"socket.io-client\";\nimport { APIError, AuthenticationError } from \"./error\";\nimport { CRM } from \"./resources/crm\";\nimport { Email } from \"./resources/email\";\nimport { EventsResource } from \"./resources/events\";\nimport { Health } from \"./resources/health\";\nimport { Logs } from \"./resources/logs\";\nimport { Marketing } from \"./resources/marketing\";\nimport { Media } from \"./resources/media\";\nimport { Meetings } from \"./resources/meet\";\nimport { Notifications } from \"./resources/notifications\";\nimport { Queue } from \"./resources/queue\";\nimport { Storage } from \"./resources/storage\";\nimport { Webhooks } from \"./resources/webhooks\";\nimport { WhatsApp } from \"./resources/whatsapp\";\nimport { Agency } from \"./resources/agency\";\nimport { Services } from \"./resources/services\";\nimport { Settings } from \"./resources/settings\";\nimport { Cors } from \"./resources/cors\";\n\ndeclare const process: any;\n\n/** @internal The canonical ECODrIx backend URL — not exposed to SDK consumers. */\nconst ECOD_API_BASE = \"https://api.ecodrix.com\";\n\n/**\n * Configuration options for the Ecodrix client.\n *\n * Minimum required: `apiKey` and `clientCode`.\n * The backend URL is managed internally and should not need to be changed.\n */\nexport interface EcodrixOptions {\n /**\n * Your ECODrIx Platform API key.\n * Obtain this from the ECODrIx dashboard under Settings → API Keys.\n * @example \"ecod_live_sk_...\"\n */\n apiKey: string;\n\n /**\n * Your tenant ID (Client Code).\n * This scopes all API requests to your specific organisation.\n * @example \"ERIX_CLNT_JHBJHF\"\n */\n clientCode?: string;\n\n /**\n * Optional Core API Key for deep system-level bypasses.\n * Only used by elevated internal SaaS modules like Nirvisham.\n */\n coreApiKey?: string;\n\n /**\n * @internal Override Socket.io URL for testing/staging.\n * Not documented — internal use only.\n */\n socketUrl?: string;\n\n /**\n * @internal Override the backend API URL. Used by the CLI and internal tests only.\n * Host projects must never set this — the production URL is hardcoded internally.\n */\n baseUrl?: string;\n}\n\n/**\n * The primary entry point for the ECODrIx SDK.\n *\n * Initialise once with your credentials and use the namespaced resources\n * to interact with every part of the platform.\n *\n * @example\n * ```typescript\n * import { Ecodrix } from \"@ecodrix/erix-api\";\n *\n * const ecod = new Ecodrix({\n * apiKey: process.env.ECOD_API_KEY!,\n * clientCode: \"ERIX_CLNT_JHBJHF\",\n * });\n *\n * await ecod.whatsapp.messages.send({ to: \"+91...\", text: \"Hello!\" });\n * const lead = await ecod.crm.leads.create({ firstName: \"Alice\", phone: \"+91...\" });\n * ```\n */\nexport class Ecodrix {\n /**\n * @internal Axios HTTP client for making API requests.\n */\n private readonly client: AxiosInstance;\n /**\n * @internal Socket.io client for real-time events.\n */\n private readonly socket: Socket;\n\n /**\n * The tenant client code this SDK instance is scoped to.\n * Useful for components that need to read the clientCode back\n * from a context-provided SDK instance.\n */\n public readonly clientCode: string | undefined;\n\n /** WhatsApp messaging and conversation management. */\n public readonly whatsapp: WhatsApp;\n\n /** CRM resources — Leads and related sub-resources. */\n public readonly crm: CRM;\n\n /** Cloudflare R2-backed media storage. */\n public readonly media: Media;\n\n /** Google Meet appointment scheduling. */\n public readonly meet: Meetings;\n\n /** Automation execution logs and provider webhook callbacks. */\n public readonly notifications: Notifications;\n\n /** Outbound email marketing engine and template management. */\n public readonly email: Email;\n\n /** Platform-wide execution logs and audit trails. */\n public readonly logs: Logs;\n\n /** Lead events and workflow automation triggers. */\n public readonly events: EventsResource;\n\n /** Cryptographic webhook signature verification. */\n public readonly webhooks: Webhooks;\n\n /** Tenant Cloud Storage mapping. */\n public readonly storage: Storage;\n\n /** Email and SMS Marketing Campaigns. */\n public readonly marketing: Marketing;\n\n /** Platform and tenant health diagnostics. */\n public readonly health: Health;\n\n /** Background job queue management. */\n public readonly queue: Queue;\n\n /** White-Label Agency administration. */\n public readonly agency: Agency;\n\n /** Multi-tenant Identity & Lifecycle services. */\n public readonly services: Services;\n\n /** Tenant environment and provider settings. */\n public readonly settings: Settings;\n\n /** Dynamic Cross-Origin Resource Sharing network policies. */\n public readonly cors: Cors;\n\n constructor(options: EcodrixOptions) {\n if (!options.apiKey) {\n throw new AuthenticationError(\"API Key is required\");\n }\n\n this.clientCode = options.clientCode?.toUpperCase();\n\n // @internal: options.baseUrl is available for CLI/test use only.\n // Host projects hardcode to prod — they never set baseUrl.\n const baseUrl = options.baseUrl ?? ECOD_API_BASE;\n const socketUrl = options.socketUrl || baseUrl;\n\n const isBrowser =\n typeof window !== \"undefined\" && typeof window.document !== \"undefined\";\n const runtime = isBrowser\n ? \"browser\"\n : typeof process !== \"undefined\"\n ? `node ${process.version}`\n : \"unknown\";\n const os = isBrowser\n ? globalThis.navigator?.userAgent || \"browser\"\n : typeof process !== \"undefined\"\n ? process.platform\n : \"unknown\";\n\n const headers: Record<string, string> = {\n \"x-api-key\": options.apiKey,\n \"x-client-code\": options.clientCode?.toUpperCase() || \"\",\n \"Content-Type\": \"application/json\",\n \"x-ecodrix-client-agent\": JSON.stringify({\n sdk_version: \"1.0.0\", // Can be auto-injected during build in future\n runtime,\n os,\n }),\n };\n\n if (options.coreApiKey) {\n headers[\"x-core-api-key\"] = options.coreApiKey;\n }\n\n this.client = axios.create({\n baseURL: baseUrl,\n headers,\n });\n\n // Make the client completely bulletproof for execution from external projects.\n // It will automatically handle network blips, 502 Bad Gateways, and 429 Rate Limits.\n axiosRetry(this.client, {\n retries: 3,\n retryDelay: axiosRetry.exponentialDelay,\n retryCondition: (error) => {\n return (\n axiosRetry.isNetworkOrIdempotentRequestError(error) ||\n error.response?.status === 429\n );\n },\n onRetry: (retryCount, error, requestConfig) => {\n const isDev =\n typeof process !== \"undefined\" &&\n process.env?.NODE_ENV === \"development\";\n if (isDev) {\n console.warn(\n `[ECODrIx SDK] Retrying request (${retryCount}/3): ${requestConfig.method?.toUpperCase()} ${requestConfig.url}. Reason: ${error.message}`,\n );\n }\n },\n });\n\n // Initialise resources\n this.whatsapp = new WhatsApp(this.client);\n this.crm = new CRM(this.client);\n this.media = new Media(this.client);\n this.meet = new Meetings(this.client);\n this.notifications = new Notifications(this.client);\n this.email = new Email(this.client);\n this.logs = new Logs(this.client);\n this.events = new EventsResource(this.client);\n this.webhooks = new Webhooks();\n this.storage = new Storage(this.client);\n this.marketing = new Marketing(this.client);\n this.health = new Health(this.client);\n this.queue = new Queue(this.client);\n this.agency = new Agency(this.client);\n this.services = new Services(this.client);\n this.settings = new Settings(this.client);\n this.cors = new Cors(this.client);\n\n // Establish persistent Socket.io connection\n this.socket = io(socketUrl, {\n extraHeaders: {\n \"x-api-key\": options.apiKey,\n \"x-client-code\": options.clientCode?.toUpperCase() || \"\",\n },\n });\n\n this.setupSocket(options.clientCode);\n\n // ─── Wappalyzer & Technology Detection ─────────────────────────────────────\n if (isBrowser) {\n const footprint = {\n version: \"1.2.2\",\n clientCode: options.clientCode,\n initializedAt: new Date().toISOString(),\n };\n // Standard identifying global\n (window as any).__ECODRIX_SDK__ = footprint;\n // Ergonomic access for developers (as attempted by the user)\n if (!(window as any).ecodrix) {\n (window as any).ecodrix = this;\n }\n }\n }\n\n /**\n * Join a specific real-time room (e.g., a conversation or a lead).\n *\n * @param roomId - The unique identifier for the room.\n */\n public joinRoom(roomId: string) {\n this.socket.emit(\"join-room\", roomId);\n }\n\n /**\n * Leave a previously joined real-time room.\n *\n * @param roomId - The unique identifier for the room.\n */\n public leaveRoom(roomId: string) {\n this.socket.emit(\"leave-room\", roomId);\n }\n\n private setupSocket(clientCode?: string) {\n this.socket.on(\"connect\", () => {\n if (clientCode) {\n // Join the tenant-scoped room to receive only relevant events.\n this.socket.emit(\"join-room\", clientCode.toUpperCase());\n }\n });\n }\n\n /**\n * Subscribe to a real-time event emitted by the ECODrIx platform.\n *\n * The SDK maintains a persistent Socket.io connection. Events are\n * scoped to your `clientCode` — you will only receive events for\n * your own tenant.\n *\n * **Standard events:**\n * - `new_message` — inbound WhatsApp message (includes conversation and message payload)\n * - `message_sent` — outbound message successfully sent\n * - `message_status_update` — WhatsApp message status change (delivered, read, failed)\n * - `conversation_updated` — metadata change (unread count, last message, status)\n * - `message_updated` — real-time updates for reactions or media processing\n * - `notification:new` — new system or CRM notification\n * - `workflow-run-update` — automation execution progress\n * - `meet.scheduled` — Google Meet appointment booked\n *\n * @param event - The event name to subscribe to.\n * @param callback - The handler function invoked when the event fires.\n * @returns `this` for method chaining.\n *\n * @example\n * ```typescript\n * ecod\n * .on(\"whatsapp.message_received\", (msg) => console.log(msg.body))\n * .on(\"automation.failed\", (err) => alertTeam(err));\n * ```\n */\n public on(event: string, callback: (...args: any[]) => void): this {\n this.socket.on(event, callback);\n return this;\n }\n\n /**\n * Gracefully disconnect the real-time Socket.io connection.\n * Call this when shutting down your server or when the client is\n * no longer needed to free up resources.\n *\n * @example\n * ```typescript\n * process.on(\"SIGTERM\", () => ecod.disconnect());\n * ```\n */\n public disconnect() {\n this.socket.disconnect();\n }\n\n /**\n * Remove a previously registered event listener.\n * Always call this in cleanup (e.g. React `useEffect` return) to prevent\n * memory leaks and duplicate handlers after reconnections.\n *\n * @param event - The event name to unsubscribe from.\n * @param callback - The exact handler reference passed to `.on()`.\n * @returns `this` for method chaining.\n */\n public off(event: string, callback: (...args: any[]) => void): this {\n this.socket.off(event, callback);\n return this;\n }\n\n /**\n * Raw Execution Escape-Hatch.\n * Send an authenticated HTTP request directly to the ECODrIx backend from ANY external project.\n *\n * This is extremely powerful giving you full unrestricted access to make calls\n * against new, experimental, or completely custom backend APIs while still benefitting\n * from the SDK's built-in authentication and automatic `axios-retry` logic.\n *\n * @example\n * ```typescript\n * const { data } = await ecod.request(\"POST\", \"/api/saas/experimental-feature\", { flag: true });\n * console.log(data);\n * ```\n */\n public async request<T = any>(\n method: Method,\n path: string,\n data?: any,\n params?: any,\n ): Promise<T> {\n try {\n const response = await this.client.request<T>({\n method,\n url: path,\n data,\n params,\n });\n return response.data;\n } catch (error: any) {\n if (error.response) {\n throw new APIError(\n error.response.data?.message ||\n error.response.data?.error ||\n \"Raw Execution Failed\",\n error.response.status,\n error.response.data?.code,\n );\n }\n throw new APIError(error.message || \"Network Error\");\n }\n }\n}\n","/**\n * Typed error hierarchy for the @ecodrix/erix-api SDK.\n *\n * All errors thrown by the SDK extend `EcodrixError`, so a single\n * `catch` block can handle them all, while still allowing granular\n * differentiation between auth failures, rate limits, and generic API errors.\n *\n * @example\n * ```typescript\n * import { APIError, AuthenticationError, RateLimitError } from \"@ecodrix/erix-api\";\n *\n * try {\n * await ecod.crm.leads.retrieve(\"invalid_id\");\n * } catch (err) {\n * if (err instanceof AuthenticationError) {\n * console.error(\"Invalid API key or client code.\");\n * } else if (err instanceof RateLimitError) {\n * console.warn(\"Slow down — rate limit hit.\");\n * } else if (err instanceof APIError) {\n * console.error(`API error ${err.status}: ${err.message}`);\n * }\n * }\n * ```\n */\n\n/** Base class for all ECODrIx SDK errors. */\nexport class EcodrixError extends Error {\n constructor(message: string) {\n super(message);\n this.name = \"EcodrixError\";\n }\n}\n\n/**\n * Represents an error returned by the ECODrIx API.\n * Carries the HTTP `status` code and an optional `code` string.\n */\nexport class APIError extends EcodrixError {\n /** HTTP status code returned by the API (e.g. 400, 404, 500). */\n public status?: number;\n /** Machine-readable error code (e.g. `\"NOT_FOUND\"`, `\"VALIDATION_ERROR\"`). */\n public code?: string;\n\n constructor(message: string, status?: number, code?: string) {\n super(message);\n this.name = \"APIError\";\n this.status = status;\n this.code = code;\n }\n}\n\n/**\n * Thrown when the API key or client code is missing, invalid, or expired.\n * HTTP 401.\n */\nexport class AuthenticationError extends APIError {\n constructor(message = \"Invalid API Key or Client Code\") {\n super(message, 401, \"AUTH_FAILED\");\n this.name = \"AuthenticationError\";\n }\n}\n\n/**\n * Thrown when the rate limit for the API key has been exceeded.\n * HTTP 429. Implement exponential backoff before retrying.\n */\nexport class RateLimitError extends APIError {\n constructor(message = \"Too many requests. Please slow down.\") {\n super(message, 429, \"RATE_LIMIT_EXCEEDED\");\n this.name = \"RateLimitError\";\n }\n}\n","import type { AxiosInstance, AxiosRequestConfig } from \"axios\";\nimport { APIError } from \"./error\";\n\nexport interface RequestOptions extends AxiosRequestConfig {\n /**\n * If true, will not add the x-client-code header.\n */\n ignoreClientCode?: boolean;\n\n /**\n * Safe execution idempotency key.\n * If provided, the backend will safely ignore duplicate requests retried with the same key.\n */\n idempotencyKey?: string;\n}\n\nexport abstract class APIResource {\n public constructor(protected readonly client: AxiosInstance) {}\n\n protected async post<T>(url: string, data?: any, options?: RequestOptions): Promise<T> {\n try {\n const config = this.buildConfig(options);\n const response = await this.client.post(url, data, config);\n return response.data;\n } catch (error: any) {\n this.handleError(error);\n }\n }\n\n protected async get<T>(url: string, options?: RequestOptions): Promise<T> {\n try {\n const config = this.buildConfig(options);\n const response = await this.client.get(url, config);\n return response.data;\n } catch (error: any) {\n this.handleError(error);\n }\n }\n\n protected async patch<T>(url: string, data?: any, options?: RequestOptions): Promise<T> {\n try {\n const config = this.buildConfig(options);\n const response = await this.client.patch(url, data, config);\n return response.data;\n } catch (error: any) {\n this.handleError(error);\n }\n }\n\n protected async put<T>(url: string, data?: any, options?: RequestOptions): Promise<T> {\n try {\n const config = this.buildConfig(options);\n const response = await this.client.put(url, data, config);\n return response.data;\n } catch (error: any) {\n this.handleError(error);\n }\n }\n\n protected async deleteRequest<T>(url: string, options?: RequestOptions): Promise<T> {\n try {\n const config = this.buildConfig(options);\n const response = await this.client.delete(url, config);\n return response.data;\n } catch (error: any) {\n this.handleError(error);\n }\n }\n\n private buildConfig(options?: RequestOptions): AxiosRequestConfig | undefined {\n if (!options) return undefined;\n\n const config: AxiosRequestConfig = { ...options };\n if (options.idempotencyKey) {\n config.headers = {\n ...config.headers,\n \"Idempotency-Key\": options.idempotencyKey,\n };\n }\n return config;\n }\n\n private handleError(error: any): never {\n if (error.response) {\n throw new APIError(\n error.response.data?.message || error.response.data?.error || \"API Request Failed\",\n error.response.status,\n error.response.data?.code,\n );\n }\n throw new APIError(error.message || \"Network Error\");\n }\n}\n","import { APIResource } from \"../../resource\";\n\nexport interface LogActivityParams {\n leadId: string;\n type: \"note\" | \"call\" | \"email\" | \"meeting\" | \"whatsapp\" | \"system\";\n title: string;\n body?: string;\n metadata?: Record<string, any>;\n}\n\nexport interface LogCallParams {\n durationMinutes: number;\n summary: string;\n outcome: \"answered\" | \"no_answer\" | \"busy\" | \"voicemail\" | \"wrong_number\";\n}\n\nexport class Notes extends APIResource {\n /**\n * List all notes for a specific lead.\n *\n * @param leadId - The unique ID of the lead.\n * @example\n * ```typescript\n * const notes = await erixClient.crm.activities.notes.list(\"lead_123\");\n * ```\n */\n async list<T = any>(leadId: string) {\n return this.get<T>(`/api/crm/leads/${leadId}/notes`);\n }\n\n /**\n * Add a new descriptive note to a lead's profile.\n *\n * @param leadId - The unique ID of the lead.\n * @param params - The note content.\n * @example\n * ```typescript\n * await erixClient.crm.activities.notes.create(\"lead_123\", {\n * content: \"Customer is interested in the enterprise plan.\"\n * });\n * ```\n */\n async create<T = any>(leadId: string, params: { content: string }) {\n return this.post<T>(`/api/crm/leads/${leadId}/notes`, params);\n }\n\n /**\n * Update an existing note.\n */\n async update<T = any>(noteId: string, content: string) {\n return this.patch<T>(`/api/crm/notes/${noteId}`, { content });\n }\n\n /**\n * Pin or unpin a note to the top of the feed.\n */\n async pin<T = any>(noteId: string, isPinned = true) {\n return this.patch<T>(`/api/crm/notes/${noteId}/pin`, { isPinned });\n }\n\n /**\n * Delete a note.\n */\n async delete(noteId: string) {\n return this.deleteRequest(`/api/crm/notes/${noteId}`);\n }\n}\n\nexport class Activities extends APIResource {\n public notes: Notes;\n\n constructor(client: any) {\n super(client);\n this.notes = new Notes(client);\n }\n\n /**\n * Retrieve the complete chronological timeline of all activities for a lead.\n *\n * @param leadId - The unique ID of the lead.\n * @param params - Optional pagination parameters.\n * @example\n * ```typescript\n * const timeline = await erixClient.crm.activities.timeline(\"lead_123\", { limit: 10 });\n * ```\n */\n async timeline<T = any>(leadId: string, params?: { page?: number; limit?: number }) {\n return this.get<T>(`/api/crm/leads/${leadId}/timeline`, { params } as any);\n }\n\n /**\n * List specific activities (filtered by type).\n */\n async list<T = any>(leadId: string, params?: { type?: string; page?: number; limit?: number }) {\n return this.get<T>(`/api/crm/leads/${leadId}/activities`, { params: { ...params } } as any);\n }\n\n /**\n * Generic method to log a business activity/event (e.g., system events, manual tasks).\n *\n * @param params - Activity details (leadId, type, title, body).\n * @example\n * ```typescript\n * await erixClient.crm.activities.log({\n * leadId: \"lead_123\",\n * type: \"system\",\n * title: \"Meeting Scheduled\",\n * body: \"Initial consultation booked for Friday.\"\n * });\n * ```\n */\n async log<T = any>(params: LogActivityParams) {\n return this.post<T>(`/api/crm/leads/${params.leadId}/activities`, params);\n }\n\n /**\n * Specific method to log communication outcomes.\n */\n async logCall<T = any>(leadId: string, params: LogCallParams) {\n return this.post<T>(`/api/crm/leads/${leadId}/calls`, params);\n }\n}\n","import { APIResource } from \"../../resource\";\n\nexport type AnalyticsRange = \"24h\" | \"7d\" | \"30d\" | \"60d\" | \"90d\" | \"365d\";\n\nexport interface AnalyticsParams {\n range?: AnalyticsRange;\n from?: string;\n to?: string;\n pipelineId?: string;\n}\n\nexport class Analytics extends APIResource {\n /**\n * Retrieve high-level CRM performance KPIs.\n * Includes total leads, pipeline value, won revenue, and conversion rates.\n *\n * @param params - Optional filters including time range (24h, 7d, 30d, etc.) and custom date bounds.\n * @returns {Promise<any>} KPI summary object containing core business metrics.\n * @example\n * ```typescript\n * const stats = await erixClient.crm.analytics.overview({ range: \"30d\" });\n * console.log(stats.avgScore);\n * ```\n */\n async overview<T = any>(params?: AnalyticsParams) {\n return this.get<T>(\"/api/crm/analytics/overview\", { params } as any);\n }\n\n /**\n * Get stage-by-stage lead counts and conversion percentages for a pipeline.\n * Useful for identifying funnel bottlenecks and drop-off points.\n *\n * @param pipelineId - The unique ID of the pipeline to analyze.\n * @returns {Promise<any>} Array of funnel stages with count and conversion data.\n * @example\n * ```typescript\n * const funnel = await erixClient.crm.analytics.funnel(\"pipe_123\");\n * ```\n */\n async funnel<T = any>(pipelineId: string) {\n return this.get<T>(\"/api/crm/analytics/funnel\", {\n params: { pipelineId },\n } as any);\n }\n\n /**\n * Revenue forecast: Calculates expected revenue based on deal value × stage probability.\n * Helps in sales planning and goal setting.\n *\n * @param pipelineId - Optional pipeline ID to filter the forecast.\n * @returns {Promise<any>} Forecast data including weighted expected revenue.\n * @example\n * ```typescript\n * const prognosis = await erixClient.crm.analytics.forecast(\"pipe_123\");\n * ```\n */\n async forecast<T = any>(pipelineId?: string) {\n return this.get<T>(\"/api/crm/analytics/forecast\", {\n params: { pipelineId },\n } as any);\n }\n\n /**\n * Lead source breakdown: count, conversion rate, and total value per source.\n *\n * @param params - Time range filters.\n * @returns {Promise<any>} Breakdown of how different marketing channels are performing.\n */\n async sources<T = any>(params?: AnalyticsParams) {\n return this.get<T>(\"/api/crm/analytics/sources\", { params } as any);\n }\n\n /**\n * Team leaderboard: Evaluates agent performance across won deals, revenue, and activity.\n *\n * @param params - Time range filters.\n * @returns {Promise<any>} Ranked list of team members by performance.\n */\n async team<T = any>(params?: AnalyticsParams) {\n return this.get<T>(\"/api/crm/analytics/team\", { params } as any);\n }\n\n /**\n * Activity heatmap: Daily activity counts by type.\n * Ideal for visualizing engagement patterns on a calendar view.\n *\n * @param params - Time range filters.\n * @returns {Promise<any>} Time-series data of team activities.\n */\n async heatmap<T = any>(params?: AnalyticsParams) {\n return this.get<T>(\"/api/crm/analytics/heatmap\", { params } as any);\n }\n\n /**\n * Score distribution: Groups leads into buckets based on their calculated score (0-100).\n *\n * @returns {Promise<any>} Volume of leads in different readiness tiers.\n */\n async scores<T = any>() {\n return this.get<T>(\"/api/crm/analytics/scores\");\n }\n\n /**\n * Avg time in stage: Measures the velocity of leads through the sales pipeline.\n *\n * @param pipelineId - Target pipeline ID.\n * @returns {Promise<any>} Velocity metrics per stage.\n */\n async stageTime<T = any>(pipelineId: string) {\n return this.get<T>(\"/api/crm/analytics/stage-time\", {\n params: { pipelineId },\n } as any);\n }\n\n /**\n * Tiered Growth Report matching business sophistication (Pulse, Growth, Weapon).\n * Provides deep tactical and strategic insights.\n *\n * @param params - Filtering and range parameters.\n */\n async tiered<T = any>(params?: AnalyticsParams) {\n return this.get<T>(\"/api/crm/analytics/tiered\", { params } as any);\n }\n\n /**\n * Consolidated analytics including CRM overview and WhatsApp messaging metrics.\n *\n * @param params - Time range filters.\n */\n async summary<T = any>(params?: AnalyticsParams) {\n return this.get<T>(\"/api/crm/analytics/summary\", { params } as any);\n }\n\n /**\n * Retrieve WhatsApp messaging volume and delivery performance analytics.\n * Includes total sent, delivered, read, and daily volume trends.\n *\n * @param params - Optional filters (time range).\n * @example\n * ```typescript\n * const waStats = await erixClient.crm.analytics.whatsapp({ range: \"7d\" });\n * console.log(waStats.totalSent);\n * ```\n */\n async whatsapp<T = any>(params?: AnalyticsParams) {\n return this.get<T>(\"/api/crm/analytics/whatsapp\", { params } as any);\n }\n}\n","import { APIResource } from \"../../resource\";\n\nexport class AutomationDashboard extends APIResource {\n /**\n * Retrieve summary statistics for automation health (total, success, failed).\n *\n * @returns Stats object.\n * @example\n * ```typescript\n * const stats = await erixClient.crm.automationDashboard.stats();\n * ```\n */\n async stats<T = any>() {\n return this.get<T>(\"/api/crm/automation/stats\");\n }\n\n /**\n * List recent EventLog entries representing automation executions.\n *\n * @param params - Optional filters (limit, status).\n * @example\n * ```typescript\n * const logs = await erixClient.crm.automationDashboard.logs({ status: \"failed\" });\n * ```\n */\n async logs<T = any>(params?: { limit?: number; status?: string }) {\n return this.get<T>(\"/api/crm/automation/logs\", { params } as any);\n }\n\n /**\n * Re-emit a failed event log to re-trigger its associated automation rules.\n *\n * @param logId - The unique ID of the failed event log.\n * @example\n * ```typescript\n * await erixClient.crm.automationDashboard.retryFailedEvent(\"log_123\");\n * ```\n */\n async retryFailedEvent<T = any>(logId: string) {\n return this.post<T>(`/api/crm/automation/logs/${logId}/retry`, {});\n }\n}\n","import { APIResource } from \"../../resource\";\n\nexport interface AutomationRulePayload {\n name: string;\n trigger: string;\n isActive?: boolean;\n nodes: any[];\n edges: any[];\n}\n\nexport class Automations extends APIResource {\n /**\n * List all automation rules (workflows) configured for the tenant.\n *\n * @returns Array of automation rule objects.\n * @example\n * ```typescript\n * const rules = await erixClient.crm.automations.list();\n * ```\n */\n async list<T = any>() {\n return this.get<T>(\"/api/crm/automations\");\n }\n\n /**\n * Create a new automation rule with triggers and workflow nodes.\n *\n * @param payload - The automation rule definition (trigger, nodes, edges).\n * @returns The created automation rule.\n * @example\n * ```typescript\n * await erixClient.crm.automations.create({\n * name: \"Welcome Email Workflow\",\n * trigger: \"contact_created\",\n * nodes: [...],\n * edges: [...]\n * });\n * ```\n */\n async create<T = any>(payload: AutomationRulePayload) {\n return this.post<T>(\"/api/crm/automations\", payload);\n }\n\n /**\n * Update an existing automation rule.\n */\n async update<T = any>(ruleId: string, payload: Partial<AutomationRulePayload>) {\n return this.patch<T>(`/api/crm/automations/${ruleId}`, payload as any);\n }\n\n /**\n * Enable or disable an automation rule.\n */\n async toggle<T = any>(ruleId: string) {\n return this.patch<T>(`/api/crm/automations/${ruleId}/toggle`);\n }\n\n /**\n * Delete an automation rule.\n */\n async delete<T = any>(ruleId: string) {\n return this.deleteRequest(`/api/crm/automations/${ruleId}`);\n }\n\n /**\n * Bulk delete rules.\n */\n async bulkDelete<T = any>(ruleIds: string[]) {\n return this.post<T>(\"/api/crm/automations/bulk-delete\", { ids: ruleIds });\n }\n\n /**\n * Dry-run test an automation rule against a specific lead to verify logic.\n *\n * @param ruleId - The ID of the rule to test.\n * @param leadId - The ID of the lead to run the test against.\n * @example\n * ```typescript\n * await erixClient.crm.automations.test(\"rule_123\", \"lead_456\");\n * ```\n */\n async test<T = any>(ruleId: string, leadId: string) {\n return this.post<T>(`/api/crm/automations/${ruleId}/test`, { leadId });\n }\n\n /**\n * Get available event triggers for automations.\n */\n async getAvailableEvents<T = any>() {\n return this.post<T>(\"/api/crm/automations/events\", {});\n }\n\n /**\n * List enrollments for a rule.\n */\n async enrollments<T = any>(\n ruleId: string,\n params?: {\n status?: string;\n page?: number;\n limit?: number;\n startDate?: string;\n endDate?: string;\n },\n ) {\n return this.get<T>(`/api/crm/automations/${ruleId}/enrollments`, { params });\n }\n\n /**\n * Get an enrollment detail.\n */\n async getEnrollment<T = any>(enrollmentId: string) {\n return this.get<T>(`/api/crm/automations/enrollments/${enrollmentId}`);\n }\n\n /**\n * Pause an enrollment.\n */\n async pauseEnrollment<T = any>(ruleId: string, enrollmentId: string) {\n return this.post<T>(`/api/crm/automations/${ruleId}/enrollments/${enrollmentId}/pause`, {});\n }\n\n /**\n * Resume an enrollment.\n */\n async resumeEnrollment<T = any>(ruleId: string, enrollmentId: string) {\n return this.post<T>(`/api/crm/automations/${ruleId}/enrollments/${enrollmentId}/resume`, {});\n }\n\n /**\n * List workflow runs.\n */\n async runs<T = any>(ruleId: string) {\n return this.get<T>(`/api/crm/automations/${ruleId}/runs`);\n }\n\n /**\n * Get run details.\n */\n async getRun<T = any>(runId: string) {\n return this.get<T>(`/api/crm/automations/runs/${runId}`);\n }\n\n /**\n * Resume a paused run.\n */\n async resumeRun<T = any>(runId: string) {\n return this.post<T>(`/api/crm/automations/runs/${runId}/resume`, {});\n }\n\n /**\n * Abort a running workflow.\n */\n async abortRun<T = any>(runId: string) {\n return this.post<T>(`/api/crm/automations/runs/${runId}/abort`, {});\n }\n\n /**\n * Emit an external webhook event to unlock a `wait_event` node inside a\n * paused workflow run. Required when integrating third-party tools that\n * need to resume a suspended automation.\n *\n * @param ruleId - The automation rule that contains the wait_event node.\n * @param eventName - The event name that should match the node's condition.\n * @param payload - Arbitrary data forwarded to the node context.\n */\n async webhookEvent<T = any>(ruleId: string, eventName: string, payload?: any) {\n return this.post<T>(\"/api/crm/webhook-event\", { ruleId, eventName, payload });\n }\n}\n","import { APIResource } from \"../../resource\";\nimport type { ResourceManifest } from \"../../types/metadata\";\n\n/**\n * Valid statuses for a CRM Lead.\n */\nexport type LeadStatus = \"new\" | \"contacted\" | \"qualified\" | \"won\" | \"lost\" | \"archived\";\n\n/**\n * Common lead acquisition sources. Additional string values are allowed.\n */\nexport type LeadSource = \"website\" | \"whatsapp\" | \"direct\" | \"referral\" | string;\n\n/**\n * Parameters for creating a new CRM Lead.\n */\nexport interface CreateLeadParams {\n /** Lead's first name. Required. */\n firstName: string;\n /** Lead's last name. */\n lastName?: string;\n /** Lead's email address. */\n email?: string;\n /** Lead's phone number in E.164 format (e.g. \"+919876543210\"). */\n phone?: string;\n /**\n * Acquisition channel.\n */\n source?: LeadSource;\n /** Arbitrary key-value metadata (UTM params, order IDs, etc.). */\n metadata?: Record<string, any>;\n /** Pipeline ID to assign the lead */\n pipelineId?: string;\n /** Stage ID to assign the lead */\n stageId?: string;\n}\n\n/**\n * Options for listing leads.\n */\nexport interface ListLeadsParams {\n status?: LeadStatus;\n pipelineId?: string;\n stageId?: string;\n source?: LeadSource;\n assignedTo?: string;\n tags?: string[] | string;\n minScore?: number;\n search?: string;\n startDate?: string;\n endDate?: string;\n appointmentId?: string;\n bookingId?: string;\n orderId?: string;\n meetingId?: string;\n page?: number;\n limit?: number;\n sortBy?: string;\n sortDir?: \"asc\" | \"desc\";\n}\n\n/**\n * Options for upserting a lead.\n */\nexport interface UpsertLeadParams {\n leadData: Partial<CreateLeadParams> & { phone: string; name?: string };\n moduleInfo?: any;\n trigger?: string;\n pipelineId?: string;\n stageId?: string;\n}\n\n/**\n * CRM Lead resource — full lifecycle management.\n *\n * Access via `ecod.crm.leads`.\n *\n * @example\n * ```typescript\n * const { data: lead } = await ecod.crm.leads.create({\n * firstName: \"Alice\",\n * phone: \"+919876543210\",\n * source: \"website\",\n * });\n * ```\n */\nexport class Leads extends APIResource {\n /**\n * Create a new lead in the CRM pipeline.\n *\n * @param params - Lead creation parameters. `firstName` is required.\n * @returns The newly created Lead document.\n * @example\n * ```typescript\n * const lead = await erixClient.crm.leads.create({\n * firstName: \"Alice\",\n * phone: \"+919876543210\",\n * source: \"website\"\n * });\n * ```\n */\n async create<T = any>(params: CreateLeadParams) {\n return this.post<T>(\"/api/crm/leads\", params);\n }\n\n /**\n * Introspect the Leads resource and provide a \"Blueprint\" for UI generation.\n *\n * This method returns a list of all fields (standard + custom), their types,\n * labels, and suggested UI controls. Erix React uses this to render SmartForms\n * and tables dynamically.\n */\n async describe(): Promise<ResourceManifest> {\n // 1. Fetch custom fields from the tenant configuration\n const customFieldsRes: any = await this.fields();\n const customFields = Array.isArray(customFieldsRes.data) ? customFieldsRes.data : [];\n\n // 2. Define the core system fields\n const systemFields: any[] = [\n {\n key: \"firstName\",\n label: \"First Name\",\n type: \"string\",\n required: true,\n group: \"Basic Info\",\n },\n { key: \"lastName\", label: \"Last Name\", type: \"string\", required: false, group: \"Basic Info\" },\n { key: \"phone\", label: \"Phone Number\", type: \"phone\", required: true, group: \"Contact\" },\n { key: \"email\", label: \"Email Address\", type: \"email\", required: false, group: \"Contact\" },\n {\n key: \"status\",\n label: \"Status\",\n type: \"select\",\n required: true,\n options: [\n { label: \"New\", value: \"new\" },\n { label: \"Contacted\", value: \"contacted\" },\n { label: \"Qualified\", value: \"qualified\" },\n { label: \"Won\", value: \"won\" },\n { label: \"Lost\", value: \"lost\" },\n ],\n },\n { key: \"value\", label: \"Lead Value\", type: \"currency\", required: false },\n { key: \"source\", label: \"Source\", type: \"string\", required: false },\n ];\n\n // 3. Map custom fields to FieldManifest shape\n const mappedCustom = customFields.map((f: any) => ({\n key: `metadata.extra.${f.name}`,\n label: f.label || f.name,\n type: f.type || \"string\",\n required: !!f.required,\n options: f.options,\n group: \"Custom Fields\",\n }));\n\n return {\n name: \"Lead\",\n fields: [...systemFields, ...mappedCustom],\n uiHints: {\n icon: \"User\",\n primaryColor: \"#3b82f6\",\n defaultSort: { field: \"createdAt\", direction: \"desc\" },\n summaryFields: [\"firstName\", \"lastName\", \"phone\", \"status\"],\n },\n };\n }\n\n /**\n * Upsert a lead by phone number. If a lead with the same phone exists,\n * it will be updated; otherwise, a new lead is created.\n *\n * @param params - Upsert parameters containing leadData with a phone number.\n * @returns The newly created or updated Lead document.\n * @example\n * ```typescript\n * await erixClient.crm.leads.upsert({\n * leadData: { phone: \"+919876543210\", firstName: \"Alice\" }\n * });\n * ```\n */\n async upsert<T = any>(params: UpsertLeadParams) {\n return this.post<T>(\"/api/crm/leads/upsert\", params);\n }\n\n /**\n * Bulk ingest leads efficiently in parallel using automatic chunking.\n * Prevents rate limit exhaustion by executing `chunkSize` requests at a time.\n *\n * @param leads - Array of leads to create.\n * @param chunkSize - Number of leads to send concurrently (default: 50)\n * @returns Array of created lead results.\n */\n async createMany(leads: CreateLeadParams[], chunkSize = 50): Promise<any[]> {\n const results: any[] = [];\n\n for (let i = 0; i < leads.length; i += chunkSize) {\n const chunk = leads.slice(i, i + chunkSize);\n\n const chunkPromises = chunk.map((lead) => this.create(lead));\n const chunkResults = await Promise.allSettled(chunkPromises);\n\n for (const res of chunkResults) {\n if (res.status === \"fulfilled\") {\n results.push(res.value);\n } else {\n throw res.reason;\n }\n }\n }\n\n return results;\n }\n\n /**\n * Bulk upsert (import) leads.\n *\n * @param leads - Array of leads to import.\n */\n async import<T = any>(leads: Partial<CreateLeadParams>[]) {\n return this.post<T>(\"/api/crm/leads/import\", { leads });\n }\n\n /**\n * List CRM leads with optional filtering and pagination.\n *\n * @param params - Filter options (status, source, pipelineId, page, limit, etc.)\n * @returns Paginated list of Lead documents.\n * @example\n * ```typescript\n * const leads = await erixClient.crm.leads.list({\n * status: \"new\",\n * source: \"website\",\n * limit: 20\n * });\n * ```\n */\n async list<T = any>(params?: ListLeadsParams) {\n const queryParams = { ...params } as any;\n if (Array.isArray(queryParams.tags)) {\n queryParams.tags = queryParams.tags.join(\",\");\n }\n return this.get<T>(\"/api/crm/leads\", { params: queryParams } as any);\n }\n\n /**\n * Auto-paginating iterator for leads.\n * Seamlessly fetches leads page by page as you iterate.\n *\n * @example\n * ```typescript\n * for await (const lead of ecod.crm.leads.listAutoPaging<Lead>()) {\n * console.log(lead.firstName);\n * }\n * ```\n */\n async *listAutoPaging<T = any>(params?: ListLeadsParams): AsyncGenerator<T, void, unknown> {\n let currentPage = params?.page || 1;\n let hasMore = true;\n\n while (hasMore) {\n const response: any = await this.list<any>({\n ...params,\n page: currentPage,\n });\n\n const items = Array.isArray(response.data) ? response.data : response || [];\n\n if (items.length === 0) {\n hasMore = false;\n break;\n }\n\n for (const item of items) {\n yield item as T;\n }\n\n if (response.pagination && currentPage < response.pagination.pages) {\n currentPage++;\n } else if (!response.pagination && items.length > 0) {\n // Fallback: If no explicit pagination struct, assume simple array and just keep pulling until empty\n currentPage++;\n } else {\n hasMore = false;\n }\n }\n }\n\n /**\n * Retrieve a single lead by its unique ID.\n *\n * @param leadId - The MongoDB ObjectId of the lead.\n * @returns The Lead document, or a 404 error if not found.\n * @example\n * ```typescript\n * const lead = await erixClient.crm.leads.retrieve(\"64abc...\");\n * ```\n */\n async retrieve<T = any>(leadId: string) {\n return this.get<T>(`/api/crm/leads/${leadId}`);\n }\n\n /**\n * Retrieve a single lead by its phone number.\n *\n * @param phone - Lead's phone number.\n */\n async retrieveByPhone<T = any>(phone: string) {\n // URL-encode the phone to handle '+' safe\n return this.get<T>(`/api/crm/leads/phone/${encodeURIComponent(phone)}`);\n }\n\n /**\n * Retrieve a single lead by a reference key and value.\n *\n * @param refKey - Reference key metadata.\n * @param refValue - Reference value.\n */\n async retrieveByRef<T = any>(refKey: string, refValue: string) {\n return this.get<T>(\n `/api/crm/leads/ref/${encodeURIComponent(refKey)}/${encodeURIComponent(refValue)}`,\n );\n }\n\n /**\n * Update the fields of an existing lead.\n *\n * @param leadId - The ID of the lead to update.\n * @param params - Partial lead fields to update.\n * @returns The updated Lead document.\n * @example\n * ```typescript\n * await erixClient.crm.leads.update(\"64abc...\", {\n * lastName: \"Smith\",\n * status: \"qualified\"\n * });\n * ```\n */\n async update<T = any>(leadId: string, params: Partial<CreateLeadParams>) {\n return this.patch<T>(`/api/crm/leads/${leadId}`, params);\n }\n\n /**\n * Move a lead to a new stage in a pipeline.\n *\n * @param leadId - ID of the lead.\n * @param stageId - Target stage ID.\n */\n async move<T = any>(leadId: string, stageId: string) {\n return this.patch<T>(`/api/crm/leads/${leadId}/move`, { stageId });\n }\n\n /**\n * Convert a lead (mark as won or lost with reason).\n *\n * @param leadId - ID of the lead.\n * @param outcome - \"won\" | \"lost\"\n * @param reason - Reason for the outcome.\n */\n async convert<T = any>(leadId: string, outcome: \"won\" | \"lost\", reason?: string) {\n return this.post<T>(`/api/crm/leads/${leadId}/convert`, {\n outcome,\n reason,\n });\n }\n\n /**\n * Update the tags of a lead.\n *\n * @param leadId - ID of the lead.\n * @param options - Tags to add or remove.\n */\n async tags<T = any>(leadId: string, options: { add?: string[]; remove?: string[] }) {\n return this.patch<T>(`/api/crm/leads/${leadId}/tags`, options);\n }\n\n /**\n * Recalculate lead score based on activities and interactions.\n *\n * @param leadId - ID of the lead.\n */\n async recalculateScore<T = any>(leadId: string) {\n return this.post<T>(`/api/crm/leads/${leadId}/score`, {});\n }\n\n /**\n * Update embedded metadata/references of a lead without touching core fields.\n *\n * @param leadId - ID of the lead.\n * @param metadata - Metadata object indicating { refs, extra }\n */\n async updateMetadata<T = any>(\n leadId: string,\n metadata: { refs?: Record<string, any>; extra?: Record<string, any> },\n ) {\n return this.patch<T>(`/api/crm/leads/${leadId}/metadata`, metadata);\n }\n\n /**\n * Introspect available custom fields configured by the tenant limit.\n */\n async fields<T = any>() {\n return this.get<T>(\"/api/crm/leads/fields\");\n }\n\n /**\n * List all notes for a specific lead.\n */\n async notes<T = any>(leadId: string) {\n return this.get<T>(`/api/crm/leads/${leadId}/notes`);\n }\n\n /**\n * Retrieve the complete chronological timeline for a lead.\n */\n async activities<T = any>(leadId: string, params?: { page?: number; limit?: number }) {\n return this.get<T>(`/api/crm/leads/${leadId}/timeline`, { params } as any);\n }\n\n /**\n * Add a note to a lead.\n */\n async createNote<T = any>(leadId: string, params: { content: string }) {\n return this.post<T>(`/api/crm/leads/${leadId}/notes`, params);\n }\n\n /**\n * Update an existing note.\n */\n async updateNote<T = any>(leadId: string, noteId: string, params: { content: string }) {\n return this.patch<T>(`/api/crm/notes/${noteId}`, params);\n }\n\n /**\n * Delete a note.\n */\n async deleteNote<T = any>(leadId: string, noteId: string) {\n return this.deleteRequest(`/api/crm/notes/${noteId}`);\n }\n\n /**\n * Archive (soft-delete) a single lead.\n *\n * @param leadId - The ID of the lead to archive.\n */\n async delete(leadId: string) {\n return this.deleteRequest(`/api/crm/leads/${leadId}`);\n }\n\n /**\n * Bulk archive multiple leads.\n *\n * @param ids - Array of lead IDs to archive.\n */\n async bulkDelete(ids: string[]) {\n return this.deleteRequest(\"/api/crm/leads\", { data: { ids } });\n }\n}\n","import { APIResource } from \"../../resource\";\n\nexport class Payments extends APIResource {\n /**\n * Record an inbound payment/transaction against a lead or specific appointment.\n *\n * @param payload - Payment details (leadId, amount, currency, description).\n * @example\n * ```typescript\n * await erixClient.crm.payments.capture({\n * leadId: \"lead_123\",\n * amount: 5000,\n * currency: \"INR\",\n * description: \"Consultation Fee\"\n * });\n * ```\n */\n async capture<T = any>(payload: {\n leadId: string;\n amount: number;\n currency?: string;\n description?: string;\n appointmentId?: string;\n }) {\n return this.post<T>(\"/api/crm/payments/capture\", payload);\n }\n}\n","import { APIResource } from \"../../resource\";\nimport type { ResourceManifest } from \"../../types/metadata\";\n\nexport interface CreatePipelineParams {\n name: string;\n isDefault?: boolean;\n stages?: any[]; // Typically an array of stage objects\n}\n\nexport interface PipelineStageParams {\n name: string;\n color?: string;\n probability?: number;\n}\n\nexport class Pipelines extends APIResource {\n /**\n * List all CRM pipelines and their configured stages.\n *\n * @returns Array of pipeline objects with nested stages.\n * @example\n * ```typescript\n * const pipelines = await erixClient.crm.pipelines.list();\n * ```\n */\n async list<T = any>() {\n return this.get<T>(\"/api/crm/pipelines\");\n }\n\n /**\n * Introspect a pipeline and provide a manifest of its stages.\n *\n * Returns metadata about stage colors, probabilities, and order.\n * Erix React uses this to build kanban boards and stage pickers.\n *\n * @param pipelineId - The unique ID of the pipeline.\n */\n async getStageManifest(pipelineId: string): Promise<ResourceManifest> {\n const pipeline: any = await this.retrieve(pipelineId);\n const stages = Array.isArray(pipeline.data?.stages) ? pipeline.data.stages : [];\n\n return {\n name: `Pipeline: ${pipeline.data?.name || pipelineId}`,\n fields: stages.map((s: any) => ({\n key: s._id,\n label: s.name,\n type: \"string\", // Labels are strings\n required: true,\n options: [{ label: s.name, value: s._id }],\n group: \"Stages\",\n uiHints: {\n color: s.color || \"#cbd5e1\",\n probability: s.probability,\n },\n })) as any,\n uiHints: {\n icon: \"Columns\",\n primaryColor: \"#6366f1\",\n },\n };\n }\n\n /**\n * Create a new CRM sales or support pipeline.\n *\n * @param payload - Pipeline details (name and array of stage names).\n * @returns The created pipeline record.\n * @example\n * ```typescript\n * await erixClient.crm.pipelines.create({\n * name: \"Sales Pipeline\",\n * stages: [\"Lead\", \"Contacted\", \"Proposal\", \"Negotiation\", \"Closed\"]\n * });\n * ```\n */\n async create<T = any>(payload: { name: string; stages: string[] }) {\n return this.post<T>(\"/api/crm/pipelines\", payload);\n }\n\n /**\n * Retrieve a single pipeline configuration by ID.\n *\n * @param pipelineId - The unique ID of the pipeline.\n * @example\n * ```typescript\n * const pipeline = await erixClient.crm.pipelines.retrieve(\"pipe_123\");\n * ```\n */\n async retrieve<T = any>(pipelineId: string) {\n return this.get<T>(`/api/crm/pipelines/${pipelineId}`);\n }\n\n /**\n * Update an existing pipeline.\n */\n async update<T = any>(pipelineId: string, payload: Partial<{ name: string; stages: string[] }>) {\n return this.patch<T>(`/api/crm/pipelines/${pipelineId}`, payload as any);\n }\n\n /**\n * Set pipeline as the tenant's default.\n */\n async setDefault<T = any>(pipelineId: string) {\n return this.patch<T>(`/api/crm/pipelines/${pipelineId}/default`, {});\n }\n\n /**\n * Duplicate a pipeline with a new name.\n */\n async duplicate<T = any>(pipelineId: string, newName: string) {\n return this.post<T>(`/api/crm/pipelines/${pipelineId}/duplicate`, {\n newName,\n });\n }\n\n /**\n * Archive a pipeline.\n */\n async archive<T = any>(pipelineId: string) {\n return this.patch<T>(`/api/crm/pipelines/${pipelineId}/archive`, {});\n }\n\n /**\n * Delete a pipeline permanently.\n */\n async delete(pipelineId: string) {\n return this.deleteRequest(`/api/crm/pipelines/${pipelineId}`);\n }\n\n /**\n * Retrieve a Kanban-style board representation of the pipeline with leads nested.\n *\n * @param pipelineId - The unique ID of the pipeline.\n * @example\n * ```typescript\n * const board = await erixClient.crm.pipelines.board(\"pipe_123\");\n * ```\n */\n async board<T = any>(pipelineId: string) {\n return this.get<T>(`/api/crm/pipelines/${pipelineId}/board`);\n }\n\n /**\n * Retrieve a revenue forecast based on stage probabilities for a pipeline.\n */\n async forecast<T = any>(pipelineId: string) {\n return this.get<T>(`/api/crm/pipelines/${pipelineId}/forecast`);\n }\n\n // --- Stage Management ---\n\n /**\n * Add a new stage to the pipeline.\n *\n * @param pipelineId - The unique ID of the pipeline.\n * @param params - Stage details (name, color, probability).\n * @example\n * ```typescript\n * await erixClient.crm.pipelines.addStage(\"pipe_123\", {\n * name: \"Decision Maker Bought In\",\n * color: \"#FF5733\",\n * probability: 80\n * });\n * ```\n */\n async addStage<T = any>(pipelineId: string, params: PipelineStageParams) {\n return this.post<T>(`/api/crm/pipelines/${pipelineId}/stages`, params);\n }\n\n /**\n * Change the order of stages inside the pipeline.\n */\n async reorderStages<T = any>(pipelineId: string, orderArray: string[]) {\n return this.patch<T>(`/api/crm/pipelines/${pipelineId}/stages/reorder`, {\n order: orderArray,\n });\n }\n\n /**\n * Update a specific stage.\n */\n async updateStage<T = any>(stageId: string, params: Partial<PipelineStageParams>) {\n return this.patch<T>(`/api/crm/stages/${stageId}`, params);\n }\n\n /**\n * Delete a stage permanently.\n *\n * @param stageId - The unique ID of the stage to delete.\n * @param moveLeadsToStageId - Optional fallback stageId to move active leads to before deletion.\n */\n async deleteStage(stageId: string, moveLeadsToStageId?: string) {\n return this.deleteRequest(`/api/crm/stages/${stageId}`, {\n data: moveLeadsToStageId ? { moveLeadsToStageId } : undefined,\n });\n }\n}\n","import { APIResource } from \"../../resource\";\n\nexport interface ScoringConfig {\n decayDays: number;\n thresholds: {\n hot: number;\n warm: number;\n };\n rules: any[]; // Specific rule shapes\n}\n\nexport class Scoring extends APIResource {\n /**\n * Retrieve the tenant's global lead scoring configuration (rules, decay, thresholds).\n *\n * @returns The scoring configuration object.\n * @example\n * ```typescript\n * const config = await erixClient.crm.scoring.getConfig();\n * ```\n */\n async getConfig<T = any>() {\n return this.get<T>(\"/api/crm/scoring\");\n }\n\n /**\n * Update scoring configuration.\n */\n async updateConfig<T = any>(payload: Partial<ScoringConfig>) {\n return this.patch<T>(\"/api/crm/scoring\", payload as any);\n }\n\n /**\n * Force an immediate score recalculation for a specific lead.\n * Useful when profile data changes significantly.\n *\n * @param leadId - The unique ID of the lead.\n * @example\n * ```typescript\n * await erixClient.crm.scoring.recalculate(\"lead_123\");\n * ```\n */\n async recalculate<T = any>(leadId: string) {\n return this.post<T>(`/api/crm/scoring/${leadId}/recalculate`, {});\n }\n}\n","import { APIResource } from \"../../resource\";\n\nexport class Sequences extends APIResource {\n /**\n * Manually enroll a lead into a specific automation drip sequence (Workflow).\n *\n * @param payload - Enrollment details (leadId, ruleId, and custom variables).\n * @example\n * ```typescript\n * await erixClient.crm.sequences.enroll({\n * leadId: \"lead_123\",\n * ruleId: \"rule_456\",\n * variables: { start_date: \"2026-05-01\" }\n * });\n * ```\n */\n async enroll<T = any>(payload: {\n leadId: string;\n ruleId: string;\n variables?: Record<string, any>;\n }) {\n return this.post<T>(\"/api/crm/sequences/enroll\", payload);\n }\n\n /**\n * Unenroll a lead from a currently running automation sequence.\n *\n * @param enrollmentId - The unique ID of the sequence enrollment.\n * @example\n * ```typescript\n * await erixClient.crm.sequences.unenroll(\"enroll_123\");\n * ```\n */\n async unenroll<T = any>(enrollmentId: string) {\n return this.deleteRequest(`/api/crm/sequences/unenroll/${enrollmentId}`);\n }\n\n /**\n * List all active and completed sequence enrollments for a specific lead.\n *\n * @param leadId - The unique ID of the lead.\n * @returns Array of enrollment records.\n * @example\n * ```typescript\n * const enrollments = await erixClient.crm.sequences.listForLead(\"lead_123\");\n * ```\n */\n async listForLead<T = any>(leadId: string) {\n return this.get<T>(`/api/crm/sequences/lead/${leadId}`);\n }\n}\n","import type { AxiosInstance } from \"axios\";\nimport { Activities } from \"./activities\";\nimport { Analytics } from \"./analytics\";\nimport { AutomationDashboard } from \"./automationDashboard\";\nimport { Automations } from \"./automations\";\nimport { Leads } from \"./leads\";\nimport { Payments } from \"./payments\";\nimport { Pipelines } from \"./pipelines\";\nimport { Scoring } from \"./scoring\";\nimport { Sequences } from \"./sequences\";\n\nexport class CRM {\n public leads: Leads;\n public pipelines: Pipelines;\n public activities: Activities;\n public analytics: Analytics;\n public automations: Automations;\n public sequences: Sequences;\n public scoring: Scoring;\n public payments: Payments;\n public automationDashboard: AutomationDashboard;\n\n constructor(client: AxiosInstance) {\n this.leads = new Leads(client);\n this.pipelines = new Pipelines(client);\n this.activities = new Activities(client);\n this.analytics = new Analytics(client);\n this.automations = new Automations(client);\n this.sequences = new Sequences(client);\n this.scoring = new Scoring(client);\n this.payments = new Payments(client);\n this.automationDashboard = new AutomationDashboard(client);\n }\n}\n","import { APIResource } from \"../resource\";\n\n/**\n * Payload to send a high-throughput email campaign.\n */\nexport interface SendCampaignPayload {\n /** Array of recipient email addresses. */\n recipients: string[];\n /** Subject line of the email. */\n subject: string;\n /** HTML body of the email. */\n html: string;\n}\n\n/**\n * Interface representing the result of a campaign dispatch.\n */\nexport interface CampaignResult {\n success: boolean;\n message?: string;\n [key: string]: any;\n}\n\nexport interface EmailTemplate {\n id: string;\n name: string;\n description?: string;\n subject: string;\n preheader?: string;\n htmlBody: string;\n textBody?: string;\n category: \"marketing\" | \"transactional\" | \"sequence\";\n status: \"draft\" | \"published\" | \"archived\";\n type: \"standard\" | \"layout\";\n layoutId?: string;\n thumbnail?: string;\n variableMapping?: any[];\n createdAt: string;\n updatedAt: string;\n}\n\nexport interface CreateTemplateDTO {\n name: string;\n subject: string;\n htmlBody: string;\n description?: string;\n category?: \"marketing\" | \"transactional\" | \"sequence\";\n status?: \"draft\" | \"published\" | \"archived\";\n variableMapping?: any[];\n}\n\nexport interface TemplatePreviewResponse {\n success: boolean;\n data: {\n subject: string;\n html: string;\n text?: string;\n };\n}\n\n/**\n * Outbound email marketing engine and template management.\n *\n * Access via `ecod.email`.\n */\nexport class Email extends APIResource {\n /**\n * Send an HTML email campaign to a list of recipients.\n */\n async sendCampaign(payload: SendCampaignPayload): Promise<CampaignResult> {\n return this.post<CampaignResult>(\"/api/saas/emails/campaign\", payload);\n }\n\n /**\n * Send a system test email to validate your current SMTP configuration.\n */\n async sendTest(to: string): Promise<CampaignResult> {\n return this.post<CampaignResult>(\"/api/saas/emails/test\", { to });\n }\n\n // --- Template Management ---\n\n /**\n * List all email templates.\n */\n async listTemplates(query?: any): Promise<{ success: boolean; data: EmailTemplate[] }> {\n return this.get<{ success: boolean; data: EmailTemplate[] }>(\"/api/saas/mail/templates\", {\n params: query,\n });\n }\n\n /**\n * Get a single email template by ID.\n */\n async getTemplate(id: string): Promise<{ success: boolean; data: EmailTemplate }> {\n return this.get<{ success: boolean; data: EmailTemplate }>(`/api/saas/mail/templates/${id}`);\n }\n\n /**\n * Create a new email template.\n */\n async createTemplate(\n data: CreateTemplateDTO,\n ): Promise<{ success: boolean; data: EmailTemplate }> {\n return this.post<{ success: boolean; data: EmailTemplate }>(\"/api/saas/mail/templates\", data);\n }\n\n /**\n * Update an existing email template.\n */\n async updateTemplate(\n id: string,\n data: Partial<CreateTemplateDTO>,\n ): Promise<{ success: boolean; data: EmailTemplate }> {\n return this.put<{ success: boolean; data: EmailTemplate }>(\n `/api/saas/mail/templates/${id}`,\n data,\n );\n }\n\n /**\n * Delete an email template.\n */\n async deleteTemplate(id: string, force = false): Promise<{ success: boolean }> {\n return this.deleteRequest<{ success: boolean }>(`/api/saas/mail/templates/${id}`, {\n params: { force },\n });\n }\n\n /**\n * Preview a template with dynamic variable resolution.\n */\n async previewTemplate(\n id: string,\n params: { leadId?: string; variables?: Record<string, any> },\n ): Promise<TemplatePreviewResponse> {\n return this.post<TemplatePreviewResponse>(`/api/saas/mail/templates/${id}/preview`, params);\n }\n}\n\n/** @deprecated Use Email instead */\nexport class EmailResource extends Email {}\n","import type { AxiosInstance } from \"axios\";\nimport { APIResource } from \"../resource\";\n\n/**\n * Event definition representing an entry point capable of triggering automations.\n */\nexport interface EventDefinition {\n name: string;\n displayName: string;\n description?: string;\n pipelineId?: string;\n stageId?: string;\n defaultSource?: string;\n [key: string]: any;\n}\n\n/**\n * Payload to register/assign a new custom event definition.\n */\nexport interface AssignEventPayload {\n /** The internal machine-readable name of the event (e.g. \"webinar_joined\") */\n name: string;\n /** Human-readable display name */\n displayName: string;\n /** Event description */\n description?: string;\n /** ID of the pipeline to associate with matching leads */\n pipelineId?: string;\n /** ID of the stage within the pipeline */\n stageId?: string;\n /** Default source tag for leads created via this event */\n defaultSource?: string;\n}\n\n/**\n * Payload to programmatically trigger an event/workflow.\n */\nexport interface TriggerPayload {\n /** The name of the event to fire (e.g., \"webinar_joined\") */\n trigger: string;\n /** Phone number of the lead (E.164 format) */\n phone: string;\n /** Email of the lead */\n email?: string;\n /** Key-value pairs for string templates */\n variables?: Record<string, string>;\n /** Deep payload data mapping to the event */\n data?: any;\n /** URL to receive an acknowledgment callback when processing completes */\n callbackUrl?: string;\n /** Secret metadata passed back to the callback URL */\n callbackMetadata?: any;\n /** Auto-create lead if phone does not exist in CRM */\n createLeadIfMissing?: boolean;\n /** Pre-fill data if creating a new lead */\n leadData?: {\n firstName?: string;\n lastName?: string;\n source?: string;\n };\n /** Delay execution of matched workflows (in seconds) */\n delaySeconds?: number;\n /** Delay execution of matched workflows (in minutes) */\n delayMinutes?: number;\n /** Explicit ISO timestamp to trigger the workflow run */\n runAt?: string;\n /** Automatically generate a Google Meet appointment if matched actions require it */\n requiresMeet?: boolean;\n /** Configuration details for the generated Google Meet appointment */\n meetConfig?: {\n summary?: string;\n description?: string;\n startTime?: string;\n duration?: number;\n timezone?: string;\n attendees?: string[];\n };\n}\n\n/**\n * Response returned when triggering an event.\n */\nexport interface TriggerResponse {\n success: boolean;\n data?: {\n eventLogId: string;\n trigger: string;\n leadId: string;\n rulesMatched: number;\n };\n message?: string;\n code?: string;\n}\n\nexport class EventsResource extends APIResource {\n /**\n * List all available event definitions (both system and custom) that can trigger automations.\n *\n * @returns Array of event definitions.\n * @example\n * ```typescript\n * const events = await erixClient.events.list();\n * ```\n */\n async list(): Promise<{ success: boolean; data: EventDefinition[] }> {\n return this.get<{ success: boolean; data: EventDefinition[] }>(\"/api/saas/events\");\n }\n\n /**\n * Register a new custom event entry point into the CRM automation engine.\n * Useful when introducing new granular triggers.\n */\n async assign(payload: AssignEventPayload): Promise<{ success: boolean; data: EventDefinition }> {\n return this.post<{ success: boolean; data: EventDefinition }>(\n \"/api/saas/events/assign\",\n payload,\n );\n }\n\n /**\n * Deactivate a custom event assignment by name.\n */\n async unassign(name: string): Promise<{ success: boolean; data: any }> {\n return this.post<{ success: boolean; data: any }>(\"/api/saas/events/unassign\", { name });\n }\n\n /**\n * Deactivate multiple custom event assignments simultaneously.\n */\n async unassignBulk(names: string[]): Promise<{ success: boolean; message: string }> {\n return this.post<{ success: boolean; message: string }>(\"/api/saas/events/unassign/bulk\", {\n names,\n });\n }\n\n /**\n * Programmatically trigger an automation workflow by firing a specific event.\n * This matches the event against active Automation Rules and executes linked actions.\n *\n * @param payload - The trigger details (event name, lead phone/email, variables).\n * @returns Trigger response with diagnostic info (eventLogId, matched rules).\n * @example\n * ```typescript\n * await erixClient.events.trigger({\n * trigger: \"webinar_joined\",\n * phone: \"+919876543210\",\n * variables: { webinar_name: \"AI Masterclass\" },\n * createLeadIfMissing: true\n * });\n * ```\n */\n async trigger(payload: TriggerPayload): Promise<TriggerResponse> {\n return this.post<TriggerResponse>(\"/api/saas/workflows/trigger\", payload);\n }\n\n // --- CRM Custom Events ---\n\n /**\n * List all custom event definitions.\n */\n async listCustomEvents<T = any>() {\n return this.get<T>(\"/api/saas/crm/custom-events\");\n }\n\n /**\n * Create or upsert a custom event definition.\n */\n async createCustomEvent<T = any>(payload: {\n name: string;\n displayName: string;\n description?: string;\n }) {\n return this.post<T>(\"/api/saas/crm/custom-events\", payload);\n }\n\n /**\n * Delete a custom event definition.\n */\n async deleteCustomEvent<T = any>(id: string) {\n return this.deleteRequest<T>(`/api/saas/crm/custom-events/${id}`);\n }\n\n /**\n * Manually emit a custom event to trigger workflows based on its definition.\n */\n async emit<T = any>(payload: { eventName: string; leadId: string; data?: any }) {\n return this.post<T>(\"/api/saas/crm/events/emit\", payload);\n }\n}\n","import { APIResource } from \"../resource\";\n\nexport interface SystemHealth {\n status: string;\n version: string;\n env: string;\n uptime: number;\n db: string;\n queueDepth: number;\n timestamp: string;\n}\n\nexport interface ClientHealth {\n clientCode: string;\n services: {\n whatsapp: \"connected\" | \"not_configured\";\n email: \"configured\" | \"not_configured\";\n googleMeet: \"configured\" | \"not_configured\";\n };\n activeAutomations: number;\n queueDepth: number;\n timestamp: string;\n}\n\nexport interface JobStatus {\n jobId: string;\n status: string;\n attempts: number;\n maxAttempts: number;\n lastError: any;\n runAt: string;\n completedAt: string | null;\n failedAt: string | null;\n createdAt: string;\n}\n\n/**\n * Platform and tenant-specific health diagnostics.\n *\n * Access via `ecod.health`.\n */\nexport class Health extends APIResource {\n /**\n * Perform a global platform health check.\n * Verify that the core API, database, and background workers are operational.\n */\n async system(): Promise<SystemHealth> {\n const res = await this.get<{ success: boolean; data: SystemHealth }>(\"/api/saas/health\");\n return res.data;\n }\n\n /**\n * Tenant-specific health check.\n *\n * Identifies correctly configured third-party integrations (WhatsApp, SMTP, Google Meet)\n * and reports active automation counts.\n */\n async clientHealth(): Promise<ClientHealth> {\n const res = await this.get<{ success: boolean; data: ClientHealth }>(\"/api/saas/health/client\");\n return res.data;\n }\n\n /**\n * Alias for clientHealth to match diagnostic terminology.\n */\n async getDiagnosticReport(): Promise<ClientHealth> {\n return this.clientHealth();\n }\n\n /**\n * Lookup the execution status of a background job.\n *\n * Use this to poll for completion of long-running tasks like bulk exports\n * or campaign dispatches.\n *\n * @param jobId - The unique ID of the background job.\n */\n async jobStatus(jobId: string): Promise<JobStatus> {\n const res = await this.get<{ success: boolean; data: JobStatus }>(\n `/api/saas/jobs/status/${jobId}`,\n );\n return res.data;\n }\n}\n","import { APIResource } from \"../resource\";\n\nexport interface LogPaginationQuery {\n page?: number;\n limit?: number;\n trigger?: string;\n status?: \"received\" | \"processing\" | \"completed\" | \"partial\" | \"failed\";\n from?: string;\n to?: string;\n}\n\nexport interface EventLog {\n id: string;\n trigger: string;\n phone?: string;\n email?: string;\n status: \"received\" | \"processing\" | \"completed\" | \"partial\" | \"failed\";\n rulesMatched: number;\n jobsCreated: number;\n meetLink?: string;\n callbackUrl?: string;\n callbackStatus: \"not_required\" | \"sent\" | \"failed\";\n payload: any;\n error?: string;\n idempotencyKey?: string;\n processedAt?: string;\n createdAt: string;\n updatedAt: string;\n}\n\nexport interface CallbackLog {\n id: string;\n callbackUrl: string;\n method: string;\n payload: any;\n jobId?: string;\n enrollmentId?: string;\n responseStatus: number;\n responseBody: string;\n status: \"sent\" | \"failed\" | \"pending_retry\";\n attempts: number;\n lastAttemptAt?: string;\n signature?: string;\n createdAt: string;\n}\n\nexport interface LogResponse<T> {\n success: boolean;\n data: T[];\n pagination: {\n total: number;\n page: number;\n limit: number;\n pages: number;\n };\n}\n\n/**\n * Audit and execution logs for platform events and webhooks.\n *\n * Access via `ecod.logs`.\n */\nexport class Logs extends APIResource {\n /**\n * List event execution logs with optional filtering.\n *\n * Use this to audit automation triggers and debug workflow execution.\n */\n async listEventLogs(query?: LogPaginationQuery): Promise<LogResponse<EventLog>> {\n return this.get<LogResponse<EventLog>>(\"/api/saas/events/logs\", {\n params: query,\n });\n }\n\n /**\n * Get detailed information for a single event execution.\n */\n async getEventLog(id: string): Promise<{ success: boolean; data: EventLog }> {\n return this.get<{ success: boolean; data: EventLog }>(`/api/saas/events/logs/${id}`);\n }\n\n /**\n * List webhook callback logs (outbound responses from ECODrIx to your system).\n */\n async listCallbackLogs(query?: LogPaginationQuery): Promise<LogResponse<CallbackLog>> {\n return this.get<LogResponse<CallbackLog>>(\"/api/saas/callbacks/logs\", {\n params: query,\n });\n }\n\n /**\n * Get high-level execution statistics for the tenant.\n */\n async getStats(): Promise<{ success: boolean; data: any }> {\n return this.get<{ success: boolean; data: any }>(\"/api/saas/events/stats\");\n }\n}\n","import { APIResource } from \"../resource\";\n\nexport interface SendCampaignParams {\n recipients: string[];\n subject: string;\n html: string;\n}\n\nexport class Emails extends APIResource {\n /**\n * Dispatch a bulk email campaign to a list of recipients.\n *\n * @param params - The campaign details (recipients, subject, html).\n * @returns The dispatch result.\n * @example\n * ```typescript\n * await erixClient.marketing.emails.sendCampaign({\n * recipients: [\"user@example.com\"],\n * subject: \"Special Offer\",\n * html: \"<p>Check out our deal!</p>\"\n * });\n * ```\n */\n async sendCampaign<T = any>(params: SendCampaignParams) {\n return this.post<T>(\"/api/saas/marketing/emails/campaign\", params);\n }\n\n /**\n * Send a test verification email (used to verify SMTP functionality).\n */\n async sendTest<T = any>(to: string) {\n return this.post<T>(\"/api/saas/marketing/emails/test\", { to });\n }\n}\nexport class Campaigns extends APIResource {\n /**\n * List all email and SMS marketing campaigns with optional status filtering.\n *\n * @param params - Optional filters (status, limit).\n * @returns Paginated list of campaign objects.\n * @example\n * ```typescript\n * const campaigns = await erixClient.marketing.campaigns.list({ status: \"sent\" });\n * ```\n */\n async list<T = any>(params?: { status?: string; limit?: number }) {\n return this.get<T>(\"/api/saas/marketing/campaigns\", { params } as any);\n }\n\n /**\n * Create a new marketing campaign (Email or SMS).\n *\n * @param payload - Campaign details (name, type, content).\n * @returns The created campaign record.\n * @example\n * ```typescript\n * await erixClient.marketing.campaigns.create({\n * name: \"Spring Sale\",\n * type: \"email\",\n * subject: \"Our Spring Sale is Here!\",\n * html: \"<h1>BIG DEALS!</h1>\"\n * });\n * ```\n */\n async create<T = any>(payload: {\n name: string;\n type: string;\n subject?: string;\n html?: string;\n templateId?: string;\n recipients?: string[];\n }) {\n return this.post<T>(\"/api/saas/marketing/campaigns\", payload);\n }\n\n /**\n * Retrieve full details for a specific marketing campaign.\n *\n * @param campaignId - The unique ID of the campaign.\n * @example\n * ```typescript\n * const campaign = await erixClient.marketing.campaigns.retrieve(\"camp_123\");\n * ```\n */\n async retrieve<T = any>(campaignId: string) {\n return this.get<T>(`/api/saas/marketing/campaigns/${campaignId}`);\n }\n\n /**\n * Update a campaign.\n */\n async update<T = any>(campaignId: string, payload: any) {\n return this.patch<T>(`/api/saas/marketing/campaigns/${campaignId}`, payload);\n }\n\n /**\n * Delete a campaign.\n */\n async delete<T = any>(campaignId: string) {\n return this.deleteRequest<T>(`/api/saas/marketing/campaigns/${campaignId}`);\n }\n\n /**\n * Send a campaign immediately or schedule it for a later date.\n *\n * @param campaignId - The ID of the campaign to dispatch.\n * @param payload - Optional scheduling information (ISO timestamp).\n * @example\n * ```typescript\n * // Send immediately\n * await erixClient.marketing.campaigns.send(\"camp_123\");\n *\n * // Schedule for tomorrow\n * await erixClient.marketing.campaigns.send(\"camp_123\", {\n * scheduledAt: \"2026-04-10T09:00:00Z\"\n * });\n * ```\n */\n async send<T = any>(campaignId: string, payload?: { scheduledAt?: string }) {\n return this.post<T>(`/api/saas/marketing/campaigns/${campaignId}/send`, payload || {});\n }\n\n /**\n * Get detailed delivery and engagement statistics for a campaign.\n * Includes opens, clicks, bounces, and delivery failures.\n *\n * @param campaignId - The ID of the campaign.\n * @returns Stats summary object.\n * @example\n * ```typescript\n * const report = await erixClient.marketing.campaigns.stats(\"camp_123\");\n * console.log(`Open Rate: ${report.openRate}%`);\n * ```\n */\n async stats<T = any>(campaignId: string) {\n return this.get<T>(`/api/saas/marketing/campaigns/${campaignId}/stats`);\n }\n}\n\nexport class WhatsAppMarketing extends APIResource {\n /**\n * Dispatch a template-based WhatsApp message with CRM-integrated variable resolution.\n *\n * Unlike direct WhatsApp sending, this endpoint documentation automatically pulls data from the CRM\n * based on the provided variables mapping.\n *\n * @param params - Template details and recipient phone.\n * @example\n * ```typescript\n * await erixClient.marketing.whatsapp.sendTemplate({\n * phone: \"+919876543210\",\n * templateName: \"order_update\",\n * variables: { \"1\": \"Order #123\" }\n * });\n * ```\n */\n async sendTemplate<T = any>(params: {\n phone: string;\n templateName: string;\n languageCode?: string;\n variables?: Record<string, string>;\n resolvedVariables?: Record<string, string>;\n }) {\n return this.post<T>(\"/api/saas/marketing/whatsapp/send-template\", params);\n }\n}\n\nexport class Marketing extends APIResource {\n public emails: Emails;\n public campaigns: Campaigns;\n public whatsapp: WhatsAppMarketing;\n\n constructor(client: any) {\n super(client);\n this.emails = new Emails(client);\n this.campaigns = new Campaigns(client);\n this.whatsapp = new WhatsAppMarketing(client);\n }\n}\n","import axios from \"axios\";\nimport { APIResource } from \"../resource\";\n\n/**\n * Options for the `upload()` elite helper.\n */\nexport interface UploadOptions {\n /**\n * The destination folder key in R2.\n * @example \"customer_documents\" | \"avatars\" | \"invoices\"\n */\n folder: string;\n /**\n * The desired filename, including extension.\n * @example \"contract.pdf\" | \"profile.jpg\"\n */\n filename: string;\n /**\n * The MIME type of the file.\n * @example \"application/pdf\" | \"image/jpeg\" | \"video/mp4\"\n */\n contentType: string;\n}\n\n/**\n * Cloudflare R2-backed media resource.\n *\n * Access via `ecod.media`.\n *\n * The `upload()` method is the recommended approach. It acts as a client-side\n * orchestrator: it fetches a presigned URL from the backend, uploads directly\n * to R2 (bypassing the API server), then confirms the upload — all in one call.\n *\n * @example\n * ```typescript\n * const { data } = await ecod.media.upload(fileBuffer, {\n * folder: \"invoices\",\n * filename: \"invoice-001.pdf\",\n * contentType: \"application/pdf\",\n * });\n * console.log(data.url); // → https://cdn.ecodrix.com/invoices/invoice-001.pdf\n * ```\n */\nexport class Media extends APIResource {\n /**\n * Get current storage usage metrics for the tenant.\n *\n * @returns `{ usedMB, limitMB, fileCount }`\n *\n * @example\n * ```typescript\n * const { data } = await ecod.media.getUsage();\n * console.log(`${data.usedMB} / ${data.limitMB} MB used`);\n * ```\n */\n async getUsage() {\n return this.get(\"/api/saas/storage/usage\");\n }\n\n /**\n * Create a new top-level folder in the tenant's R2 bucket.\n *\n * @param name - Folder name (alphanumeric, hyphens, underscores).\n *\n * @example\n * ```typescript\n * await ecod.media.createFolder(\"patient_records\");\n * ```\n */\n async createFolder(name: string) {\n return this.post(\"/api/saas/storage/folders\", { name });\n }\n\n /**\n * List files within a folder, with optional date / search filtering.\n *\n * @param folder - The folder name to list, **or `\"*\"` to fetch all folders**\n * for the tenant in a single call (returns a merged flat list with a\n * `folder` field on each file so callers can group/filter client-side).\n * @param params - Optional `year`, `month`, and keyword search `q` filters.\n * @returns `{ data: { files, count, totalSizeBytes } }`.\n *\n * @example Single folder\n * ```typescript\n * const { data } = await ecod.media.list(\"invoices\", { q: \"contract\" });\n * // data.files → files only from the \"invoices\" folder\n * ```\n *\n * @example All folders\n * ```typescript\n * const { data } = await ecod.media.list(\"*\");\n * // data.files → merged files from every folder the tenant has\n * // Each file has a `folder` field indicating its source folder\n * ```\n */\n async list(folder: string, params?: { year?: string; month?: string; q?: string }) {\n return this.get(`/api/saas/storage/files/${folder}`, { params } as any);\n }\n\n /**\n * Delete a file from R2 by its storage key.\n *\n * @param key - The full storage key of the file (e.g. `\"invoices/contract.pdf\"`).\n *\n * @example\n * ```typescript\n * await ecod.media.delete(\"invoices/old-contract.pdf\");\n * ```\n */\n async delete(key: string) {\n return this.deleteRequest(\"/api/saas/storage/files\", { params: { key } });\n }\n\n /**\n * Request a temporary presigned download URL for a private file.\n *\n * @param key - The full storage key of the file.\n * @returns `{ url }` — a time-limited download URL.\n *\n * @example\n * ```typescript\n * const { data } = await ecod.media.getDownloadUrl(\"invoices/contract.pdf\");\n * // → { url: \"https://cdn.ecodrix.com/...?token=...\" }\n * ```\n */\n async getDownloadUrl(key: string) {\n return this.post(\"/api/saas/storage/download-url\", { key });\n }\n\n /**\n * **Elite Upload Helper** — uploads a file to Cloudflare R2 in a single call.\n *\n * This orchestrates 3 steps transparently:\n * 1. Fetch a presigned `PUT` URL from the ECODrIx backend.\n * 2. Upload the file _directly_ to R2 (no API proxy, maximum throughput).\n * 3. Confirm the upload with the backend so it is indexed and tracked.\n *\n * Works with Node.js `Buffer`, browser `File`/`Blob`, or any stream-like\n * object that Axios can PUT.\n *\n * @param file - The file data to upload.\n * @param options - Folder, filename, and content type.\n * @returns Confirmed file metadata including `key` and `url`.\n *\n * @example Node.js\n * ```typescript\n * import { readFileSync } from \"fs\";\n * const buf = readFileSync(\"./invoice.pdf\");\n * const { data } = await ecod.media.upload(buf, {\n * folder: \"invoices\",\n * filename: \"invoice-001.pdf\",\n * contentType: \"application/pdf\",\n * });\n * ```\n *\n * @example Browser\n * ```typescript\n * const file = inputElement.files[0];\n * const { data } = await ecod.media.upload(file, {\n * folder: \"avatars\",\n * filename: file.name,\n * contentType: file.type,\n * });\n * ```\n */\n async upload(file: any, options: UploadOptions): Promise<any> {\n // Step 1: Get presigned URL\n const response = await this.post<any>(\"/api/saas/storage/upload-url\", options);\n const { uploadUrl, key } = response.data;\n\n // Step 2: Upload directly to R2 (bypasses the API server for performance)\n await axios.put(uploadUrl, file, {\n headers: { \"Content-Type\": options.contentType },\n });\n\n const sizeBytes = file.size || file.byteLength || 0;\n\n // Step 3: Confirm with backend\n return this.post(\"/api/saas/storage/confirm-upload\", { key, sizeBytes });\n }\n}\n\n/** @deprecated Use Media instead */\nexport class MediaResource extends Media {}\n","import { APIResource } from \"../resource\";\n\n/**\n * Parameters for scheduling a new Google Meet appointment.\n */\nexport interface CreateMeetingParams {\n /** The CRM Lead ID this meeting belongs to. */\n leadId: string;\n /** Full name of the external participant. */\n participantName: string;\n /** Phone number of the participant in E.164 format. */\n participantPhone: string;\n /**\n * Meeting start time.\n * @example new Date(\"2026-04-10T10:00:00.000Z\")\n */\n startTime: Date | string;\n /**\n * Meeting end time.\n * @example new Date(\"2026-04-10T10:30:00.000Z\")\n */\n endTime: Date | string;\n /** Arbitrary metadata to attach to the meeting record. */\n metadata?: Record<string, any>;\n}\n\n/**\n * Parameters for updating an existing meeting.\n */\nexport interface UpdateMeetingParams {\n /**\n * Update the meeting status.\n * @example \"scheduled\" | \"completed\" | \"cancelled\"\n */\n status?: string;\n /** Update the payment status for paid consultations. */\n paymentStatus?: string;\n /** New start time for rescheduling. */\n startTime?: Date | string;\n /** New end time for rescheduling. */\n endTime?: Date | string;\n /** Duration in minutes. */\n duration?: number;\n}\n\n/**\n * Google Meet appointment scheduling resource.\n *\n * Access via `ecod.meet`.\n *\n * @example\n * ```typescript\n * const { data } = await ecod.meet.create({\n * leadId: \"64abc...\",\n * participantName: \"Alice\",\n * participantPhone: \"+919876543210\",\n * startTime: \"2026-04-10T10:00:00Z\",\n * endTime: \"2026-04-10T10:30:00Z\",\n * });\n * console.log(data.meetLink); // → https://meet.google.com/abc-defg-hij\n * ```\n */\nexport class Meetings extends APIResource {\n /**\n * Schedule a new Google Meet with a lead.\n *\n * The backend automatically creates a Google Calendar event and generates\n * a Meet link, then sends confirmation notifications via WhatsApp.\n *\n * @param data - Meeting details.\n * @returns The created Meeting document including `meetLink`.\n *\n * @example\n * ```typescript\n * const { data } = await ecod.meet.create({\n * leadId: \"64abc...\",\n * participantName: \"Alice\",\n * participantPhone: \"+91...\",\n * startTime: \"2026-04-10T10:00:00Z\",\n * endTime: \"2026-04-10T10:30:00Z\",\n * });\n * ```\n */\n async create(data: CreateMeetingParams): Promise<any> {\n return this.post(\"/api/saas/meet\", data);\n }\n\n /**\n * List all meetings for the tenant, with optional filters.\n *\n * @param params - `leadId` to filter by lead; `status` to filter by state.\n * @returns Array of Meeting documents.\n *\n * @example\n * ```typescript\n * const { data } = await ecod.meet.list({ status: \"scheduled\" });\n * ```\n */\n async list(params?: { leadId?: string; status?: string }): Promise<any> {\n return this.get(\"/api/saas/meet\", { params } as any);\n }\n\n /**\n * Retrieve the full details for a specific meeting.\n *\n * @param meetingId - The unique meeting ID.\n * @returns The Meeting document.\n *\n * @example\n * ```typescript\n * const { data } = await ecod.meet.retrieve(\"meeting_id\");\n * ```\n */\n async retrieve(meetingId: string): Promise<any> {\n return this.get(`/api/saas/meet/${meetingId}`);\n }\n\n /**\n * Update or reschedule an existing meeting.\n *\n * Partial updates are supported — only supply the fields you wish to change.\n *\n * @param meetingId - The meeting to update.\n * @param data - Fields to update.\n * @returns The updated Meeting document.\n *\n * @example\n * ```typescript\n * // Reschedule\n * await ecod.meet.update(\"meeting_id\", {\n * startTime: \"2026-04-11T11:00:00Z\",\n * endTime: \"2026-04-11T11:30:00Z\",\n * });\n * ```\n */\n async update<T = any>(meetingId: string, data: UpdateMeetingParams) {\n return this.patch<T>(`/api/saas/meet/${meetingId}`, data);\n }\n\n /**\n * Reschedule an existing meeting. Provides explicit method for time modifications.\n */\n async reschedule<T = any>(\n meetingId: string,\n params: { startTime: Date | string; endTime: Date | string; duration?: number },\n ) {\n return this.patch<T>(`/api/saas/meet/${meetingId}`, params);\n }\n\n /**\n * Cancel a meeting. This sets the meeting status to `\"cancelled\"`.\n *\n * @param meetingId - The meeting to cancel.\n *\n * @example\n * ```typescript\n * await ecod.meet.delete(\"meeting_id\");\n * ```\n */\n async delete(meetingId: string): Promise<any> {\n return this.update(meetingId, { status: \"cancelled\" });\n }\n}\n","import { APIResource } from \"../resource\";\n\n/**\n * Filters for querying event and automation execution logs.\n */\nexport interface LogFilter {\n /** Page number for pagination (1-indexed). */\n page?: number;\n /** Maximum number of records to return per page. */\n limit?: number;\n /**\n * Filter by automation trigger name.\n * @example \"lead_created\" | \"appointment_booked\"\n */\n trigger?: string;\n /**\n * Filter by execution status.\n * @example \"success\" | \"failed\" | \"pending\"\n */\n status?: string;\n /** Filter logs associated with a specific phone number. */\n phone?: string;\n /** Start of the date range (inclusive). ISO 8601 or Date object. */\n startDate?: string | Date;\n /** End of the date range (inclusive). ISO 8601 or Date object. */\n endDate?: string | Date;\n}\n\n/**\n * Automation event log and provider callback resource.\n *\n * Access via `ecod.notifications`.\n *\n * This resource is **read-only**. It exposes platform audit trails — useful\n * for debugging automation failures, monitoring webhook callbacks, and\n * building internal ops dashboards.\n *\n * @example\n * ```typescript\n * // Find failed automations in April\n * const { data } = await ecod.notifications.listLogs({\n * status: \"failed\",\n * startDate: \"2026-04-01\",\n * endDate: \"2026-04-30\",\n * });\n * ```\n */\nexport class Notifications extends APIResource {\n /**\n * List automation execution logs with optional filtering.\n *\n * Each log entry represents one automation run triggered by a platform event.\n * Filter by `status: \"failed\"` to build a failure alerting pipeline.\n *\n * @param params - Optional filter criteria.\n * @returns Paginated list of event log objects.\n *\n * @example\n * ```typescript\n * const { data: failed } = await ecod.notifications.listLogs({\n * status: \"failed\",\n * trigger: \"lead_created\",\n * limit: 50,\n * });\n * ```\n */\n async listLogs(params?: LogFilter) {\n return this.get(\"/api/saas/events/logs\", { params } as any);\n }\n\n /**\n * Retrieve the full details for a single automation event log entry.\n *\n * @param logId - The unique log ID.\n * @returns A single event log document including the payload and error trace.\n *\n * @example\n * ```typescript\n * const { data } = await ecod.notifications.retrieveLog(\"log_64abc...\");\n * console.log(data.error); // → \"Provider timeout after 30s\"\n * ```\n */\n async retrieveLog(logId: string) {\n return this.get(`/api/saas/events/logs/${logId}`);\n }\n\n /**\n * Get a summary statistics object for automation event execution.\n *\n * @param params - Optional date range for the summary window.\n * @returns `{ total, success, failed, pending }` counts.\n *\n * @example\n * ```typescript\n * const { data: stats } = await ecod.notifications.getStats({\n * startDate: \"2026-04-01\",\n * endDate: \"2026-04-30\",\n * });\n * console.log(`Failed: ${stats.failed} / ${stats.total}`);\n * ```\n */\n async getStats(params?: { startDate?: string; endDate?: string }) {\n return this.get(\"/api/saas/events/stats\", { params } as any);\n }\n\n /**\n * List external provider webhook callback logs.\n *\n * These are inbound HTTP callbacks from third-party providers\n * (payment gateways, email services, etc.) stored for audit purposes.\n *\n * @param params - Pagination and date filter options.\n * @returns Paginated list of callback log records.\n *\n * @example\n * ```typescript\n * const { data } = await ecod.notifications.listCallbacks({ limit: 20 });\n * ```\n */\n async listCallbacks(params?: Omit<LogFilter, \"trigger\" | \"phone\">) {\n return this.get(\"/api/saas/callbacks/logs\", { params } as any);\n }\n\n // --- CRM Notifications (Alerts) ---\n // Backend routes mounted at /api/crm — see crm.router.ts + notification.routes.ts\n\n /**\n * List unread CRM notifications and alerts (e.g., lead assignments, system alerts).\n *\n * @param params - Optional filters (limit, unreadOnly).\n * @returns Paginated list of notification objects.\n * @example\n * ```typescript\n * const alerts = await erixClient.notifications.listAlerts({ unreadOnly: true });\n * ```\n */\n async listAlerts<T = any>(params?: { limit?: number; unreadOnly?: boolean }) {\n return this.get<T>(\"/api/crm/notifications\", { params } as any);\n }\n\n /**\n * Dismiss/mark a specific notification alert as read.\n *\n * @param notificationId - The unique ID of the notification.\n * @example\n * ```typescript\n * await erixClient.notifications.dismissAlert(\"alert_123\");\n * ```\n */\n async dismissAlert<T = any>(notificationId: string) {\n return this.patch<T>(`/api/crm/notifications/${notificationId}/dismiss`);\n }\n\n /**\n * Clear all notifications for the current tenant immediately.\n *\n * @example\n * ```typescript\n * await erixClient.notifications.clearAllAlerts();\n * ```\n */\n async clearAllAlerts<T = any>() {\n return this.deleteRequest<T>(\"/api/crm/notifications/clear-all\");\n }\n\n /**\n * Retry an action from a notification (e.g. failed automation send).\n *\n * @param notificationId - The unique ID of the notification.\n * @example\n * ```typescript\n * await erixClient.notifications.retryAction(\"alert_123\");\n * ```\n */\n async retryAction<T = any>(notificationId: string) {\n return this.post<T>(`/api/crm/notifications/${notificationId}/retry`, {});\n }\n}\n","import { APIResource } from \"../resource\";\n\nexport interface JobStats {\n waiting: number;\n active: number;\n completed: number;\n failed: number;\n delayed: number;\n}\n\nexport class Queue extends APIResource {\n /**\n * List all background jobs that have failed execution.\n *\n * @returns Array of failed job objects.\n * @example\n * ```typescript\n * const failed = await erixClient.queue.listFailed();\n * ```\n */\n async listFailed<T = any>() {\n return this.get<T>(\"/api/saas/admin/queue/failed\");\n }\n\n /**\n * Get real-time health statistics for the background job queue (waiting, active, failed).\n *\n * @returns Queue statistics summary.\n * @example\n * ```typescript\n * const stats = await erixClient.queue.getStats();\n * console.log(`Active Jobs: ${stats.active}`);\n * ```\n */\n async getStats<T = JobStats>() {\n return this.get<T>(\"/api/saas/admin/queue/stats\");\n }\n\n /**\n * Manually retry a failed background job.\n *\n * @param jobId - The unique ID of the failed job.\n * @example\n * ```typescript\n * await erixClient.queue.retryJob(\"job_123\");\n * ```\n */\n async retryJob<T = any>(jobId: string) {\n return this.post<T>(`/api/saas/admin/queue/${jobId}/retry`, {});\n }\n\n /**\n * Remove a job from the queue.\n *\n * @param jobId - The unique ID of the job to delete.\n * @example\n * ```typescript\n * await erixClient.queue.deleteJob(\"job_123\");\n * ```\n */\n async deleteJob<T = any>(jobId: string) {\n return this.deleteRequest<T>(`/api/saas/admin/queue/${jobId}`);\n }\n}\n","import { APIResource } from \"../resource\";\n\nexport class Folders extends APIResource {\n /**\n * Create a new folder in the tenant's cloud storage.\n *\n * @param name - The name of the folder to create.\n * @example\n * ```typescript\n * await erixClient.storage.folders.create(\"Invoices\");\n * ```\n */\n async create<T = any>(name: string) {\n return this.post<T>(\"/api/saas/storage/folders\", { name });\n }\n\n /**\n * Delete a folder and its contents.\n */\n async delete<T = any>(folderPath: string) {\n return this.deleteRequest<T>(`/api/saas/storage/folders/${encodeURIComponent(folderPath)}`);\n }\n}\n\nexport class Files extends APIResource {\n /**\n * List files within a specific folder.\n *\n * @param folder - The folder name or path.\n * @param params - Optional year/month filters for organized storage.\n * @example\n * ```typescript\n * const files = await erixClient.storage.files.list(\"Invoices\", { year: \"2026\" });\n * ```\n */\n async list<T = any>(folder: string, params?: { year?: string; month?: string }) {\n return this.get<T>(`/api/saas/storage/files/${folder}`, { params } as any);\n }\n\n /**\n * Get a presigned upload URL for direct-to-cloud browser uploads.\n * This allows the client to upload files directly to R2/S3 without hitting the backend.\n *\n * @param params - Upload parameters (folder, filename, contentType).\n * @example\n * ```typescript\n * const { data } = await erixClient.storage.files.getUploadUrl({\n * folder: \"Invoices\",\n * filename: \"inv_1.pdf\",\n * contentType: \"application/pdf\"\n * });\n * // Now use data.url with a PUT request\n * ```\n */\n async getUploadUrl<T = any>(params: {\n folder: string;\n filename: string;\n contentType: string;\n }) {\n return this.post<T>(\"/api/saas/storage/upload-url\", params);\n }\n\n /**\n * Notify backend after a successful direct browser upload.\n */\n async confirmUpload<T = any>(params: { key: string; sizeBytes: number }) {\n return this.post<T>(\"/api/saas/storage/confirm-upload\", params);\n }\n\n /**\n * Get a presigned download URL for an R2 key.\n */\n async getDownloadUrl<T = any>(key: string) {\n return this.post<T>(\"/api/saas/storage/download-url\", { key });\n }\n\n /**\n * Delete a file by key.\n */\n async delete(key: string) {\n return this.deleteRequest(\"/api/saas/storage/files\", { params: { key } } as any);\n }\n}\n\nexport class Storage extends APIResource {\n public folders: Folders;\n public files: Files;\n\n constructor(client: any) {\n super(client);\n this.folders = new Folders(client);\n this.files = new Files(client);\n }\n\n /**\n * Get tenant storage usage and quota limitations.\n */\n async usage<T = any>() {\n return this.get<T>(\"/api/saas/storage/usage\");\n }\n}\n","import { APIError } from \"../error\";\n\nexport class WebhookSignatureError extends APIError {\n constructor(message: string) {\n super(message, 400, \"invalid_signature\");\n this.name = \"WebhookSignatureError\";\n }\n}\n\n/**\n * Validates and constructs webhook events sent by the ECODrIx platform.\n * Ensures the payload has not been tampered with.\n *\n * @example\n * ```typescript\n * import { ecod } from \"./services/ecodrix\";\n *\n * app.post(\"/api/webhooks\", async (req, res) => {\n * try {\n * const event = await ecod.webhooks.constructEvent(\n * req.rawBody,\n * req.headers[\"x-ecodrix-signature\"],\n * process.env.ECOD_WEBHOOK_SECRET\n * );\n * console.log(\"Verified event:\", event.type);\n * res.send({ received: true });\n * } catch (err) {\n * res.status(400).send(`Webhook Error: ${err.message}`);\n * }\n * });\n * ```\n */\nexport class Webhooks {\n /**\n * Cryptographically validates a webhook payload.\n * Note: This method dynamically imports Node's `crypto` module, meaning it will only execute gracefully in a Server environment.\n *\n * @param payload - The raw request body as a string or Buffer.\n * @param signature - The `x-ecodrix-signature` header value.\n * @param secret - The webhook signing secret for your tenant.\n * @returns The parsed JSON object of the event if the signature is valid.\n * @throws WebhookSignatureError if the validation fails.\n */\n public async constructEvent(\n payload: string | Buffer,\n signature: string | string[] | undefined,\n secret: string,\n ): Promise<any> {\n if (!signature) {\n throw new WebhookSignatureError(\"No webhook signature provided\");\n }\n\n let sig = Array.isArray(signature) ? signature[0] : signature;\n if (sig.startsWith(\"sha256=\")) {\n sig = sig.slice(7);\n }\n\n try {\n // Dynamic import ensures Isomorphic bundles (like Vite UI) don't crash on import,\n // and only throw if someone incorrectly tries to verify a webhook in the browser.\n const crypto = await import(\"node:crypto\");\n\n const hmac = crypto.createHmac(\"sha256\", secret);\n const digest = hmac.update(payload).digest(\"hex\");\n\n const isValid = crypto.timingSafeEqual(Buffer.from(digest), Buffer.from(sig));\n\n if (!isValid) {\n throw new WebhookSignatureError(\"Invalid webhook signature provided\");\n }\n\n return JSON.parse(payload.toString(\"utf8\"));\n } catch (error: any) {\n if (error instanceof WebhookSignatureError) {\n throw error;\n }\n throw new WebhookSignatureError(`Webhook payload parsing failed: ${error.message}`);\n }\n }\n}\n","import { APIResource } from \"../../resource\";\n\nexport interface CreateBroadcastParams {\n /** Optional name for the broadcast campaign */\n name?: string;\n /** Name of the Meta template to send */\n templateName: string;\n /** Language code (defaults to en_US) */\n templateLanguage?: string;\n /** List of recipients with their phone numbers and variable overrides */\n recipients: {\n phone: string;\n variables?: string[];\n }[];\n}\n\nexport class Broadcasts extends APIResource {\n /**\n * List past and active WhatsApp broadcast campaigns.\n *\n * @param params - Optional filter parameters (page, limit, status).\n * @returns Paginated list of broadcast records.\n * @example\n * ```typescript\n * const broadcasts = await erixClient.whatsapp.broadcasts.list({ limit: 10 });\n * ```\n */\n async list<T = any>(params?: Record<string, any>) {\n return this.get<T>(\"/api/saas/chat/broadcasts\", { params } as any);\n }\n\n /**\n * Retrieve full details and real-time stats for a specific broadcast campaign.\n *\n * @param id - The unique identifier of the broadcast.\n * @returns The broadcast record including sent/failed counts.\n * @example\n * ```typescript\n * const stats = await erixClient.whatsapp.broadcasts.retrieve(\"bc_123\");\n * console.log(`Success Rate: ${(stats.sentCount / stats.totalRecipients) * 100}%`);\n * ```\n */\n async retrieve<T = any>(id: string) {\n return this.get<T>(`/api/saas/chat/broadcasts/${id}`);\n }\n\n /**\n * Create a new broadcast campaign to send template messages to multiple recipients.\n *\n * @param params - Broadcast configuration (name, templateName, recipients).\n * @returns The newly created broadcast record.\n * @example\n * ```typescript\n * await erixClient.whatsapp.broadcasts.create({\n * name: \"Spring Sale\",\n * templateName: \"promo_code\",\n * recipients: [\n * { phone: \"+919876543210\", variables: [\"SAVE10\"] }\n * ]\n * });\n * ```\n */\n async create<T = any>(params: CreateBroadcastParams) {\n return this.post<T>(\"/api/saas/chat/broadcast\", params);\n }\n\n /**\n * Update broadcast metadata, such as its name or administrative status.\n *\n * @param id - The unique ID of the broadcast.\n * @param data - The fields to update (name, status).\n * @example\n * ```typescript\n * await erixClient.whatsapp.broadcasts.update(\"bc_123\", { name: \"Revised Spring Sale\" });\n * ```\n */\n async update<T = any>(id: string, data: { name?: string; status?: string }) {\n return this.patch<T>(`/api/saas/chat/broadcasts/${id}`, data);\n }\n\n /**\n * Delete a broadcast campaign record.\n * Note: This does not cancel messages already in flight but removes the record from the dashboard.\n *\n * @param id - The unique ID of the broadcast.\n * @example\n * ```typescript\n * await erixClient.whatsapp.broadcasts.delete(\"bc_123\");\n * ```\n */\n async delete<T = any>(id: string) {\n return this.deleteRequest<T>(`/api/saas/chat/broadcasts/${id}`);\n }\n}\n","import { APIResource } from \"../../resource\";\n\nexport interface ListParams {\n limit?: number;\n before?: string;\n after?: string;\n status?: string;\n}\n\nexport class Conversations extends APIResource {\n /**\n * List conversations for the tenant.\n * @deprecated Use `list` method from `ErixClient` instead.\n * @param params - List parameters.\n * @returns List of conversations.\n * @example\n * ```typescript\n * import { ErixClient } from \"erix-react\";\n * const erixClient = new ErixClient({ apiKey: \"YOUR_API_KEY\" });\n * const conversations = await erixClient.whatsapp.conversations.list();\n * ```\n */\n async list<T = any>(params?: ListParams) {\n return this.get<T>(\"/api/saas/chat/conversations\", { params } as any);\n }\n\n /**\n * Create a new conversation explicitly.\n *\n * @param params - Conversation details.\n * @example\n * ```typescript\n * const conversation = await erixClient.whatsapp.conversations.create({\n * phone: \"+919876543210\",\n * name: \"John Doe\"\n * });\n * ```\n */\n async create<T = any>(params: { phone: string; name?: string }) {\n return this.post<T>(\"/api/saas/chat/conversations\", params);\n }\n\n /**\n * Retrieve details of a specific conversation.\n *\n * @param conversationId - The unique ID of the conversation.\n * @example\n * ```typescript\n * const conversation = await erixClient.whatsapp.conversations.retrieve(\"conv_123\");\n * ```\n */\n async retrieve<T = any>(conversationId: string) {\n return this.get<T>(`/api/saas/chat/conversations/${conversationId}`);\n }\n\n /**\n * Get messages for a specific conversation.\n *\n * @param conversationId - The unique ID of the conversation.\n * @param params - Pagination and filter parameters.\n * @example\n * ```typescript\n * const messages = await erixClient.whatsapp.conversations.messages(\"conv_123\", { limit: 50 });\n * ```\n */\n async messages<T = any>(conversationId: string, params?: ListParams) {\n return this.get<T>(`/api/saas/chat/conversations/${conversationId}/messages`, {\n params,\n } as any);\n }\n\n /**\n * Link a conversation to a lead in the CRM.\n *\n * @param conversationId - The unique ID of the conversation.\n * @param leadId - The unique ID of the lead to link.\n * @param leadData - Optional additional lead metadata.\n * @example\n * ```typescript\n * await erixClient.whatsapp.conversations.linkLead(\"conv_123\", \"lead_456\");\n * ```\n */\n async linkLead<T = any>(conversationId: string, leadId: string, leadData?: any) {\n return this.post<T>(`/api/saas/chat/conversations/${conversationId}/link-lead`, {\n leadId,\n leadData,\n });\n }\n\n /**\n * Mark a conversation as read (clear unread count).\n *\n * @param conversationId - The unique ID of the conversation.\n * @example\n * ```typescript\n * await erixClient.whatsapp.conversations.markRead(\"conv_123\");\n * ```\n */\n async markRead<T = any>(conversationId: string) {\n return this.post<T>(`/api/saas/chat/conversations/${conversationId}/read`, {});\n }\n\n /**\n * Delete a conversation.\n *\n * @param conversationId - The unique ID of the conversation.\n * @example\n * ```typescript\n * await erixClient.whatsapp.conversations.delete(\"conv_123\");\n * ```\n */\n async delete(conversationId: string) {\n return this.deleteRequest(`/api/saas/chat/conversations/${conversationId}`);\n }\n\n /**\n * Bulk delete conversations.\n *\n * @param ids - Array of conversation IDs to delete.\n * @example\n * ```typescript\n * await erixClient.whatsapp.conversations.bulkDelete([\"conv_1\", \"conv_2\"]);\n * ```\n */\n async bulkDelete<T = any>(ids: string[]) {\n return this.post<T>(\"/api/saas/chat/conversations/bulk-delete\", { ids });\n }\n}\n","import { APIResource } from \"../../resource\";\n\n/**\n * Parameters for sending a free-form WhatsApp message.\n */\nexport interface SendMessageParams {\n /**\n * Recipient's phone number in E.164 format.\n * @example \"+919876543210\"\n */\n to?: string;\n /**\n * The unique ID of the conversation. If supplied, `to` is resolved automatically.\n */\n conversationId?: string;\n /** Plain text body of the message. */\n text?: string;\n /** Public URL of the media asset to send. */\n mediaUrl?: string;\n /** MIME category of the media. */\n mediaType?: \"image\" | \"video\" | \"audio\" | \"document\";\n /** The `messageId` of the message to reply to (quoted replies). */\n replyToId?: string;\n /** Filename shown to the recipient (required for `document` type). */\n filename?: string;\n /** Arbitrary metadata stored with the message record. */\n metadata?: Record<string, any>;\n /** Template name for template messages. */\n templateName?: string;\n /** Template language for template messages. */\n templateLanguage?: string;\n /** Alternative language parameter. */\n language?: string;\n /** Template variables. */\n variables?: string[];\n}\n\n/**\n * Parameters for sending a pre-approved WhatsApp Business template.\n */\nexport interface SendTemplateParams {\n /**\n * Recipient's phone number in E.164 format.\n * @example \"+919876543210\"\n */\n to?: string;\n /**\n * The unique ID of the conversation.\n */\n conversationId?: string;\n /** The exact template name as approved in Meta Business Manager. */\n templateName: string;\n /**\n * BCP-47 language code for the template.\n * @default \"en_US\"\n */\n language?: string;\n /**\n * Ordered array of variable substitutions for template placeholders.\n * @example [\"Alice\", \"10 April 2026\", \"10:00 AM\"]\n */\n variables?: string[];\n /** Optional header media URL (for templates with media headers). */\n mediaUrl?: string;\n /** Media type for the header (e.g. \"image\", \"document\"). */\n mediaType?: string;\n /** User ID of the agent sending the message. */\n userId?: string;\n /** Optional filename for media headers. */\n filename?: string;\n /** Template language for template messages. */\n templateLanguage?: string;\n}\n\n/**\n * WhatsApp outbound messaging resource.\n *\n * Access via `ecod.whatsapp.messages`.\n *\n * @example\n * ```typescript\n * await ecod.whatsapp.messages.send({\n * to: \"+919876543210\",\n * text: \"Your appointment is confirmed!\",\n * });\n * ```\n */\n/**\n * Resolved media metadata returned by any upload endpoint.\n * `variants` is only present for raster images (JPEG, PNG, WebP, AVIF, GIF).\n */\nexport interface ChatMediaMeta {\n /** Raw CDN URL — always present, all media types */\n url: string;\n /** Categorical type — \"image\" | \"video\" | \"audio\" | \"document\" */\n type: \"image\" | \"video\" | \"audio\" | \"document\";\n /** Cloudflare-optimised variant URLs. Only present for raster images. */\n variants?: {\n /** 150px WebP — use for list thumbnails and chat bubbles */\n thumb: string;\n /** 600px WebP — use for modal previews */\n medium: string;\n /** 1200px WebP — use for hero or full-screen views */\n full: string;\n /** Original CDN URL, no transformation */\n raw: string;\n };\n /** Storage key within the tenant bucket */\n key?: string;\n /** Original filename */\n fileName?: string;\n}\n\nexport class Messages extends APIResource {\n /**\n * Send a free-text or media message to a WhatsApp number.\n *\n * For text-only messages, supply `text`. For media, supply `mediaUrl`\n * and `mediaType`. Both can be combined in a single message.\n *\n * @param params - Message parameters including recipient, text, and media.\n * @returns The created message record from the database.\n *\n * @example Send a simple text message\n * ```typescript\n * await erixClient.whatsapp.messages.send({\n * to: \"+919876543210\",\n * text: \"Hello from Ecodrix!\",\n * });\n * ```\n *\n * @example Send an image with a caption\n * ```typescript\n * await erixClient.whatsapp.messages.send({\n * to: \"+919876543210\",\n * text: \"Check out this flyer\",\n * mediaUrl: \"https://example.com/flyer.jpg\",\n * mediaType: \"image\",\n * });\n * ```\n */\n async send<T = any>(params: SendMessageParams) {\n return this.post<T>(\"/api/saas/chat/send\", params);\n }\n\n /**\n * Send a pre-approved WhatsApp Business template message.\n *\n * Templates must be approved in Meta Business Manager before they can be sent.\n * Variable placeholders (e.g., {{1}}, {{2}}) are replaced with values from the\n * `variables` array in order.\n *\n * @param params - Template message configuration (name, language, variables).\n * @returns The created message record.\n *\n * @example\n * ```typescript\n * await erixClient.whatsapp.messages.sendTemplate({\n * to: \"+919876543210\",\n * templateName: \"welcome_user\",\n * language: \"en_US\",\n * variables: [\"Alice\"], // Replaces {{1}} in template\n * });\n * ```\n */\n async sendTemplate<T = any>(params: SendTemplateParams) {\n return this.post<T>(\"/api/saas/chat/send\", {\n ...params,\n templateLanguage: params.language || params.templateLanguage || \"en_US\",\n });\n }\n\n /**\n * Star or unstar a message.\n *\n * @param messageId - The ID of the message.\n * @param isStarred - Boolean indicating whether to star or unstar.\n */\n async star<T = any>(messageId: string, isStarred: boolean) {\n return this.post<T>(`/api/saas/chat/messages/${messageId}/star`, {\n isStarred,\n });\n }\n\n /**\n * React to a message with an emoji.\n *\n * @param messageId - The ID of the message.\n * @param reaction - The emoji (e.g. \"👍\") to react with, or empty string to remove.\n */\n async react<T = any>(messageId: string, reaction: string) {\n return this.post<T>(`/api/saas/chat/messages/${messageId}/react`, {\n reaction,\n });\n }\n\n /**\n * Mark all messages in a conversation as read (double-tick).\n *\n * @param conversationId - The conversation to mark as read.\n *\n * @example\n * ```typescript\n * await ecod.whatsapp.messages.markRead(\"conv_64abc...\");\n * ```\n */\n async markRead(conversationId: string) {\n return this.post(`/api/saas/chat/conversations/${conversationId}/read`);\n }\n\n /**\n * Upload a media file for WhatsApp chat.\n *\n * Works with any file type — image, video, audio, or document.\n * For raster images the response includes Cloudflare-optimised `variants`\n * (thumb 150px, medium 600px, full 1200px). Non-image types return only `url`.\n *\n * @param file - The file to upload (File, Blob, or Buffer).\n * @returns Full media metadata `{ url, type, variants?, key, fileName }`.\n *\n * @example\n * ```typescript\n * const file = input.files[0];\n * const { data } = await ecod.whatsapp.messages.upload(file);\n * // For images: data.variants.thumb → 150px WebP from Cloudflare\n * // For video/audio: use data.url directly in <video> or <audio>\n * ```\n */\n async upload(file: any): Promise<{ success: boolean; data: ChatMediaMeta }> {\n const formData = new FormData();\n formData.append(\"file\", file);\n\n return this.post<{ success: boolean; data: ChatMediaMeta }>(\"/api/saas/chat/upload\", formData, {\n headers: {\n \"Content-Type\": \"multipart/form-data\",\n },\n });\n }\n}\n","import { APIResource } from \"../../resource\";\nimport type { ResourceManifest } from \"../../types/metadata\";\n\nexport interface TemplateMapping {\n mappings: any[];\n onEmptyVariable: string;\n}\n\nexport class Templates extends APIResource {\n /**\n * List all WhatsApp message templates in the tenant database.\n *\n * @param params - Optional filter parameters (status, mappingStatus, channel).\n * @returns List of message templates.\n * @example\n * ```typescript\n * const templates = await erixClient.whatsapp.templates.list({ status: \"APPROVED\" });\n * ```\n */\n async list<T = any>(params?: {\n status?: string;\n mappingStatus?: string;\n channel?: string;\n }) {\n return this.get<T>(\"/api/saas/chat/templates\", { params } as any);\n }\n\n /**\n * Synchronize templates from the Meta WhatsApp Business API.\n * This updates the local database with the latest template status and content from Meta.\n *\n * @returns Success status of the sync operation.\n * @example\n * ```typescript\n * await erixClient.whatsapp.templates.sync();\n * ```\n */\n async sync<T = any>() {\n return this.post<T>(\"/api/saas/chat/templates/sync\", {});\n }\n\n /**\n * Retrieve details of a specific WhatsApp template.\n *\n * @param templateIdentifier - The name or ID of the template.\n * @returns Detailed template object including components and status.\n * @example\n * ```typescript\n * const template = await erixClient.whatsapp.templates.retrieve(\"welcome_message\");\n * ```\n */\n async retrieve<T = any>(templateIdentifier: string) {\n return this.get<T>(`/api/saas/chat/templates/${encodeURIComponent(templateIdentifier)}`);\n }\n\n /**\n * Create a new WhatsApp template manually (Draft).\n *\n * @param payload - Template configuration (name, category, language, components).\n * @example\n * ```typescript\n * await erixClient.whatsapp.templates.create({\n * name: \"new_promotion\",\n * category: \"MARKETING\",\n * language: \"en_US\",\n * components: [...]\n * });\n * ```\n */\n async create<T = any>(payload: any) {\n return this.post<T>(\"/api/saas/chat/templates\", payload);\n }\n\n /**\n * Update an existing WhatsApp template.\n *\n * @param templateId - The unique ID of the template.\n * @param payload - Updated template configuration.\n */\n async update<T = any>(templateId: string, payload: any) {\n return this.put<T>(`/api/saas/chat/templates/${templateId}`, payload);\n }\n\n /**\n * Delete a WhatsApp template from both the local database and Meta (if specified).\n *\n * @param templateName - The name of the template to delete.\n * @param force - If true, attempts to delete from Meta API as well.\n * @example\n * ```typescript\n * await erixClient.whatsapp.templates.deleteTemplate(\"old_template\", true);\n * ```\n */\n async deleteTemplate<T = any>(templateName: string, force?: boolean) {\n return this.deleteRequest<T>(\n `/api/saas/chat/templates/${encodeURIComponent(templateName)}${force ? \"?force=true\" : \"\"}`,\n );\n }\n\n /**\n * List available configuration options for variable mapping.\n *\n * @example\n * ```typescript\n * const config = await erixClient.whatsapp.templates.mappingConfig();\n * ```\n */\n async mappingConfig<T = any>() {\n return this.get<T>(\"/api/saas/chat/templates/mapping/config\");\n }\n\n /**\n * List CRM collections available for variable mapping (Leads, Deals, etc.).\n */\n async collections<T = any>() {\n return this.get<T>(\"/api/saas/chat/templates/collections\");\n }\n\n /**\n * List fields for a specific CRM collection to be used in mapping.\n *\n * @param collectionName - The name of the CRM collection.\n */\n async collectionFields<T = any>(collectionName: string) {\n return this.get<T>(\n `/api/saas/chat/templates/collections/${encodeURIComponent(collectionName)}/fields`,\n );\n }\n\n /**\n * Update variable mappings for a template to automate personalization.\n *\n * @param templateName - Name of the template.\n * @param payload - Mapping definitions.\n */\n async updateMapping<T = any>(templateName: string, payload: TemplateMapping) {\n return this.put<T>(\n `/api/saas/chat/templates/${encodeURIComponent(templateName)}/mapping`,\n payload,\n );\n }\n\n /**\n * Validate if a template is ready for automated sending based on its mappings.\n */\n async validate<T = any>(templateName: string) {\n return this.get<T>(`/api/saas/chat/templates/${encodeURIComponent(templateName)}/validate`);\n }\n\n /**\n * Preview a template resolution with sample data.\n *\n * @param templateName - Name of the template.\n * @param context - Lead data or variable overrides for preview.\n * @example\n * ```typescript\n * const preview = await erixClient.whatsapp.templates.preview(\"welcome\", {\n * lead: { firstName: \"Alice\" }\n * });\n * ```\n */\n async preview<T = any>(templateName: string, context: { lead?: any; vars?: any }) {\n return this.post<T>(`/api/saas/chat/templates/${encodeURIComponent(templateName)}/preview`, {\n context,\n });\n }\n\n /**\n * Introspect a template and provide a manifest of its required variables.\n *\n * This is used by Erix React to build dynamic \"Mapping Forms\" where users\n * can connect CRM fields to WhatsApp variables.\n *\n * @param templateIdentifier - The name or ID of the template.\n */\n async getVariableManifest(templateIdentifier: string): Promise<ResourceManifest> {\n const template: any = await this.retrieve(templateIdentifier);\n const components = Array.isArray(template.data?.components) ? template.data.components : [];\n\n const fields: any[] = [];\n\n for (const comp of components) {\n // Look for {{n}} pattern in text components\n if (comp.text) {\n const vars = comp.text.match(/{{(\\d+)}}/g);\n if (vars) {\n for (const v of vars) {\n const index = v.replace(/{{|}}/g, \"\");\n fields.push({\n key: `var_${index}`,\n label: `${comp.type} Var {{${index}}}`,\n type: \"string\",\n required: true,\n group: comp.type,\n description: `Variable placeholder in template ${comp.type}`,\n });\n }\n }\n }\n }\n\n return {\n name: `Template variables: ${template.data?.name || templateIdentifier}`,\n fields,\n uiHints: {\n icon: \"Variables\",\n primaryColor: \"#059669\",\n },\n };\n }\n\n /**\n * Check which automations or sequences are currently using this template.\n */\n async checkUsage<T = any>(templateName: string) {\n return this.get<T>(`/api/saas/chat/templates/${encodeURIComponent(templateName)}/usage`);\n }\n}\n","import type { AxiosInstance } from \"axios\";\nimport { APIResource } from \"../../resource\";\nimport { Broadcasts } from \"./broadcasts\";\nimport { Conversations } from \"./conversations\";\nimport { Messages } from \"./messages\";\nimport { Templates } from \"./templates\";\n\nexport interface SendTemplatePayload {\n /** Phone number in E.164 format. */\n phone: string;\n /** Name of the pre-approved WhatsApp template. */\n templateName: string;\n /** Language code (defaults to \"en\"). */\n languageCode?: string;\n /** Key-value pairs matching variables in your template (e.g., {{1}}, {{2}}). */\n variables?: Record<string, string>;\n /** Explicitly resolved variables if bypassing the internal resolution engine. */\n resolvedVariables?: any[];\n}\n\nexport class WhatsApp extends APIResource {\n public messages: Messages;\n public conversations: Conversations;\n public broadcasts: Broadcasts;\n public templates: Templates;\n\n constructor(client: AxiosInstance) {\n super(client);\n this.messages = new Messages(client);\n this.conversations = new Conversations(client);\n this.broadcasts = new Broadcasts(client);\n this.templates = new Templates(client);\n }\n\n /**\n * Upload an asset directly to chat storage.\n */\n async upload<T = any>(file: Blob | Buffer | File | any, filename: string) {\n const form = new FormData();\n form.append(\"file\", file, filename);\n return this.post<T>(\"/api/saas/chat/upload\", form, {\n headers:\n typeof (form as any).getHeaders === \"function\" ? (form as any).getHeaders() : undefined,\n });\n }\n\n /**\n * Dispatch a WhatsApp template message directly to a specific phone number.\n * Bypasses the automation queue for immediate high-priority delivery.\n *\n * @param payload - The template dispatch payload.\n * @returns Information about the dispatched message.\n */\n async sendTemplate(payload: SendTemplatePayload): Promise<{\n success: boolean;\n messageId?: string;\n templateName?: string;\n resolvedVariables?: any[];\n }> {\n return this.post<{\n success: boolean;\n messageId?: string;\n templateName?: string;\n resolvedVariables?: any[];\n }>(\"/api/saas/marketing/whatsapp/send-template\", payload);\n }\n}\n","import { APIResource } from \"../resource\";\n\nexport class Agency extends APIResource {\n /**\n * List all available blueprints.\n */\n async listBlueprints<T = any>() {\n return this.get<T>(\"/api/agency/blueprints\");\n }\n\n /**\n * Create a new blueprint configuration (\"Gold Standard\").\n */\n async createBlueprint<T = any>(payload: any) {\n return this.post<T>(\"/api/agency/blueprints\", payload);\n }\n\n /**\n * Deploy a blueprint to a specific tenant client code.\n */\n async deployBlueprint<T = any>(payload: { clientCode: string; blueprintId: string }) {\n return this.post<T>(\"/api/agency/blueprints/deploy\", payload);\n }\n\n /**\n * Get aggregate portfolio statistics for an agency.\n */\n async getPortfolioStats<T = any>(agencyCode: string) {\n return this.get<T>(`/api/agency/portfolio/${agencyCode}/stats`);\n }\n\n /**\n * Get proactive health report for an agency portfolio.\n */\n async getPortfolioHealth<T = any>(agencyCode: string) {\n return this.get<T>(`/api/agency/portfolio/${agencyCode}/health`);\n }\n\n /**\n * View consumption usage for a specific client code.\n */\n async getUsage<T = any>(clientCode: string) {\n return this.get<T>(`/api/agency/usage/${clientCode}`);\n }\n\n /**\n * List staff members under a specific agency code.\n */\n async listStaff<T = any>(agencyCode: string) {\n return this.get<T>(`/api/agency/staff/${agencyCode}`);\n }\n\n /**\n * Create a new staff member for an agency.\n */\n async createStaff<T = any>(payload: any) {\n return this.post<T>(\"/api/agency/staff\", payload);\n }\n}\n","import { APIResource } from \"../resource\";\n\nexport class Clients extends APIResource {\n /**\n * List all clients in the ecosystem.\n */\n async list<T = any>() {\n return this.get<T>(\"/api/services/clients\");\n }\n\n /**\n * Get client count and auto-generate a unique code.\n */\n async getCountAndGenerateCode<T = any>() {\n return this.get<T>(\"/api/services/clients/count\");\n }\n\n /**\n * Retrieve a single client by client code.\n */\n async retrieve<T = any>(clientCode: string) {\n return this.get<T>(`/api/services/clients/${clientCode}`);\n }\n\n /**\n * Get API Key for a specific client (Admin Only).\n */\n async getApiKey<T = any>(clientCode: string) {\n return this.get<T>(`/api/services/clients/${clientCode}/api-key`);\n }\n\n /**\n * Generate or rotate API Key for a specific client (Admin Only).\n */\n async rotateApiKey<T = any>(clientCode: string) {\n return this.post<T>(`/api/services/clients/${clientCode}/api-key`, {});\n }\n\n /**\n * Create a new client identity and provision initial resources.\n */\n async create<T = any>(payload: {\n name: string;\n clientCode: string;\n business?: any;\n plan?: any;\n }) {\n return this.post<T>(\"/api/services/clients\", payload);\n }\n\n /**\n * Get active service configuration for a specific client.\n */\n async getConfig<T = any>(clientCode: string) {\n return this.get<T>(`/api/services/clients/${clientCode}/config`);\n }\n\n /**\n * Update active service configuration for a specific client.\n */\n async updateConfig<T = any>(clientCode: string, payload: any) {\n return this.patch<T>(`/api/services/clients/${clientCode}/config`, payload);\n }\n\n /**\n * Get decrypted secrets for a specific client.\n */\n async getSecrets<T = any>(clientCode: string) {\n return this.get<T>(`/api/services/clients/${clientCode}/secrets`);\n }\n\n /**\n * Set secrets for a specific client.\n */\n async updateSecrets<T = any>(clientCode: string, payload: any) {\n return this.post<T>(`/api/services/clients/${clientCode}/secrets`, payload);\n }\n\n /**\n * Completely replace secrets for a specific client.\n */\n async replaceSecrets<T = any>(clientCode: string, payload: any) {\n return this.put<T>(`/api/services/clients/${clientCode}/secrets`, payload);\n }\n\n /**\n * Partially update secrets for a specific client.\n */\n async patchSecrets<T = any>(clientCode: string, payload: any) {\n return this.patch<T>(`/api/services/clients/${clientCode}/secrets`, payload);\n }\n\n /**\n * Retrieve Data Source connection metadata.\n */\n async getDataSource<T = any>(clientCode: string) {\n return this.get<T>(`/api/services/clients/${clientCode}/datasource`);\n }\n\n /**\n * Configure Data Source metadata.\n */\n async manageDataSource<T = any>(clientCode: string, payload: any) {\n return this.post<T>(`/api/services/clients/${clientCode}/datasource`, payload);\n }\n\n /**\n * Update Client Identity and perform cascading updates if required.\n */\n async updateIdentity<T = any>(id: string, payload: any) {\n return this.patch<T>(`/api/services/clients/${id}/identity`, payload);\n }\n\n /**\n * Initiate Google Re-authentication for OAuth tokens.\n */\n async googleReauth<T = any>(clientCode: string, payload: { authCode?: string } = {}) {\n return this.post<T>(`/api/services/clients/${clientCode}/google/reauth`, payload);\n }\n\n /**\n * Delete a client and perform cascading cleanup.\n */\n async delete<T = any>(id: string) {\n return this.deleteRequest<T>(`/api/services/clients/${id}`);\n }\n}\n\nexport class Blogs extends APIResource {\n /**\n * Retrieve public corporate blogs/news.\n */\n async list<T = any>() {\n return this.get<T>(\"/api/services/blogs\");\n }\n}\n\nexport class GlobalLeads extends APIResource {\n /**\n * Add a corporate lead capture entry.\n */\n async add<T = any>(payload: any) {\n return this.post<T>(\"/api/services/add-lead\", payload);\n }\n}\n\nexport class Services extends APIResource {\n public clients: Clients;\n public blogs: Blogs;\n public globalLeads: GlobalLeads;\n\n constructor(client: any) {\n super(client);\n this.clients = new Clients(client);\n this.blogs = new Blogs(client);\n this.globalLeads = new GlobalLeads(client);\n }\n}\n","import { APIResource } from \"../resource\";\n\nexport class EmailConfig extends APIResource {\n /**\n * Retrieve current email provider configuration and domain verification statuses.\n */\n async getConfig<T = any>() {\n return this.get<T>(\"/api/settings/email\");\n }\n\n /**\n * Switch the active email provider.\n */\n async switchProvider<T = any>(provider: string) {\n return this.post<T>(\"/api/settings/email/provider\", { provider });\n }\n\n /**\n * Provide explicit SMTP credentials and connection preferences.\n */\n async saveSmtp<T = any>(payload: any) {\n return this.post<T>(\"/api/settings/email/smtp\", payload);\n }\n\n /**\n * Initialize a new domain for SES identity verification.\n */\n async initDomainVerification<T = any>(domain: string) {\n return this.post<T>(\"/api/settings/email/ses/domain\", { domain });\n }\n\n /**\n * Confirm \"From\" details and finalize configuration payload.\n */\n async saveEmailConfig<T = any>(payload: {\n fromName: string;\n fromEmail: string;\n replyTo?: string;\n }) {\n return this.post<T>(\"/api/settings/email/ses/config\", payload);\n }\n\n /**\n * Check status of AWS SES domain validation DNS records.\n */\n async checkSesVerification<T = any>() {\n return this.get<T>(\"/api/settings/email/ses/verify\");\n }\n\n /**\n * Remove a verified SES domain identity and clean up local secrets.\n */\n async removeSesIdentity<T = any>() {\n return this.deleteRequest<T>(\"/api/settings/email/ses/domain\");\n }\n\n /**\n * Send a test email to verify infrastructure is correctly bound.\n */\n async sendTest<T = any>(toEmail: string) {\n return this.post<T>(\"/api/settings/email/test\", { toEmail });\n }\n\n /**\n * Define customized global email footers, limits, and specific campaign policies.\n */\n async saveAdvancedConfig<T = any>(payload: any) {\n return this.post<T>(\"/api/settings/email/advanced\", payload);\n }\n\n /**\n * Retrieve email configuration health properties including bounce limits metrics.\n */\n async getHealth<T = any>() {\n return this.get<T>(\"/api/settings/email/health\");\n }\n\n /**\n * Upgrade configurations dynamically to add DMARC enforcement records.\n */\n async fixDmarc<T = any>() {\n return this.post<T>(\"/api/settings/email/ses/fix-dmarc\", {});\n }\n\n /**\n * Discover internally available providers constants metadata.\n */\n async listProviders<T = any>() {\n return this.get<T>(\"/api/settings/email/providers\");\n }\n}\n\nexport class Settings extends APIResource {\n public email: EmailConfig;\n\n constructor(client: any) {\n super(client);\n this.email = new EmailConfig(client);\n }\n}\n","import { APIResource } from \"../resource\";\n\nexport interface CorsOriginCreatePayload {\n url: string;\n name?: string;\n allowedHeaders?: string[];\n allowedMethods?: string[];\n}\n\nexport interface CorsOriginUpdatePayload {\n url?: string;\n name?: string;\n allowedHeaders?: string[];\n allowedMethods?: string[];\n isActive?: boolean;\n}\n\nexport class Cors extends APIResource {\n /**\n * List all dynamic cross-origin policies.\n */\n async list<T = any>() {\n return this.get<T>(\"/api/saas/cors\");\n }\n\n /**\n * Register a new cross-origin client for the SaaS API network dynamically.\n */\n async create<T = any>(payload: CorsOriginCreatePayload) {\n return this.post<T>(\"/api/saas/cors\", payload);\n }\n\n /**\n * Adjust active states or configurations for an existing origin policy.\n */\n async update<T = any>(id: string, payload: CorsOriginUpdatePayload) {\n return this.patch<T>(`/api/saas/cors/${id}`, payload);\n }\n\n /**\n * Irreversibly drop support for a cross-origin client URL policy permanently.\n */\n async delete<T = any>(id: string) {\n return this.deleteRequest<T>(`/api/saas/cors/${id}`);\n }\n}\n","export { Ecodrix, type EcodrixOptions } from \"./core\";\nexport * from \"./types/metadata\";\nexport * from \"./error\";\nexport * from \"./resources/crm/activities\";\nexport * from \"./resources/crm/analytics\";\nexport * from \"./resources/crm/automationDashboard\";\nexport * from \"./resources/crm/automations\";\nexport * from \"./resources/crm/index\";\nexport * from \"./resources/crm/leads\";\nexport * from \"./resources/crm/payments\";\nexport * from \"./resources/crm/pipelines\";\nexport * from \"./resources/crm/scoring\";\nexport * from \"./resources/crm/sequences\";\nexport * from \"./resources/email\";\nexport * from \"./resources/events\";\nexport * from \"./resources/health\";\nexport * from \"./resources/logs\";\nexport * from \"./resources/marketing\";\nexport * from \"./resources/media\";\nexport * from \"./resources/meet\";\nexport * from \"./resources/notifications\";\nexport * from \"./resources/queue\";\nexport * from \"./resources/storage\";\nexport * from \"./resources/webhooks\";\nexport * from \"./resources/whatsapp/broadcasts\";\nexport * from \"./resources/whatsapp/conversations\";\n// Resource Type Exports\nexport * from \"./resources/whatsapp/index\";\nexport * from \"./resources/whatsapp/messages\";\nexport * from \"./resources/whatsapp/templates\";\n\n// Export the main client also as default for better ergonomics\nimport { Ecodrix } from \"./core\";\nexport default Ecodrix;\n\nexport * from \"./resources/agency\";\nexport * from \"./resources/services\";\nexport * from \"./resources/settings\";\nexport * from \"./resources/cors\";\n"],"mappings":"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","names":["axios","axiosRetry","io","EcodrixError","message","APIError","status","code","__publicField","AuthenticationError","RateLimitError","APIResource","client","url","data","options","config","error","__spreadValues","__spreadProps","_a","_b","_c","APIError","Notes","APIResource","leadId","params","noteId","content","isPinned","Activities","client","__publicField","__spreadValues","Analytics","APIResource","params","pipelineId","AutomationDashboard","APIResource","params","logId","Automations","APIResource","payload","ruleId","ruleIds","leadId","params","enrollmentId","runId","eventName","Leads","APIResource","params","customFieldsRes","customFields","systemFields","mappedCustom","f","leads","chunkSize","results","i","chunkPromises","lead","chunkResults","res","queryParams","__spreadValues","__asyncGenerator","currentPage","hasMore","response","__await","__spreadProps","items","item","leadId","phone","refKey","refValue","stageId","outcome","reason","options","metadata","noteId","ids","Payments","APIResource","payload","Pipelines","APIResource","pipelineId","_a","_b","pipeline","stages","s","payload","newName","params","orderArray","stageId","moveLeadsToStageId","Scoring","APIResource","payload","leadId","Sequences","APIResource","payload","enrollmentId","leadId","CRM","client","__publicField","Leads","Pipelines","Activities","Analytics","Automations","Sequences","Scoring","Payments","AutomationDashboard","Email","APIResource","payload","to","query","id","data","force","params","EmailResource","EventsResource","APIResource","payload","name","names","id","Health","APIResource","jobId","Logs","APIResource","query","id","Emails","APIResource","params","to","Campaigns","payload","campaignId","WhatsAppMarketing","Marketing","client","__publicField","axios","Media","APIResource","name","folder","params","key","file","options","response","uploadUrl","axios","sizeBytes","MediaResource","Meetings","APIResource","data","params","meetingId","Notifications","APIResource","params","logId","notificationId","Queue","APIResource","jobId","Folders","APIResource","name","folderPath","Files","folder","params","key","Storage","client","__publicField","WebhookSignatureError","APIError","message","Webhooks","payload","signature","secret","sig","crypto","digest","error","Broadcasts","APIResource","params","id","data","Conversations","APIResource","params","conversationId","leadId","leadData","ids","Messages","APIResource","params","__spreadProps","__spreadValues","messageId","isStarred","reaction","conversationId","file","formData","Templates","APIResource","params","templateIdentifier","payload","templateId","templateName","force","collectionName","context","_a","_b","template","components","fields","comp","vars","v","index","WhatsApp","APIResource","client","__publicField","Messages","Conversations","Broadcasts","Templates","file","filename","form","payload","Agency","APIResource","payload","agencyCode","clientCode","Clients","APIResource","clientCode","payload","id","Blogs","GlobalLeads","Services","client","__publicField","EmailConfig","APIResource","provider","payload","domain","toEmail","Settings","client","__publicField","Cors","APIResource","payload","id","ECOD_API_BASE","Ecodrix","options","__publicField","_a","_b","_c","_d","_e","AuthenticationError","baseUrl","socketUrl","isBrowser","runtime","os","headers","axios","axiosRetry","error","retryCount","requestConfig","WhatsApp","CRM","Media","Meetings","Notifications","Email","Logs","EventsResource","Webhooks","Storage","Marketing","Health","Queue","Agency","Services","Settings","Cors","io","footprint","roomId","clientCode","event","callback","method","path","data","params","APIError","index_default","Ecodrix"]}
1
+ {"version":3,"sources":["../../../src/core.ts","../../../src/error.ts","../../../src/resource.ts","../../../src/resources/crm/activities.ts","../../../src/resources/crm/analytics.ts","../../../src/resources/crm/automationDashboard.ts","../../../src/resources/crm/automations.ts","../../../src/resources/crm/leads.ts","../../../src/resources/crm/payments.ts","../../../src/resources/crm/pipelines.ts","../../../src/resources/crm/scoring.ts","../../../src/resources/crm/sequences.ts","../../../src/resources/crm/index.ts","../../../src/resources/email.ts","../../../src/resources/events.ts","../../../src/resources/health.ts","../../../src/resources/logs.ts","../../../src/resources/marketing.ts","../../../src/resources/media.ts","../../../src/resources/meet.ts","../../../src/resources/notifications.ts","../../../src/resources/queue.ts","../../../src/resources/storage.ts","../../../src/resources/webhooks.ts","../../../src/resources/whatsapp/broadcasts.ts","../../../src/resources/whatsapp/conversations.ts","../../../src/resources/whatsapp/messages.ts","../../../src/resources/whatsapp/templates.ts","../../../src/resources/whatsapp/index.ts","../../../src/resources/agency.ts","../../../src/resources/services.ts","../../../src/resources/settings.ts","../../../src/resources/cors.ts","../../../src/index.ts"],"sourcesContent":["import axios, { type AxiosInstance, type Method } from \"axios\";\nimport axiosRetry from \"axios-retry\";\nimport { type Socket, io } from \"socket.io-client\";\nimport { APIError, AuthenticationError } from \"./error\";\nimport { CRM } from \"./resources/crm\";\nimport { Email } from \"./resources/email\";\nimport { EventsResource } from \"./resources/events\";\nimport { Health } from \"./resources/health\";\nimport { Logs } from \"./resources/logs\";\nimport { Marketing } from \"./resources/marketing\";\nimport { Media } from \"./resources/media\";\nimport { Meetings } from \"./resources/meet\";\nimport { Notifications } from \"./resources/notifications\";\nimport { Queue } from \"./resources/queue\";\nimport { Storage } from \"./resources/storage\";\nimport { Webhooks } from \"./resources/webhooks\";\nimport { WhatsApp } from \"./resources/whatsapp\";\nimport { Agency } from \"./resources/agency\";\nimport { Services } from \"./resources/services\";\nimport { Settings } from \"./resources/settings\";\nimport { Cors } from \"./resources/cors\";\n\ndeclare const process: any;\n\n/** @internal The canonical ECODrIx backend URL — not exposed to SDK consumers. */\nconst ECOD_API_BASE = \"https://api.ecodrix.com\";\n\n/**\n * Configuration options for the Ecodrix client.\n *\n * Minimum required: `apiKey` and `clientCode`.\n * The backend URL is managed internally and should not need to be changed.\n */\nexport interface EcodrixOptions {\n /**\n * Your ECODrIx Platform API key.\n * Obtain this from the ECODrIx dashboard under Settings → API Keys.\n * @example \"ecod_live_sk_...\"\n */\n apiKey: string;\n\n /**\n * Your tenant ID (Client Code).\n * This scopes all API requests to your specific organisation.\n * @example \"ERIX_CLNT_JHBJHF\"\n */\n clientCode?: string;\n\n /**\n * Optional Core API Key for deep system-level bypasses.\n * Only used by elevated internal SaaS modules like Nirvisham.\n */\n coreApiKey?: string;\n\n /**\n * @internal Override Socket.io URL for testing/staging.\n * Not documented — internal use only.\n */\n socketUrl?: string;\n\n /**\n * @internal Override the backend API URL. Used by the CLI and internal tests only.\n * Host projects must never set this — the production URL is hardcoded internally.\n */\n baseUrl?: string;\n}\n\n/**\n * The primary entry point for the ECODrIx SDK.\n *\n * Initialise once with your credentials and use the namespaced resources\n * to interact with every part of the platform.\n *\n * @example\n * ```typescript\n * import { Ecodrix } from \"@ecodrix/erix-api\";\n *\n * const ecod = new Ecodrix({\n * apiKey: process.env.ECOD_API_KEY!,\n * clientCode: \"ERIX_CLNT_JHBJHF\",\n * });\n *\n * await ecod.whatsapp.messages.send({ to: \"+91...\", text: \"Hello!\" });\n * const lead = await ecod.crm.leads.create({ firstName: \"Alice\", phone: \"+91...\" });\n * ```\n */\nexport class Ecodrix {\n /**\n * @internal Axios HTTP client for making API requests.\n */\n private readonly client: AxiosInstance;\n /**\n * @internal Socket.io client for real-time events.\n */\n private readonly socket: Socket;\n\n /**\n * The tenant client code this SDK instance is scoped to.\n * Useful for components that need to read the clientCode back\n * from a context-provided SDK instance.\n */\n public readonly clientCode: string | undefined;\n\n /** WhatsApp messaging and conversation management. */\n public readonly whatsapp: WhatsApp;\n\n /** CRM resources — Leads and related sub-resources. */\n public readonly crm: CRM;\n\n /** Cloudflare R2-backed media storage. */\n public readonly media: Media;\n\n /** Google Meet appointment scheduling. */\n public readonly meet: Meetings;\n\n /** Automation execution logs and provider webhook callbacks. */\n public readonly notifications: Notifications;\n\n /** Outbound email marketing engine and template management. */\n public readonly email: Email;\n\n /** Platform-wide execution logs and audit trails. */\n public readonly logs: Logs;\n\n /** Lead events and workflow automation triggers. */\n public readonly events: EventsResource;\n\n /** Cryptographic webhook signature verification. */\n public readonly webhooks: Webhooks;\n\n /** Tenant Cloud Storage mapping. */\n public readonly storage: Storage;\n\n /** Email and SMS Marketing Campaigns. */\n public readonly marketing: Marketing;\n\n /** Platform and tenant health diagnostics. */\n public readonly health: Health;\n\n /** Background job queue management. */\n public readonly queue: Queue;\n\n /** White-Label Agency administration. */\n public readonly agency: Agency;\n\n /** Multi-tenant Identity & Lifecycle services. */\n public readonly services: Services;\n\n /** Tenant environment and provider settings. */\n public readonly settings: Settings;\n\n /** Dynamic Cross-Origin Resource Sharing network policies. */\n public readonly cors: Cors;\n\n constructor(options: EcodrixOptions) {\n if (!options.apiKey) {\n throw new AuthenticationError(\"API Key is required\");\n }\n\n this.clientCode = options.clientCode?.toUpperCase();\n\n // @internal: options.baseUrl is available for CLI/test use only.\n // Host projects hardcode to prod — they never set baseUrl.\n const baseUrl = options.baseUrl ?? ECOD_API_BASE;\n const socketUrl = options.socketUrl || baseUrl;\n\n const isBrowser =\n typeof window !== \"undefined\" && typeof window.document !== \"undefined\";\n const runtime = isBrowser\n ? \"browser\"\n : typeof process !== \"undefined\"\n ? `node ${process.version}`\n : \"unknown\";\n const os = isBrowser\n ? globalThis.navigator?.userAgent || \"browser\"\n : typeof process !== \"undefined\"\n ? process.platform\n : \"unknown\";\n\n const headers: Record<string, string> = {\n \"x-api-key\": options.apiKey,\n \"x-client-code\": options.clientCode?.toUpperCase() || \"\",\n \"Content-Type\": \"application/json\",\n \"x-ecodrix-client-agent\": JSON.stringify({\n sdk_version: \"1.0.0\", // Can be auto-injected during build in future\n runtime,\n os,\n }),\n };\n\n if (options.coreApiKey) {\n headers[\"x-core-api-key\"] = options.coreApiKey;\n }\n\n this.client = axios.create({\n baseURL: baseUrl,\n headers,\n });\n\n // Make the client completely bulletproof for execution from external projects.\n // It will automatically handle network blips, 502 Bad Gateways, and 429 Rate Limits.\n axiosRetry(this.client, {\n retries: 3,\n retryDelay: axiosRetry.exponentialDelay,\n retryCondition: (error) => {\n return (\n axiosRetry.isNetworkOrIdempotentRequestError(error) ||\n error.response?.status === 429\n );\n },\n onRetry: (retryCount, error, requestConfig) => {\n const isDev =\n typeof process !== \"undefined\" &&\n process.env?.NODE_ENV === \"development\";\n if (isDev) {\n console.warn(\n `[ECODrIx SDK] Retrying request (${retryCount}/3): ${requestConfig.method?.toUpperCase()} ${requestConfig.url}. Reason: ${error.message}`,\n );\n }\n },\n });\n\n // Initialise resources\n this.whatsapp = new WhatsApp(this.client);\n this.crm = new CRM(this.client);\n this.media = new Media(this.client);\n this.meet = new Meetings(this.client);\n this.notifications = new Notifications(this.client);\n this.email = new Email(this.client);\n this.logs = new Logs(this.client);\n this.events = new EventsResource(this.client);\n this.webhooks = new Webhooks();\n this.storage = new Storage(this.client);\n this.marketing = new Marketing(this.client);\n this.health = new Health(this.client);\n this.queue = new Queue(this.client);\n this.agency = new Agency(this.client);\n this.services = new Services(this.client);\n this.settings = new Settings(this.client);\n this.cors = new Cors(this.client);\n\n // Establish persistent Socket.io connection\n this.socket = io(socketUrl, {\n extraHeaders: {\n \"x-api-key\": options.apiKey,\n \"x-client-code\": options.clientCode?.toUpperCase() || \"\",\n },\n });\n\n this.setupSocket(options.clientCode);\n\n // ─── Wappalyzer & Technology Detection ─────────────────────────────────────\n if (isBrowser) {\n const footprint = {\n version: \"1.2.2\",\n clientCode: options.clientCode,\n initializedAt: new Date().toISOString(),\n };\n // Standard identifying global\n (window as any).__ECODRIX_SDK__ = footprint;\n // Ergonomic access for developers (as attempted by the user)\n if (!(window as any).ecodrix) {\n (window as any).ecodrix = this;\n }\n }\n }\n\n /**\n * Join a specific real-time room (e.g., a conversation or a lead).\n *\n * @param roomId - The unique identifier for the room.\n */\n public joinRoom(roomId: string) {\n this.socket.emit(\"join-room\", roomId);\n }\n\n /**\n * Leave a previously joined real-time room.\n *\n * @param roomId - The unique identifier for the room.\n */\n public leaveRoom(roomId: string) {\n this.socket.emit(\"leave-room\", roomId);\n }\n\n private setupSocket(clientCode?: string) {\n this.socket.on(\"connect\", () => {\n if (clientCode) {\n // Join the tenant-scoped room to receive only relevant events.\n this.socket.emit(\"join-room\", clientCode.toUpperCase());\n }\n });\n }\n\n /**\n * Subscribe to a real-time event emitted by the ECODrIx platform.\n *\n * The SDK maintains a persistent Socket.io connection. Events are\n * scoped to your `clientCode` — you will only receive events for\n * your own tenant.\n *\n * **Standard events:**\n * - `new_message` — inbound WhatsApp message (includes conversation and message payload)\n * - `message_sent` — outbound message successfully sent\n * - `message_status_update` — WhatsApp message status change (delivered, read, failed)\n * - `conversation_updated` — metadata change (unread count, last message, status)\n * - `message_updated` — real-time updates for reactions or media processing\n * - `notification:new` — new system or CRM notification\n * - `workflow-run-update` — automation execution progress\n * - `meet.scheduled` — Google Meet appointment booked\n *\n * @param event - The event name to subscribe to.\n * @param callback - The handler function invoked when the event fires.\n * @returns `this` for method chaining.\n *\n * @example\n * ```typescript\n * ecod\n * .on(\"whatsapp.message_received\", (msg) => console.log(msg.body))\n * .on(\"automation.failed\", (err) => alertTeam(err));\n * ```\n */\n public on(event: string, callback: (...args: any[]) => void): this {\n this.socket.on(event, callback);\n return this;\n }\n\n /**\n * Gracefully disconnect the real-time Socket.io connection.\n * Call this when shutting down your server or when the client is\n * no longer needed to free up resources.\n *\n * @example\n * ```typescript\n * process.on(\"SIGTERM\", () => ecod.disconnect());\n * ```\n */\n public disconnect() {\n this.socket.disconnect();\n }\n\n /**\n * Remove a previously registered event listener.\n * Always call this in cleanup (e.g. React `useEffect` return) to prevent\n * memory leaks and duplicate handlers after reconnections.\n *\n * @param event - The event name to unsubscribe from.\n * @param callback - The exact handler reference passed to `.on()`.\n * @returns `this` for method chaining.\n */\n public off(event: string, callback: (...args: any[]) => void): this {\n this.socket.off(event, callback);\n return this;\n }\n\n /**\n * Raw Execution Escape-Hatch.\n * Send an authenticated HTTP request directly to the ECODrIx backend from ANY external project.\n *\n * This is extremely powerful giving you full unrestricted access to make calls\n * against new, experimental, or completely custom backend APIs while still benefitting\n * from the SDK's built-in authentication and automatic `axios-retry` logic.\n *\n * @example\n * ```typescript\n * const { data } = await ecod.request(\"POST\", \"/api/saas/experimental-feature\", { flag: true });\n * console.log(data);\n * ```\n */\n public async request<T = any>(\n method: Method,\n path: string,\n data?: any,\n params?: any,\n ): Promise<T> {\n try {\n const response = await this.client.request<T>({\n method,\n url: path,\n data,\n params,\n });\n return response.data;\n } catch (error: any) {\n if (error.response) {\n throw new APIError(\n error.response.data?.message ||\n error.response.data?.error ||\n \"Raw Execution Failed\",\n error.response.status,\n error.response.data?.code,\n );\n }\n throw new APIError(error.message || \"Network Error\");\n }\n }\n}\n","/**\n * Typed error hierarchy for the @ecodrix/erix-api SDK.\n *\n * All errors thrown by the SDK extend `EcodrixError`, so a single\n * `catch` block can handle them all, while still allowing granular\n * differentiation between auth failures, rate limits, and generic API errors.\n *\n * @example\n * ```typescript\n * import { APIError, AuthenticationError, RateLimitError } from \"@ecodrix/erix-api\";\n *\n * try {\n * await ecod.crm.leads.retrieve(\"invalid_id\");\n * } catch (err) {\n * if (err instanceof AuthenticationError) {\n * console.error(\"Invalid API key or client code.\");\n * } else if (err instanceof RateLimitError) {\n * console.warn(\"Slow down — rate limit hit.\");\n * } else if (err instanceof APIError) {\n * console.error(`API error ${err.status}: ${err.message}`);\n * }\n * }\n * ```\n */\n\n/** Base class for all ECODrIx SDK errors. */\nexport class EcodrixError extends Error {\n constructor(message: string) {\n super(message);\n this.name = \"EcodrixError\";\n }\n}\n\n/**\n * Represents an error returned by the ECODrIx API.\n * Carries the HTTP `status` code and an optional `code` string.\n */\nexport class APIError extends EcodrixError {\n /** HTTP status code returned by the API (e.g. 400, 404, 500). */\n public status?: number;\n /** Machine-readable error code (e.g. `\"NOT_FOUND\"`, `\"VALIDATION_ERROR\"`). */\n public code?: string;\n\n constructor(message: string, status?: number, code?: string) {\n super(message);\n this.name = \"APIError\";\n this.status = status;\n this.code = code;\n }\n}\n\n/**\n * Thrown when the API key or client code is missing, invalid, or expired.\n * HTTP 401.\n */\nexport class AuthenticationError extends APIError {\n constructor(message = \"Invalid API Key or Client Code\") {\n super(message, 401, \"AUTH_FAILED\");\n this.name = \"AuthenticationError\";\n }\n}\n\n/**\n * Thrown when the rate limit for the API key has been exceeded.\n * HTTP 429. Implement exponential backoff before retrying.\n */\nexport class RateLimitError extends APIError {\n constructor(message = \"Too many requests. Please slow down.\") {\n super(message, 429, \"RATE_LIMIT_EXCEEDED\");\n this.name = \"RateLimitError\";\n }\n}\n","import type { AxiosInstance, AxiosRequestConfig } from \"axios\";\nimport { APIError } from \"./error\";\n\nexport interface RequestOptions extends AxiosRequestConfig {\n /**\n * If true, will not add the x-client-code header.\n */\n ignoreClientCode?: boolean;\n\n /**\n * Safe execution idempotency key.\n * If provided, the backend will safely ignore duplicate requests retried with the same key.\n */\n idempotencyKey?: string;\n}\n\nexport abstract class APIResource {\n public constructor(protected readonly client: AxiosInstance) {}\n\n protected async post<T>(url: string, data?: any, options?: RequestOptions): Promise<T> {\n try {\n const config = this.buildConfig(options);\n const response = await this.client.post(url, data, config);\n return response.data;\n } catch (error: any) {\n this.handleError(error);\n }\n }\n\n protected async get<T>(url: string, options?: RequestOptions): Promise<T> {\n try {\n const config = this.buildConfig(options);\n const response = await this.client.get(url, config);\n return response.data;\n } catch (error: any) {\n this.handleError(error);\n }\n }\n\n protected async patch<T>(url: string, data?: any, options?: RequestOptions): Promise<T> {\n try {\n const config = this.buildConfig(options);\n const response = await this.client.patch(url, data, config);\n return response.data;\n } catch (error: any) {\n this.handleError(error);\n }\n }\n\n protected async put<T>(url: string, data?: any, options?: RequestOptions): Promise<T> {\n try {\n const config = this.buildConfig(options);\n const response = await this.client.put(url, data, config);\n return response.data;\n } catch (error: any) {\n this.handleError(error);\n }\n }\n\n protected async deleteRequest<T>(url: string, options?: RequestOptions): Promise<T> {\n try {\n const config = this.buildConfig(options);\n const response = await this.client.delete(url, config);\n return response.data;\n } catch (error: any) {\n this.handleError(error);\n }\n }\n\n private buildConfig(options?: RequestOptions): AxiosRequestConfig | undefined {\n if (!options) return undefined;\n\n const config: AxiosRequestConfig = { ...options };\n if (options.idempotencyKey) {\n config.headers = {\n ...config.headers,\n \"Idempotency-Key\": options.idempotencyKey,\n };\n }\n return config;\n }\n\n private handleError(error: any): never {\n if (error.response) {\n throw new APIError(\n error.response.data?.message || error.response.data?.error || \"API Request Failed\",\n error.response.status,\n error.response.data?.code,\n );\n }\n throw new APIError(error.message || \"Network Error\");\n }\n}\n","import { APIResource } from \"../../resource\";\n\nexport interface LogActivityParams {\n leadId: string;\n type: \"note\" | \"call\" | \"email\" | \"meeting\" | \"whatsapp\" | \"system\";\n title: string;\n body?: string;\n metadata?: Record<string, any>;\n}\n\nexport interface LogCallParams {\n durationMinutes: number;\n summary: string;\n outcome: \"answered\" | \"no_answer\" | \"busy\" | \"voicemail\" | \"wrong_number\";\n}\n\nexport class Notes extends APIResource {\n /**\n * List all notes for a specific lead.\n *\n * @param leadId - The unique ID of the lead.\n * @example\n * ```typescript\n * const notes = await erixClient.crm.activities.notes.list(\"lead_123\");\n * ```\n */\n async list<T = any>(leadId: string) {\n return this.get<T>(`/api/crm/leads/${leadId}/notes`);\n }\n\n /**\n * Add a new descriptive note to a lead's profile.\n *\n * @param leadId - The unique ID of the lead.\n * @param params - The note content.\n * @example\n * ```typescript\n * await erixClient.crm.activities.notes.create(\"lead_123\", {\n * content: \"Customer is interested in the enterprise plan.\"\n * });\n * ```\n */\n async create<T = any>(leadId: string, params: { content: string }) {\n return this.post<T>(`/api/crm/leads/${leadId}/notes`, params);\n }\n\n /**\n * Update an existing note.\n */\n async update<T = any>(noteId: string, content: string) {\n return this.patch<T>(`/api/crm/notes/${noteId}`, { content });\n }\n\n /**\n * Pin or unpin a note to the top of the feed.\n */\n async pin<T = any>(noteId: string, isPinned = true) {\n return this.patch<T>(`/api/crm/notes/${noteId}/pin`, { isPinned });\n }\n\n /**\n * Delete a note.\n */\n async delete(noteId: string) {\n return this.deleteRequest(`/api/crm/notes/${noteId}`);\n }\n}\n\nexport class Activities extends APIResource {\n public notes: Notes;\n\n constructor(client: any) {\n super(client);\n this.notes = new Notes(client);\n }\n\n /**\n * Retrieve the complete chronological timeline of all activities for a lead.\n *\n * @param leadId - The unique ID of the lead.\n * @param params - Optional pagination parameters.\n * @example\n * ```typescript\n * const timeline = await erixClient.crm.activities.timeline(\"lead_123\", { limit: 10 });\n * ```\n */\n async timeline<T = any>(leadId: string, params?: { page?: number; limit?: number }) {\n return this.get<T>(`/api/crm/leads/${leadId}/timeline`, { params } as any);\n }\n\n /**\n * List specific activities (filtered by type).\n */\n async list<T = any>(leadId: string, params?: { type?: string; page?: number; limit?: number }) {\n return this.get<T>(`/api/crm/leads/${leadId}/activities`, { params: { ...params } } as any);\n }\n\n /**\n * Generic method to log a business activity/event (e.g., system events, manual tasks).\n *\n * @param params - Activity details (leadId, type, title, body).\n * @example\n * ```typescript\n * await erixClient.crm.activities.log({\n * leadId: \"lead_123\",\n * type: \"system\",\n * title: \"Meeting Scheduled\",\n * body: \"Initial consultation booked for Friday.\"\n * });\n * ```\n */\n async log<T = any>(params: LogActivityParams) {\n return this.post<T>(`/api/crm/leads/${params.leadId}/activities`, params);\n }\n\n /**\n * Specific method to log communication outcomes.\n */\n async logCall<T = any>(leadId: string, params: LogCallParams) {\n return this.post<T>(`/api/crm/leads/${leadId}/calls`, params);\n }\n}\n","import { APIResource } from \"../../resource\";\n\nexport type AnalyticsRange = \"24h\" | \"7d\" | \"30d\" | \"60d\" | \"90d\" | \"365d\";\n\nexport interface AnalyticsParams {\n range?: AnalyticsRange;\n from?: string;\n to?: string;\n pipelineId?: string;\n}\n\nexport class Analytics extends APIResource {\n /**\n * Retrieve high-level CRM performance KPIs.\n * Includes total leads, pipeline value, won revenue, and conversion rates.\n *\n * @param params - Optional filters including time range (24h, 7d, 30d, etc.) and custom date bounds.\n * @returns {Promise<any>} KPI summary object containing core business metrics.\n * @example\n * ```typescript\n * const stats = await erixClient.crm.analytics.overview({ range: \"30d\" });\n * console.log(stats.avgScore);\n * ```\n */\n async overview<T = any>(params?: AnalyticsParams) {\n return this.get<T>(\"/api/crm/analytics/overview\", { params } as any);\n }\n\n /**\n * Get stage-by-stage lead counts and conversion percentages for a pipeline.\n * Useful for identifying funnel bottlenecks and drop-off points.\n *\n * @param pipelineId - The unique ID of the pipeline to analyze.\n * @returns {Promise<any>} Array of funnel stages with count and conversion data.\n * @example\n * ```typescript\n * const funnel = await erixClient.crm.analytics.funnel(\"pipe_123\");\n * ```\n */\n async funnel<T = any>(pipelineId: string) {\n return this.get<T>(\"/api/crm/analytics/funnel\", {\n params: { pipelineId },\n } as any);\n }\n\n /**\n * Revenue forecast: Calculates expected revenue based on deal value × stage probability.\n * Helps in sales planning and goal setting.\n *\n * @param pipelineId - Optional pipeline ID to filter the forecast.\n * @returns {Promise<any>} Forecast data including weighted expected revenue.\n * @example\n * ```typescript\n * const prognosis = await erixClient.crm.analytics.forecast(\"pipe_123\");\n * ```\n */\n async forecast<T = any>(pipelineId?: string) {\n return this.get<T>(\"/api/crm/analytics/forecast\", {\n params: { pipelineId },\n } as any);\n }\n\n /**\n * Lead source breakdown: count, conversion rate, and total value per source.\n *\n * @param params - Time range filters.\n * @returns {Promise<any>} Breakdown of how different marketing channels are performing.\n */\n async sources<T = any>(params?: AnalyticsParams) {\n return this.get<T>(\"/api/crm/analytics/sources\", { params } as any);\n }\n\n /**\n * Team leaderboard: Evaluates agent performance across won deals, revenue, and activity.\n *\n * @param params - Time range filters.\n * @returns {Promise<any>} Ranked list of team members by performance.\n */\n async team<T = any>(params?: AnalyticsParams) {\n return this.get<T>(\"/api/crm/analytics/team\", { params } as any);\n }\n\n /**\n * Activity heatmap: Daily activity counts by type.\n * Ideal for visualizing engagement patterns on a calendar view.\n *\n * @param params - Time range filters.\n * @returns {Promise<any>} Time-series data of team activities.\n */\n async heatmap<T = any>(params?: AnalyticsParams) {\n return this.get<T>(\"/api/crm/analytics/heatmap\", { params } as any);\n }\n\n /**\n * Score distribution: Groups leads into buckets based on their calculated score (0-100).\n *\n * @returns {Promise<any>} Volume of leads in different readiness tiers.\n */\n async scores<T = any>() {\n return this.get<T>(\"/api/crm/analytics/scores\");\n }\n\n /**\n * Avg time in stage: Measures the velocity of leads through the sales pipeline.\n *\n * @param pipelineId - Target pipeline ID.\n * @returns {Promise<any>} Velocity metrics per stage.\n */\n async stageTime<T = any>(pipelineId: string) {\n return this.get<T>(\"/api/crm/analytics/stage-time\", {\n params: { pipelineId },\n } as any);\n }\n\n /**\n * Tiered Growth Report matching business sophistication (Pulse, Growth, Weapon).\n * Provides deep tactical and strategic insights.\n *\n * @param params - Filtering and range parameters.\n */\n async tiered<T = any>(params?: AnalyticsParams) {\n return this.get<T>(\"/api/crm/analytics/tiered\", { params } as any);\n }\n\n /**\n * Consolidated analytics including CRM overview and WhatsApp messaging metrics.\n *\n * @param params - Time range filters.\n */\n async summary<T = any>(params?: AnalyticsParams) {\n return this.get<T>(\"/api/crm/analytics/summary\", { params } as any);\n }\n\n /**\n * Retrieve WhatsApp messaging volume and delivery performance analytics.\n * Includes total sent, delivered, read, and daily volume trends.\n *\n * @param params - Optional filters (time range).\n * @example\n * ```typescript\n * const waStats = await erixClient.crm.analytics.whatsapp({ range: \"7d\" });\n * console.log(waStats.totalSent);\n * ```\n */\n async whatsapp<T = any>(params?: AnalyticsParams) {\n return this.get<T>(\"/api/crm/analytics/whatsapp\", { params } as any);\n }\n}\n","import { APIResource } from \"../../resource\";\n\nexport class AutomationDashboard extends APIResource {\n /**\n * Retrieve summary statistics for automation health (total, success, failed).\n *\n * @returns Stats object.\n * @example\n * ```typescript\n * const stats = await erixClient.crm.automationDashboard.stats();\n * ```\n */\n async stats<T = any>() {\n return this.get<T>(\"/api/crm/automation/stats\");\n }\n\n /**\n * List recent EventLog entries representing automation executions.\n *\n * @param params - Optional filters (limit, status).\n * @example\n * ```typescript\n * const logs = await erixClient.crm.automationDashboard.logs({ status: \"failed\" });\n * ```\n */\n async logs<T = any>(params?: { limit?: number; status?: string }) {\n return this.get<T>(\"/api/crm/automation/logs\", { params } as any);\n }\n\n /**\n * Re-emit a failed event log to re-trigger its associated automation rules.\n *\n * @param logId - The unique ID of the failed event log.\n * @example\n * ```typescript\n * await erixClient.crm.automationDashboard.retryFailedEvent(\"log_123\");\n * ```\n */\n async retryFailedEvent<T = any>(logId: string) {\n return this.post<T>(`/api/crm/automation/logs/${logId}/retry`, {});\n }\n}\n","import { APIResource } from \"../../resource\";\n\nexport interface AutomationRulePayload {\n name: string;\n trigger: string;\n isActive?: boolean;\n nodes: any[];\n edges: any[];\n}\n\nexport class Automations extends APIResource {\n /**\n * List all automation rules (workflows) configured for the tenant.\n *\n * @returns Array of automation rule objects.\n * @example\n * ```typescript\n * const rules = await erixClient.crm.automations.list();\n * ```\n */\n async list<T = any>() {\n return this.get<T>(\"/api/crm/automations\");\n }\n\n /**\n * Create a new automation rule with triggers and workflow nodes.\n *\n * @param payload - The automation rule definition (trigger, nodes, edges).\n * @returns The created automation rule.\n * @example\n * ```typescript\n * await erixClient.crm.automations.create({\n * name: \"Welcome Email Workflow\",\n * trigger: \"contact_created\",\n * nodes: [...],\n * edges: [...]\n * });\n * ```\n */\n async create<T = any>(payload: AutomationRulePayload) {\n return this.post<T>(\"/api/crm/automations\", payload);\n }\n\n /**\n * Update an existing automation rule.\n */\n async update<T = any>(ruleId: string, payload: Partial<AutomationRulePayload>) {\n return this.patch<T>(`/api/crm/automations/${ruleId}`, payload as any);\n }\n\n /**\n * Enable or disable an automation rule.\n */\n async toggle<T = any>(ruleId: string) {\n return this.patch<T>(`/api/crm/automations/${ruleId}/toggle`);\n }\n\n /**\n * Delete an automation rule.\n */\n async delete<T = any>(ruleId: string) {\n return this.deleteRequest(`/api/crm/automations/${ruleId}`);\n }\n\n /**\n * Bulk delete rules.\n */\n async bulkDelete<T = any>(ruleIds: string[]) {\n return this.post<T>(\"/api/crm/automations/bulk-delete\", { ids: ruleIds });\n }\n\n /**\n * Dry-run test an automation rule against a specific lead to verify logic.\n *\n * @param ruleId - The ID of the rule to test.\n * @param leadId - The ID of the lead to run the test against.\n * @example\n * ```typescript\n * await erixClient.crm.automations.test(\"rule_123\", \"lead_456\");\n * ```\n */\n async test<T = any>(ruleId: string, leadId: string) {\n return this.post<T>(`/api/crm/automations/${ruleId}/test`, { leadId });\n }\n\n /**\n * Get available event triggers for automations.\n */\n async getAvailableEvents<T = any>() {\n return this.post<T>(\"/api/crm/automations/events\", {});\n }\n\n /**\n * List enrollments for a rule.\n */\n async enrollments<T = any>(\n ruleId: string,\n params?: {\n status?: string;\n page?: number;\n limit?: number;\n startDate?: string;\n endDate?: string;\n },\n ) {\n return this.get<T>(`/api/crm/automations/${ruleId}/enrollments`, { params });\n }\n\n /**\n * Get an enrollment detail.\n */\n async getEnrollment<T = any>(enrollmentId: string) {\n return this.get<T>(`/api/crm/automations/enrollments/${enrollmentId}`);\n }\n\n /**\n * Pause an enrollment.\n */\n async pauseEnrollment<T = any>(ruleId: string, enrollmentId: string) {\n return this.post<T>(`/api/crm/automations/${ruleId}/enrollments/${enrollmentId}/pause`, {});\n }\n\n /**\n * Resume an enrollment.\n */\n async resumeEnrollment<T = any>(ruleId: string, enrollmentId: string) {\n return this.post<T>(`/api/crm/automations/${ruleId}/enrollments/${enrollmentId}/resume`, {});\n }\n\n /**\n * List workflow runs.\n */\n async runs<T = any>(ruleId: string) {\n return this.get<T>(`/api/crm/automations/${ruleId}/runs`);\n }\n\n /**\n * Get run details.\n */\n async getRun<T = any>(runId: string) {\n return this.get<T>(`/api/crm/automations/runs/${runId}`);\n }\n\n /**\n * Resume a paused run.\n */\n async resumeRun<T = any>(runId: string) {\n return this.post<T>(`/api/crm/automations/runs/${runId}/resume`, {});\n }\n\n /**\n * Abort a running workflow.\n */\n async abortRun<T = any>(runId: string) {\n return this.post<T>(`/api/crm/automations/runs/${runId}/abort`, {});\n }\n\n /**\n * Emit an external webhook event to unlock a `wait_event` node inside a\n * paused workflow run. Required when integrating third-party tools that\n * need to resume a suspended automation.\n *\n * @param ruleId - The automation rule that contains the wait_event node.\n * @param eventName - The event name that should match the node's condition.\n * @param payload - Arbitrary data forwarded to the node context.\n */\n async webhookEvent<T = any>(ruleId: string, eventName: string, payload?: any) {\n return this.post<T>(\"/api/crm/webhook-event\", { ruleId, eventName, payload });\n }\n}\n","import { APIResource } from \"../../resource\";\nimport type { ResourceManifest } from \"../../types/metadata\";\n\n/**\n * Valid statuses for a CRM Lead.\n */\nexport type LeadStatus = \"new\" | \"contacted\" | \"qualified\" | \"won\" | \"lost\" | \"archived\";\n\n/**\n * Common lead acquisition sources. Additional string values are allowed.\n */\nexport type LeadSource = \"website\" | \"whatsapp\" | \"direct\" | \"referral\" | string;\n\n/**\n * Parameters for creating a new CRM Lead.\n */\nexport interface CreateLeadParams {\n /** Lead's first name. Required. */\n firstName: string;\n /** Lead's last name. */\n lastName?: string;\n /** Lead's email address. */\n email?: string;\n /** Lead's phone number in E.164 format (e.g. \"+919876543210\"). */\n phone?: string;\n /**\n * Acquisition channel.\n */\n source?: LeadSource;\n /** Arbitrary key-value metadata (UTM params, order IDs, etc.). */\n metadata?: Record<string, any>;\n /** Pipeline ID to assign the lead */\n pipelineId?: string;\n /** Stage ID to assign the lead */\n stageId?: string;\n}\n\n/**\n * Options for listing leads.\n */\nexport interface ListLeadsParams {\n status?: LeadStatus;\n pipelineId?: string;\n stageId?: string;\n source?: LeadSource;\n assignedTo?: string;\n tags?: string[] | string;\n minScore?: number;\n search?: string;\n startDate?: string;\n endDate?: string;\n appointmentId?: string;\n bookingId?: string;\n orderId?: string;\n meetingId?: string;\n page?: number;\n limit?: number;\n sortBy?: string;\n sortDir?: \"asc\" | \"desc\";\n}\n\n/**\n * Options for upserting a lead.\n */\nexport interface UpsertLeadParams {\n leadData: Partial<CreateLeadParams> & { phone: string; name?: string };\n moduleInfo?: any;\n trigger?: string;\n pipelineId?: string;\n stageId?: string;\n}\n\n/**\n * CRM Lead resource — full lifecycle management.\n *\n * Access via `ecod.crm.leads`.\n *\n * @example\n * ```typescript\n * const { data: lead } = await ecod.crm.leads.create({\n * firstName: \"Alice\",\n * phone: \"+919876543210\",\n * source: \"website\",\n * });\n * ```\n */\nexport class Leads extends APIResource {\n /**\n * Create a new lead in the CRM pipeline.\n *\n * @param params - Lead creation parameters. `firstName` is required.\n * @returns The newly created Lead document.\n * @example\n * ```typescript\n * const lead = await erixClient.crm.leads.create({\n * firstName: \"Alice\",\n * phone: \"+919876543210\",\n * source: \"website\"\n * });\n * ```\n */\n async create<T = any>(params: CreateLeadParams) {\n return this.post<T>(\"/api/crm/leads\", params);\n }\n\n /**\n * Introspect the Leads resource and provide a \"Blueprint\" for UI generation.\n *\n * This method returns a list of all fields (standard + custom), their types,\n * labels, and suggested UI controls. Erix React uses this to render SmartForms\n * and tables dynamically.\n */\n async describe(): Promise<ResourceManifest> {\n // 1. Fetch custom fields from the tenant configuration\n const customFieldsRes: any = await this.fields();\n const customFields = Array.isArray(customFieldsRes.data) ? customFieldsRes.data : [];\n\n // 2. Define the core system fields\n const systemFields: any[] = [\n {\n key: \"firstName\",\n label: \"First Name\",\n type: \"string\",\n required: true,\n group: \"Basic Info\",\n },\n { key: \"lastName\", label: \"Last Name\", type: \"string\", required: false, group: \"Basic Info\" },\n { key: \"phone\", label: \"Phone Number\", type: \"phone\", required: true, group: \"Contact\" },\n { key: \"email\", label: \"Email Address\", type: \"email\", required: false, group: \"Contact\" },\n {\n key: \"status\",\n label: \"Status\",\n type: \"select\",\n required: true,\n options: [\n { label: \"New\", value: \"new\" },\n { label: \"Contacted\", value: \"contacted\" },\n { label: \"Qualified\", value: \"qualified\" },\n { label: \"Won\", value: \"won\" },\n { label: \"Lost\", value: \"lost\" },\n ],\n },\n { key: \"value\", label: \"Lead Value\", type: \"currency\", required: false },\n { key: \"source\", label: \"Source\", type: \"string\", required: false },\n ];\n\n // 3. Map custom fields to FieldManifest shape\n const mappedCustom = customFields.map((f: any) => ({\n key: `metadata.extra.${f.name}`,\n label: f.label || f.name,\n type: f.type || \"string\",\n required: !!f.required,\n options: f.options,\n group: \"Custom Fields\",\n }));\n\n return {\n name: \"Lead\",\n fields: [...systemFields, ...mappedCustom],\n uiHints: {\n icon: \"User\",\n primaryColor: \"#3b82f6\",\n defaultSort: { field: \"createdAt\", direction: \"desc\" },\n summaryFields: [\"firstName\", \"lastName\", \"phone\", \"status\"],\n },\n };\n }\n\n /**\n * Upsert a lead by phone number. If a lead with the same phone exists,\n * it will be updated; otherwise, a new lead is created.\n *\n * @param params - Upsert parameters containing leadData with a phone number.\n * @returns The newly created or updated Lead document.\n * @example\n * ```typescript\n * await erixClient.crm.leads.upsert({\n * leadData: { phone: \"+919876543210\", firstName: \"Alice\" }\n * });\n * ```\n */\n async upsert<T = any>(params: UpsertLeadParams) {\n return this.post<T>(\"/api/crm/leads/upsert\", params);\n }\n\n /**\n * Bulk ingest leads efficiently in parallel using automatic chunking.\n * Prevents rate limit exhaustion by executing `chunkSize` requests at a time.\n *\n * @param leads - Array of leads to create.\n * @param chunkSize - Number of leads to send concurrently (default: 50)\n * @returns Array of created lead results.\n */\n async createMany(leads: CreateLeadParams[], chunkSize = 50): Promise<any[]> {\n const results: any[] = [];\n\n for (let i = 0; i < leads.length; i += chunkSize) {\n const chunk = leads.slice(i, i + chunkSize);\n\n const chunkPromises = chunk.map((lead) => this.create(lead));\n const chunkResults = await Promise.allSettled(chunkPromises);\n\n for (const res of chunkResults) {\n if (res.status === \"fulfilled\") {\n results.push(res.value);\n } else {\n throw res.reason;\n }\n }\n }\n\n return results;\n }\n\n /**\n * Bulk upsert (import) leads.\n *\n * @param leads - Array of leads to import.\n */\n async import<T = any>(leads: Partial<CreateLeadParams>[]) {\n return this.post<T>(\"/api/crm/leads/import\", { leads });\n }\n\n /**\n * List CRM leads with optional filtering and pagination.\n *\n * @param params - Filter options (status, source, pipelineId, page, limit, etc.)\n * @returns Paginated list of Lead documents.\n * @example\n * ```typescript\n * const leads = await erixClient.crm.leads.list({\n * status: \"new\",\n * source: \"website\",\n * limit: 20\n * });\n * ```\n */\n async list<T = any>(params?: ListLeadsParams) {\n const queryParams = { ...params } as any;\n if (Array.isArray(queryParams.tags)) {\n queryParams.tags = queryParams.tags.join(\",\");\n }\n return this.get<T>(\"/api/crm/leads\", { params: queryParams } as any);\n }\n\n /**\n * Auto-paginating iterator for leads.\n * Seamlessly fetches leads page by page as you iterate.\n *\n * @example\n * ```typescript\n * for await (const lead of ecod.crm.leads.listAutoPaging<Lead>()) {\n * console.log(lead.firstName);\n * }\n * ```\n */\n async *listAutoPaging<T = any>(params?: ListLeadsParams): AsyncGenerator<T, void, unknown> {\n let currentPage = params?.page || 1;\n let hasMore = true;\n\n while (hasMore) {\n const response: any = await this.list<any>({\n ...params,\n page: currentPage,\n });\n\n const items = Array.isArray(response.data) ? response.data : response || [];\n\n if (items.length === 0) {\n hasMore = false;\n break;\n }\n\n for (const item of items) {\n yield item as T;\n }\n\n if (response.pagination && currentPage < response.pagination.pages) {\n currentPage++;\n } else if (!response.pagination && items.length > 0) {\n // Fallback: If no explicit pagination struct, assume simple array and just keep pulling until empty\n currentPage++;\n } else {\n hasMore = false;\n }\n }\n }\n\n /**\n * Retrieve a single lead by its unique ID.\n *\n * @param leadId - The MongoDB ObjectId of the lead.\n * @returns The Lead document, or a 404 error if not found.\n * @example\n * ```typescript\n * const lead = await erixClient.crm.leads.retrieve(\"64abc...\");\n * ```\n */\n async retrieve<T = any>(leadId: string) {\n return this.get<T>(`/api/crm/leads/${leadId}`);\n }\n\n /**\n * Retrieve a single lead by its phone number.\n *\n * @param phone - Lead's phone number.\n */\n async retrieveByPhone<T = any>(phone: string) {\n // URL-encode the phone to handle '+' safe\n return this.get<T>(`/api/crm/leads/phone/${encodeURIComponent(phone)}`);\n }\n\n /**\n * Retrieve a single lead by a reference key and value.\n *\n * @param refKey - Reference key metadata.\n * @param refValue - Reference value.\n */\n async retrieveByRef<T = any>(refKey: string, refValue: string) {\n return this.get<T>(\n `/api/crm/leads/ref/${encodeURIComponent(refKey)}/${encodeURIComponent(refValue)}`,\n );\n }\n\n /**\n * Update the fields of an existing lead.\n *\n * @param leadId - The ID of the lead to update.\n * @param params - Partial lead fields to update.\n * @returns The updated Lead document.\n * @example\n * ```typescript\n * await erixClient.crm.leads.update(\"64abc...\", {\n * lastName: \"Smith\",\n * status: \"qualified\"\n * });\n * ```\n */\n async update<T = any>(leadId: string, params: Partial<CreateLeadParams>) {\n return this.patch<T>(`/api/crm/leads/${leadId}`, params);\n }\n\n /**\n * Move a lead to a new stage in a pipeline.\n *\n * @param leadId - ID of the lead.\n * @param stageId - Target stage ID.\n */\n async move<T = any>(leadId: string, stageId: string) {\n return this.patch<T>(`/api/crm/leads/${leadId}/move`, { stageId });\n }\n\n /**\n * Convert a lead (mark as won or lost with reason).\n *\n * @param leadId - ID of the lead.\n * @param outcome - \"won\" | \"lost\"\n * @param reason - Reason for the outcome.\n */\n async convert<T = any>(leadId: string, outcome: \"won\" | \"lost\", reason?: string) {\n return this.post<T>(`/api/crm/leads/${leadId}/convert`, {\n outcome,\n reason,\n });\n }\n\n /**\n * Update the tags of a lead.\n *\n * @param leadId - ID of the lead.\n * @param options - Tags to add or remove.\n */\n async tags<T = any>(leadId: string, options: { add?: string[]; remove?: string[] }) {\n return this.patch<T>(`/api/crm/leads/${leadId}/tags`, options);\n }\n\n /**\n * Recalculate lead score based on activities and interactions.\n *\n * @param leadId - ID of the lead.\n */\n async recalculateScore<T = any>(leadId: string) {\n return this.post<T>(`/api/crm/leads/${leadId}/score`, {});\n }\n\n /**\n * Update embedded metadata/references of a lead without touching core fields.\n *\n * @param leadId - ID of the lead.\n * @param metadata - Metadata object indicating { refs, extra }\n */\n async updateMetadata<T = any>(\n leadId: string,\n metadata: { refs?: Record<string, any>; extra?: Record<string, any> },\n ) {\n return this.patch<T>(`/api/crm/leads/${leadId}/metadata`, metadata);\n }\n\n /**\n * Introspect available custom fields configured by the tenant limit.\n */\n async fields<T = any>() {\n return this.get<T>(\"/api/crm/leads/fields\");\n }\n\n /**\n * List all notes for a specific lead.\n */\n async notes<T = any>(leadId: string) {\n return this.get<T>(`/api/crm/leads/${leadId}/notes`);\n }\n\n /**\n * Retrieve the complete chronological timeline for a lead.\n */\n async activities<T = any>(leadId: string, params?: { page?: number; limit?: number }) {\n return this.get<T>(`/api/crm/leads/${leadId}/timeline`, { params } as any);\n }\n\n /**\n * Add a note to a lead.\n */\n async createNote<T = any>(leadId: string, params: { content: string }) {\n return this.post<T>(`/api/crm/leads/${leadId}/notes`, params);\n }\n\n /**\n * Update an existing note.\n */\n async updateNote<T = any>(leadId: string, noteId: string, params: { content: string }) {\n return this.patch<T>(`/api/crm/notes/${noteId}`, params);\n }\n\n /**\n * Delete a note.\n */\n async deleteNote<T = any>(leadId: string, noteId: string) {\n return this.deleteRequest(`/api/crm/notes/${noteId}`);\n }\n\n /**\n * Archive (soft-delete) a single lead.\n *\n * @param leadId - The ID of the lead to archive.\n */\n async delete(leadId: string) {\n return this.deleteRequest(`/api/crm/leads/${leadId}`);\n }\n\n /**\n * Bulk archive multiple leads.\n *\n * @param ids - Array of lead IDs to archive.\n */\n async bulkDelete(ids: string[]) {\n return this.deleteRequest(\"/api/crm/leads\", { data: { ids } });\n }\n}\n","import { APIResource } from \"../../resource\";\n\nexport class Payments extends APIResource {\n /**\n * Record an inbound payment/transaction against a lead or specific appointment.\n *\n * @param payload - Payment details (leadId, amount, currency, description).\n * @example\n * ```typescript\n * await erixClient.crm.payments.capture({\n * leadId: \"lead_123\",\n * amount: 5000,\n * currency: \"INR\",\n * description: \"Consultation Fee\"\n * });\n * ```\n */\n async capture<T = any>(payload: {\n leadId: string;\n amount: number;\n currency?: string;\n description?: string;\n appointmentId?: string;\n }) {\n return this.post<T>(\"/api/crm/payments/capture\", payload);\n }\n}\n","import { APIResource } from \"../../resource\";\nimport type { ResourceManifest } from \"../../types/metadata\";\n\nexport interface CreatePipelineParams {\n name: string;\n isDefault?: boolean;\n stages?: any[]; // Typically an array of stage objects\n}\n\nexport interface PipelineStageParams {\n name: string;\n color?: string;\n probability?: number;\n}\n\nexport class Pipelines extends APIResource {\n /**\n * List all CRM pipelines and their configured stages.\n *\n * @returns Array of pipeline objects with nested stages.\n * @example\n * ```typescript\n * const pipelines = await erixClient.crm.pipelines.list();\n * ```\n */\n async list<T = any>() {\n return this.get<T>(\"/api/crm/pipelines\");\n }\n\n /**\n * Introspect a pipeline and provide a manifest of its stages.\n *\n * Returns metadata about stage colors, probabilities, and order.\n * Erix React uses this to build kanban boards and stage pickers.\n *\n * @param pipelineId - The unique ID of the pipeline.\n */\n async getStageManifest(pipelineId: string): Promise<ResourceManifest> {\n const pipeline: any = await this.retrieve(pipelineId);\n const stages = Array.isArray(pipeline.data?.stages)\n ? pipeline.data.stages\n : [];\n\n return {\n name: `Pipeline: ${pipeline.data?.name || pipelineId}`,\n fields: stages.map((s: any) => ({\n key: s._id,\n label: s.name,\n type: \"string\", // Labels are strings\n required: true,\n options: [{ label: s.name, value: s._id }],\n group: \"Stages\",\n uiHints: {\n color: s.color || \"#cbd5e1\",\n probability: s.probability,\n },\n })) as any,\n uiHints: {\n icon: \"Columns\",\n primaryColor: \"#6366f1\",\n },\n };\n }\n\n /**\n * Create a new CRM sales or support pipeline.\n *\n * @param payload - Pipeline details (name and array of stage names).\n * @returns The created pipeline record.\n * @example\n * ```typescript\n * await erixClient.crm.pipelines.create({\n * name: \"Sales Pipeline\",\n * stages: [\"Lead\", \"Contacted\", \"Proposal\", \"Negotiation\", \"Closed\"]\n * });\n * ```\n */\n async create<T = any>(payload: { name: string; stages: string[] }) {\n return this.post<T>(\"/api/crm/pipelines\", payload);\n }\n\n /**\n * Retrieve a single pipeline configuration by ID.\n *\n * @param pipelineId - The unique ID of the pipeline.\n * @example\n * ```typescript\n * const pipeline = await erixClient.crm.pipelines.retrieve(\"pipe_123\");\n * ```\n */\n async retrieve<T = any>(pipelineId: string) {\n return this.get<T>(`/api/crm/pipelines/${pipelineId}`);\n }\n\n /**\n * Update an existing pipeline.\n */\n async update<T = any>(\n pipelineId: string,\n payload: Partial<{ name: string; stages: string[] }>,\n ) {\n return this.patch<T>(`/api/crm/pipelines/${pipelineId}`, payload as any);\n }\n\n /**\n * Set pipeline as the tenant's default.\n */\n async setDefault<T = any>(pipelineId: string) {\n return this.patch<T>(`/api/crm/pipelines/${pipelineId}/default`, {});\n }\n\n /**\n * Duplicate a pipeline with a new name.\n */\n async duplicate<T = any>(pipelineId: string, newName: string) {\n return this.post<T>(`/api/crm/pipelines/${pipelineId}/duplicate`, {\n newName,\n });\n }\n\n /**\n * Archive a pipeline.\n */\n async archive<T = any>(pipelineId: string) {\n return this.patch<T>(`/api/crm/pipelines/${pipelineId}/archive`, {});\n }\n\n /**\n * Delete a pipeline permanently.\n */\n async delete(pipelineId: string) {\n return this.deleteRequest(`/api/crm/pipelines/${pipelineId}`);\n }\n\n /**\n * Check if a pipeline is in use (e.g. has leads attached).\n */\n async checkInUse<T = any>(pipelineId: string) {\n return this.get<T>(`/api/crm/pipelines/${pipelineId}/in-use`);\n }\n\n /**\n * Retrieve a Kanban-style board representation of the pipeline with leads nested.\n *\n * @param pipelineId - The unique ID of the pipeline.\n * @example\n * ```typescript\n * const board = await erixClient.crm.pipelines.board(\"pipe_123\");\n * ```\n */\n async board<T = any>(pipelineId: string) {\n return this.get<T>(`/api/crm/pipelines/${pipelineId}/board`);\n }\n\n /**\n * Retrieve a revenue forecast based on stage probabilities for a pipeline.\n */\n async forecast<T = any>(pipelineId: string) {\n return this.get<T>(`/api/crm/pipelines/${pipelineId}/forecast`);\n }\n\n // --- Stage Management ---\n\n /**\n * Add a new stage to the pipeline.\n *\n * @param pipelineId - The unique ID of the pipeline.\n * @param params - Stage details (name, color, probability).\n * @example\n * ```typescript\n * await erixClient.crm.pipelines.addStage(\"pipe_123\", {\n * name: \"Decision Maker Bought In\",\n * color: \"#FF5733\",\n * probability: 80\n * });\n * ```\n */\n async addStage<T = any>(pipelineId: string, params: PipelineStageParams) {\n return this.post<T>(`/api/crm/pipelines/${pipelineId}/stages`, params);\n }\n\n /**\n * Change the order of stages inside the pipeline.\n */\n async reorderStages<T = any>(pipelineId: string, orderArray: string[]) {\n return this.patch<T>(`/api/crm/pipelines/${pipelineId}/stages/reorder`, {\n order: orderArray,\n });\n }\n\n /**\n * Update a specific stage.\n */\n async updateStage<T = any>(\n stageId: string,\n params: Partial<PipelineStageParams>,\n ) {\n return this.patch<T>(`/api/crm/stages/${stageId}`, params);\n }\n\n /**\n * Delete a stage permanently.\n *\n * @param stageId - The unique ID of the stage to delete.\n * @param moveLeadsToStageId - Optional fallback stageId to move active leads to before deletion.\n */\n async deleteStage(stageId: string, moveLeadsToStageId?: string) {\n return this.deleteRequest(`/api/crm/stages/${stageId}`, {\n data: moveLeadsToStageId ? { moveLeadsToStageId } : undefined,\n });\n }\n}\n","import { APIResource } from \"../../resource\";\n\nexport interface ScoringConfig {\n decayDays: number;\n thresholds: {\n hot: number;\n warm: number;\n };\n rules: any[]; // Specific rule shapes\n}\n\nexport class Scoring extends APIResource {\n /**\n * Retrieve the tenant's global lead scoring configuration (rules, decay, thresholds).\n *\n * @returns The scoring configuration object.\n * @example\n * ```typescript\n * const config = await erixClient.crm.scoring.getConfig();\n * ```\n */\n async getConfig<T = any>() {\n return this.get<T>(\"/api/crm/scoring\");\n }\n\n /**\n * Update scoring configuration.\n */\n async updateConfig<T = any>(payload: Partial<ScoringConfig>) {\n return this.patch<T>(\"/api/crm/scoring\", payload as any);\n }\n\n /**\n * Force an immediate score recalculation for a specific lead.\n * Useful when profile data changes significantly.\n *\n * @param leadId - The unique ID of the lead.\n * @example\n * ```typescript\n * await erixClient.crm.scoring.recalculate(\"lead_123\");\n * ```\n */\n async recalculate<T = any>(leadId: string) {\n return this.post<T>(`/api/crm/scoring/${leadId}/recalculate`, {});\n }\n}\n","import { APIResource } from \"../../resource\";\n\nexport class Sequences extends APIResource {\n /**\n * Manually enroll a lead into a specific automation drip sequence (Workflow).\n *\n * @param payload - Enrollment details (leadId, ruleId, and custom variables).\n * @example\n * ```typescript\n * await erixClient.crm.sequences.enroll({\n * leadId: \"lead_123\",\n * ruleId: \"rule_456\",\n * variables: { start_date: \"2026-05-01\" }\n * });\n * ```\n */\n async enroll<T = any>(payload: {\n leadId: string;\n ruleId: string;\n variables?: Record<string, any>;\n }) {\n return this.post<T>(\"/api/crm/sequences/enroll\", payload);\n }\n\n /**\n * Unenroll a lead from a currently running automation sequence.\n *\n * @param enrollmentId - The unique ID of the sequence enrollment.\n * @example\n * ```typescript\n * await erixClient.crm.sequences.unenroll(\"enroll_123\");\n * ```\n */\n async unenroll<T = any>(enrollmentId: string) {\n return this.deleteRequest(`/api/crm/sequences/unenroll/${enrollmentId}`);\n }\n\n /**\n * List all active and completed sequence enrollments for a specific lead.\n *\n * @param leadId - The unique ID of the lead.\n * @returns Array of enrollment records.\n * @example\n * ```typescript\n * const enrollments = await erixClient.crm.sequences.listForLead(\"lead_123\");\n * ```\n */\n async listForLead<T = any>(leadId: string) {\n return this.get<T>(`/api/crm/sequences/lead/${leadId}`);\n }\n}\n","import type { AxiosInstance } from \"axios\";\nimport { Activities } from \"./activities\";\nimport { Analytics } from \"./analytics\";\nimport { AutomationDashboard } from \"./automationDashboard\";\nimport { Automations } from \"./automations\";\nimport { Leads } from \"./leads\";\nimport { Payments } from \"./payments\";\nimport { Pipelines } from \"./pipelines\";\nimport { Scoring } from \"./scoring\";\nimport { Sequences } from \"./sequences\";\n\nexport class CRM {\n public leads: Leads;\n public pipelines: Pipelines;\n public activities: Activities;\n public analytics: Analytics;\n public automations: Automations;\n public sequences: Sequences;\n public scoring: Scoring;\n public payments: Payments;\n public automationDashboard: AutomationDashboard;\n\n constructor(client: AxiosInstance) {\n this.leads = new Leads(client);\n this.pipelines = new Pipelines(client);\n this.activities = new Activities(client);\n this.analytics = new Analytics(client);\n this.automations = new Automations(client);\n this.sequences = new Sequences(client);\n this.scoring = new Scoring(client);\n this.payments = new Payments(client);\n this.automationDashboard = new AutomationDashboard(client);\n }\n}\n","import { APIResource } from \"../resource\";\n\n/**\n * Payload to send a high-throughput email campaign.\n */\nexport interface SendCampaignPayload {\n /** Array of recipient email addresses. */\n recipients: string[];\n /** Subject line of the email. */\n subject: string;\n /** HTML body of the email. */\n html: string;\n}\n\n/**\n * Interface representing the result of a campaign dispatch.\n */\nexport interface CampaignResult {\n success: boolean;\n message?: string;\n [key: string]: any;\n}\n\nexport interface EmailTemplate {\n id: string;\n name: string;\n description?: string;\n subject: string;\n preheader?: string;\n htmlBody: string;\n textBody?: string;\n category: \"marketing\" | \"transactional\" | \"sequence\";\n status: \"draft\" | \"published\" | \"archived\";\n type: \"standard\" | \"layout\";\n layoutId?: string;\n thumbnail?: string;\n variableMapping?: any[];\n createdAt: string;\n updatedAt: string;\n}\n\nexport interface CreateTemplateDTO {\n name: string;\n subject: string;\n htmlBody: string;\n description?: string;\n category?: \"marketing\" | \"transactional\" | \"sequence\";\n status?: \"draft\" | \"published\" | \"archived\";\n variableMapping?: any[];\n}\n\nexport interface TemplatePreviewResponse {\n success: boolean;\n data: {\n subject: string;\n html: string;\n text?: string;\n };\n}\n\n/**\n * Outbound email marketing engine and template management.\n *\n * Access via `ecod.email`.\n */\nexport class Email extends APIResource {\n /**\n * Send an HTML email campaign to a list of recipients.\n */\n async sendCampaign(payload: SendCampaignPayload): Promise<CampaignResult> {\n return this.post<CampaignResult>(\"/api/saas/emails/campaign\", payload);\n }\n\n /**\n * Send a system test email to validate your current SMTP configuration.\n */\n async sendTest(to: string): Promise<CampaignResult> {\n return this.post<CampaignResult>(\"/api/saas/emails/test\", { to });\n }\n\n // --- Template Management ---\n\n /**\n * List all email templates.\n */\n async listTemplates(query?: any): Promise<{ success: boolean; data: EmailTemplate[] }> {\n return this.get<{ success: boolean; data: EmailTemplate[] }>(\"/api/saas/mail/templates\", {\n params: query,\n });\n }\n\n /**\n * Get a single email template by ID.\n */\n async getTemplate(id: string): Promise<{ success: boolean; data: EmailTemplate }> {\n return this.get<{ success: boolean; data: EmailTemplate }>(`/api/saas/mail/templates/${id}`);\n }\n\n /**\n * Create a new email template.\n */\n async createTemplate(\n data: CreateTemplateDTO,\n ): Promise<{ success: boolean; data: EmailTemplate }> {\n return this.post<{ success: boolean; data: EmailTemplate }>(\"/api/saas/mail/templates\", data);\n }\n\n /**\n * Update an existing email template.\n */\n async updateTemplate(\n id: string,\n data: Partial<CreateTemplateDTO>,\n ): Promise<{ success: boolean; data: EmailTemplate }> {\n return this.put<{ success: boolean; data: EmailTemplate }>(\n `/api/saas/mail/templates/${id}`,\n data,\n );\n }\n\n /**\n * Delete an email template.\n */\n async deleteTemplate(id: string, force = false): Promise<{ success: boolean }> {\n return this.deleteRequest<{ success: boolean }>(`/api/saas/mail/templates/${id}`, {\n params: { force },\n });\n }\n\n /**\n * Preview a template with dynamic variable resolution.\n */\n async previewTemplate(\n id: string,\n params: { leadId?: string; variables?: Record<string, any> },\n ): Promise<TemplatePreviewResponse> {\n return this.post<TemplatePreviewResponse>(`/api/saas/mail/templates/${id}/preview`, params);\n }\n}\n\n/** @deprecated Use Email instead */\nexport class EmailResource extends Email {}\n","import type { AxiosInstance } from \"axios\";\nimport { APIResource } from \"../resource\";\n\n/**\n * Event definition representing an entry point capable of triggering automations.\n */\nexport interface EventDefinition {\n name: string;\n displayName: string;\n description?: string;\n pipelineId?: string;\n stageId?: string;\n defaultSource?: string;\n [key: string]: any;\n}\n\n/**\n * Payload to register/assign a new custom event definition.\n */\nexport interface AssignEventPayload {\n /** The internal machine-readable name of the event (e.g. \"webinar_joined\") */\n name: string;\n /** Human-readable display name */\n displayName: string;\n /** Event description */\n description?: string;\n /** ID of the pipeline to associate with matching leads */\n pipelineId?: string;\n /** ID of the stage within the pipeline */\n stageId?: string;\n /** Default source tag for leads created via this event */\n defaultSource?: string;\n}\n\n/**\n * Payload to programmatically trigger an event/workflow.\n */\nexport interface TriggerPayload {\n /** The name of the event to fire (e.g., \"webinar_joined\") */\n trigger: string;\n /** Phone number of the lead (E.164 format) */\n phone: string;\n /** Email of the lead */\n email?: string;\n /** Key-value pairs for string templates */\n variables?: Record<string, string>;\n /** Deep payload data mapping to the event */\n data?: any;\n /** URL to receive an acknowledgment callback when processing completes */\n callbackUrl?: string;\n /** Secret metadata passed back to the callback URL */\n callbackMetadata?: any;\n /** Auto-create lead if phone does not exist in CRM */\n createLeadIfMissing?: boolean;\n /** Pre-fill data if creating a new lead */\n leadData?: {\n firstName?: string;\n lastName?: string;\n source?: string;\n };\n /** Delay execution of matched workflows (in seconds) */\n delaySeconds?: number;\n /** Delay execution of matched workflows (in minutes) */\n delayMinutes?: number;\n /** Explicit ISO timestamp to trigger the workflow run */\n runAt?: string;\n /** Automatically generate a Google Meet appointment if matched actions require it */\n requiresMeet?: boolean;\n /** Configuration details for the generated Google Meet appointment */\n meetConfig?: {\n summary?: string;\n description?: string;\n startTime?: string;\n duration?: number;\n timezone?: string;\n attendees?: string[];\n };\n}\n\n/**\n * Response returned when triggering an event.\n */\nexport interface TriggerResponse {\n success: boolean;\n data?: {\n eventLogId: string;\n trigger: string;\n leadId: string;\n rulesMatched: number;\n };\n message?: string;\n code?: string;\n}\n\nexport class EventsResource extends APIResource {\n /**\n * List all available event definitions (both system and custom) that can trigger automations.\n *\n * @returns Array of event definitions.\n * @example\n * ```typescript\n * const events = await erixClient.events.list();\n * ```\n */\n async list(): Promise<{ success: boolean; data: EventDefinition[] }> {\n return this.get<{ success: boolean; data: EventDefinition[] }>(\"/api/saas/events\");\n }\n\n /**\n * Register a new custom event entry point into the CRM automation engine.\n * Useful when introducing new granular triggers.\n */\n async assign(payload: AssignEventPayload): Promise<{ success: boolean; data: EventDefinition }> {\n return this.post<{ success: boolean; data: EventDefinition }>(\n \"/api/saas/events/assign\",\n payload,\n );\n }\n\n /**\n * Deactivate a custom event assignment by name.\n */\n async unassign(name: string): Promise<{ success: boolean; data: any }> {\n return this.post<{ success: boolean; data: any }>(\"/api/saas/events/unassign\", { name });\n }\n\n /**\n * Deactivate multiple custom event assignments simultaneously.\n */\n async unassignBulk(names: string[]): Promise<{ success: boolean; message: string }> {\n return this.post<{ success: boolean; message: string }>(\"/api/saas/events/unassign/bulk\", {\n names,\n });\n }\n\n /**\n * Programmatically trigger an automation workflow by firing a specific event.\n * This matches the event against active Automation Rules and executes linked actions.\n *\n * @param payload - The trigger details (event name, lead phone/email, variables).\n * @returns Trigger response with diagnostic info (eventLogId, matched rules).\n * @example\n * ```typescript\n * await erixClient.events.trigger({\n * trigger: \"webinar_joined\",\n * phone: \"+919876543210\",\n * variables: { webinar_name: \"AI Masterclass\" },\n * createLeadIfMissing: true\n * });\n * ```\n */\n async trigger(payload: TriggerPayload): Promise<TriggerResponse> {\n return this.post<TriggerResponse>(\"/api/saas/workflows/trigger\", payload);\n }\n\n // --- CRM Custom Events ---\n\n /**\n * List all custom event definitions.\n */\n async listCustomEvents<T = any>() {\n return this.get<T>(\"/api/saas/crm/custom-events\");\n }\n\n /**\n * Create or upsert a custom event definition.\n */\n async createCustomEvent<T = any>(payload: {\n name: string;\n displayName: string;\n description?: string;\n }) {\n return this.post<T>(\"/api/saas/crm/custom-events\", payload);\n }\n\n /**\n * Delete a custom event definition.\n */\n async deleteCustomEvent<T = any>(id: string) {\n return this.deleteRequest<T>(`/api/saas/crm/custom-events/${id}`);\n }\n\n /**\n * Manually emit a custom event to trigger workflows based on its definition.\n */\n async emit<T = any>(payload: { eventName: string; leadId: string; data?: any }) {\n return this.post<T>(\"/api/saas/crm/events/emit\", payload);\n }\n}\n","import { APIResource } from \"../resource\";\n\nexport interface SystemHealth {\n status: string;\n version: string;\n env: string;\n uptime: number;\n db: string;\n queueDepth: number;\n timestamp: string;\n}\n\nexport interface ClientHealth {\n clientCode: string;\n services: {\n whatsapp: \"connected\" | \"not_configured\";\n email: \"configured\" | \"not_configured\";\n googleMeet: \"configured\" | \"not_configured\";\n };\n activeAutomations: number;\n queueDepth: number;\n timestamp: string;\n}\n\nexport interface JobStatus {\n jobId: string;\n status: string;\n attempts: number;\n maxAttempts: number;\n lastError: any;\n runAt: string;\n completedAt: string | null;\n failedAt: string | null;\n createdAt: string;\n}\n\n/**\n * Platform and tenant-specific health diagnostics.\n *\n * Access via `ecod.health`.\n */\nexport class Health extends APIResource {\n /**\n * Perform a global platform health check.\n * Verify that the core API, database, and background workers are operational.\n */\n async system(): Promise<SystemHealth> {\n const res = await this.get<{ success: boolean; data: SystemHealth }>(\"/api/saas/health\");\n return res.data;\n }\n\n /**\n * Tenant-specific health check.\n *\n * Identifies correctly configured third-party integrations (WhatsApp, SMTP, Google Meet)\n * and reports active automation counts.\n */\n async clientHealth(): Promise<ClientHealth> {\n const res = await this.get<{ success: boolean; data: ClientHealth }>(\"/api/saas/health/client\");\n return res.data;\n }\n\n /**\n * Alias for clientHealth to match diagnostic terminology.\n */\n async getDiagnosticReport(): Promise<ClientHealth> {\n return this.clientHealth();\n }\n\n /**\n * Lookup the execution status of a background job.\n *\n * Use this to poll for completion of long-running tasks like bulk exports\n * or campaign dispatches.\n *\n * @param jobId - The unique ID of the background job.\n */\n async jobStatus(jobId: string): Promise<JobStatus> {\n const res = await this.get<{ success: boolean; data: JobStatus }>(\n `/api/saas/jobs/status/${jobId}`,\n );\n return res.data;\n }\n}\n","import { APIResource } from \"../resource\";\n\nexport interface LogPaginationQuery {\n page?: number;\n limit?: number;\n trigger?: string;\n status?: \"received\" | \"processing\" | \"completed\" | \"partial\" | \"failed\";\n from?: string;\n to?: string;\n}\n\nexport interface EventLog {\n id: string;\n trigger: string;\n phone?: string;\n email?: string;\n status: \"received\" | \"processing\" | \"completed\" | \"partial\" | \"failed\";\n rulesMatched: number;\n jobsCreated: number;\n meetLink?: string;\n callbackUrl?: string;\n callbackStatus: \"not_required\" | \"sent\" | \"failed\";\n payload: any;\n error?: string;\n idempotencyKey?: string;\n processedAt?: string;\n createdAt: string;\n updatedAt: string;\n}\n\nexport interface CallbackLog {\n id: string;\n callbackUrl: string;\n method: string;\n payload: any;\n jobId?: string;\n enrollmentId?: string;\n responseStatus: number;\n responseBody: string;\n status: \"sent\" | \"failed\" | \"pending_retry\";\n attempts: number;\n lastAttemptAt?: string;\n signature?: string;\n createdAt: string;\n}\n\nexport interface LogResponse<T> {\n success: boolean;\n data: T[];\n pagination: {\n total: number;\n page: number;\n limit: number;\n pages: number;\n };\n}\n\n/**\n * Audit and execution logs for platform events and webhooks.\n *\n * Access via `ecod.logs`.\n */\nexport class Logs extends APIResource {\n /**\n * List event execution logs with optional filtering.\n *\n * Use this to audit automation triggers and debug workflow execution.\n */\n async listEventLogs(query?: LogPaginationQuery): Promise<LogResponse<EventLog>> {\n return this.get<LogResponse<EventLog>>(\"/api/saas/events/logs\", {\n params: query,\n });\n }\n\n /**\n * Get detailed information for a single event execution.\n */\n async getEventLog(id: string): Promise<{ success: boolean; data: EventLog }> {\n return this.get<{ success: boolean; data: EventLog }>(`/api/saas/events/logs/${id}`);\n }\n\n /**\n * List webhook callback logs (outbound responses from ECODrIx to your system).\n */\n async listCallbackLogs(query?: LogPaginationQuery): Promise<LogResponse<CallbackLog>> {\n return this.get<LogResponse<CallbackLog>>(\"/api/saas/callbacks/logs\", {\n params: query,\n });\n }\n\n /**\n * Get high-level execution statistics for the tenant.\n */\n async getStats(): Promise<{ success: boolean; data: any }> {\n return this.get<{ success: boolean; data: any }>(\"/api/saas/events/stats\");\n }\n}\n","import { APIResource } from \"../resource\";\n\nexport interface SendCampaignParams {\n recipients: string[];\n subject: string;\n html: string;\n}\n\nexport class Emails extends APIResource {\n /**\n * Dispatch a bulk email campaign to a list of recipients.\n *\n * @param params - The campaign details (recipients, subject, html).\n * @returns The dispatch result.\n * @example\n * ```typescript\n * await erixClient.marketing.emails.sendCampaign({\n * recipients: [\"user@example.com\"],\n * subject: \"Special Offer\",\n * html: \"<p>Check out our deal!</p>\"\n * });\n * ```\n */\n async sendCampaign<T = any>(params: SendCampaignParams) {\n return this.post<T>(\"/api/saas/marketing/emails/campaign\", params);\n }\n\n /**\n * Send a test verification email (used to verify SMTP functionality).\n */\n async sendTest<T = any>(to: string) {\n return this.post<T>(\"/api/saas/marketing/emails/test\", { to });\n }\n}\nexport class Campaigns extends APIResource {\n /**\n * List all email and SMS marketing campaigns with optional status filtering.\n *\n * @param params - Optional filters (status, limit).\n * @returns Paginated list of campaign objects.\n * @example\n * ```typescript\n * const campaigns = await erixClient.marketing.campaigns.list({ status: \"sent\" });\n * ```\n */\n async list<T = any>(params?: { status?: string; limit?: number }) {\n return this.get<T>(\"/api/saas/marketing/campaigns\", { params } as any);\n }\n\n /**\n * Create a new marketing campaign (Email or SMS).\n *\n * @param payload - Campaign details (name, type, content).\n * @returns The created campaign record.\n * @example\n * ```typescript\n * await erixClient.marketing.campaigns.create({\n * name: \"Spring Sale\",\n * type: \"email\",\n * subject: \"Our Spring Sale is Here!\",\n * html: \"<h1>BIG DEALS!</h1>\"\n * });\n * ```\n */\n async create<T = any>(payload: {\n name: string;\n type: string;\n subject?: string;\n html?: string;\n templateId?: string;\n recipients?: string[];\n }) {\n return this.post<T>(\"/api/saas/marketing/campaigns\", payload);\n }\n\n /**\n * Retrieve full details for a specific marketing campaign.\n *\n * @param campaignId - The unique ID of the campaign.\n * @example\n * ```typescript\n * const campaign = await erixClient.marketing.campaigns.retrieve(\"camp_123\");\n * ```\n */\n async retrieve<T = any>(campaignId: string) {\n return this.get<T>(`/api/saas/marketing/campaigns/${campaignId}`);\n }\n\n /**\n * Update a campaign.\n */\n async update<T = any>(campaignId: string, payload: any) {\n return this.patch<T>(`/api/saas/marketing/campaigns/${campaignId}`, payload);\n }\n\n /**\n * Delete a campaign.\n */\n async delete<T = any>(campaignId: string) {\n return this.deleteRequest<T>(`/api/saas/marketing/campaigns/${campaignId}`);\n }\n\n /**\n * Send a campaign immediately or schedule it for a later date.\n *\n * @param campaignId - The ID of the campaign to dispatch.\n * @param payload - Optional scheduling information (ISO timestamp).\n * @example\n * ```typescript\n * // Send immediately\n * await erixClient.marketing.campaigns.send(\"camp_123\");\n *\n * // Schedule for tomorrow\n * await erixClient.marketing.campaigns.send(\"camp_123\", {\n * scheduledAt: \"2026-04-10T09:00:00Z\"\n * });\n * ```\n */\n async send<T = any>(campaignId: string, payload?: { scheduledAt?: string }) {\n return this.post<T>(`/api/saas/marketing/campaigns/${campaignId}/send`, payload || {});\n }\n\n /**\n * Get detailed delivery and engagement statistics for a campaign.\n * Includes opens, clicks, bounces, and delivery failures.\n *\n * @param campaignId - The ID of the campaign.\n * @returns Stats summary object.\n * @example\n * ```typescript\n * const report = await erixClient.marketing.campaigns.stats(\"camp_123\");\n * console.log(`Open Rate: ${report.openRate}%`);\n * ```\n */\n async stats<T = any>(campaignId: string) {\n return this.get<T>(`/api/saas/marketing/campaigns/${campaignId}/stats`);\n }\n}\n\nexport class WhatsAppMarketing extends APIResource {\n /**\n * Dispatch a template-based WhatsApp message with CRM-integrated variable resolution.\n *\n * Unlike direct WhatsApp sending, this endpoint documentation automatically pulls data from the CRM\n * based on the provided variables mapping.\n *\n * @param params - Template details and recipient phone.\n * @example\n * ```typescript\n * await erixClient.marketing.whatsapp.sendTemplate({\n * phone: \"+919876543210\",\n * templateName: \"order_update\",\n * variables: { \"1\": \"Order #123\" }\n * });\n * ```\n */\n async sendTemplate<T = any>(params: {\n phone: string;\n templateName: string;\n languageCode?: string;\n variables?: Record<string, string>;\n resolvedVariables?: Record<string, string>;\n }) {\n return this.post<T>(\"/api/saas/marketing/whatsapp/send-template\", params);\n }\n}\n\nexport class Marketing extends APIResource {\n public emails: Emails;\n public campaigns: Campaigns;\n public whatsapp: WhatsAppMarketing;\n\n constructor(client: any) {\n super(client);\n this.emails = new Emails(client);\n this.campaigns = new Campaigns(client);\n this.whatsapp = new WhatsAppMarketing(client);\n }\n}\n","import axios from \"axios\";\nimport { APIResource } from \"../resource\";\n\n/**\n * Options for the `upload()` elite helper.\n */\nexport interface UploadOptions {\n /**\n * The destination folder key in R2.\n * @example \"customer_documents\" | \"avatars\" | \"invoices\"\n */\n folder: string;\n /**\n * The desired filename, including extension.\n * @example \"contract.pdf\" | \"profile.jpg\"\n */\n filename: string;\n /**\n * The MIME type of the file.\n * @example \"application/pdf\" | \"image/jpeg\" | \"video/mp4\"\n */\n contentType: string;\n}\n\n/**\n * Cloudflare R2-backed media resource.\n *\n * Access via `ecod.media`.\n *\n * The `upload()` method is the recommended approach. It acts as a client-side\n * orchestrator: it fetches a presigned URL from the backend, uploads directly\n * to R2 (bypassing the API server), then confirms the upload — all in one call.\n *\n * @example\n * ```typescript\n * const { data } = await ecod.media.upload(fileBuffer, {\n * folder: \"invoices\",\n * filename: \"invoice-001.pdf\",\n * contentType: \"application/pdf\",\n * });\n * console.log(data.url); // → https://cdn.ecodrix.com/invoices/invoice-001.pdf\n * ```\n */\nexport class Media extends APIResource {\n /**\n * Get current storage usage metrics for the tenant.\n *\n * @returns `{ usedMB, limitMB, fileCount }`\n *\n * @example\n * ```typescript\n * const { data } = await ecod.media.getUsage();\n * console.log(`${data.usedMB} / ${data.limitMB} MB used`);\n * ```\n */\n async getUsage() {\n return this.get(\"/api/saas/storage/usage\");\n }\n\n /**\n * Create a new top-level folder in the tenant's R2 bucket.\n *\n * @param name - Folder name (alphanumeric, hyphens, underscores).\n *\n * @example\n * ```typescript\n * await ecod.media.createFolder(\"patient_records\");\n * ```\n */\n async createFolder(name: string) {\n return this.post(\"/api/saas/storage/folders\", { name });\n }\n\n /**\n * List files within a folder, with optional date / search filtering.\n *\n * @param folder - The folder name to list, **or `\"*\"` to fetch all folders**\n * for the tenant in a single call (returns a merged flat list with a\n * `folder` field on each file so callers can group/filter client-side).\n * @param params - Optional `year`, `month`, and keyword search `q` filters.\n * @returns `{ data: { files, count, totalSizeBytes } }`.\n *\n * @example Single folder\n * ```typescript\n * const { data } = await ecod.media.list(\"invoices\", { q: \"contract\" });\n * // data.files → files only from the \"invoices\" folder\n * ```\n *\n * @example All folders\n * ```typescript\n * const { data } = await ecod.media.list(\"*\");\n * // data.files → merged files from every folder the tenant has\n * // Each file has a `folder` field indicating its source folder\n * ```\n */\n async list(folder: string, params?: { year?: string; month?: string; q?: string }) {\n return this.get(`/api/saas/storage/files/${folder}`, { params } as any);\n }\n\n /**\n * Delete a file from R2 by its storage key.\n *\n * @param key - The full storage key of the file (e.g. `\"invoices/contract.pdf\"`).\n *\n * @example\n * ```typescript\n * await ecod.media.delete(\"invoices/old-contract.pdf\");\n * ```\n */\n async delete(key: string) {\n return this.deleteRequest(\"/api/saas/storage/files\", { params: { key } });\n }\n\n /**\n * Request a temporary presigned download URL for a private file.\n *\n * @param key - The full storage key of the file.\n * @returns `{ url }` — a time-limited download URL.\n *\n * @example\n * ```typescript\n * const { data } = await ecod.media.getDownloadUrl(\"invoices/contract.pdf\");\n * // → { url: \"https://cdn.ecodrix.com/...?token=...\" }\n * ```\n */\n async getDownloadUrl(key: string) {\n return this.post(\"/api/saas/storage/download-url\", { key });\n }\n\n /**\n * **Elite Upload Helper** — uploads a file to Cloudflare R2 in a single call.\n *\n * This orchestrates 3 steps transparently:\n * 1. Fetch a presigned `PUT` URL from the ECODrIx backend.\n * 2. Upload the file _directly_ to R2 (no API proxy, maximum throughput).\n * 3. Confirm the upload with the backend so it is indexed and tracked.\n *\n * Works with Node.js `Buffer`, browser `File`/`Blob`, or any stream-like\n * object that Axios can PUT.\n *\n * @param file - The file data to upload.\n * @param options - Folder, filename, and content type.\n * @returns Confirmed file metadata including `key` and `url`.\n *\n * @example Node.js\n * ```typescript\n * import { readFileSync } from \"fs\";\n * const buf = readFileSync(\"./invoice.pdf\");\n * const { data } = await ecod.media.upload(buf, {\n * folder: \"invoices\",\n * filename: \"invoice-001.pdf\",\n * contentType: \"application/pdf\",\n * });\n * ```\n *\n * @example Browser\n * ```typescript\n * const file = inputElement.files[0];\n * const { data } = await ecod.media.upload(file, {\n * folder: \"avatars\",\n * filename: file.name,\n * contentType: file.type,\n * });\n * ```\n */\n async upload(file: any, options: UploadOptions): Promise<any> {\n // Step 1: Get presigned URL\n const response = await this.post<any>(\"/api/saas/storage/upload-url\", options);\n const { uploadUrl, key } = response.data;\n\n // Step 2: Upload directly to R2 (bypasses the API server for performance)\n await axios.put(uploadUrl, file, {\n headers: { \"Content-Type\": options.contentType },\n });\n\n const sizeBytes = file.size || file.byteLength || 0;\n\n // Step 3: Confirm with backend\n return this.post(\"/api/saas/storage/confirm-upload\", { key, sizeBytes });\n }\n}\n\n/** @deprecated Use Media instead */\nexport class MediaResource extends Media {}\n","import { APIResource } from \"../resource\";\n\n/**\n * Parameters for scheduling a new Google Meet appointment.\n */\nexport interface CreateMeetingParams {\n /** The CRM Lead ID this meeting belongs to. */\n leadId: string;\n /** Full name of the external participant. */\n participantName: string;\n /** Phone number of the participant in E.164 format. */\n participantPhone: string;\n /**\n * Meeting start time.\n * @example new Date(\"2026-04-10T10:00:00.000Z\")\n */\n startTime: Date | string;\n /**\n * Meeting end time.\n * @example new Date(\"2026-04-10T10:30:00.000Z\")\n */\n endTime: Date | string;\n /** Arbitrary metadata to attach to the meeting record. */\n metadata?: Record<string, any>;\n}\n\n/**\n * Parameters for updating an existing meeting.\n */\nexport interface UpdateMeetingParams {\n /**\n * Update the meeting status.\n * @example \"scheduled\" | \"completed\" | \"cancelled\"\n */\n status?: string;\n /** Update the payment status for paid consultations. */\n paymentStatus?: string;\n /** New start time for rescheduling. */\n startTime?: Date | string;\n /** New end time for rescheduling. */\n endTime?: Date | string;\n /** Duration in minutes. */\n duration?: number;\n}\n\n/**\n * Google Meet appointment scheduling resource.\n *\n * Access via `ecod.meet`.\n *\n * @example\n * ```typescript\n * const { data } = await ecod.meet.create({\n * leadId: \"64abc...\",\n * participantName: \"Alice\",\n * participantPhone: \"+919876543210\",\n * startTime: \"2026-04-10T10:00:00Z\",\n * endTime: \"2026-04-10T10:30:00Z\",\n * });\n * console.log(data.meetLink); // → https://meet.google.com/abc-defg-hij\n * ```\n */\nexport class Meetings extends APIResource {\n /**\n * Schedule a new Google Meet with a lead.\n *\n * The backend automatically creates a Google Calendar event and generates\n * a Meet link, then sends confirmation notifications via WhatsApp.\n *\n * @param data - Meeting details.\n * @returns The created Meeting document including `meetLink`.\n *\n * @example\n * ```typescript\n * const { data } = await ecod.meet.create({\n * leadId: \"64abc...\",\n * participantName: \"Alice\",\n * participantPhone: \"+91...\",\n * startTime: \"2026-04-10T10:00:00Z\",\n * endTime: \"2026-04-10T10:30:00Z\",\n * });\n * ```\n */\n async create(data: CreateMeetingParams): Promise<any> {\n return this.post(\"/api/saas/meet\", data);\n }\n\n /**\n * List all meetings for the tenant, with optional filters.\n *\n * @param params - `leadId` to filter by lead; `status` to filter by state.\n * @returns Array of Meeting documents.\n *\n * @example\n * ```typescript\n * const { data } = await ecod.meet.list({ status: \"scheduled\" });\n * ```\n */\n async list(params?: { leadId?: string; status?: string }): Promise<any> {\n return this.get(\"/api/saas/meet\", { params } as any);\n }\n\n /**\n * Retrieve the full details for a specific meeting.\n *\n * @param meetingId - The unique meeting ID.\n * @returns The Meeting document.\n *\n * @example\n * ```typescript\n * const { data } = await ecod.meet.retrieve(\"meeting_id\");\n * ```\n */\n async retrieve(meetingId: string): Promise<any> {\n return this.get(`/api/saas/meet/${meetingId}`);\n }\n\n /**\n * Update or reschedule an existing meeting.\n *\n * Partial updates are supported — only supply the fields you wish to change.\n *\n * @param meetingId - The meeting to update.\n * @param data - Fields to update.\n * @returns The updated Meeting document.\n *\n * @example\n * ```typescript\n * // Reschedule\n * await ecod.meet.update(\"meeting_id\", {\n * startTime: \"2026-04-11T11:00:00Z\",\n * endTime: \"2026-04-11T11:30:00Z\",\n * });\n * ```\n */\n async update<T = any>(meetingId: string, data: UpdateMeetingParams) {\n return this.patch<T>(`/api/saas/meet/${meetingId}`, data);\n }\n\n /**\n * Reschedule an existing meeting. Provides explicit method for time modifications.\n */\n async reschedule<T = any>(\n meetingId: string,\n params: { startTime: Date | string; endTime: Date | string; duration?: number },\n ) {\n return this.patch<T>(`/api/saas/meet/${meetingId}`, params);\n }\n\n /**\n * Cancel a meeting. This sets the meeting status to `\"cancelled\"`.\n *\n * @param meetingId - The meeting to cancel.\n *\n * @example\n * ```typescript\n * await ecod.meet.delete(\"meeting_id\");\n * ```\n */\n async delete(meetingId: string): Promise<any> {\n return this.update(meetingId, { status: \"cancelled\" });\n }\n}\n","import { APIResource } from \"../resource\";\n\n/**\n * Filters for querying event and automation execution logs.\n */\nexport interface LogFilter {\n /** Page number for pagination (1-indexed). */\n page?: number;\n /** Maximum number of records to return per page. */\n limit?: number;\n /**\n * Filter by automation trigger name.\n * @example \"lead_created\" | \"appointment_booked\"\n */\n trigger?: string;\n /**\n * Filter by execution status.\n * @example \"success\" | \"failed\" | \"pending\"\n */\n status?: string;\n /** Filter logs associated with a specific phone number. */\n phone?: string;\n /** Start of the date range (inclusive). ISO 8601 or Date object. */\n startDate?: string | Date;\n /** End of the date range (inclusive). ISO 8601 or Date object. */\n endDate?: string | Date;\n}\n\n/**\n * Automation event log and provider callback resource.\n *\n * Access via `ecod.notifications`.\n *\n * This resource is **read-only**. It exposes platform audit trails — useful\n * for debugging automation failures, monitoring webhook callbacks, and\n * building internal ops dashboards.\n *\n * @example\n * ```typescript\n * // Find failed automations in April\n * const { data } = await ecod.notifications.listLogs({\n * status: \"failed\",\n * startDate: \"2026-04-01\",\n * endDate: \"2026-04-30\",\n * });\n * ```\n */\nexport class Notifications extends APIResource {\n /**\n * List automation execution logs with optional filtering.\n *\n * Each log entry represents one automation run triggered by a platform event.\n * Filter by `status: \"failed\"` to build a failure alerting pipeline.\n *\n * @param params - Optional filter criteria.\n * @returns Paginated list of event log objects.\n *\n * @example\n * ```typescript\n * const { data: failed } = await ecod.notifications.listLogs({\n * status: \"failed\",\n * trigger: \"lead_created\",\n * limit: 50,\n * });\n * ```\n */\n async listLogs(params?: LogFilter) {\n return this.get(\"/api/saas/events/logs\", { params } as any);\n }\n\n /**\n * Retrieve the full details for a single automation event log entry.\n *\n * @param logId - The unique log ID.\n * @returns A single event log document including the payload and error trace.\n *\n * @example\n * ```typescript\n * const { data } = await ecod.notifications.retrieveLog(\"log_64abc...\");\n * console.log(data.error); // → \"Provider timeout after 30s\"\n * ```\n */\n async retrieveLog(logId: string) {\n return this.get(`/api/saas/events/logs/${logId}`);\n }\n\n /**\n * Get a summary statistics object for automation event execution.\n *\n * @param params - Optional date range for the summary window.\n * @returns `{ total, success, failed, pending }` counts.\n *\n * @example\n * ```typescript\n * const { data: stats } = await ecod.notifications.getStats({\n * startDate: \"2026-04-01\",\n * endDate: \"2026-04-30\",\n * });\n * console.log(`Failed: ${stats.failed} / ${stats.total}`);\n * ```\n */\n async getStats(params?: { startDate?: string; endDate?: string }) {\n return this.get(\"/api/saas/events/stats\", { params } as any);\n }\n\n /**\n * List external provider webhook callback logs.\n *\n * These are inbound HTTP callbacks from third-party providers\n * (payment gateways, email services, etc.) stored for audit purposes.\n *\n * @param params - Pagination and date filter options.\n * @returns Paginated list of callback log records.\n *\n * @example\n * ```typescript\n * const { data } = await ecod.notifications.listCallbacks({ limit: 20 });\n * ```\n */\n async listCallbacks(params?: Omit<LogFilter, \"trigger\" | \"phone\">) {\n return this.get(\"/api/saas/callbacks/logs\", { params } as any);\n }\n\n // --- CRM Notifications (Alerts) ---\n // Backend routes mounted at /api/crm — see crm.router.ts + notification.routes.ts\n\n /**\n * List unread CRM notifications and alerts (e.g., lead assignments, system alerts).\n *\n * @param params - Optional filters (limit, unreadOnly).\n * @returns Paginated list of notification objects.\n * @example\n * ```typescript\n * const alerts = await erixClient.notifications.listAlerts({ unreadOnly: true });\n * ```\n */\n async listAlerts<T = any>(params?: { limit?: number; unreadOnly?: boolean }) {\n return this.get<T>(\"/api/crm/notifications\", { params } as any);\n }\n\n /**\n * Dismiss/mark a specific notification alert as read.\n *\n * @param notificationId - The unique ID of the notification.\n * @example\n * ```typescript\n * await erixClient.notifications.dismissAlert(\"alert_123\");\n * ```\n */\n async dismissAlert<T = any>(notificationId: string) {\n return this.patch<T>(`/api/crm/notifications/${notificationId}/dismiss`);\n }\n\n /**\n * Clear all notifications for the current tenant immediately.\n *\n * @example\n * ```typescript\n * await erixClient.notifications.clearAllAlerts();\n * ```\n */\n async clearAllAlerts<T = any>() {\n return this.deleteRequest<T>(\"/api/crm/notifications/clear-all\");\n }\n\n /**\n * Retry an action from a notification (e.g. failed automation send).\n *\n * @param notificationId - The unique ID of the notification.\n * @example\n * ```typescript\n * await erixClient.notifications.retryAction(\"alert_123\");\n * ```\n */\n async retryAction<T = any>(notificationId: string) {\n return this.post<T>(`/api/crm/notifications/${notificationId}/retry`, {});\n }\n}\n","import { APIResource } from \"../resource\";\n\nexport interface JobStats {\n waiting: number;\n active: number;\n completed: number;\n failed: number;\n delayed: number;\n}\n\nexport class Queue extends APIResource {\n /**\n * List all background jobs that have failed execution.\n *\n * @returns Array of failed job objects.\n * @example\n * ```typescript\n * const failed = await erixClient.queue.listFailed();\n * ```\n */\n async listFailed<T = any>() {\n return this.get<T>(\"/api/saas/admin/queue/failed\");\n }\n\n /**\n * Get real-time health statistics for the background job queue (waiting, active, failed).\n *\n * @returns Queue statistics summary.\n * @example\n * ```typescript\n * const stats = await erixClient.queue.getStats();\n * console.log(`Active Jobs: ${stats.active}`);\n * ```\n */\n async getStats<T = JobStats>() {\n return this.get<T>(\"/api/saas/admin/queue/stats\");\n }\n\n /**\n * Manually retry a failed background job.\n *\n * @param jobId - The unique ID of the failed job.\n * @example\n * ```typescript\n * await erixClient.queue.retryJob(\"job_123\");\n * ```\n */\n async retryJob<T = any>(jobId: string) {\n return this.post<T>(`/api/saas/admin/queue/${jobId}/retry`, {});\n }\n\n /**\n * Remove a job from the queue.\n *\n * @param jobId - The unique ID of the job to delete.\n * @example\n * ```typescript\n * await erixClient.queue.deleteJob(\"job_123\");\n * ```\n */\n async deleteJob<T = any>(jobId: string) {\n return this.deleteRequest<T>(`/api/saas/admin/queue/${jobId}`);\n }\n}\n","import { APIResource } from \"../resource\";\n\nexport class Folders extends APIResource {\n /**\n * Create a new folder in the tenant's cloud storage.\n *\n * @param name - The name of the folder to create.\n * @example\n * ```typescript\n * await erixClient.storage.folders.create(\"Invoices\");\n * ```\n */\n async create<T = any>(name: string) {\n return this.post<T>(\"/api/saas/storage/folders\", { name });\n }\n\n /**\n * Delete a folder and its contents.\n */\n async delete<T = any>(folderPath: string) {\n return this.deleteRequest<T>(`/api/saas/storage/folders/${encodeURIComponent(folderPath)}`);\n }\n}\n\nexport class Files extends APIResource {\n /**\n * List files within a specific folder.\n *\n * @param folder - The folder name or path.\n * @param params - Optional year/month filters for organized storage.\n * @example\n * ```typescript\n * const files = await erixClient.storage.files.list(\"Invoices\", { year: \"2026\" });\n * ```\n */\n async list<T = any>(folder: string, params?: { year?: string; month?: string }) {\n return this.get<T>(`/api/saas/storage/files/${folder}`, { params } as any);\n }\n\n /**\n * Get a presigned upload URL for direct-to-cloud browser uploads.\n * This allows the client to upload files directly to R2/S3 without hitting the backend.\n *\n * @param params - Upload parameters (folder, filename, contentType).\n * @example\n * ```typescript\n * const { data } = await erixClient.storage.files.getUploadUrl({\n * folder: \"Invoices\",\n * filename: \"inv_1.pdf\",\n * contentType: \"application/pdf\"\n * });\n * // Now use data.url with a PUT request\n * ```\n */\n async getUploadUrl<T = any>(params: {\n folder: string;\n filename: string;\n contentType: string;\n }) {\n return this.post<T>(\"/api/saas/storage/upload-url\", params);\n }\n\n /**\n * Notify backend after a successful direct browser upload.\n */\n async confirmUpload<T = any>(params: { key: string; sizeBytes: number }) {\n return this.post<T>(\"/api/saas/storage/confirm-upload\", params);\n }\n\n /**\n * Get a presigned download URL for an R2 key.\n */\n async getDownloadUrl<T = any>(key: string) {\n return this.post<T>(\"/api/saas/storage/download-url\", { key });\n }\n\n /**\n * Delete a file by key.\n */\n async delete(key: string) {\n return this.deleteRequest(\"/api/saas/storage/files\", { params: { key } } as any);\n }\n}\n\nexport class Storage extends APIResource {\n public folders: Folders;\n public files: Files;\n\n constructor(client: any) {\n super(client);\n this.folders = new Folders(client);\n this.files = new Files(client);\n }\n\n /**\n * Get tenant storage usage and quota limitations.\n */\n async usage<T = any>() {\n return this.get<T>(\"/api/saas/storage/usage\");\n }\n}\n","import { APIError } from \"../error\";\n\nexport class WebhookSignatureError extends APIError {\n constructor(message: string) {\n super(message, 400, \"invalid_signature\");\n this.name = \"WebhookSignatureError\";\n }\n}\n\n/**\n * Validates and constructs webhook events sent by the ECODrIx platform.\n * Ensures the payload has not been tampered with.\n *\n * @example\n * ```typescript\n * import { ecod } from \"./services/ecodrix\";\n *\n * app.post(\"/api/webhooks\", async (req, res) => {\n * try {\n * const event = await ecod.webhooks.constructEvent(\n * req.rawBody,\n * req.headers[\"x-ecodrix-signature\"],\n * process.env.ECOD_WEBHOOK_SECRET\n * );\n * console.log(\"Verified event:\", event.type);\n * res.send({ received: true });\n * } catch (err) {\n * res.status(400).send(`Webhook Error: ${err.message}`);\n * }\n * });\n * ```\n */\nexport class Webhooks {\n /**\n * Cryptographically validates a webhook payload.\n * Note: This method dynamically imports Node's `crypto` module, meaning it will only execute gracefully in a Server environment.\n *\n * @param payload - The raw request body as a string or Buffer.\n * @param signature - The `x-ecodrix-signature` header value.\n * @param secret - The webhook signing secret for your tenant.\n * @returns The parsed JSON object of the event if the signature is valid.\n * @throws WebhookSignatureError if the validation fails.\n */\n public async constructEvent(\n payload: string | Buffer,\n signature: string | string[] | undefined,\n secret: string,\n ): Promise<any> {\n if (!signature) {\n throw new WebhookSignatureError(\"No webhook signature provided\");\n }\n\n let sig = Array.isArray(signature) ? signature[0] : signature;\n if (sig.startsWith(\"sha256=\")) {\n sig = sig.slice(7);\n }\n\n try {\n // Dynamic import ensures Isomorphic bundles (like Vite UI) don't crash on import,\n // and only throw if someone incorrectly tries to verify a webhook in the browser.\n const crypto = await import(\"node:crypto\");\n\n const hmac = crypto.createHmac(\"sha256\", secret);\n const digest = hmac.update(payload).digest(\"hex\");\n\n const isValid = crypto.timingSafeEqual(Buffer.from(digest), Buffer.from(sig));\n\n if (!isValid) {\n throw new WebhookSignatureError(\"Invalid webhook signature provided\");\n }\n\n return JSON.parse(payload.toString(\"utf8\"));\n } catch (error: any) {\n if (error instanceof WebhookSignatureError) {\n throw error;\n }\n throw new WebhookSignatureError(`Webhook payload parsing failed: ${error.message}`);\n }\n }\n}\n","import { APIResource } from \"../../resource\";\n\nexport interface CreateBroadcastParams {\n /** Optional name for the broadcast campaign */\n name?: string;\n /** Name of the Meta template to send */\n templateName: string;\n /** Language code (defaults to en_US) */\n templateLanguage?: string;\n /** List of recipients with their phone numbers and variable overrides */\n recipients: {\n phone: string;\n variables?: string[];\n }[];\n}\n\nexport class Broadcasts extends APIResource {\n /**\n * List past and active WhatsApp broadcast campaigns.\n *\n * @param params - Optional filter parameters (page, limit, status).\n * @returns Paginated list of broadcast records.\n * @example\n * ```typescript\n * const broadcasts = await erixClient.whatsapp.broadcasts.list({ limit: 10 });\n * ```\n */\n async list<T = any>(params?: Record<string, any>) {\n return this.get<T>(\"/api/saas/chat/broadcasts\", { params } as any);\n }\n\n /**\n * Retrieve full details and real-time stats for a specific broadcast campaign.\n *\n * @param id - The unique identifier of the broadcast.\n * @returns The broadcast record including sent/failed counts.\n * @example\n * ```typescript\n * const stats = await erixClient.whatsapp.broadcasts.retrieve(\"bc_123\");\n * console.log(`Success Rate: ${(stats.sentCount / stats.totalRecipients) * 100}%`);\n * ```\n */\n async retrieve<T = any>(id: string) {\n return this.get<T>(`/api/saas/chat/broadcasts/${id}`);\n }\n\n /**\n * Create a new broadcast campaign to send template messages to multiple recipients.\n *\n * @param params - Broadcast configuration (name, templateName, recipients).\n * @returns The newly created broadcast record.\n * @example\n * ```typescript\n * await erixClient.whatsapp.broadcasts.create({\n * name: \"Spring Sale\",\n * templateName: \"promo_code\",\n * recipients: [\n * { phone: \"+919876543210\", variables: [\"SAVE10\"] }\n * ]\n * });\n * ```\n */\n async create<T = any>(params: CreateBroadcastParams) {\n return this.post<T>(\"/api/saas/chat/broadcast\", params);\n }\n\n /**\n * Update broadcast metadata, such as its name or administrative status.\n *\n * @param id - The unique ID of the broadcast.\n * @param data - The fields to update (name, status).\n * @example\n * ```typescript\n * await erixClient.whatsapp.broadcasts.update(\"bc_123\", { name: \"Revised Spring Sale\" });\n * ```\n */\n async update<T = any>(id: string, data: { name?: string; status?: string }) {\n return this.patch<T>(`/api/saas/chat/broadcasts/${id}`, data);\n }\n\n /**\n * Delete a broadcast campaign record.\n * Note: This does not cancel messages already in flight but removes the record from the dashboard.\n *\n * @param id - The unique ID of the broadcast.\n * @example\n * ```typescript\n * await erixClient.whatsapp.broadcasts.delete(\"bc_123\");\n * ```\n */\n async delete<T = any>(id: string) {\n return this.deleteRequest<T>(`/api/saas/chat/broadcasts/${id}`);\n }\n}\n","import { APIResource } from \"../../resource\";\n\nexport interface ListParams {\n limit?: number;\n before?: string;\n after?: string;\n status?: string;\n}\n\nexport class Conversations extends APIResource {\n /**\n * List conversations for the tenant.\n * @deprecated Use `list` method from `ErixClient` instead.\n * @param params - List parameters.\n * @returns List of conversations.\n * @example\n * ```typescript\n * import { ErixClient } from \"erix-react\";\n * const erixClient = new ErixClient({ apiKey: \"YOUR_API_KEY\" });\n * const conversations = await erixClient.whatsapp.conversations.list();\n * ```\n */\n async list<T = any>(params?: ListParams) {\n return this.get<T>(\"/api/saas/chat/conversations\", { params } as any);\n }\n\n /**\n * Create a new conversation explicitly.\n *\n * @param params - Conversation details.\n * @example\n * ```typescript\n * const conversation = await erixClient.whatsapp.conversations.create({\n * phone: \"+919876543210\",\n * name: \"John Doe\"\n * });\n * ```\n */\n async create<T = any>(params: { phone: string; name?: string }) {\n return this.post<T>(\"/api/saas/chat/conversations\", params);\n }\n\n /**\n * Retrieve details of a specific conversation.\n *\n * @param conversationId - The unique ID of the conversation.\n * @example\n * ```typescript\n * const conversation = await erixClient.whatsapp.conversations.retrieve(\"conv_123\");\n * ```\n */\n async retrieve<T = any>(conversationId: string) {\n return this.get<T>(`/api/saas/chat/conversations/${conversationId}`);\n }\n\n /**\n * Get messages for a specific conversation.\n *\n * @param conversationId - The unique ID of the conversation.\n * @param params - Pagination and filter parameters.\n * @example\n * ```typescript\n * const messages = await erixClient.whatsapp.conversations.messages(\"conv_123\", { limit: 50 });\n * ```\n */\n async messages<T = any>(conversationId: string, params?: ListParams) {\n return this.get<T>(`/api/saas/chat/conversations/${conversationId}/messages`, {\n params,\n } as any);\n }\n\n /**\n * Link a conversation to a lead in the CRM.\n *\n * @param conversationId - The unique ID of the conversation.\n * @param leadId - The unique ID of the lead to link.\n * @param leadData - Optional additional lead metadata.\n * @example\n * ```typescript\n * await erixClient.whatsapp.conversations.linkLead(\"conv_123\", \"lead_456\");\n * ```\n */\n async linkLead<T = any>(conversationId: string, leadId: string, leadData?: any) {\n return this.post<T>(`/api/saas/chat/conversations/${conversationId}/link-lead`, {\n leadId,\n leadData,\n });\n }\n\n /**\n * Mark a conversation as read (clear unread count).\n *\n * @param conversationId - The unique ID of the conversation.\n * @example\n * ```typescript\n * await erixClient.whatsapp.conversations.markRead(\"conv_123\");\n * ```\n */\n async markRead<T = any>(conversationId: string) {\n return this.post<T>(`/api/saas/chat/conversations/${conversationId}/read`, {});\n }\n\n /**\n * Delete a conversation.\n *\n * @param conversationId - The unique ID of the conversation.\n * @example\n * ```typescript\n * await erixClient.whatsapp.conversations.delete(\"conv_123\");\n * ```\n */\n async delete(conversationId: string) {\n return this.deleteRequest(`/api/saas/chat/conversations/${conversationId}`);\n }\n\n /**\n * Bulk delete conversations.\n *\n * @param ids - Array of conversation IDs to delete.\n * @example\n * ```typescript\n * await erixClient.whatsapp.conversations.bulkDelete([\"conv_1\", \"conv_2\"]);\n * ```\n */\n async bulkDelete<T = any>(ids: string[]) {\n return this.post<T>(\"/api/saas/chat/conversations/bulk-delete\", { ids });\n }\n}\n","import { APIResource } from \"../../resource\";\n\n/**\n * Parameters for sending a free-form WhatsApp message.\n */\nexport interface SendMessageParams {\n /**\n * Recipient's phone number in E.164 format.\n * @example \"+919876543210\"\n */\n to?: string;\n /**\n * The unique ID of the conversation. If supplied, `to` is resolved automatically.\n */\n conversationId?: string;\n /** Plain text body of the message. */\n text?: string;\n /** Public URL of the media asset to send. */\n mediaUrl?: string;\n /** MIME category of the media. */\n mediaType?: \"image\" | \"video\" | \"audio\" | \"document\";\n /** The `messageId` of the message to reply to (quoted replies). */\n replyToId?: string;\n /** Filename shown to the recipient (required for `document` type). */\n filename?: string;\n /** Arbitrary metadata stored with the message record. */\n metadata?: Record<string, any>;\n /** Template name for template messages. */\n templateName?: string;\n /** Template language for template messages. */\n templateLanguage?: string;\n /** Alternative language parameter. */\n language?: string;\n /** Template variables. */\n variables?: string[];\n}\n\n/**\n * Parameters for sending a pre-approved WhatsApp Business template.\n */\nexport interface SendTemplateParams {\n /**\n * Recipient's phone number in E.164 format.\n * @example \"+919876543210\"\n */\n to?: string;\n /**\n * The unique ID of the conversation.\n */\n conversationId?: string;\n /** The exact template name as approved in Meta Business Manager. */\n templateName: string;\n /**\n * BCP-47 language code for the template.\n * @default \"en_US\"\n */\n language?: string;\n /**\n * Ordered array of variable substitutions for template placeholders.\n * @example [\"Alice\", \"10 April 2026\", \"10:00 AM\"]\n */\n variables?: string[];\n /** Optional header media URL (for templates with media headers). */\n mediaUrl?: string;\n /** Media type for the header (e.g. \"image\", \"document\"). */\n mediaType?: string;\n /** User ID of the agent sending the message. */\n userId?: string;\n /** Optional filename for media headers. */\n filename?: string;\n /** Template language for template messages. */\n templateLanguage?: string;\n}\n\n/**\n * WhatsApp outbound messaging resource.\n *\n * Access via `ecod.whatsapp.messages`.\n *\n * @example\n * ```typescript\n * await ecod.whatsapp.messages.send({\n * to: \"+919876543210\",\n * text: \"Your appointment is confirmed!\",\n * });\n * ```\n */\n/**\n * Resolved media metadata returned by any upload endpoint.\n * `variants` is only present for raster images (JPEG, PNG, WebP, AVIF, GIF).\n */\nexport interface ChatMediaMeta {\n /** Raw CDN URL — always present, all media types */\n url: string;\n /** Categorical type — \"image\" | \"video\" | \"audio\" | \"document\" */\n type: \"image\" | \"video\" | \"audio\" | \"document\";\n /** Cloudflare-optimised variant URLs. Only present for raster images. */\n variants?: {\n /** 150px WebP — use for list thumbnails and chat bubbles */\n thumb: string;\n /** 600px WebP — use for modal previews */\n medium: string;\n /** 1200px WebP — use for hero or full-screen views */\n full: string;\n /** Original CDN URL, no transformation */\n raw: string;\n };\n /** Storage key within the tenant bucket */\n key?: string;\n /** Original filename */\n fileName?: string;\n}\n\nexport class Messages extends APIResource {\n /**\n * Send a free-text or media message to a WhatsApp number.\n *\n * For text-only messages, supply `text`. For media, supply `mediaUrl`\n * and `mediaType`. Both can be combined in a single message.\n *\n * @param params - Message parameters including recipient, text, and media.\n * @returns The created message record from the database.\n *\n * @example Send a simple text message\n * ```typescript\n * await erixClient.whatsapp.messages.send({\n * to: \"+919876543210\",\n * text: \"Hello from Ecodrix!\",\n * });\n * ```\n *\n * @example Send an image with a caption\n * ```typescript\n * await erixClient.whatsapp.messages.send({\n * to: \"+919876543210\",\n * text: \"Check out this flyer\",\n * mediaUrl: \"https://example.com/flyer.jpg\",\n * mediaType: \"image\",\n * });\n * ```\n */\n async send<T = any>(params: SendMessageParams) {\n return this.post<T>(\"/api/saas/chat/send\", params);\n }\n\n /**\n * Send a pre-approved WhatsApp Business template message.\n *\n * Templates must be approved in Meta Business Manager before they can be sent.\n * Variable placeholders (e.g., {{1}}, {{2}}) are replaced with values from the\n * `variables` array in order.\n *\n * @param params - Template message configuration (name, language, variables).\n * @returns The created message record.\n *\n * @example\n * ```typescript\n * await erixClient.whatsapp.messages.sendTemplate({\n * to: \"+919876543210\",\n * templateName: \"welcome_user\",\n * language: \"en_US\",\n * variables: [\"Alice\"], // Replaces {{1}} in template\n * });\n * ```\n */\n async sendTemplate<T = any>(params: SendTemplateParams) {\n return this.post<T>(\"/api/saas/chat/send\", {\n ...params,\n templateLanguage: params.language || params.templateLanguage || \"en_US\",\n });\n }\n\n /**\n * Star or unstar a message.\n *\n * @param messageId - The ID of the message.\n * @param isStarred - Boolean indicating whether to star or unstar.\n */\n async star<T = any>(messageId: string, isStarred: boolean) {\n return this.post<T>(`/api/saas/chat/messages/${messageId}/star`, {\n isStarred,\n });\n }\n\n /**\n * React to a message with an emoji.\n *\n * @param messageId - The ID of the message.\n * @param reaction - The emoji (e.g. \"👍\") to react with, or empty string to remove.\n */\n async react<T = any>(messageId: string, reaction: string) {\n return this.post<T>(`/api/saas/chat/messages/${messageId}/react`, {\n reaction,\n });\n }\n\n /**\n * Mark all messages in a conversation as read (double-tick).\n *\n * @param conversationId - The conversation to mark as read.\n *\n * @example\n * ```typescript\n * await ecod.whatsapp.messages.markRead(\"conv_64abc...\");\n * ```\n */\n async markRead(conversationId: string) {\n return this.post(`/api/saas/chat/conversations/${conversationId}/read`);\n }\n\n /**\n * Upload a media file for WhatsApp chat.\n *\n * Works with any file type — image, video, audio, or document.\n * For raster images the response includes Cloudflare-optimised `variants`\n * (thumb 150px, medium 600px, full 1200px). Non-image types return only `url`.\n *\n * @param file - The file to upload (File, Blob, or Buffer).\n * @returns Full media metadata `{ url, type, variants?, key, fileName }`.\n *\n * @example\n * ```typescript\n * const file = input.files[0];\n * const { data } = await ecod.whatsapp.messages.upload(file);\n * // For images: data.variants.thumb → 150px WebP from Cloudflare\n * // For video/audio: use data.url directly in <video> or <audio>\n * ```\n */\n async upload(file: any): Promise<{ success: boolean; data: ChatMediaMeta }> {\n const formData = new FormData();\n formData.append(\"file\", file);\n\n return this.post<{ success: boolean; data: ChatMediaMeta }>(\"/api/saas/chat/upload\", formData, {\n headers: {\n \"Content-Type\": \"multipart/form-data\",\n },\n });\n }\n}\n","import { APIResource } from \"../../resource\";\nimport type { ResourceManifest } from \"../../types/metadata\";\n\nexport interface TemplateMapping {\n mappings: any[];\n onEmptyVariable: string;\n}\n\nexport class Templates extends APIResource {\n /**\n * List all WhatsApp message templates in the tenant database.\n *\n * @param params - Optional filter parameters (status, mappingStatus, channel).\n * @returns List of message templates.\n * @example\n * ```typescript\n * const templates = await erixClient.whatsapp.templates.list({ status: \"APPROVED\" });\n * ```\n */\n async list<T = any>(params?: {\n status?: string;\n mappingStatus?: string;\n channel?: string;\n }) {\n return this.get<T>(\"/api/saas/chat/templates\", { params } as any);\n }\n\n /**\n * Synchronize templates from the Meta WhatsApp Business API.\n * This updates the local database with the latest template status and content from Meta.\n *\n * @returns Success status of the sync operation.\n * @example\n * ```typescript\n * await erixClient.whatsapp.templates.sync();\n * ```\n */\n async sync<T = any>() {\n return this.post<T>(\"/api/saas/chat/templates/sync\", {});\n }\n\n /**\n * Retrieve details of a specific WhatsApp template.\n *\n * @param templateIdentifier - The name or ID of the template.\n * @returns Detailed template object including components and status.\n * @example\n * ```typescript\n * const template = await erixClient.whatsapp.templates.retrieve(\"welcome_message\");\n * ```\n */\n async retrieve<T = any>(templateIdentifier: string) {\n return this.get<T>(`/api/saas/chat/templates/${encodeURIComponent(templateIdentifier)}`);\n }\n\n /**\n * Create a new WhatsApp template manually (Draft).\n *\n * @param payload - Template configuration (name, category, language, components).\n * @example\n * ```typescript\n * await erixClient.whatsapp.templates.create({\n * name: \"new_promotion\",\n * category: \"MARKETING\",\n * language: \"en_US\",\n * components: [...]\n * });\n * ```\n */\n async create<T = any>(payload: any) {\n return this.post<T>(\"/api/saas/chat/templates\", payload);\n }\n\n /**\n * Update an existing WhatsApp template.\n *\n * @param templateId - The unique ID of the template.\n * @param payload - Updated template configuration.\n */\n async update<T = any>(templateId: string, payload: any) {\n return this.put<T>(`/api/saas/chat/templates/${templateId}`, payload);\n }\n\n /**\n * Delete a WhatsApp template from both the local database and Meta (if specified).\n *\n * @param templateName - The name of the template to delete.\n * @param force - If true, attempts to delete from Meta API as well.\n * @example\n * ```typescript\n * await erixClient.whatsapp.templates.deleteTemplate(\"old_template\", true);\n * ```\n */\n async deleteTemplate<T = any>(templateName: string, force?: boolean) {\n return this.deleteRequest<T>(\n `/api/saas/chat/templates/${encodeURIComponent(templateName)}${force ? \"?force=true\" : \"\"}`,\n );\n }\n\n /**\n * List available configuration options for variable mapping.\n *\n * @example\n * ```typescript\n * const config = await erixClient.whatsapp.templates.mappingConfig();\n * ```\n */\n async mappingConfig<T = any>() {\n return this.get<T>(\"/api/saas/chat/templates/mapping/config\");\n }\n\n /**\n * List CRM collections available for variable mapping (Leads, Deals, etc.).\n */\n async collections<T = any>() {\n return this.get<T>(\"/api/saas/chat/templates/collections\");\n }\n\n /**\n * List fields for a specific CRM collection to be used in mapping.\n *\n * @param collectionName - The name of the CRM collection.\n */\n async collectionFields<T = any>(collectionName: string) {\n return this.get<T>(\n `/api/saas/chat/templates/collections/${encodeURIComponent(collectionName)}/fields`,\n );\n }\n\n /**\n * Update variable mappings for a template to automate personalization.\n *\n * @param templateName - Name of the template.\n * @param payload - Mapping definitions.\n */\n async updateMapping<T = any>(templateName: string, payload: TemplateMapping) {\n return this.put<T>(\n `/api/saas/chat/templates/${encodeURIComponent(templateName)}/mapping`,\n payload,\n );\n }\n\n /**\n * Validate if a template is ready for automated sending based on its mappings.\n */\n async validate<T = any>(templateName: string) {\n return this.get<T>(`/api/saas/chat/templates/${encodeURIComponent(templateName)}/validate`);\n }\n\n /**\n * Preview a template resolution with sample data.\n *\n * @param templateName - Name of the template.\n * @param context - Lead data or variable overrides for preview.\n * @example\n * ```typescript\n * const preview = await erixClient.whatsapp.templates.preview(\"welcome\", {\n * lead: { firstName: \"Alice\" }\n * });\n * ```\n */\n async preview<T = any>(templateName: string, context: { lead?: any; vars?: any }) {\n return this.post<T>(`/api/saas/chat/templates/${encodeURIComponent(templateName)}/preview`, {\n context,\n });\n }\n\n /**\n * Introspect a template and provide a manifest of its required variables.\n *\n * This is used by Erix React to build dynamic \"Mapping Forms\" where users\n * can connect CRM fields to WhatsApp variables.\n *\n * @param templateIdentifier - The name or ID of the template.\n */\n async getVariableManifest(templateIdentifier: string): Promise<ResourceManifest> {\n const template: any = await this.retrieve(templateIdentifier);\n const components = Array.isArray(template.data?.components) ? template.data.components : [];\n\n const fields: any[] = [];\n\n for (const comp of components) {\n // Look for {{n}} pattern in text components\n if (comp.text) {\n const vars = comp.text.match(/{{(\\d+)}}/g);\n if (vars) {\n for (const v of vars) {\n const index = v.replace(/{{|}}/g, \"\");\n fields.push({\n key: `var_${index}`,\n label: `${comp.type} Var {{${index}}}`,\n type: \"string\",\n required: true,\n group: comp.type,\n description: `Variable placeholder in template ${comp.type}`,\n });\n }\n }\n }\n }\n\n return {\n name: `Template variables: ${template.data?.name || templateIdentifier}`,\n fields,\n uiHints: {\n icon: \"Variables\",\n primaryColor: \"#059669\",\n },\n };\n }\n\n /**\n * Check which automations or sequences are currently using this template.\n */\n async checkUsage<T = any>(templateName: string) {\n return this.get<T>(`/api/saas/chat/templates/${encodeURIComponent(templateName)}/usage`);\n }\n}\n","import type { AxiosInstance } from \"axios\";\nimport { APIResource } from \"../../resource\";\nimport { Broadcasts } from \"./broadcasts\";\nimport { Conversations } from \"./conversations\";\nimport { Messages } from \"./messages\";\nimport { Templates } from \"./templates\";\n\nexport interface SendTemplatePayload {\n /** Phone number in E.164 format. */\n phone: string;\n /** Name of the pre-approved WhatsApp template. */\n templateName: string;\n /** Language code (defaults to \"en\"). */\n languageCode?: string;\n /** Key-value pairs matching variables in your template (e.g., {{1}}, {{2}}). */\n variables?: Record<string, string>;\n /** Explicitly resolved variables if bypassing the internal resolution engine. */\n resolvedVariables?: any[];\n}\n\nexport class WhatsApp extends APIResource {\n public messages: Messages;\n public conversations: Conversations;\n public broadcasts: Broadcasts;\n public templates: Templates;\n\n constructor(client: AxiosInstance) {\n super(client);\n this.messages = new Messages(client);\n this.conversations = new Conversations(client);\n this.broadcasts = new Broadcasts(client);\n this.templates = new Templates(client);\n }\n\n /**\n * Upload an asset directly to chat storage.\n */\n async upload<T = any>(file: Blob | Buffer | File | any, filename: string) {\n const form = new FormData();\n form.append(\"file\", file, filename);\n return this.post<T>(\"/api/saas/chat/upload\", form, {\n headers:\n typeof (form as any).getHeaders === \"function\" ? (form as any).getHeaders() : undefined,\n });\n }\n\n /**\n * Dispatch a WhatsApp template message directly to a specific phone number.\n * Bypasses the automation queue for immediate high-priority delivery.\n *\n * @param payload - The template dispatch payload.\n * @returns Information about the dispatched message.\n */\n async sendTemplate(payload: SendTemplatePayload): Promise<{\n success: boolean;\n messageId?: string;\n templateName?: string;\n resolvedVariables?: any[];\n }> {\n return this.post<{\n success: boolean;\n messageId?: string;\n templateName?: string;\n resolvedVariables?: any[];\n }>(\"/api/saas/marketing/whatsapp/send-template\", payload);\n }\n}\n","import { APIResource } from \"../resource\";\n\nexport class Agency extends APIResource {\n /**\n * List all available blueprints.\n */\n async listBlueprints<T = any>() {\n return this.get<T>(\"/api/agency/blueprints\");\n }\n\n /**\n * Create a new blueprint configuration (\"Gold Standard\").\n */\n async createBlueprint<T = any>(payload: any) {\n return this.post<T>(\"/api/agency/blueprints\", payload);\n }\n\n /**\n * Deploy a blueprint to a specific tenant client code.\n */\n async deployBlueprint<T = any>(payload: { clientCode: string; blueprintId: string }) {\n return this.post<T>(\"/api/agency/blueprints/deploy\", payload);\n }\n\n /**\n * Get aggregate portfolio statistics for an agency.\n */\n async getPortfolioStats<T = any>(agencyCode: string) {\n return this.get<T>(`/api/agency/portfolio/${agencyCode}/stats`);\n }\n\n /**\n * Get proactive health report for an agency portfolio.\n */\n async getPortfolioHealth<T = any>(agencyCode: string) {\n return this.get<T>(`/api/agency/portfolio/${agencyCode}/health`);\n }\n\n /**\n * View consumption usage for a specific client code.\n */\n async getUsage<T = any>(clientCode: string) {\n return this.get<T>(`/api/agency/usage/${clientCode}`);\n }\n\n /**\n * List staff members under a specific agency code.\n */\n async listStaff<T = any>(agencyCode: string) {\n return this.get<T>(`/api/agency/staff/${agencyCode}`);\n }\n\n /**\n * Create a new staff member for an agency.\n */\n async createStaff<T = any>(payload: any) {\n return this.post<T>(\"/api/agency/staff\", payload);\n }\n}\n","import { APIResource } from \"../resource\";\n\nexport class Clients extends APIResource {\n /**\n * List all clients in the ecosystem.\n */\n async list<T = any>() {\n return this.get<T>(\"/api/services/clients\");\n }\n\n /**\n * Get client count and auto-generate a unique code.\n */\n async getCountAndGenerateCode<T = any>() {\n return this.get<T>(\"/api/services/clients/count\");\n }\n\n /**\n * Retrieve a single client by client code.\n */\n async retrieve<T = any>(clientCode: string) {\n return this.get<T>(`/api/services/clients/${clientCode}`);\n }\n\n /**\n * Get API Key for a specific client (Admin Only).\n */\n async getApiKey<T = any>(clientCode: string) {\n return this.get<T>(`/api/services/clients/${clientCode}/api-key`);\n }\n\n /**\n * Generate or rotate API Key for a specific client (Admin Only).\n */\n async rotateApiKey<T = any>(clientCode: string) {\n return this.post<T>(`/api/services/clients/${clientCode}/api-key`, {});\n }\n\n /**\n * Create a new client identity and provision initial resources.\n */\n async create<T = any>(payload: {\n name: string;\n clientCode: string;\n business?: any;\n plan?: any;\n }) {\n return this.post<T>(\"/api/services/clients\", payload);\n }\n\n /**\n * Get active service configuration for a specific client.\n */\n async getConfig<T = any>(clientCode: string) {\n return this.get<T>(`/api/services/clients/${clientCode}/config`);\n }\n\n /**\n * Update active service configuration for a specific client.\n */\n async updateConfig<T = any>(clientCode: string, payload: any) {\n return this.patch<T>(`/api/services/clients/${clientCode}/config`, payload);\n }\n\n /**\n * Get decrypted secrets for a specific client.\n */\n async getSecrets<T = any>(clientCode: string) {\n return this.get<T>(`/api/services/clients/${clientCode}/secrets`);\n }\n\n /**\n * Set secrets for a specific client.\n */\n async updateSecrets<T = any>(clientCode: string, payload: any) {\n return this.post<T>(`/api/services/clients/${clientCode}/secrets`, payload);\n }\n\n /**\n * Completely replace secrets for a specific client.\n */\n async replaceSecrets<T = any>(clientCode: string, payload: any) {\n return this.put<T>(`/api/services/clients/${clientCode}/secrets`, payload);\n }\n\n /**\n * Partially update secrets for a specific client.\n */\n async patchSecrets<T = any>(clientCode: string, payload: any) {\n return this.patch<T>(`/api/services/clients/${clientCode}/secrets`, payload);\n }\n\n /**\n * Retrieve Data Source connection metadata.\n */\n async getDataSource<T = any>(clientCode: string) {\n return this.get<T>(`/api/services/clients/${clientCode}/datasource`);\n }\n\n /**\n * Configure Data Source metadata.\n */\n async manageDataSource<T = any>(clientCode: string, payload: any) {\n return this.post<T>(`/api/services/clients/${clientCode}/datasource`, payload);\n }\n\n /**\n * Update Client Identity and perform cascading updates if required.\n */\n async updateIdentity<T = any>(id: string, payload: any) {\n return this.patch<T>(`/api/services/clients/${id}/identity`, payload);\n }\n\n /**\n * Initiate Google Re-authentication for OAuth tokens.\n */\n async googleReauth<T = any>(clientCode: string, payload: { authCode?: string } = {}) {\n return this.post<T>(`/api/services/clients/${clientCode}/google/reauth`, payload);\n }\n\n /**\n * Delete a client and perform cascading cleanup.\n */\n async delete<T = any>(id: string) {\n return this.deleteRequest<T>(`/api/services/clients/${id}`);\n }\n}\n\nexport class Blogs extends APIResource {\n /**\n * Retrieve public corporate blogs/news.\n */\n async list<T = any>() {\n return this.get<T>(\"/api/services/blogs\");\n }\n}\n\nexport class GlobalLeads extends APIResource {\n /**\n * Add a corporate lead capture entry.\n */\n async add<T = any>(payload: any) {\n return this.post<T>(\"/api/services/add-lead\", payload);\n }\n}\n\nexport class Services extends APIResource {\n public clients: Clients;\n public blogs: Blogs;\n public globalLeads: GlobalLeads;\n\n constructor(client: any) {\n super(client);\n this.clients = new Clients(client);\n this.blogs = new Blogs(client);\n this.globalLeads = new GlobalLeads(client);\n }\n}\n","import { APIResource } from \"../resource\";\n\nexport class EmailConfig extends APIResource {\n /**\n * Retrieve current email provider configuration and domain verification statuses.\n */\n async getConfig<T = any>() {\n return this.get<T>(\"/api/settings/email\");\n }\n\n /**\n * Switch the active email provider.\n */\n async switchProvider<T = any>(provider: string) {\n return this.post<T>(\"/api/settings/email/provider\", { provider });\n }\n\n /**\n * Provide explicit SMTP credentials and connection preferences.\n */\n async saveSmtp<T = any>(payload: any) {\n return this.post<T>(\"/api/settings/email/smtp\", payload);\n }\n\n /**\n * Initialize a new domain for SES identity verification.\n */\n async initDomainVerification<T = any>(domain: string) {\n return this.post<T>(\"/api/settings/email/ses/domain\", { domain });\n }\n\n /**\n * Confirm \"From\" details and finalize configuration payload.\n */\n async saveEmailConfig<T = any>(payload: {\n fromName: string;\n fromEmail: string;\n replyTo?: string;\n }) {\n return this.post<T>(\"/api/settings/email/ses/config\", payload);\n }\n\n /**\n * Check status of AWS SES domain validation DNS records.\n */\n async checkSesVerification<T = any>() {\n return this.get<T>(\"/api/settings/email/ses/verify\");\n }\n\n /**\n * Remove a verified SES domain identity and clean up local secrets.\n */\n async removeSesIdentity<T = any>() {\n return this.deleteRequest<T>(\"/api/settings/email/ses/domain\");\n }\n\n /**\n * Send a test email to verify infrastructure is correctly bound.\n */\n async sendTest<T = any>(toEmail: string) {\n return this.post<T>(\"/api/settings/email/test\", { toEmail });\n }\n\n /**\n * Define customized global email footers, limits, and specific campaign policies.\n */\n async saveAdvancedConfig<T = any>(payload: any) {\n return this.post<T>(\"/api/settings/email/advanced\", payload);\n }\n\n /**\n * Retrieve email configuration health properties including bounce limits metrics.\n */\n async getHealth<T = any>() {\n return this.get<T>(\"/api/settings/email/health\");\n }\n\n /**\n * Upgrade configurations dynamically to add DMARC enforcement records.\n */\n async fixDmarc<T = any>() {\n return this.post<T>(\"/api/settings/email/ses/fix-dmarc\", {});\n }\n\n /**\n * Discover internally available providers constants metadata.\n */\n async listProviders<T = any>() {\n return this.get<T>(\"/api/settings/email/providers\");\n }\n}\n\nexport class Settings extends APIResource {\n public email: EmailConfig;\n\n constructor(client: any) {\n super(client);\n this.email = new EmailConfig(client);\n }\n}\n","import { APIResource } from \"../resource\";\n\nexport interface CorsOriginCreatePayload {\n url: string;\n name?: string;\n allowedHeaders?: string[];\n allowedMethods?: string[];\n}\n\nexport interface CorsOriginUpdatePayload {\n url?: string;\n name?: string;\n allowedHeaders?: string[];\n allowedMethods?: string[];\n isActive?: boolean;\n}\n\nexport class Cors extends APIResource {\n /**\n * List all dynamic cross-origin policies.\n */\n async list<T = any>() {\n return this.get<T>(\"/api/saas/cors\");\n }\n\n /**\n * Register a new cross-origin client for the SaaS API network dynamically.\n */\n async create<T = any>(payload: CorsOriginCreatePayload) {\n return this.post<T>(\"/api/saas/cors\", payload);\n }\n\n /**\n * Adjust active states or configurations for an existing origin policy.\n */\n async update<T = any>(id: string, payload: CorsOriginUpdatePayload) {\n return this.patch<T>(`/api/saas/cors/${id}`, payload);\n }\n\n /**\n * Irreversibly drop support for a cross-origin client URL policy permanently.\n */\n async delete<T = any>(id: string) {\n return this.deleteRequest<T>(`/api/saas/cors/${id}`);\n }\n}\n","export { Ecodrix, type EcodrixOptions } from \"./core\";\nexport * from \"./types/metadata\";\nexport * from \"./error\";\nexport * from \"./resources/crm/activities\";\nexport * from \"./resources/crm/analytics\";\nexport * from \"./resources/crm/automationDashboard\";\nexport * from \"./resources/crm/automations\";\nexport * from \"./resources/crm/index\";\nexport * from \"./resources/crm/leads\";\nexport * from \"./resources/crm/payments\";\nexport * from \"./resources/crm/pipelines\";\nexport * from \"./resources/crm/scoring\";\nexport * from \"./resources/crm/sequences\";\nexport * from \"./resources/email\";\nexport * from \"./resources/events\";\nexport * from \"./resources/health\";\nexport * from \"./resources/logs\";\nexport * from \"./resources/marketing\";\nexport * from \"./resources/media\";\nexport * from \"./resources/meet\";\nexport * from \"./resources/notifications\";\nexport * from \"./resources/queue\";\nexport * from \"./resources/storage\";\nexport * from \"./resources/webhooks\";\nexport * from \"./resources/whatsapp/broadcasts\";\nexport * from \"./resources/whatsapp/conversations\";\n// Resource Type Exports\nexport * from \"./resources/whatsapp/index\";\nexport * from \"./resources/whatsapp/messages\";\nexport * from \"./resources/whatsapp/templates\";\n\n// Export the main client also as default for better ergonomics\nimport { Ecodrix } from \"./core\";\nexport default Ecodrix;\n\nexport * from \"./resources/agency\";\nexport * from \"./resources/services\";\nexport * from \"./resources/settings\";\nexport * from \"./resources/cors\";\n"],"mappings":"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","names":["axios","axiosRetry","io","EcodrixError","message","APIError","status","code","__publicField","AuthenticationError","RateLimitError","APIResource","client","url","data","options","config","error","__spreadValues","__spreadProps","_a","_b","_c","APIError","Notes","APIResource","leadId","params","noteId","content","isPinned","Activities","client","__publicField","__spreadValues","Analytics","APIResource","params","pipelineId","AutomationDashboard","APIResource","params","logId","Automations","APIResource","payload","ruleId","ruleIds","leadId","params","enrollmentId","runId","eventName","Leads","APIResource","params","customFieldsRes","customFields","systemFields","mappedCustom","f","leads","chunkSize","results","i","chunkPromises","lead","chunkResults","res","queryParams","__spreadValues","__asyncGenerator","currentPage","hasMore","response","__await","__spreadProps","items","item","leadId","phone","refKey","refValue","stageId","outcome","reason","options","metadata","noteId","ids","Payments","APIResource","payload","Pipelines","APIResource","pipelineId","_a","_b","pipeline","stages","s","payload","newName","params","orderArray","stageId","moveLeadsToStageId","Scoring","APIResource","payload","leadId","Sequences","APIResource","payload","enrollmentId","leadId","CRM","client","__publicField","Leads","Pipelines","Activities","Analytics","Automations","Sequences","Scoring","Payments","AutomationDashboard","Email","APIResource","payload","to","query","id","data","force","params","EmailResource","EventsResource","APIResource","payload","name","names","id","Health","APIResource","jobId","Logs","APIResource","query","id","Emails","APIResource","params","to","Campaigns","payload","campaignId","WhatsAppMarketing","Marketing","client","__publicField","axios","Media","APIResource","name","folder","params","key","file","options","response","uploadUrl","axios","sizeBytes","MediaResource","Meetings","APIResource","data","params","meetingId","Notifications","APIResource","params","logId","notificationId","Queue","APIResource","jobId","Folders","APIResource","name","folderPath","Files","folder","params","key","Storage","client","__publicField","WebhookSignatureError","APIError","message","Webhooks","payload","signature","secret","sig","crypto","digest","error","Broadcasts","APIResource","params","id","data","Conversations","APIResource","params","conversationId","leadId","leadData","ids","Messages","APIResource","params","__spreadProps","__spreadValues","messageId","isStarred","reaction","conversationId","file","formData","Templates","APIResource","params","templateIdentifier","payload","templateId","templateName","force","collectionName","context","_a","_b","template","components","fields","comp","vars","v","index","WhatsApp","APIResource","client","__publicField","Messages","Conversations","Broadcasts","Templates","file","filename","form","payload","Agency","APIResource","payload","agencyCode","clientCode","Clients","APIResource","clientCode","payload","id","Blogs","GlobalLeads","Services","client","__publicField","EmailConfig","APIResource","provider","payload","domain","toEmail","Settings","client","__publicField","Cors","APIResource","payload","id","ECOD_API_BASE","Ecodrix","options","__publicField","_a","_b","_c","_d","_e","AuthenticationError","baseUrl","socketUrl","isBrowser","runtime","os","headers","axios","axiosRetry","error","retryCount","requestConfig","WhatsApp","CRM","Media","Meetings","Notifications","Email","Logs","EventsResource","Webhooks","Storage","Marketing","Health","Queue","Agency","Services","Settings","Cors","io","footprint","roomId","clientCode","event","callback","method","path","data","params","APIError","index_default","Ecodrix"]}