@ecodrix/erix-api 3.1.1 → 3.2.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
@@ -1,4 +1,6 @@
1
1
  import { AxiosInstance, AxiosRequestConfig, Method } from 'axios';
2
+ import { W as WebchatSettingsPatch, a as WebchatOwnerSettings, A as APIError, b as AuthenticationError, R as RateLimitError } from './error-DuNpKP1d.js';
3
+ export { c as APIErrorIssue, E as EcodrixError, P as PermissionError, V as VisitorMessage, d as VisitorTyping, e as WebchatSettings, t as toAPIError } from './error-DuNpKP1d.js';
2
4
 
3
5
  /** Supported API route versions. Add `"v2"` here the day the server ships it. */
4
6
  type ApiVersion = "v1" | "v2" | "v3";
@@ -45,7 +47,7 @@ declare class Notes extends APIResource {
45
47
  * @param leadId - The unique ID of the lead.
46
48
  * @example
47
49
  * ```typescript
48
- * const notes = await erixClient.crm.activities.notes.list("lead_123");
50
+ * const notes = await ecod.product.erix.activities.notes.list("lead_123");
49
51
  * ```
50
52
  */
51
53
  list<T = any>(leadId: string): Promise<T>;
@@ -56,7 +58,7 @@ declare class Notes extends APIResource {
56
58
  * @param params - The note content.
57
59
  * @example
58
60
  * ```typescript
59
- * await erixClient.crm.activities.notes.create("lead_123", {
61
+ * await ecod.product.erix.activities.notes.create("lead_123", {
60
62
  * content: "Customer is interested in the enterprise plan."
61
63
  * });
62
64
  * ```
@@ -87,7 +89,7 @@ declare class Activities extends APIResource {
87
89
  * @param params - Optional pagination parameters.
88
90
  * @example
89
91
  * ```typescript
90
- * const timeline = await erixClient.crm.activities.timeline("lead_123", { limit: 10 });
92
+ * const timeline = await ecod.product.erix.activities.timeline("lead_123", { limit: 10 });
91
93
  * ```
92
94
  */
93
95
  timeline<T = any>(leadId: string, params?: {
@@ -108,7 +110,7 @@ declare class Activities extends APIResource {
108
110
  * @param params - Activity details (leadId, type, title, body).
109
111
  * @example
110
112
  * ```typescript
111
- * await erixClient.crm.activities.log({
113
+ * await ecod.product.erix.activities.log({
112
114
  * leadId: "lead_123",
113
115
  * type: "system",
114
116
  * title: "Meeting Scheduled",
@@ -139,7 +141,7 @@ declare class Analytics extends APIResource {
139
141
  * @returns {Promise<any>} KPI summary object containing core business metrics.
140
142
  * @example
141
143
  * ```typescript
142
- * const stats = await erixClient.crm.analytics.overview({ range: "30d" });
144
+ * const stats = await ecod.product.erix.analytics.overview({ range: "30d" });
143
145
  * console.log(stats.avgScore);
144
146
  * ```
145
147
  */
@@ -152,7 +154,7 @@ declare class Analytics extends APIResource {
152
154
  * @returns {Promise<any>} Array of funnel stages with count and conversion data.
153
155
  * @example
154
156
  * ```typescript
155
- * const funnel = await erixClient.crm.analytics.funnel("pipe_123");
157
+ * const funnel = await ecod.product.erix.analytics.funnel("pipe_123");
156
158
  * ```
157
159
  */
158
160
  funnel<T = any>(pipelineId: string): Promise<T>;
@@ -164,7 +166,7 @@ declare class Analytics extends APIResource {
164
166
  * @returns {Promise<any>} Forecast data including weighted expected revenue.
165
167
  * @example
166
168
  * ```typescript
167
- * const prognosis = await erixClient.crm.analytics.forecast("pipe_123");
169
+ * const prognosis = await ecod.product.erix.analytics.forecast("pipe_123");
168
170
  * ```
169
171
  */
170
172
  forecast<T = any>(pipelineId?: string): Promise<T>;
@@ -217,7 +219,7 @@ declare class Analytics extends APIResource {
217
219
  * @returns {Promise<any>} Consolidated analytics object containing CRM overview and WhatsApp messaging metrics.
218
220
  * @example
219
221
  * ```typescript
220
- * const stats = await erixClient.crm.analytics.summary({ range: "30d" });
222
+ * const stats = await ecod.product.erix.analytics.summary({ range: "30d" });
221
223
  * console.log(stats.overview.totalLeads);
222
224
  * ```
223
225
  */
@@ -229,7 +231,7 @@ declare class Analytics extends APIResource {
229
231
  * @param params - Optional filters (time range).
230
232
  * @example
231
233
  * ```typescript
232
- * const waStats = await erixClient.crm.analytics.whatsapp({ range: "7d" });
234
+ * const waStats = await ecod.product.erix.analytics.whatsapp({ range: "7d" });
233
235
  * console.log(waStats.totalSent);
234
236
  * ```
235
237
  */
@@ -261,10 +263,10 @@ declare class Analytics extends APIResource {
261
263
  *
262
264
  * @example
263
265
  * ```typescript
264
- * const checklist = await ecod.crm.documents.getChecklist("lead-id");
265
- * await ecod.crm.documents.createChecklist("lead-id", "consultant__business");
266
- * await ecod.crm.documents.markReceived("lead-id", "pan_card", fileUrl);
267
- * await ecod.crm.documents.sendReminder("lead-id");
266
+ * const checklist = await ecod.product.erix.documents.getChecklist("lead-id");
267
+ * await ecod.product.erix.documents.createChecklist("lead-id", "consultant__business");
268
+ * await ecod.product.erix.documents.markReceived("lead-id", "pan_card", fileUrl);
269
+ * await ecod.product.erix.documents.sendReminder("lead-id");
268
270
  * ```
269
271
  */
270
272
  declare class CRMDocuments extends APIResource {
@@ -299,9 +301,9 @@ declare class CRMDocuments extends APIResource {
299
301
  *
300
302
  * @example
301
303
  * ```typescript
302
- * const csv = await ecod.crm.invoiceExport.csv({ from: "2026-01-01", status: "paid" });
303
- * const tally = await ecod.crm.invoiceExport.tally();
304
- * const zoho = await ecod.crm.invoiceExport.zoho({ from: "2026-06-01", to: "2026-08-31" });
304
+ * const csv = await ecod.product.erix.invoiceExport.csv({ from: "2026-01-01", status: "paid" });
305
+ * const tally = await ecod.product.erix.invoiceExport.tally();
306
+ * const zoho = await ecod.product.erix.invoiceExport.zoho({ from: "2026-06-01", to: "2026-08-31" });
305
307
  * ```
306
308
  */
307
309
  declare class CRMInvoiceExport extends APIResource {
@@ -559,11 +561,11 @@ interface UpsertLeadParams {
559
561
  /**
560
562
  * CRM Lead resource — full lifecycle management.
561
563
  *
562
- * Access via `ecod.crm.leads`.
564
+ * Access via `ecod.product.erix.leads`.
563
565
  *
564
566
  * @example
565
567
  * ```typescript
566
- * const { data: lead } = await ecod.crm.leads.create({
568
+ * const { data: lead } = await ecod.product.erix.leads.create({
567
569
  * firstName: "Alice",
568
570
  * phone: "+919876543210",
569
571
  * source: "website",
@@ -578,7 +580,7 @@ declare class Leads extends APIResource {
578
580
  * @returns The newly created Lead document.
579
581
  * @example
580
582
  * ```typescript
581
- * const lead = await erixClient.crm.leads.create({
583
+ * const lead = await ecod.product.erix.leads.create({
582
584
  * firstName: "Alice",
583
585
  * phone: "+919876543210",
584
586
  * source: "website"
@@ -602,7 +604,7 @@ declare class Leads extends APIResource {
602
604
  * @returns The newly created or updated Lead document.
603
605
  * @example
604
606
  * ```typescript
605
- * await erixClient.crm.leads.upsert({
607
+ * await ecod.product.erix.leads.upsert({
606
608
  * leadData: { phone: "+919876543210", firstName: "Alice" }
607
609
  * });
608
610
  * ```
@@ -638,8 +640,8 @@ declare class Leads extends APIResource {
638
640
  * @returns Paginated list of Lead documents.
639
641
  * @example
640
642
  * ```typescript
641
- * const leads = await erixClient.crm.leads.list({
642
- * status: "new",
643
+ * const leads = await ecod.product.erix.leads.list({
644
+ * status: "open",
643
645
  * source: "website",
644
646
  * limit: 20
645
647
  * });
@@ -652,7 +654,7 @@ declare class Leads extends APIResource {
652
654
  *
653
655
  * @example
654
656
  * ```typescript
655
- * for await (const lead of ecod.crm.leads.listAutoPaging<Lead>()) {
657
+ * for await (const lead of ecod.product.erix.leads.listAutoPaging<Lead>()) {
656
658
  * console.log(lead.firstName);
657
659
  * }
658
660
  * ```
@@ -665,7 +667,7 @@ declare class Leads extends APIResource {
665
667
  * @returns The Lead document, or a 404 error if not found.
666
668
  * @example
667
669
  * ```typescript
668
- * const lead = await erixClient.crm.leads.retrieve("64abc...");
670
+ * const lead = await ecod.product.erix.leads.retrieve("64abc...");
669
671
  * ```
670
672
  */
671
673
  retrieve<T = any>(leadId: string): Promise<T>;
@@ -704,9 +706,9 @@ declare class Leads extends APIResource {
704
706
  * @returns The updated Lead document.
705
707
  * @example
706
708
  * ```typescript
707
- * await erixClient.crm.leads.update("64abc...", {
709
+ * await ecod.product.erix.leads.update("64abc...", {
708
710
  * lastName: "Smith",
709
- * status: "qualified"
711
+ * status: "won"
710
712
  * });
711
713
  * ```
712
714
  */
@@ -792,12 +794,31 @@ declare class Leads extends APIResource {
792
794
  */
793
795
  deleteNote<T = any>(leadId: string, noteId: string): Promise<unknown>;
794
796
  /**
795
- * Delete a single lead permanently.
797
+ * Archive a single lead (the server soft-deletes: the lead leaves lists and
798
+ * the board but its history stays). To remove a person's data for good,
799
+ * use {@link erase}.
796
800
  *
797
- * @param leadId - The ID of the lead to delete.
798
- * ---- **Done** ---- API Endpoint
801
+ * @param leadId - The ID of the lead to archive.
799
802
  */
800
803
  delete(leadId: string): Promise<unknown>;
804
+ /**
805
+ * Everything held about one contact as JSON (DPDP right of access):
806
+ * profile, consent, notes, activity, form answers, appointments, meetings,
807
+ * invoices, conversations with messages, automation runs. Owner/admin only.
808
+ */
809
+ export<T = any>(leadId: string): Promise<T>;
810
+ /**
811
+ * Erase a contact's personal data (DPDP right to erasure) across CRM,
812
+ * inbox, channels and automations; invoices are kept for GST records.
813
+ * Irreversible. Owner/admin only.
814
+ */
815
+ erase(leadId: string): Promise<{
816
+ success: boolean;
817
+ data: {
818
+ erased: true;
819
+ invoicesKept: number;
820
+ };
821
+ }>;
801
822
  /**
802
823
  * Bulk archive multiple leads.
803
824
  *
@@ -861,7 +882,7 @@ declare class Payments extends APIResource {
861
882
  * @param payload - Payment details (leadId, amount, currency, description).
862
883
  * @example
863
884
  * ```typescript
864
- * await erixClient.crm.payments.capture({
885
+ * await ecod.product.erix.payments.capture({
865
886
  * leadId: "lead_123",
866
887
  * amount: 5000,
867
888
  * currency: "INR",
@@ -920,7 +941,7 @@ declare class Pipelines extends APIResource {
920
941
  * @returns Array of pipeline objects with nested stages.
921
942
  * @example
922
943
  * ```typescript
923
- * const pipelines = await erixClient.crm.pipelines.list();
944
+ * const pipelines = await ecod.product.erix.pipelines.list();
924
945
  * ```
925
946
  */
926
947
  list<T = any>(): Promise<T>;
@@ -940,7 +961,7 @@ declare class Pipelines extends APIResource {
940
961
  * @returns The created pipeline record.
941
962
  * @example
942
963
  * ```typescript
943
- * await erixClient.crm.pipelines.create({
964
+ * await ecod.product.erix.pipelines.create({
944
965
  * name: "Sales Pipeline",
945
966
  * stages: ["Lead", "Contacted", "Proposal", "Negotiation", "Closed"]
946
967
  * });
@@ -956,7 +977,7 @@ declare class Pipelines extends APIResource {
956
977
  * @param pipelineId - The unique ID of the pipeline.
957
978
  * @example
958
979
  * ```typescript
959
- * const pipeline = await erixClient.crm.pipelines.retrieve("pipe_123");
980
+ * const pipeline = await ecod.product.erix.pipelines.retrieve("pipe_123");
960
981
  * ```
961
982
  */
962
983
  retrieve<T = any>(pipelineId: string): Promise<T>;
@@ -993,7 +1014,7 @@ declare class Pipelines extends APIResource {
993
1014
  * @param pipelineId - The unique ID of the pipeline.
994
1015
  * @example
995
1016
  * ```typescript
996
- * const board = await erixClient.crm.pipelines.board("pipe_123");
1017
+ * const board = await ecod.product.erix.pipelines.board("pipe_123");
997
1018
  * ```
998
1019
  */
999
1020
  board<T = any>(pipelineId: string): Promise<T>;
@@ -1008,7 +1029,7 @@ declare class Pipelines extends APIResource {
1008
1029
  * @param params - Stage details (name, color, probability).
1009
1030
  * @example
1010
1031
  * ```typescript
1011
- * await erixClient.crm.pipelines.addStage("pipe_123", {
1032
+ * await ecod.product.erix.pipelines.addStage("pipe_123", {
1012
1033
  * name: "Decision Maker Bought In",
1013
1034
  * color: "#FF5733",
1014
1035
  * probability: 80
@@ -1067,7 +1088,7 @@ declare class Scoring extends APIResource {
1067
1088
  * @returns The scoring configuration object.
1068
1089
  * @example
1069
1090
  * ```typescript
1070
- * const config = await erixClient.crm.scoring.getConfig();
1091
+ * const config = await ecod.product.erix.scoring.getConfig();
1071
1092
  * ```
1072
1093
  */
1073
1094
  getConfig<T = any>(): Promise<T>;
@@ -1082,7 +1103,7 @@ declare class Scoring extends APIResource {
1082
1103
  * @param leadId - The unique ID of the lead.
1083
1104
  * @example
1084
1105
  * ```typescript
1085
- * await erixClient.crm.scoring.recalculate("lead_123");
1106
+ * await ecod.product.erix.scoring.recalculate("lead_123");
1086
1107
  * ```
1087
1108
  */
1088
1109
  recalculate<T = any>(leadId: string): Promise<T>;
@@ -1306,54 +1327,71 @@ declare class Checkout extends APIResource {
1306
1327
  }
1307
1328
 
1308
1329
  /**
1309
- * Payload to programmatically trigger an event/workflow.
1330
+ * Event definition representing an entry point capable of triggering automations.
1331
+ */
1332
+ interface EventDefinition {
1333
+ name: string;
1334
+ displayName: string;
1335
+ description?: string;
1336
+ pipelineId?: string;
1337
+ stageId?: string;
1338
+ defaultSource?: string;
1339
+ [key: string]: any;
1340
+ }
1341
+ /**
1342
+ * Payload to register/assign a new custom event definition.
1343
+ */
1344
+ interface AssignEventPayload {
1345
+ /** The internal machine-readable name of the event (e.g. "webinar_joined") */
1346
+ name: string;
1347
+ /** Human-readable display name */
1348
+ displayName: string;
1349
+ /** Event description */
1350
+ description?: string;
1351
+ /** ID of the pipeline to associate with matching leads */
1352
+ pipelineId?: string;
1353
+ /** ID of the stage within the pipeline */
1354
+ stageId?: string;
1355
+ /** Default source tag for leads created via this event */
1356
+ defaultSource?: string;
1357
+ }
1358
+ /**
1359
+ * Payload to programmatically trigger an event/workflow. Matches what
1360
+ * `POST /product/erix/events/trigger` accepts; unknown keys are dropped.
1310
1361
  */
1311
1362
  interface TriggerPayload {
1312
- /** The name of the event to fire (e.g., "webinar_joined") */
1363
+ /** The name of the event to fire (e.g., "webinar_joined"); no spaces, max 100. */
1313
1364
  trigger: string;
1314
1365
  /**
1315
- * Phone number of the lead (E.164 format). Phone OR email is required —
1316
- * at least one of `phone`/`email` must be provided (enforced server-side).
1366
+ * Phone number of the lead (E.164 format). Phone OR email is required unless
1367
+ * the workspace has Flow v1 (events without a contact).
1317
1368
  */
1318
1369
  phone?: string;
1319
- /**
1320
- * Email of the lead. Phone OR email is required — at least one of
1321
- * `phone`/`email` must be provided (enforced server-side).
1322
- */
1370
+ /** Email of the lead. Phone OR email is required (see `phone`). */
1323
1371
  email?: string;
1324
- /** Key-value pairs for string templates */
1325
- variables?: Record<string, string>;
1326
- /** Deep payload data mapping to the event */
1327
- data?: any;
1328
- /** URL to receive an acknowledgment callback when processing completes */
1329
- callbackUrl?: string;
1330
- /** Secret metadata passed back to the callback URL */
1331
- callbackMetadata?: any;
1332
- /** Auto-create lead if phone does not exist in CRM */
1333
- createLeadIfMissing?: boolean;
1334
- /** Pre-fill data if creating a new lead */
1372
+ /** Key-value pairs for message templates (values are sent as text). */
1373
+ variables?: Record<string, string | number | boolean>;
1374
+ /** Extra event data the flow can read. */
1375
+ data?: Record<string, unknown>;
1376
+ /** Pre-fill data if `createLeadIfMissing` creates the contact. */
1335
1377
  leadData?: {
1336
1378
  firstName?: string;
1337
1379
  lastName?: string;
1338
1380
  source?: string;
1339
1381
  };
1340
- /** Delay execution of matched workflows (in seconds) */
1382
+ /**
1383
+ * Your id for this event (max 200). A retry with the same key and trigger
1384
+ * doesn't start the flows twice. Generated by the server when omitted.
1385
+ */
1386
+ idempotencyKey?: string;
1387
+ /** Flow v1: create the contact when phone/email matches none. */
1388
+ createLeadIfMissing?: boolean;
1389
+ /** Flow v1: delay matched flows (seconds). Use one of the three delays. */
1341
1390
  delaySeconds?: number;
1342
- /** Delay execution of matched workflows (in minutes) */
1391
+ /** Flow v1: delay matched flows (minutes). */
1343
1392
  delayMinutes?: number;
1344
- /** Explicit ISO timestamp to trigger the workflow run */
1393
+ /** Flow v1: start matched flows at this ISO time (with offset). */
1345
1394
  runAt?: string;
1346
- /** Automatically generate a Google Meet appointment if matched actions require it */
1347
- requiresMeet?: boolean;
1348
- /** Configuration details for the generated Google Meet appointment */
1349
- meetConfig?: {
1350
- summary?: string;
1351
- description?: string;
1352
- startTime?: string;
1353
- duration?: number;
1354
- timezone?: string;
1355
- attendees?: string[];
1356
- };
1357
1395
  }
1358
1396
  /**
1359
1397
  * Response returned when triggering an event.
@@ -1361,9 +1399,14 @@ interface TriggerPayload {
1361
1399
  interface TriggerResponse {
1362
1400
  success: boolean;
1363
1401
  data?: {
1364
- eventLogId: string;
1365
1402
  trigger: string;
1366
- leadId: string;
1403
+ /** Yours, or the one the server generated. */
1404
+ idempotencyKey: string;
1405
+ leadId?: string;
1406
+ /** Set when a delay was applied. */
1407
+ scheduledFor?: string;
1408
+ /** Flow v1 fields sent to a workspace without Flow v1: accepted, not applied. */
1409
+ ignored?: string[];
1367
1410
  };
1368
1411
  message?: string;
1369
1412
  code?: string;
@@ -1375,10 +1418,10 @@ declare class EventsResource extends APIResource {
1375
1418
  * engine) and starts each flow whose declared trigger matches.
1376
1419
  *
1377
1420
  * @param payload - The trigger details (event name, lead phone/email, variables).
1378
- * @returns Trigger response with diagnostic info (eventLogId, trigger, leadId).
1421
+ * @returns Trigger response with diagnostic info (trigger, idempotencyKey, leadId, scheduledFor).
1379
1422
  * @example
1380
1423
  * ```typescript
1381
- * await erixClient.events.trigger({
1424
+ * await ecod.product.erix.events.trigger({
1382
1425
  * trigger: "webinar_joined",
1383
1426
  * phone: "+919876543210",
1384
1427
  * variables: { webinar_name: "AI Masterclass" },
@@ -1414,9 +1457,13 @@ declare class EventsResource extends APIResource {
1414
1457
  *
1415
1458
  * @example
1416
1459
  * ```typescript
1417
- * const invoices = await ecod.invoices.list();
1418
- * const inv = await ecod.invoices.create({ leadId, items, currency: "INR" });
1419
- * await ecod.invoices.sendViaWhatsApp(inv.id);
1460
+ * const invoices = await ecod.product.erix.invoices.list();
1461
+ * const { data: inv } = await ecod.product.erix.invoices.create({
1462
+ * clientName: "Customer name",
1463
+ * leadId,
1464
+ * items: [{ description: "Consultation", quantity: 1, rate: 1500 }],
1465
+ * });
1466
+ * await ecod.product.erix.invoices.sendWhatsApp(inv.id);
1420
1467
  * ```
1421
1468
  */
1422
1469
  declare class Invoices extends APIResource {
@@ -1454,6 +1501,30 @@ declare class Invoices extends APIResource {
1454
1501
  * Update invoice settings.
1455
1502
  */
1456
1503
  updateSettings<T = any>(payload: Record<string, unknown>): Promise<T>;
1504
+ /** Create (or reuse) the invoice's payment link on the workspace's gateway. */
1505
+ paymentLink(id: string): Promise<{
1506
+ success: boolean;
1507
+ data: {
1508
+ paymentLinkId: string;
1509
+ paymentLinkUrl: string;
1510
+ };
1511
+ }>;
1512
+ /**
1513
+ * Record money received outside the gateway (UPI, bank transfer, cash).
1514
+ * Less than the balance → `partially_paid`; covering it → `paid`. Owner or
1515
+ * admin only. `paymentId` (a UUID you generate) makes a retried call count
1516
+ * the payment once.
1517
+ */
1518
+ recordPayment<T = any>(id: string, payload: {
1519
+ amount: number;
1520
+ paidAt?: string;
1521
+ reference?: string;
1522
+ paymentId?: string;
1523
+ }): Promise<T>;
1524
+ /** Send the invoice (with its payment link) to the client on WhatsApp. */
1525
+ sendWhatsApp<T = any>(id: string): Promise<T>;
1526
+ /** Email the invoice PDF (and payment link) to the client. */
1527
+ sendEmail<T = any>(id: string): Promise<T>;
1457
1528
  }
1458
1529
 
1459
1530
  /**
@@ -1461,10 +1532,10 @@ declare class Invoices extends APIResource {
1461
1532
  *
1462
1533
  * @example
1463
1534
  * ```typescript
1464
- * const packs = await ecod.niche.workflowPacks();
1465
- * const detail = await ecod.niche.workflowPackDetail("pack_healthcare");
1466
- * const result = await ecod.niche.installWorkflowPack("pack_healthcare");
1467
- * const templates = await ecod.niche.templateSuggestions();
1535
+ * const packs = await ecod.product.erix.niche.workflowPacks();
1536
+ * const detail = await ecod.product.erix.niche.workflowPackDetail("pack_healthcare");
1537
+ * const result = await ecod.product.erix.niche.installWorkflowPack("pack_healthcare");
1538
+ * const templates = await ecod.product.erix.niche.templateSuggestions();
1468
1539
  * ```
1469
1540
  */
1470
1541
  declare class NicheResources extends APIResource {
@@ -1494,11 +1565,11 @@ declare class NicheResources extends APIResource {
1494
1565
  *
1495
1566
  * @example
1496
1567
  * ```typescript
1497
- * const docs = await ecod.projectDocuments.list(projectId);
1498
- * await ecod.projectDocuments.upload(projectId, { name: "Contract.pdf", fileKey, mimeType });
1499
- * await ecod.projectDocuments.toggleSignature(projectId, docId, true);
1500
- * await ecod.projectDocuments.addSigner(projectId, docId, { role: "client", name: "Alice" });
1501
- * await ecod.projectDocuments.stampSign(projectId, docId, { signatureImage: base64Png });
1568
+ * const docs = await ecod.product.erix.projects.list(projectId);
1569
+ * await ecod.product.erix.projects.upload(projectId, { name: "Contract.pdf", fileKey, mimeType });
1570
+ * await ecod.product.erix.projects.toggleSignature(projectId, docId, true);
1571
+ * await ecod.product.erix.projects.addSigner(projectId, docId, { role: "client", name: "Alice" });
1572
+ * await ecod.product.erix.projects.stampSign(projectId, docId, { signatureImage: base64Png });
1502
1573
  * ```
1503
1574
  */
1504
1575
  declare class ProjectDocuments extends APIResource {
@@ -1529,22 +1600,19 @@ declare class ProjectDocuments extends APIResource {
1529
1600
  email?: string;
1530
1601
  userId?: string;
1531
1602
  }): Promise<T>;
1532
- /**
1533
- * Team user signs a document (simple mark — no PDF stamp).
1534
- */
1535
- sign<T = any>(projectId: string, docId: string, payload?: {
1536
- signedFileKey?: string;
1537
- }): Promise<T>;
1538
1603
  /**
1539
1604
  * Team user declines signing a document.
1540
1605
  */
1541
1606
  decline<T = any>(projectId: string, docId: string): Promise<T>;
1542
1607
  /**
1543
- * Full signing ceremony — stamps a signature image onto the PDF,
1544
- * computes an audit seal, and re-uploads the signed copy.
1608
+ * The team's signing ceremony (owners/admins): stamps a signature image onto
1609
+ * the PDF, computes an audit seal, and re-uploads the signed copy. Signers
1610
+ * sign in the order they were added, so the team signs after the client
1611
+ * (409 `SIGN_ORDER` before that). Click-to-sign with an audit seal, not an
1612
+ * Aadhaar eSign.
1545
1613
  *
1546
1614
  * @param signatureImage - Base64-encoded PNG of the drawn/typed signature
1547
- * @param signerName - Name to stamp on the PDF
1615
+ * @param signerName - Ignored: the server stamps the signed-in person's name
1548
1616
  * @param position - Optional position override { page?, x?, y?, width?, height? }
1549
1617
  */
1550
1618
  stampSign<T = any>(projectId: string, docId: string, payload: {
@@ -1601,6 +1669,36 @@ declare class Connect extends APIResource {
1601
1669
  method: string;
1602
1670
  config?: Record<string, unknown>;
1603
1671
  }): Promise<T>;
1672
+ /**
1673
+ * Save the website chat widget's settings, add a site to its allowed
1674
+ * domains, or both (owners and admins). Send only what changes; `null`
1675
+ * resets a setting to its default. A bad value fails with `APIError` code
1676
+ * `VALIDATION_ERROR` (each field in `issues`); a site over the plan's cap
1677
+ * fails with status 402, code `WEBCHAT_DOMAIN_LIMIT`, and saves nothing.
1678
+ * Returns the webchat connection, like `configure`.
1679
+ */
1680
+ configureWebchat<T = any>(settings: WebchatSettingsPatch): Promise<T>;
1681
+ /**
1682
+ * The website chat as its owner edits it (owners and admins): the saved
1683
+ * widget settings, the allowed sites in plain text (the connection view
1684
+ * masks them) and the plan's cap on them.
1685
+ */
1686
+ webchatSettings(): Promise<{
1687
+ success: boolean;
1688
+ data: WebchatOwnerSettings;
1689
+ }>;
1690
+ /**
1691
+ * Remove a site from the website chat's allowed domains (owners and
1692
+ * admins), written any way: `https://www.example.com/` removes
1693
+ * `example.com`. Removing the last one turns the chat off on every
1694
+ * website. Returns the sites left.
1695
+ */
1696
+ removeWebchatDomain(domain: string): Promise<{
1697
+ success: boolean;
1698
+ data: {
1699
+ allowedDomains: string[];
1700
+ };
1701
+ }>;
1604
1702
  /**
1605
1703
  * Disconnect a provider.
1606
1704
  */
@@ -1746,7 +1844,7 @@ declare class Email extends APIResource {
1746
1844
  * @returns A promise resolving to the result of the test email dispatch.
1747
1845
  * @example
1748
1846
  * ```typescript
1749
- * await erixClient.email.sendTest("admin@mycompany.com");
1847
+ * await ecod.infra.connect.email.templates.sendTest("admin@mycompany.com");
1750
1848
  * ```
1751
1849
  */
1752
1850
  sendTest(to: string): Promise<CampaignResult>;
@@ -1757,7 +1855,7 @@ declare class Email extends APIResource {
1757
1855
  * @returns A promise resolving to a paginated or filtered list of templates.
1758
1856
  * @example
1759
1857
  * ```typescript
1760
- * const response = await erixClient.email.listTemplates({ category: "marketing" });
1858
+ * const response = await ecod.infra.connect.email.templates.listTemplates({ category: "marketing" });
1761
1859
  * console.log(response.data);
1762
1860
  * ```
1763
1861
  */
@@ -1772,7 +1870,7 @@ declare class Email extends APIResource {
1772
1870
  * @returns A promise resolving to the requested template details.
1773
1871
  * @example
1774
1872
  * ```typescript
1775
- * const template = await erixClient.email.getTemplate("tpl_123abc");
1873
+ * const template = await ecod.infra.connect.email.templates.getTemplate("tpl_123abc");
1776
1874
  * ```
1777
1875
  */
1778
1876
  getTemplate(id: string): Promise<{
@@ -1786,7 +1884,7 @@ declare class Email extends APIResource {
1786
1884
  * @returns A promise resolving to the newly created template.
1787
1885
  * @example
1788
1886
  * ```typescript
1789
- * const newTpl = await erixClient.email.createTemplate({
1887
+ * const newTpl = await ecod.infra.connect.email.templates.createTemplate({
1790
1888
  * name: "Welcome Series 1",
1791
1889
  * subject: "Welcome to our platform!",
1792
1890
  * htmlBody: "<h1>Welcome</h1><p>We are glad you are here.</p>"
@@ -1805,7 +1903,7 @@ declare class Email extends APIResource {
1805
1903
  * @returns A promise resolving to the updated template.
1806
1904
  * @example
1807
1905
  * ```typescript
1808
- * await erixClient.email.updateTemplate("tpl_123abc", {
1906
+ * await ecod.infra.connect.email.templates.updateTemplate("tpl_123abc", {
1809
1907
  * subject: "Updated Welcome Subject"
1810
1908
  * });
1811
1909
  * ```
@@ -1822,7 +1920,7 @@ declare class Email extends APIResource {
1822
1920
  * @returns A promise resolving to a success indicator.
1823
1921
  * @example
1824
1922
  * ```typescript
1825
- * await erixClient.email.deleteTemplate("tpl_123abc");
1923
+ * await ecod.infra.connect.email.templates.deleteTemplate("tpl_123abc");
1826
1924
  * ```
1827
1925
  */
1828
1926
  deleteTemplate(id: string, force?: boolean): Promise<{
@@ -1837,7 +1935,7 @@ declare class Email extends APIResource {
1837
1935
  * @returns A promise resolving to the rendered HTML and subject.
1838
1936
  * @example
1839
1937
  * ```typescript
1840
- * const preview = await erixClient.email.previewTemplate("tpl_123abc", {
1938
+ * const preview = await ecod.infra.connect.email.templates.previewTemplate("tpl_123abc", {
1841
1939
  * variables: { first_name: "Jane" }
1842
1940
  * });
1843
1941
  * console.log(preview.data.html);
@@ -1908,11 +2006,11 @@ interface UpdateMeetingParams {
1908
2006
  /**
1909
2007
  * Google Meet appointment scheduling resource.
1910
2008
  *
1911
- * Access via `ecod.meet`.
2009
+ * Access via `ecod.infra.connect.meet`.
1912
2010
  *
1913
2011
  * @example
1914
2012
  * ```typescript
1915
- * const { data } = await ecod.meet.create({
2013
+ * const { data } = await ecod.infra.connect.meet.create({
1916
2014
  * leadId: "64abc...",
1917
2015
  * participantName: "Alice",
1918
2016
  * participantPhone: "+919876543210",
@@ -1934,7 +2032,7 @@ declare class Meetings extends APIResource {
1934
2032
  *
1935
2033
  * @example
1936
2034
  * ```typescript
1937
- * const { data } = await ecod.meet.create({
2035
+ * const { data } = await ecod.infra.connect.meet.create({
1938
2036
  * leadId: "64abc...",
1939
2037
  * participantName: "Alice",
1940
2038
  * participantPhone: "+91...",
@@ -1952,7 +2050,7 @@ declare class Meetings extends APIResource {
1952
2050
  *
1953
2051
  * @example
1954
2052
  * ```typescript
1955
- * const { data } = await ecod.meet.list({ status: "scheduled" });
2053
+ * const { data } = await ecod.infra.connect.meet.list({ status: "scheduled" });
1956
2054
  * ```
1957
2055
  */
1958
2056
  list(params?: {
@@ -1967,7 +2065,7 @@ declare class Meetings extends APIResource {
1967
2065
  *
1968
2066
  * @example
1969
2067
  * ```typescript
1970
- * const { data } = await ecod.meet.retrieve("meeting_id");
2068
+ * const { data } = await ecod.infra.connect.meet.retrieve("meeting_id");
1971
2069
  * ```
1972
2070
  */
1973
2071
  retrieve(meetingId: string): Promise<any>;
@@ -1983,7 +2081,7 @@ declare class Meetings extends APIResource {
1983
2081
  * @example
1984
2082
  * ```typescript
1985
2083
  * // Reschedule
1986
- * await ecod.meet.update("meeting_id", {
2084
+ * await ecod.infra.connect.meet.update("meeting_id", {
1987
2085
  * startTime: "2026-04-11T11:00:00Z",
1988
2086
  * endTime: "2026-04-11T11:30:00Z",
1989
2087
  * });
@@ -2005,7 +2103,7 @@ declare class Meetings extends APIResource {
2005
2103
  *
2006
2104
  * @example
2007
2105
  * ```typescript
2008
- * await ecod.meet.delete("meeting_id");
2106
+ * await ecod.infra.connect.meet.delete("meeting_id");
2009
2107
  * ```
2010
2108
  */
2011
2109
  delete(meetingId: string): Promise<any>;
@@ -2148,7 +2246,7 @@ declare class Templates extends APIResource {
2148
2246
  * @returns List of message templates.
2149
2247
  * @example
2150
2248
  * ```typescript
2151
- * const templates = await erixClient.whatsapp.templates.list({ status: "APPROVED" });
2249
+ * const templates = await ecod.infra.connect.whatsapp.templates.list({ status: "APPROVED" });
2152
2250
  * ```
2153
2251
  */
2154
2252
  list<T = any>(params?: {
@@ -2163,7 +2261,7 @@ declare class Templates extends APIResource {
2163
2261
  * @returns Success status of the sync operation.
2164
2262
  * @example
2165
2263
  * ```typescript
2166
- * await erixClient.whatsapp.templates.sync();
2264
+ * await ecod.infra.connect.whatsapp.templates.sync();
2167
2265
  * ```
2168
2266
  */
2169
2267
  sync<T = any>(): Promise<T>;
@@ -2174,7 +2272,7 @@ declare class Templates extends APIResource {
2174
2272
  * @returns Detailed template object including components and status.
2175
2273
  * @example
2176
2274
  * ```typescript
2177
- * const template = await erixClient.whatsapp.templates.retrieve("welcome_message");
2275
+ * const template = await ecod.infra.connect.whatsapp.templates.retrieve("welcome_message");
2178
2276
  * ```
2179
2277
  */
2180
2278
  retrieve<T = any>(templateIdentifier: string): Promise<T>;
@@ -2184,7 +2282,7 @@ declare class Templates extends APIResource {
2184
2282
  * @param payload - Template configuration (name, category, language, components).
2185
2283
  * @example
2186
2284
  * ```typescript
2187
- * await erixClient.whatsapp.templates.create({
2285
+ * await ecod.infra.connect.whatsapp.templates.create({
2188
2286
  * name: "new_promotion",
2189
2287
  * category: "MARKETING",
2190
2288
  * language: "en_US",
@@ -2207,7 +2305,7 @@ declare class Templates extends APIResource {
2207
2305
  * @param force - If true, attempts to delete from Meta API as well.
2208
2306
  * @example
2209
2307
  * ```typescript
2210
- * await erixClient.whatsapp.templates.deleteTemplate("old_template", true);
2308
+ * await ecod.infra.connect.whatsapp.templates.deleteTemplate("old_template", true);
2211
2309
  * ```
2212
2310
  */
2213
2311
  deleteTemplate<T = any>(templateName: string, force?: boolean): Promise<T>;
@@ -2216,7 +2314,7 @@ declare class Templates extends APIResource {
2216
2314
  *
2217
2315
  * @example
2218
2316
  * ```typescript
2219
- * const config = await erixClient.whatsapp.templates.mappingConfig();
2317
+ * const config = await ecod.infra.connect.whatsapp.templates.mappingConfig();
2220
2318
  * ```
2221
2319
  */
2222
2320
  mappingConfig<T = any>(): Promise<T>;
@@ -2283,7 +2381,7 @@ interface UploadOptions {
2283
2381
  /**
2284
2382
  * Cloudflare R2-backed media resource.
2285
2383
  *
2286
- * Access via `ecod.media`.
2384
+ * Access via `ecod.infra.storage.media`.
2287
2385
  *
2288
2386
  * The `upload()` method is the recommended approach. It acts as a client-side
2289
2387
  * orchestrator: it fetches a presigned URL from the backend, uploads directly
@@ -2291,7 +2389,7 @@ interface UploadOptions {
2291
2389
  *
2292
2390
  * @example
2293
2391
  * ```typescript
2294
- * const { data } = await ecod.media.upload(fileBuffer, {
2392
+ * const { data } = await ecod.infra.storage.media.upload(fileBuffer, {
2295
2393
  * folder: "invoices",
2296
2394
  * filename: "invoice-001.pdf",
2297
2395
  * contentType: "application/pdf",
@@ -2307,7 +2405,7 @@ declare class Media extends APIResource {
2307
2405
  *
2308
2406
  * @example
2309
2407
  * ```typescript
2310
- * const { data } = await ecod.media.getUsage();
2408
+ * const { data } = await ecod.infra.storage.media.getUsage();
2311
2409
  * console.log(`${data.usedMB} / ${data.limitMB} MB used`);
2312
2410
  * ```
2313
2411
  */
@@ -2319,7 +2417,7 @@ declare class Media extends APIResource {
2319
2417
  *
2320
2418
  * @example
2321
2419
  * ```typescript
2322
- * await ecod.media.createFolder("patient_records");
2420
+ * await ecod.infra.storage.media.createFolder("patient_records");
2323
2421
  * ```
2324
2422
  */
2325
2423
  createFolder(name: string): Promise<unknown>;
@@ -2334,13 +2432,13 @@ declare class Media extends APIResource {
2334
2432
  *
2335
2433
  * @example Single folder
2336
2434
  * ```typescript
2337
- * const { data } = await ecod.media.list("invoices", { q: "contract" });
2435
+ * const { data } = await ecod.infra.storage.media.list("invoices", { q: "contract" });
2338
2436
  * // data.files → files only from the "invoices" folder
2339
2437
  * ```
2340
2438
  *
2341
2439
  * @example All folders
2342
2440
  * ```typescript
2343
- * const { data } = await ecod.media.list("*");
2441
+ * const { data } = await ecod.infra.storage.media.list("*");
2344
2442
  * // data.files → merged files from every folder the tenant has
2345
2443
  * // Each file has a `folder` field indicating its source folder
2346
2444
  * ```
@@ -2357,7 +2455,7 @@ declare class Media extends APIResource {
2357
2455
  *
2358
2456
  * @example
2359
2457
  * ```typescript
2360
- * await ecod.media.delete("invoices/old-contract.pdf");
2458
+ * await ecod.infra.storage.media.delete("invoices/old-contract.pdf");
2361
2459
  * ```
2362
2460
  */
2363
2461
  delete(key: string): Promise<unknown>;
@@ -2365,12 +2463,12 @@ declare class Media extends APIResource {
2365
2463
  * Request a temporary presigned download URL for a private file.
2366
2464
  *
2367
2465
  * @param key - The full storage key of the file.
2368
- * @returns `{ url }` — a time-limited download URL.
2466
+ * @returns `{ data: { downloadUrl, expiresAt } }` — a time-limited download URL.
2369
2467
  *
2370
2468
  * @example
2371
2469
  * ```typescript
2372
- * const { data } = await ecod.media.getDownloadUrl("invoices/contract.pdf");
2373
- * // → { url: "https://cdn.ecodrix.com/...?token=..." }
2470
+ * const res: any = await ecod.infra.storage.media.getDownloadUrl("invoices/contract.pdf");
2471
+ * // res.data.downloadUrl → "https://...?X-Amz-Signature=..."
2374
2472
  * ```
2375
2473
  */
2376
2474
  getDownloadUrl(key: string): Promise<unknown>;
@@ -2386,7 +2484,7 @@ declare class Media extends APIResource {
2386
2484
  *
2387
2485
  * @example
2388
2486
  * ```typescript
2389
- * const { data } = await ecod.media.aiDescribe("website/hero.jpg");
2487
+ * const { data } = await ecod.infra.storage.media.aiDescribe("website/hero.jpg");
2390
2488
  * // data.tags → ["office", "team", "modern"]
2391
2489
  * ```
2392
2490
  */
@@ -2410,7 +2508,7 @@ declare class Media extends APIResource {
2410
2508
  * ```typescript
2411
2509
  * import { readFileSync } from "fs";
2412
2510
  * const buf = readFileSync("./invoice.pdf");
2413
- * const { data } = await ecod.media.upload(buf, {
2511
+ * const { data } = await ecod.infra.storage.media.upload(buf, {
2414
2512
  * folder: "invoices",
2415
2513
  * filename: "invoice-001.pdf",
2416
2514
  * contentType: "application/pdf",
@@ -2420,7 +2518,7 @@ declare class Media extends APIResource {
2420
2518
  * @example Browser
2421
2519
  * ```typescript
2422
2520
  * const file = inputElement.files[0];
2423
- * const { data } = await ecod.media.upload(file, {
2521
+ * const { data } = await ecod.infra.storage.media.upload(file, {
2424
2522
  * folder: "avatars",
2425
2523
  * filename: file.name,
2426
2524
  * contentType: file.type,
@@ -2437,7 +2535,7 @@ declare class Folders extends APIResource {
2437
2535
  * @param name - The name of the folder to create.
2438
2536
  * @example
2439
2537
  * ```typescript
2440
- * await erixClient.storage.folders.create("Invoices");
2538
+ * await ecod.infra.storage.folders.create("Invoices");
2441
2539
  * ```
2442
2540
  */
2443
2541
  create<T = any>(name: string): Promise<T>;
@@ -2450,7 +2548,7 @@ declare class Files extends APIResource {
2450
2548
  * @param params - Optional year/month filters for organized storage.
2451
2549
  * @example
2452
2550
  * ```typescript
2453
- * const files = await erixClient.storage.files.list("Invoices", { year: "2026" });
2551
+ * const files = await ecod.infra.storage.files.list("Invoices", { year: "2026" });
2454
2552
  * ```
2455
2553
  */
2456
2554
  list<T = any>(folder: string, params?: {
@@ -2464,12 +2562,12 @@ declare class Files extends APIResource {
2464
2562
  * @param params - Upload parameters (folder, filename, contentType).
2465
2563
  * @example
2466
2564
  * ```typescript
2467
- * const { data } = await erixClient.storage.files.getUploadUrl({
2565
+ * const { data } = await ecod.infra.storage.files.getUploadUrl({
2468
2566
  * folder: "Invoices",
2469
2567
  * filename: "inv_1.pdf",
2470
2568
  * contentType: "application/pdf"
2471
2569
  * });
2472
- * // Now use data.url with a PUT request
2570
+ * // Now PUT the file to data.uploadUrl, then call confirmUpload({ key: data.key, sizeBytes })
2473
2571
  * ```
2474
2572
  */
2475
2573
  getUploadUrl<T = any>(params: {
@@ -2517,22 +2615,13 @@ declare class Health extends APIResource {
2517
2615
  }
2518
2616
 
2519
2617
  /**
2520
- * Automation event log and provider callback resource.
2521
- *
2522
- * Access via `ecod.notifications`.
2618
+ * In-app notifications (alerts) for the workspace.
2523
2619
  *
2524
- * This resource is **read-only**. It exposes platform audit trails — useful
2525
- * for debugging automation failures, monitoring webhook callbacks, and
2526
- * building internal ops dashboards.
2620
+ * Access via `ecod.platform.users.notifications`.
2527
2621
  *
2528
2622
  * @example
2529
2623
  * ```typescript
2530
- * // Find failed automations in April
2531
- * const { data } = await ecod.notifications.listLogs({
2532
- * status: "failed",
2533
- * startDate: "2026-04-01",
2534
- * endDate: "2026-04-30",
2535
- * });
2624
+ * const { data } = await ecod.platform.users.notifications.listAlerts({ unreadOnly: true });
2536
2625
  * ```
2537
2626
  */
2538
2627
  declare class Notifications extends APIResource {
@@ -2543,7 +2632,7 @@ declare class Notifications extends APIResource {
2543
2632
  * @returns Paginated list of notification objects.
2544
2633
  * @example
2545
2634
  * ```typescript
2546
- * const alerts = await erixClient.notifications.listAlerts({ unreadOnly: true });
2635
+ * const alerts = await ecod.platform.users.notifications.listAlerts({ unreadOnly: true });
2547
2636
  * ```
2548
2637
  */
2549
2638
  listAlerts<T = any>(params?: {
@@ -2556,7 +2645,7 @@ declare class Notifications extends APIResource {
2556
2645
  * @param notificationId - The unique ID of the notification.
2557
2646
  * @example
2558
2647
  * ```typescript
2559
- * await erixClient.notifications.dismissAlert("alert_123");
2648
+ * await ecod.platform.users.notifications.dismissAlert("alert_123");
2560
2649
  * ```
2561
2650
  */
2562
2651
  dismissAlert<T = any>(notificationId: string): Promise<T>;
@@ -2565,7 +2654,7 @@ declare class Notifications extends APIResource {
2565
2654
  *
2566
2655
  * @example
2567
2656
  * ```typescript
2568
- * await erixClient.notifications.clearAllAlerts();
2657
+ * await ecod.platform.users.notifications.clearAllAlerts();
2569
2658
  * ```
2570
2659
  */
2571
2660
  clearAllAlerts<T = any>(): Promise<T>;
@@ -3103,21 +3192,21 @@ interface EditOnboardingResponse {
3103
3192
  /**
3104
3193
  * Adaptive onboarding resource.
3105
3194
  *
3106
- * Mounted on the main client as `ecod.onboarding`. Mirrors the seven
3195
+ * Mounted on the main client as `ecod.platform.tenants.onboarding`. Mirrors the seven
3107
3196
  * tenant-facing routes documented in `design.md` § "API surface".
3108
3197
  *
3109
3198
  * @example
3110
3199
  * ```typescript
3111
- * await ecod.onboarding.global({
3200
+ * await ecod.platform.tenants.onboarding.global({
3112
3201
  * workspaceName: "Acme Health",
3113
3202
  * displayName: "Alice",
3114
3203
  * timezone: "Asia/Kolkata",
3115
3204
  * primaryProduct: "crm",
3116
3205
  * });
3117
3206
  *
3118
- * const { sessionId, firstStep } = await ecod.onboarding.start({ productId: "crm" });
3119
- * await ecod.onboarding.answer({ sessionId, stepId: firstStep.stepId, answer: "healthcare" });
3120
- * await ecod.onboarding.complete({ sessionId });
3207
+ * const { sessionId, firstStep } = await ecod.platform.tenants.onboarding.start({ productId: "crm" });
3208
+ * await ecod.platform.tenants.onboarding.answer({ sessionId, stepId: firstStep.stepId, answer: "healthcare" });
3209
+ * await ecod.platform.tenants.onboarding.complete({ sessionId });
3121
3210
  * ```
3122
3211
  */
3123
3212
  declare class Onboarding extends APIResource {
@@ -3672,14 +3761,14 @@ interface PersonaFollowupsResponse {
3672
3761
  /**
3673
3762
  * AI persona resource.
3674
3763
  *
3675
- * Mounted on the main client as `ecod.persona`. Reads the persona row,
3764
+ * Mounted on the main client as `ecod.platform.tenants.persona`. Reads the persona row,
3676
3765
  * accepts reinforcement events, and exposes the live confidence score.
3677
3766
  *
3678
3767
  * @example
3679
3768
  * ```typescript
3680
- * const persona = await ecod.persona.get("crm");
3769
+ * const persona = await ecod.platform.tenants.persona.get("crm");
3681
3770
  *
3682
- * await ecod.persona.reinforce({
3771
+ * await ecod.platform.tenants.persona.reinforce({
3683
3772
  * eventId: crypto.randomUUID(),
3684
3773
  * productId: "laie",
3685
3774
  * kind: "lead_approved",
@@ -3687,7 +3776,7 @@ interface PersonaFollowupsResponse {
3687
3776
  * signals: [{ signal: "funding_stage", value: "series_a" }],
3688
3777
  * });
3689
3778
  *
3690
- * const { score } = await ecod.persona.confidence("laie");
3779
+ * const { score } = await ecod.platform.tenants.persona.confidence("laie");
3691
3780
  * ```
3692
3781
  */
3693
3782
  declare class Persona extends APIResource {
@@ -3817,6 +3906,12 @@ interface KnowledgeSource {
3817
3906
  /** Why it failed, readable as-is. */
3818
3907
  error: string | null;
3819
3908
  chunkCount: number;
3909
+ /**
3910
+ * Ready, but some passages have no embedding yet (the provider refused
3911
+ * when it was read): found by keyword search only until the server's
3912
+ * automatic retry embeds them.
3913
+ */
3914
+ keywordOnly?: boolean;
3820
3915
  createdAt: string;
3821
3916
  updatedAt: string;
3822
3917
  }
@@ -3850,6 +3945,20 @@ declare class Knowledge extends APIResource {
3850
3945
  url: string;
3851
3946
  title?: string;
3852
3947
  }): Promise<Res<KnowledgeSource>>;
3948
+ /**
3949
+ * A whole website: the pages in its sitemap, each added as its own source
3950
+ * (admins). The site must be on your website chat domains or be your
3951
+ * workspace website; pages count against your plan's cap. `pagesFound` =
3952
+ * pages listed on the site, `queued` = sources added now. Fails with
3953
+ * `code` `INVALID_WEBSITE`, `WEBSITE_NOT_ALLOWED`, `KNOWLEDGE_LIMIT` or
3954
+ * `WEBSITE_UNREACHABLE`.
3955
+ */
3956
+ addWebsite(params: {
3957
+ url: string;
3958
+ }): Promise<Res<{
3959
+ pagesFound: number;
3960
+ queued: number;
3961
+ }>>;
3853
3962
  /** Upload a file (PDF, Word, text, image) to your storage and add it. */
3854
3963
  addFile(file: Blob, opts?: {
3855
3964
  title?: string;
@@ -3894,6 +4003,61 @@ interface AiAgentSettings {
3894
4003
  * connected but not yet allowed for Flow, so the agent can't answer there.
3895
4004
  */
3896
4005
  needsFlowGrant?: string[];
4006
+ /**
4007
+ * Read-only: whether the workspace's plan includes AI replies. `false` →
4008
+ * the agent never answers or drafts, even when switched on.
4009
+ */
4010
+ planAllows?: boolean;
4011
+ /**
4012
+ * Topics the AI never answers on its own — handed to a person instead:
4013
+ * preset ids that are on, plus the workspace's own keywords. `null` = never
4014
+ * chosen (every preset on). Send `null` to go back to that.
4015
+ */
4016
+ aiHumanTopics?: AiHumanTopics | null;
4017
+ /** Read-only: the always-human presets (refund, complaint, medical…). */
4018
+ humanTopicPresets?: {
4019
+ id: string;
4020
+ label: string;
4021
+ examples: string[];
4022
+ }[];
4023
+ /** Read-only: answer-review verdicts in the last 30 days. */
4024
+ reviewStats?: AiReviewStats | null;
4025
+ }
4026
+ /** Topics that always go to a person. */
4027
+ interface AiHumanTopics {
4028
+ presets: string[];
4029
+ keywords: string[];
4030
+ }
4031
+ /** Answer review, last 30 days. */
4032
+ interface AiReviewStats {
4033
+ reviewed: number;
4034
+ wrong: number;
4035
+ risky: number;
4036
+ /** Sampled, not reviewed yet. */
4037
+ waiting: number;
4038
+ }
4039
+ type AiReviewVerdict = "correct" | "wrong" | "risky";
4040
+ /** An AI reply sampled for the weekly answer review. */
4041
+ interface AiReviewItem {
4042
+ id: string;
4043
+ conversationId: string;
4044
+ /** What went out (auto-sent, or the draft as a person sent it). */
4045
+ text: string;
4046
+ /** `auto_sent` or `sent` (an approved draft). */
4047
+ status: string;
4048
+ confidence: number;
4049
+ /** How much a person edited the draft before sending (0 = as written). */
4050
+ editDistanceRatio: number | null;
4051
+ /** What auto-send decided on: grounded, chunks, tools, question… */
4052
+ grounding: unknown;
4053
+ sources: {
4054
+ sourceId: string;
4055
+ title: string;
4056
+ }[] | null;
4057
+ verdict: AiReviewVerdict | null;
4058
+ note: string | null;
4059
+ reviewedAt: string | null;
4060
+ createdAt: string;
3897
4061
  }
3898
4062
  /** An AI draft waiting for a person in the inbox (kept up to 7 days). */
3899
4063
  interface AiSuggestion {
@@ -3967,12 +4131,38 @@ interface PausedRun {
3967
4131
  recordsHeld: number | null;
3968
4132
  startedAt: string | null;
3969
4133
  createdAt: string;
4134
+ /** The held step; pass it to `decideRun` so a stale view can't decide another step. */
4135
+ nodeId?: string;
3970
4136
  /** Set when an AI agent step is held: what approving it runs. */
3971
4137
  pendingAction?: {
3972
4138
  action: string;
3973
4139
  label: string;
3974
4140
  input: Record<string, unknown>;
3975
4141
  };
4142
+ /** The held approval step's name and its "What to check" text. */
4143
+ stepName?: string;
4144
+ check?: string;
4145
+ /** Who the run is about: the contact's name, else their masked phone/email. */
4146
+ contact?: string;
4147
+ }
4148
+ /** Channels with AI outcome counts. */
4149
+ type AiOutcomeChannel = "webchat";
4150
+ /** What the AI achieved on a channel in a window. */
4151
+ interface AiOutcomeCounts {
4152
+ /** Threads with at least one visitor message. */
4153
+ chats: number;
4154
+ /** Threads the AI answered with no team reply. */
4155
+ answeredByAi: number;
4156
+ /** Threads the AI handed to a person. */
4157
+ handedOff: number;
4158
+ /** Threads linked to a contact. */
4159
+ contactsSaved: number;
4160
+ /** Appointments the AI booked. */
4161
+ bookings: number;
4162
+ }
4163
+ /** The counts for the window, and for the same length of time before it. */
4164
+ interface AiOutcomes extends AiOutcomeCounts {
4165
+ previous: AiOutcomeCounts;
3976
4166
  }
3977
4167
  /**
3978
4168
  * The AI agent: its settings and the drafts it leaves in the inbox. Drafts
@@ -3986,10 +4176,31 @@ declare class AiAgent extends APIResource {
3986
4176
  data: AiAgentSettings;
3987
4177
  }>;
3988
4178
  /** Change settings (workspace admins only). */
3989
- updateSettings(patch: Partial<Omit<AiAgentSettings, "availableTools">>): Promise<{
4179
+ updateSettings(patch: Partial<Omit<AiAgentSettings, "availableTools" | "humanTopicPresets" | "reviewStats">>): Promise<{
3990
4180
  success: boolean;
3991
4181
  data: AiAgentSettings;
3992
4182
  }>;
4183
+ /**
4184
+ * What the AI achieved on a channel in the last `days` days (1–90, default
4185
+ * 30), with `previous` for the `days` before. Default channel `webchat`.
4186
+ */
4187
+ outcomes(params?: {
4188
+ channel?: AiOutcomeChannel;
4189
+ days?: number;
4190
+ }): Promise<{
4191
+ success: boolean;
4192
+ data: AiOutcomes;
4193
+ }>;
4194
+ /** Answer review: sampled AI replies (last 30 days), waiting first. */
4195
+ reviews(status?: "waiting" | "reviewed"): Promise<{
4196
+ success: boolean;
4197
+ data: AiReviewItem[];
4198
+ }>;
4199
+ /** Answer review: mark one reply Correct / Wrong / Risky (owners and admins). */
4200
+ review(id: string, verdict: AiReviewVerdict, note?: string): Promise<{
4201
+ success: boolean;
4202
+ data: Pick<AiReviewItem, "id" | "verdict" | "note" | "reviewedAt">;
4203
+ }>;
3993
4204
  /** The draft waiting on a conversation (`data: null` when none). */
3994
4205
  suggestion(conversationId: string): Promise<{
3995
4206
  success: boolean;
@@ -4035,7 +4246,7 @@ declare class AiAgent extends APIResource {
4035
4246
  data: ModuleAgentSettings;
4036
4247
  }>;
4037
4248
  /** Let a held run continue, or stop it. */
4038
- decideRun(runId: string, decision: "approve" | "reject"): Promise<{
4249
+ decideRun(runId: string, decision: "approve" | "reject", nodeId?: string): Promise<{
4039
4250
  success: boolean;
4040
4251
  decision: string;
4041
4252
  }>;
@@ -4510,60 +4721,9 @@ declare class PlatformDomain {
4510
4721
  constructor(client: AxiosInstance);
4511
4722
  }
4512
4723
 
4513
- /**
4514
- * Typed error hierarchy for the @ecodrix/erix-api SDK.
4515
- *
4516
- * All errors thrown by the SDK extend `EcodrixError`, so a single
4517
- * `catch` block can handle them all, while still allowing granular
4518
- * differentiation between auth failures, rate limits, and generic API errors.
4519
- *
4520
- * @example
4521
- * ```typescript
4522
- * import { APIError, AuthenticationError, RateLimitError } from "@ecodrix/erix-api";
4523
- *
4524
- * try {
4525
- * await ecod.crm.leads.retrieve("invalid_id");
4526
- * } catch (err) {
4527
- * if (err instanceof AuthenticationError) {
4528
- * console.error("Invalid API key or client code.");
4529
- * } else if (err instanceof RateLimitError) {
4530
- * console.warn("Slow down — rate limit hit.");
4531
- * } else if (err instanceof APIError) {
4532
- * console.error(`API error ${err.status}: ${err.message}`);
4533
- * }
4534
- * }
4535
- * ```
4536
- */
4537
- /** Base class for all ECODrIx SDK errors. */
4538
- declare class EcodrixError extends Error {
4724
+ declare class WebhookSignatureError extends APIError {
4539
4725
  constructor(message: string);
4540
4726
  }
4541
- /**
4542
- * Represents an error returned by the ECODrIx API.
4543
- * Carries the HTTP `status` code and an optional `code` string.
4544
- */
4545
- declare class APIError extends EcodrixError {
4546
- /** HTTP status code returned by the API (e.g. 400, 404, 500). */
4547
- status?: number;
4548
- /** Machine-readable error code (e.g. `"NOT_FOUND"`, `"VALIDATION_ERROR"`). */
4549
- code?: string;
4550
- constructor(message: string, status?: number, code?: string);
4551
- }
4552
- /**
4553
- * Thrown when the API key or client code is missing, invalid, or expired.
4554
- * HTTP 401.
4555
- */
4556
- declare class AuthenticationError extends APIError {
4557
- constructor(message?: string);
4558
- }
4559
- /**
4560
- * Thrown when the rate limit for the API key has been exceeded.
4561
- * HTTP 429. Implement exponential backoff before retrying.
4562
- */
4563
- declare class RateLimitError extends APIError {
4564
- constructor(message?: string);
4565
- }
4566
-
4567
4727
  /**
4568
4728
  * Validates and constructs webhook events sent by the ECODrIx platform.
4569
4729
  * Ensures the payload has not been tampered with.
@@ -4618,7 +4778,7 @@ interface ECODrIxAPIOptions {
4618
4778
  /**
4619
4779
  * Your tenant ID (Client Code).
4620
4780
  * This scopes all API requests to your specific organisation.
4621
- * @example "ERIX_CLNT_JHBJHF"
4781
+ * @example "ERIX_CLNT_XXXXXX"
4622
4782
  */
4623
4783
  clientCode?: string;
4624
4784
  /**
@@ -4685,7 +4845,7 @@ interface ECODrIxAPIOptions {
4685
4845
  *
4686
4846
  * const ecod = new ECODrIxAPI({
4687
4847
  * apiKey: process.env.ECOD_API_KEY!,
4688
- * clientCode: "ERIX_CLNT_JHBJHF",
4848
+ * clientCode: "ERIX_CLNT_XXXXXX",
4689
4849
  * });
4690
4850
  *
4691
4851
  * await ecod.product.erix.chat.messages.send({ to: "+91...", text: "Hello!" });
@@ -4701,6 +4861,8 @@ declare class ECODrIxAPI {
4701
4861
  * @internal Socket.io client for real-time events.
4702
4862
  */
4703
4863
  private socket;
4864
+ /** Opens the realtime socket; set by the constructor, called on first use. */
4865
+ private startSocket;
4704
4866
  private socketPromise;
4705
4867
  private socketQueue;
4706
4868
  /**
@@ -4780,8 +4942,8 @@ declare class ECODrIxAPI {
4780
4942
  * @example
4781
4943
  * ```typescript
4782
4944
  * ecod
4783
- * .on("whatsapp.message_received", (msg) => console.log(msg.body))
4784
- * .on("automation.failed", (err) => alertTeam(err));
4945
+ * .on("inbox.message", ({ conversationId, message }) => console.log(conversationId, message.text))
4946
+ * .on("resync", () => refetchEverything());
4785
4947
  * ```
4786
4948
  */
4787
4949
  on(event: string, callback: (...args: any[]) => void): this;
@@ -4817,7 +4979,12 @@ declare class ECODrIxAPI {
4817
4979
  *
4818
4980
  * @example
4819
4981
  * ```typescript
4820
- * const { data } = await ecod.request("POST", "/api/saas/experimental-feature", { flag: true });
4982
+ * // Paths are relative to `<host>/<version>/api`.
4983
+ * const { data } = await ecod.request("POST", "/infra/connect/send/email", {
4984
+ * to: "customer@example.com",
4985
+ * subject: "Your order",
4986
+ * html: "<p>Thanks!</p>",
4987
+ * });
4821
4988
  * console.log(data);
4822
4989
  * ```
4823
4990
  */
@@ -5065,7 +5232,7 @@ interface CustomFieldFilter {
5065
5232
  * HTTP status code to exception type mapping
5066
5233
  * Maps specific HTTP status codes to appropriate typed exceptions
5067
5234
  */
5068
- declare const HTTP_STATUS_ERROR_MAP: Record<number, typeof APIError>;
5235
+ declare const HTTP_STATUS_ERROR_MAP: Record<number, abstract new (...args: any[]) => APIError>;
5069
5236
  /**
5070
5237
  * Enhanced error handler that maps HTTP status codes to typed exceptions
5071
5238
  *
@@ -5092,7 +5259,7 @@ declare function handleAPIError(error: any): never;
5092
5259
  * @example
5093
5260
  * ```typescript
5094
5261
  * try {
5095
- * await ecod.crm.leads.create(leadData);
5262
+ * await ecod.product.erix.leads.create(leadData);
5096
5263
  * } catch (error) {
5097
5264
  * if (isAPIError(error, AuthenticationError)) {
5098
5265
  * console.log('Authentication failed - check your API key');
@@ -5112,7 +5279,7 @@ declare function isAPIError(error: any, errorType: typeof APIError): boolean;
5112
5279
  * @example
5113
5280
  * ```typescript
5114
5281
  * try {
5115
- * await ecod.crm.leads.get('invalid_id');
5282
+ * await ecod.product.erix.leads.retrieve('invalid_id');
5116
5283
  * } catch (error) {
5117
5284
  * const details = getErrorDetails(error);
5118
5285
  * console.log(`Error ${details.status}: ${details.message} (${details.code})`);
@@ -5158,7 +5325,7 @@ declare const ERROR_RETRY_CONFIG: {
5158
5325
  * @example
5159
5326
  * ```typescript
5160
5327
  * try {
5161
- * await ecod.crm.leads.list();
5328
+ * await ecod.product.erix.leads.list();
5162
5329
  * } catch (error) {
5163
5330
  * const retryConfig = getRetryConfig(error);
5164
5331
  * if (retryConfig.shouldRetry) {
@@ -5188,4 +5355,4 @@ declare function getRetryConfig(error: any): {
5188
5355
  readonly reason: "Generic API errors may be transient and worth retrying";
5189
5356
  };
5190
5357
 
5191
- export { type AIPersona, APIError, APIResource, type AgentAutonomy, type AgentBudget, AiAgent, type AiAgentSettings, type AiAgentTool, type AiSuggestion, type AnswerFollowupBody, type AnswerOnboardingPayload, type AnswerOnboardingResponse, type ApplyCouponPayload, AuthenticationError, type BehaviorRules, type CheckboxConfig, type CheckoutAmountBreakdown, type CheckoutOrderResponse, type CheckoutProduct, type CheckoutSession, type ColorRule, type ColumnConfig, type CompleteOnboardingPayload, type CompleteOnboardingResponse, type ConfidenceResponse, ConnectInfra, type Conversation, type ListParams as ConversationListParams, type Correction, type CreateLeadParams, type CreateOrderPayload, type CreatePipelineParams, type CreateSessionPayload, type CrmView, type CurrencyConfig, type CurrencyValue, type CustomFieldFilter, type DateConfig, type DateTimeConfig, type DropdownConfig, ECODrIxAPI as ECODrIx, ECODrIxAPI, type ECODrIxAPIOptions, ERROR_RETRY_CONFIG, EcodrixError, type EditOnboardingPayload, type EditOnboardingResponse, type EmailConfig, EmailConnect, ErixChat, ErixProduct, type FieldConfig, type FieldDefinition, type FieldManifest, type FieldType, type FileConfig, type FilterOperator, type FilterRule, type FormulaConfig, type GlobalOnboardingPayload, HTTP_STATUS_ERROR_MAP, type ICP, type InboxChannel, InfraDomain, KNOWLEDGE_FILE_TYPES, Knowledge, type KnowledgePassage, type KnowledgeSource, LEAD_STATUS_VALUES, type LayoutType, type Lead, type LeadPattern, type LeadSource, type LeadStatus, type LearningMemory, type ListLeadsParams, type ManifestFieldType, type MappingField, type MappingPreviewResult, type MappingSources, type MappingValidationResult, type Message, type ModuleAgent, type ModuleAgentPatch, type ModuleAgentSettings, type ModuleAgentTool, type NichePack, type NichePackResearchConfig, type NichePackStatus, type NormalizedFieldValue, type NumberConfig, Onboarding, type OnboardingCohortRange, type OnboardingConfig, type OnboardingExperiment, type OnboardingExperimentStatus, type OnboardingExperimentVariant, type OnboardingMemoryMapping, type OnboardingOption, type OnboardingSession, type OnboardingSessionStatus, type OnboardingStateResponse, type OnboardingStep, type OnboardingStepType, type OutboundMedia, type OutreachEdit, type PaginatedResponse, type PausedRun, Persona, type PersonaFollowupQuestion, type PersonaFollowupsResponse, type PersonaIdentity, type PersonaTimelineEntry, type PersonaTimelineOptions, type PersonaTimelineResponse, type PhoneConfig, type Pipeline, type PipelineStage, type PipelineStageParams, PlatformDomain, PlatformTenants, PlatformUsers, ProductDomain, type ProgressConfig, RateLimitError, type RatingConfig, type ReinforceResponse, type ReinforcementEvent, type RelationConfig, type RelationValue, type RequestOptions, type ResourceManifest, type SendMessageParams, type SendTemplateParams, type ServiceConfig, type ServiceConfigGlobal, type ServiceConfigPerProduct, type SortRule, type StartOnboardingPayload, type StartOnboardingResponse, StorageInfra, type StoredFieldValue, type SuggestionEvent, type TagsConfig, type Template, type TemplateApiResponse, type TemplateBinding, type TemplateBindingSource, type TemplateComponent, type TemplateEmptyPolicy, type TemplateMapping, type TextConfig, type UpsertLeadParams, type UrlConfig, type VerifyPayload, type ViewConfig, type Vocabulary, WhatsAppConnect, type WorkspaceDashboardLayout, type WorkspaceDefaultAutomation, type WorkspaceDefaultField, type WorkspaceDefaultPipeline, type WorkspaceModuleConfig, type WorkspaceProfile, ECODrIxAPI as default, getErrorDetails, getRetryConfig, handleAPIError, isAPIError };
5358
+ export { type AIPersona, APIError, APIResource, type AgentAutonomy, type AgentBudget, AiAgent, type AiAgentSettings, type AiAgentTool, type AiHumanTopics, type AiOutcomeChannel, type AiOutcomeCounts, type AiOutcomes, type AiReviewItem, type AiReviewStats, type AiReviewVerdict, type AiSuggestion, type AnswerFollowupBody, type AnswerOnboardingPayload, type AnswerOnboardingResponse, type ApplyCouponPayload, type AssignEventPayload, AuthenticationError, type BehaviorRules, type CheckboxConfig, type CheckoutAmountBreakdown, type CheckoutOrderResponse, type CheckoutProduct, type CheckoutSession, type ColorRule, type ColumnConfig, type CompleteOnboardingPayload, type CompleteOnboardingResponse, type ConfidenceResponse, ConnectInfra, type Conversation, type ListParams as ConversationListParams, type Correction, type CreateLeadParams, type CreateOrderPayload, type CreatePipelineParams, type CreateSessionPayload, type CrmView, type CurrencyConfig, type CurrencyValue, type CustomFieldFilter, type DateConfig, type DateTimeConfig, type DropdownConfig, ECODrIxAPI as ECODrIx, ECODrIxAPI, type ECODrIxAPIOptions, ERROR_RETRY_CONFIG, type EditOnboardingPayload, type EditOnboardingResponse, type EmailConfig, EmailConnect, ErixChat, ErixProduct, type EventDefinition, type FieldConfig, type FieldDefinition, type FieldManifest, type FieldType, type FileConfig, type FilterOperator, type FilterRule, type FormulaConfig, type GlobalOnboardingPayload, HTTP_STATUS_ERROR_MAP, type ICP, type InboxChannel, InfraDomain, KNOWLEDGE_FILE_TYPES, Knowledge, type KnowledgePassage, type KnowledgeSource, LEAD_STATUS_VALUES, type LayoutType, type Lead, type LeadPattern, type LeadSource, type LeadStatus, type LearningMemory, type ListLeadsParams, type ManifestFieldType, type MappingField, type MappingPreviewResult, type MappingSources, type MappingValidationResult, type Message, type ModuleAgent, type ModuleAgentPatch, type ModuleAgentSettings, type ModuleAgentTool, type NichePack, type NichePackResearchConfig, type NichePackStatus, type NormalizedFieldValue, type NumberConfig, Onboarding, type OnboardingCohortRange, type OnboardingConfig, type OnboardingExperiment, type OnboardingExperimentStatus, type OnboardingExperimentVariant, type OnboardingMemoryMapping, type OnboardingOption, type OnboardingSession, type OnboardingSessionStatus, type OnboardingStateResponse, type OnboardingStep, type OnboardingStepType, type OutboundMedia, type OutreachEdit, type PaginatedResponse, type PausedRun, Persona, type PersonaFollowupQuestion, type PersonaFollowupsResponse, type PersonaIdentity, type PersonaTimelineEntry, type PersonaTimelineOptions, type PersonaTimelineResponse, type PhoneConfig, type Pipeline, type PipelineStage, type PipelineStageParams, PlatformDomain, PlatformTenants, PlatformUsers, ProductDomain, type ProgressConfig, RateLimitError, type RatingConfig, type ReinforceResponse, type ReinforcementEvent, type RelationConfig, type RelationValue, type RequestOptions, type ResourceManifest, type SendMessageParams, type SendTemplateParams, type ServiceConfig, type ServiceConfigGlobal, type ServiceConfigPerProduct, type SortRule, type StartOnboardingPayload, type StartOnboardingResponse, StorageInfra, type StoredFieldValue, type SuggestionEvent, type TagsConfig, type Template, type TemplateApiResponse, type TemplateBinding, type TemplateBindingSource, type TemplateComponent, type TemplateEmptyPolicy, type TemplateMapping, type TextConfig, type TriggerPayload, type TriggerResponse, type UpsertLeadParams, type UrlConfig, type VerifyPayload, type ViewConfig, type Vocabulary, WebchatOwnerSettings, WebchatSettingsPatch, WebhookSignatureError, Webhooks, WhatsAppConnect, type WorkspaceDashboardLayout, type WorkspaceDefaultAutomation, type WorkspaceDefaultField, type WorkspaceDefaultPipeline, type WorkspaceModuleConfig, type WorkspaceProfile, ECODrIxAPI as default, getErrorDetails, getRetryConfig, handleAPIError, isAPIError };