@ecodrix/erix-api 1.0.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/LICENSE +21 -0
- package/README.md +643 -0
- package/dist/index.d.ts +1096 -0
- package/dist/ts/browser/index.global.js +52 -0
- package/dist/ts/browser/index.global.js.map +1 -0
- package/dist/ts/cjs/index.cjs +2 -0
- package/dist/ts/cjs/index.cjs.map +1 -0
- package/dist/ts/cjs/index.d.cts +1096 -0
- package/dist/ts/esm/index.d.ts +1096 -0
- package/dist/ts/esm/index.js +2 -0
- package/dist/ts/esm/index.js.map +1 -0
- package/package.json +69 -0
- package/schema/openapi.yaml +199 -0
- package/src/core.ts +262 -0
- package/src/error.ts +72 -0
- package/src/index.ts +18 -0
- package/src/resource.ts +73 -0
- package/src/resources/crm/index.ts +10 -0
- package/src/resources/crm/leads.ts +186 -0
- package/src/resources/email.ts +51 -0
- package/src/resources/events.ts +121 -0
- package/src/resources/media.ts +174 -0
- package/src/resources/meet.ts +153 -0
- package/src/resources/notifications.ts +123 -0
- package/src/resources/webhooks.ts +85 -0
- package/src/resources/whatsapp/conversations.ts +43 -0
- package/src/resources/whatsapp/index.ts +49 -0
- package/src/resources/whatsapp/messages.ts +138 -0
package/LICENSE
ADDED
|
@@ -0,0 +1,21 @@
|
|
|
1
|
+
MIT License
|
|
2
|
+
|
|
3
|
+
Copyright (c) 2026 ECODrIx Team
|
|
4
|
+
|
|
5
|
+
Permission is hereby granted, free of charge, to any person obtaining a copy
|
|
6
|
+
of this software and associated documentation files (the "Software"), to deal
|
|
7
|
+
in the Software without restriction, including without limitation the rights
|
|
8
|
+
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
|
9
|
+
copies of the Software, and to permit persons to whom the Software is
|
|
10
|
+
furnished to do so, subject to the following conditions:
|
|
11
|
+
|
|
12
|
+
The above copyright notice and this permission notice shall be included in all
|
|
13
|
+
copies or substantial portions of the Software.
|
|
14
|
+
|
|
15
|
+
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
|
16
|
+
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
|
17
|
+
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
|
18
|
+
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
|
19
|
+
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
|
20
|
+
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
|
|
21
|
+
SOFTWARE.
|
package/README.md
ADDED
|
@@ -0,0 +1,643 @@
|
|
|
1
|
+
# @ecodrix/erix-api
|
|
2
|
+
|
|
3
|
+
<div align="center">
|
|
4
|
+
|
|
5
|
+
[](https://www.npmjs.com/package/@ecodrix/erix-api)
|
|
6
|
+
[](https://opensource.org/licenses/MIT)
|
|
7
|
+
[](https://www.typescriptlang.org/)
|
|
8
|
+
[](./schema/openapi.yaml)
|
|
9
|
+
|
|
10
|
+
**The official, isomorphic SDK for the [ECODrIx](https://ecodrix.com) platform.**
|
|
11
|
+
|
|
12
|
+
Manage WhatsApp conversations, CRM leads, file storage, and Google Meet appointments — all from a single, type-safe library.
|
|
13
|
+
|
|
14
|
+
</div>
|
|
15
|
+
|
|
16
|
+
---
|
|
17
|
+
|
|
18
|
+
## Table of Contents
|
|
19
|
+
|
|
20
|
+
- [Installation](#installation)
|
|
21
|
+
- [Quick Start](#quick-start)
|
|
22
|
+
- [Configuration](#configuration)
|
|
23
|
+
- [Resources](#resources)
|
|
24
|
+
- [WhatsApp](#whatsapp)
|
|
25
|
+
- [CRM — Leads](#crm--leads)
|
|
26
|
+
- [Meetings](#meetings)
|
|
27
|
+
- [Media (Storage)](#media-storage)
|
|
28
|
+
- [Email](#email)
|
|
29
|
+
- [Events & Workflows](#events--workflows)
|
|
30
|
+
- [Notifications & Logs](#notifications--logs)
|
|
31
|
+
- [Enterprise Capabilities](#enterprise-capabilities)
|
|
32
|
+
- [Auto-Paginating Iterators](#auto-paginating-iterators)
|
|
33
|
+
- [Bulk Data Chunking](#bulk-data-chunking)
|
|
34
|
+
- [Idempotency Keys](#idempotency-keys)
|
|
35
|
+
- [Webhook Signature Verification](#webhook-signature-verification)
|
|
36
|
+
- [Raw Execution Engine](#raw-execution-engine)
|
|
37
|
+
- [Real-time Events](#real-time-events)
|
|
38
|
+
- [Error Handling](#error-handling)
|
|
39
|
+
- [Browser / CDN Usage](#browser--cdn-usage)
|
|
40
|
+
|
|
41
|
+
---
|
|
42
|
+
|
|
43
|
+
## Installation
|
|
44
|
+
|
|
45
|
+
```bash
|
|
46
|
+
# pnpm (recommended)
|
|
47
|
+
pnpm add @ecodrix/erix-api
|
|
48
|
+
|
|
49
|
+
# npm
|
|
50
|
+
npm install @ecodrix/erix-api
|
|
51
|
+
|
|
52
|
+
# yarn
|
|
53
|
+
yarn add @ecodrix/erix-api
|
|
54
|
+
```
|
|
55
|
+
|
|
56
|
+
> **Requires**: Node.js >= 18
|
|
57
|
+
|
|
58
|
+
---
|
|
59
|
+
|
|
60
|
+
## Quick Start
|
|
61
|
+
|
|
62
|
+
```typescript
|
|
63
|
+
import { Ecodrix } from "@ecodrix/erix-api";
|
|
64
|
+
|
|
65
|
+
const ecod = new Ecodrix({
|
|
66
|
+
apiKey: "your_api_key",
|
|
67
|
+
clientCode: "YOUR_CLIENT_CODE", // Your tenant ID
|
|
68
|
+
});
|
|
69
|
+
|
|
70
|
+
// Send a WhatsApp message
|
|
71
|
+
await ecod.whatsapp.messages.send({
|
|
72
|
+
to: "+919876543210",
|
|
73
|
+
text: "Hello from ECODrIx!",
|
|
74
|
+
});
|
|
75
|
+
|
|
76
|
+
// Create a CRM lead
|
|
77
|
+
const lead = await ecod.crm.leads.create({
|
|
78
|
+
firstName: "Jhon",
|
|
79
|
+
phone: "+919876543210",
|
|
80
|
+
source: "website",
|
|
81
|
+
});
|
|
82
|
+
|
|
83
|
+
console.log(lead.data.id);
|
|
84
|
+
```
|
|
85
|
+
|
|
86
|
+
---
|
|
87
|
+
|
|
88
|
+
## Configuration
|
|
89
|
+
|
|
90
|
+
Pass an options object to `new Ecodrix(options)`:
|
|
91
|
+
|
|
92
|
+
| Option | Type | Required | Default | Description |
|
|
93
|
+
| ------------ | -------- | ----------- | ------------------------- | ---------------------------------------------- |
|
|
94
|
+
| `apiKey` | `string` | ✅ Yes | — | Your ECOD Platform API key |
|
|
95
|
+
| `clientCode` | `string` | Recommended | — | Your tenant ID (scopes all requests) |
|
|
96
|
+
| `baseUrl` | `string` | No | `https://api.ecodrix.com` | Override the API base URL (e.g. for local dev) |
|
|
97
|
+
| `socketUrl` | `string` | No | Same as `baseUrl` | Override the Socket.io server URL |
|
|
98
|
+
|
|
99
|
+
```typescript
|
|
100
|
+
const ecod = new Ecodrix({
|
|
101
|
+
apiKey: process.env.ECOD_API_KEY!,
|
|
102
|
+
clientCode: process.env.ECOD_CLIENT_CODE,
|
|
103
|
+
baseUrl: "http://localhost:4000", // For local development
|
|
104
|
+
});
|
|
105
|
+
```
|
|
106
|
+
|
|
107
|
+
---
|
|
108
|
+
|
|
109
|
+
## Resources
|
|
110
|
+
|
|
111
|
+
Every resource follows the same predictable CRUD interface:
|
|
112
|
+
|
|
113
|
+
| Method | Description |
|
|
114
|
+
| --------------------- | ---------------------------------- |
|
|
115
|
+
| `.create(params)` | Create a new record |
|
|
116
|
+
| `.list(params?)` | List records with optional filters |
|
|
117
|
+
| `.retrieve(id)` | Get a single record by ID |
|
|
118
|
+
| `.update(id, params)` | Update a record |
|
|
119
|
+
| `.delete(id)` | Delete or cancel a record |
|
|
120
|
+
|
|
121
|
+
---
|
|
122
|
+
|
|
123
|
+
### WhatsApp
|
|
124
|
+
|
|
125
|
+
Access via `ecod.whatsapp`.
|
|
126
|
+
|
|
127
|
+
#### `ecod.whatsapp.messages`
|
|
128
|
+
|
|
129
|
+
**Send a text message**
|
|
130
|
+
|
|
131
|
+
```typescript
|
|
132
|
+
await ecod.whatsapp.messages.send({
|
|
133
|
+
to: "+919876543210",
|
|
134
|
+
text: "Your appointment is confirmed!",
|
|
135
|
+
});
|
|
136
|
+
```
|
|
137
|
+
|
|
138
|
+
**Send a media message (image, video, document, audio)**
|
|
139
|
+
|
|
140
|
+
```typescript
|
|
141
|
+
await ecod.whatsapp.messages.send({
|
|
142
|
+
to: "+919876543210",
|
|
143
|
+
mediaUrl: "https://cdn.ecodrix.com/invoice.pdf",
|
|
144
|
+
mediaType: "document",
|
|
145
|
+
filename: "invoice.pdf",
|
|
146
|
+
});
|
|
147
|
+
```
|
|
148
|
+
|
|
149
|
+
**Send a pre-approved template message**
|
|
150
|
+
|
|
151
|
+
```typescript
|
|
152
|
+
await ecod.whatsapp.messages.sendTemplate({
|
|
153
|
+
to: "+919876543210",
|
|
154
|
+
templateName: "appointment_reminder",
|
|
155
|
+
language: "en_US",
|
|
156
|
+
variables: ["Dhanesh", "Tomorrow 10AM"],
|
|
157
|
+
});
|
|
158
|
+
```
|
|
159
|
+
|
|
160
|
+
**Send a Meta-approved direct template (Bypass queues)**
|
|
161
|
+
|
|
162
|
+
Use this specifically to dispatch high-priority utility templates containing dynamic variable maps.
|
|
163
|
+
|
|
164
|
+
```typescript
|
|
165
|
+
const { messageId } = await ecod.whatsapp.sendTemplate({
|
|
166
|
+
phone: "+919876543210",
|
|
167
|
+
templateName: "payment_confirmation",
|
|
168
|
+
variables: {
|
|
169
|
+
name: "Dhanesh",
|
|
170
|
+
amount: "₹1,500"
|
|
171
|
+
}
|
|
172
|
+
});
|
|
173
|
+
```
|
|
174
|
+
|
|
175
|
+
**Mark a conversation as read**
|
|
176
|
+
|
|
177
|
+
```typescript
|
|
178
|
+
await ecod.whatsapp.messages.markRead("conversation_id");
|
|
179
|
+
```
|
|
180
|
+
|
|
181
|
+
#### `ecod.whatsapp.conversations`
|
|
182
|
+
|
|
183
|
+
```typescript
|
|
184
|
+
// List conversations (cursor-based pagination)
|
|
185
|
+
const { data } = await ecod.whatsapp.conversations.list({ limit: 20 });
|
|
186
|
+
|
|
187
|
+
// Get a specific conversation
|
|
188
|
+
const conv = await ecod.whatsapp.conversations.retrieve("conversation_id");
|
|
189
|
+
|
|
190
|
+
// Archive a conversation
|
|
191
|
+
await ecod.whatsapp.conversations.delete("conversation_id");
|
|
192
|
+
```
|
|
193
|
+
|
|
194
|
+
---
|
|
195
|
+
|
|
196
|
+
### CRM — Leads
|
|
197
|
+
|
|
198
|
+
Access via `ecod.crm.leads`.
|
|
199
|
+
|
|
200
|
+
**Create a Lead**
|
|
201
|
+
|
|
202
|
+
```typescript
|
|
203
|
+
const { data: lead } = await ecod.crm.leads.create({
|
|
204
|
+
firstName: "Dhanesh",
|
|
205
|
+
lastName: "Kumar",
|
|
206
|
+
phone: "+919876543210",
|
|
207
|
+
email: "dhanesh@example.com",
|
|
208
|
+
source: "website", // 'website' | 'whatsapp' | 'direct' | ...
|
|
209
|
+
metadata: {
|
|
210
|
+
utmSource: "google",
|
|
211
|
+
},
|
|
212
|
+
});
|
|
213
|
+
```
|
|
214
|
+
|
|
215
|
+
**List Leads (with filters)**
|
|
216
|
+
|
|
217
|
+
```typescript
|
|
218
|
+
const { data: leads } = await ecod.crm.leads.list({
|
|
219
|
+
status: "new", // filter by status
|
|
220
|
+
source: "whatsapp",
|
|
221
|
+
page: 1,
|
|
222
|
+
limit: 25,
|
|
223
|
+
});
|
|
224
|
+
```
|
|
225
|
+
|
|
226
|
+
*(See [Enterprise Capabilities](#enterprise-capabilities) for efficient auto-pagination or bulk-creation tricks like `listAutoPaging` and `createMany`).*
|
|
227
|
+
|
|
228
|
+
**Retrieve a Lead by ID**
|
|
229
|
+
|
|
230
|
+
```typescript
|
|
231
|
+
const { data: lead } = await ecod.crm.leads.retrieve("lead_id");
|
|
232
|
+
```
|
|
233
|
+
|
|
234
|
+
**Update a Lead**
|
|
235
|
+
|
|
236
|
+
```typescript
|
|
237
|
+
await ecod.crm.leads.update("lead_id", {
|
|
238
|
+
email: "new@email.com",
|
|
239
|
+
metadata: { score: 95 },
|
|
240
|
+
});
|
|
241
|
+
```
|
|
242
|
+
|
|
243
|
+
**Delete / Archive a Lead**
|
|
244
|
+
|
|
245
|
+
```typescript
|
|
246
|
+
await ecod.crm.leads.delete("lead_id");
|
|
247
|
+
```
|
|
248
|
+
|
|
249
|
+
---
|
|
250
|
+
|
|
251
|
+
### Meetings
|
|
252
|
+
|
|
253
|
+
Access via `ecod.meet`. Backed by **Google Meet**.
|
|
254
|
+
|
|
255
|
+
**Schedule a Meeting**
|
|
256
|
+
|
|
257
|
+
```typescript
|
|
258
|
+
const { data: meeting } = await ecod.meet.create({
|
|
259
|
+
leadId: "lead_id",
|
|
260
|
+
participantName: "Dhanesh Kumar",
|
|
261
|
+
participantPhone: "+919876543210",
|
|
262
|
+
startTime: "2026-04-10T10:00:00.000Z",
|
|
263
|
+
endTime: "2026-04-10T10:30:00.000Z",
|
|
264
|
+
});
|
|
265
|
+
|
|
266
|
+
console.log(meeting.meetLink); // → https://meet.google.com/abc-defg-hij
|
|
267
|
+
```
|
|
268
|
+
|
|
269
|
+
**List Meetings**
|
|
270
|
+
|
|
271
|
+
```typescript
|
|
272
|
+
const { data: meetings } = await ecod.meet.list({ status: "scheduled" });
|
|
273
|
+
```
|
|
274
|
+
|
|
275
|
+
**Retrieve a Meeting**
|
|
276
|
+
|
|
277
|
+
```typescript
|
|
278
|
+
const { data } = await ecod.meet.retrieve("meeting_id");
|
|
279
|
+
```
|
|
280
|
+
|
|
281
|
+
**Reschedule a Meeting**
|
|
282
|
+
|
|
283
|
+
```typescript
|
|
284
|
+
await ecod.meet.update("meeting_id", {
|
|
285
|
+
startTime: "2026-04-11T11:00:00.000Z",
|
|
286
|
+
endTime: "2026-04-11T11:30:00.000Z",
|
|
287
|
+
});
|
|
288
|
+
```
|
|
289
|
+
|
|
290
|
+
**Cancel a Meeting**
|
|
291
|
+
|
|
292
|
+
```typescript
|
|
293
|
+
await ecod.meet.delete("meeting_id");
|
|
294
|
+
```
|
|
295
|
+
|
|
296
|
+
---
|
|
297
|
+
|
|
298
|
+
### Storage
|
|
299
|
+
|
|
300
|
+
Access via `ecod.storage`. Powered by **Cloudflare R2**.
|
|
301
|
+
|
|
302
|
+
**Upload a File (Elite Helper)**
|
|
303
|
+
|
|
304
|
+
This single call handles the entire R2 presigned-URL orchestration for you:
|
|
305
|
+
|
|
306
|
+
1. Requests a presigned PUT URL from the backend.
|
|
307
|
+
2. Uploads the file directly to R2 (no proxy overhead).
|
|
308
|
+
3. Confirms the upload with the backend.
|
|
309
|
+
|
|
310
|
+
```typescript
|
|
311
|
+
// Node.js: from a Buffer
|
|
312
|
+
import { readFileSync } from "fs";
|
|
313
|
+
|
|
314
|
+
const fileBuffer = readFileSync("./contract.pdf");
|
|
315
|
+
const { data } = await ecod.storage.upload(fileBuffer, {
|
|
316
|
+
folder: "customer_documents",
|
|
317
|
+
filename: "contract.pdf",
|
|
318
|
+
contentType: "application/pdf",
|
|
319
|
+
});
|
|
320
|
+
|
|
321
|
+
console.log(data.url); // → https://cdn.ecodrix.com/customer_documents/contract.pdf
|
|
322
|
+
|
|
323
|
+
// Browser: from an <input> file
|
|
324
|
+
const file = document.getElementById("file-input").files[0];
|
|
325
|
+
const { data } = await ecod.storage.upload(file, {
|
|
326
|
+
folder: "avatars",
|
|
327
|
+
filename: file.name,
|
|
328
|
+
contentType: file.type,
|
|
329
|
+
});
|
|
330
|
+
filename: "dhanesh.png",
|
|
331
|
+
contentType: "image/png"
|
|
332
|
+
});
|
|
333
|
+
|
|
334
|
+
console.log(data.url);
|
|
335
|
+
// -> https://cdn.ecodrix.com/avatars/dhanesh.png
|
|
336
|
+
```
|
|
337
|
+
|
|
338
|
+
**Get a Presigned URL for Private Assets**
|
|
339
|
+
|
|
340
|
+
```javascript
|
|
341
|
+
const { data } = await ecod.media.getDownloadUrl("confidential/contract.pdf");
|
|
342
|
+
```
|
|
343
|
+
|
|
344
|
+
**Monitor Quota & Usage**
|
|
345
|
+
|
|
346
|
+
```javascript
|
|
347
|
+
const { data: usage } = await ecod.media.getUsage();
|
|
348
|
+
console.log(`${usage.usedMB} MB used of ${usage.limitMB} MB`);
|
|
349
|
+
```
|
|
350
|
+
|
|
351
|
+
---
|
|
352
|
+
|
|
353
|
+
### Email
|
|
354
|
+
|
|
355
|
+
Access via `ecod.email`.
|
|
356
|
+
|
|
357
|
+
**Send an Email Campaign**
|
|
358
|
+
|
|
359
|
+
Dispatch an HTML email campaign to a given array of recipients. Powered by Ecodrix or AWS SES depending on tenant configuration.
|
|
360
|
+
|
|
361
|
+
```typescript
|
|
362
|
+
const { success } = await ecod.email.sendEmailCampaign({
|
|
363
|
+
subject: "Summer Subscription Discount!",
|
|
364
|
+
recipients: ["user@example.com", "lead@example.com"],
|
|
365
|
+
html: "<h1>Get 20% off all plans today!</h1>",
|
|
366
|
+
});
|
|
367
|
+
```
|
|
368
|
+
|
|
369
|
+
**Send a Test Email**
|
|
370
|
+
|
|
371
|
+
Send a system verification email to validate SMTP configuration for your tenant.
|
|
372
|
+
|
|
373
|
+
```typescript
|
|
374
|
+
const { success } = await ecod.email.sendTestEmail("admin@example.com");
|
|
375
|
+
```
|
|
376
|
+
|
|
377
|
+
---
|
|
378
|
+
|
|
379
|
+
### Events & Workflows
|
|
380
|
+
|
|
381
|
+
Access via `ecod.events`. Programmatically integrate the CRM's automation engine with your external apps.
|
|
382
|
+
|
|
383
|
+
**Retrieve Global Triggers**
|
|
384
|
+
|
|
385
|
+
Fetch all active automation triggers belonging to the current tenant.
|
|
386
|
+
|
|
387
|
+
```typescript
|
|
388
|
+
const { data: triggers } = await ecod.events.list();
|
|
389
|
+
```
|
|
390
|
+
|
|
391
|
+
**Register a Custom Event Definition**
|
|
392
|
+
|
|
393
|
+
Register a new entry point that you want to show up in the CRM Automation Builder.
|
|
394
|
+
|
|
395
|
+
```typescript
|
|
396
|
+
await ecod.events.assign({
|
|
397
|
+
name: "cart_abandoned",
|
|
398
|
+
displayName: "Shopping Cart Abandoned",
|
|
399
|
+
pipelineId: "pipeline_123", /* Auto map leads to this pipeline */
|
|
400
|
+
});
|
|
401
|
+
```
|
|
402
|
+
|
|
403
|
+
**Emit a Payload / Trigger Workflow**
|
|
404
|
+
|
|
405
|
+
Inject generic data into the `EventBus` to fire customized automation rules.
|
|
406
|
+
|
|
407
|
+
```typescript
|
|
408
|
+
await ecod.events.trigger({
|
|
409
|
+
trigger: "cart_abandoned",
|
|
410
|
+
phone: "+919876543210", // Primary matching key
|
|
411
|
+
variables: { items: "T-Shirt, Mug", total: "₹850" },
|
|
412
|
+
createLeadIfMissing: true, // Upsert lead if it's a new customer
|
|
413
|
+
});
|
|
414
|
+
```
|
|
415
|
+
|
|
416
|
+
---
|
|
417
|
+
|
|
418
|
+
### Notifications & Logs
|
|
419
|
+
|
|
420
|
+
Access via `ecod.notifications`. View automation and webhook audit logs.
|
|
421
|
+
|
|
422
|
+
**List Automation Execution Logs**
|
|
423
|
+
|
|
424
|
+
```typescript
|
|
425
|
+
const { data: logs } = await ecod.notifications.listLogs({
|
|
426
|
+
trigger: "lead_created",
|
|
427
|
+
status: "failed", // filter to only failed automations
|
|
428
|
+
startDate: "2026-04-01",
|
|
429
|
+
endDate: "2026-04-30",
|
|
430
|
+
limit: 50,
|
|
431
|
+
});
|
|
432
|
+
```
|
|
433
|
+
|
|
434
|
+
**Retrieve a Specific Log**
|
|
435
|
+
|
|
436
|
+
```typescript
|
|
437
|
+
const { data: log } = await ecod.notifications.retrieveLog("log_id");
|
|
438
|
+
```
|
|
439
|
+
|
|
440
|
+
**Get Automation Stats Summary**
|
|
441
|
+
|
|
442
|
+
```typescript
|
|
443
|
+
const { data: stats } = await ecod.notifications.getStats({
|
|
444
|
+
startDate: "2026-04-01",
|
|
445
|
+
endDate: "2026-04-30",
|
|
446
|
+
});
|
|
447
|
+
```
|
|
448
|
+
|
|
449
|
+
**List Provider Callback Logs (Webhooks)**
|
|
450
|
+
|
|
451
|
+
```typescript
|
|
452
|
+
const { data: callbacks } = await ecod.notifications.listCallbacks({
|
|
453
|
+
limit: 20,
|
|
454
|
+
});
|
|
455
|
+
```
|
|
456
|
+
|
|
457
|
+
---
|
|
458
|
+
|
|
459
|
+
## Enterprise Capabilities
|
|
460
|
+
|
|
461
|
+
The SDK is equipped with state-of-the-art native patterns for robust execution, zero-downtime performance, and unparalleled developer experience. All network requests automatically utilize an exponential-backoff retry engine to gracefully handle temporary network errors.
|
|
462
|
+
|
|
463
|
+
### Auto-Paginating Iterators
|
|
464
|
+
To rapidly ingest records without manually iterating pages, use standard Node.js `for await` loops. The SDK controls memory buffers and page fetching dynamically.
|
|
465
|
+
|
|
466
|
+
```typescript
|
|
467
|
+
// Look how beautiful this developer experience is:
|
|
468
|
+
for await (const lead of ecod.crm.leads.listAutoPaging({ status: "won" })) {
|
|
469
|
+
await syncToMyDatabase(lead);
|
|
470
|
+
}
|
|
471
|
+
```
|
|
472
|
+
|
|
473
|
+
### Bulk Data Chunking
|
|
474
|
+
Need to insert 5,000 leads at once but worried about network congestion or rate limits? `createMany` automatically chunks arrays into concurrent streams.
|
|
475
|
+
|
|
476
|
+
```typescript
|
|
477
|
+
// The users array chunked into safe parallel batched requests
|
|
478
|
+
const results = await ecod.crm.leads.createMany(massiveArrayOfLeads, 100);
|
|
479
|
+
console.log(`Successfully ingested ${results.length} leads.`);
|
|
480
|
+
```
|
|
481
|
+
|
|
482
|
+
### Idempotency Keys
|
|
483
|
+
Because the SDK provides an automatic network retry engine (`axios-retry`), temporary blips could duplicate events. Passing an `idempotencyKey` strictly tells the backend: "Only execute this once, even if I accidentally retry the same payload."
|
|
484
|
+
|
|
485
|
+
```typescript
|
|
486
|
+
await ecod.email.sendEmailCampaign(
|
|
487
|
+
{ subject: "Promo", recipients: ["user@example.com"] },
|
|
488
|
+
{ idempotencyKey: "promo_campaign_uuid_123_abc" }
|
|
489
|
+
);
|
|
490
|
+
```
|
|
491
|
+
|
|
492
|
+
### Webhook Signature Verification
|
|
493
|
+
Verify cryptographic webhook payloads issued by the ECODrIx platform reliably in Node environments, mitigating spoofing attacks seamlessly.
|
|
494
|
+
|
|
495
|
+
```typescript
|
|
496
|
+
app.post("/api/webhooks", express.raw({ type: "application/json" }), async (req, res) => {
|
|
497
|
+
try {
|
|
498
|
+
const event = await ecod.webhooks.constructEvent(
|
|
499
|
+
req.body.toString(),
|
|
500
|
+
req.headers['x-ecodrix-signature'],
|
|
501
|
+
"whsec_your_secret_key"
|
|
502
|
+
);
|
|
503
|
+
console.log("Verified event received:", event);
|
|
504
|
+
} catch (err) {
|
|
505
|
+
return res.status(400).send(`Invalid signature: ${err.message}`);
|
|
506
|
+
}
|
|
507
|
+
});
|
|
508
|
+
```
|
|
509
|
+
|
|
510
|
+
### Raw Execution Engine
|
|
511
|
+
Need to execute an experimental, undocumented, or beta endpoint but still want full authentication mapping, global headers, and intelligent retries?
|
|
512
|
+
|
|
513
|
+
```typescript
|
|
514
|
+
// Bypass strictly typed resources with full network resiliency
|
|
515
|
+
const customData = await ecod.request(
|
|
516
|
+
"POST",
|
|
517
|
+
"/api/saas/beta-feature-route",
|
|
518
|
+
{ experimentalFlag: true }
|
|
519
|
+
);
|
|
520
|
+
```
|
|
521
|
+
|
|
522
|
+
---
|
|
523
|
+
|
|
524
|
+
## Real-time Events
|
|
525
|
+
|
|
526
|
+
The SDK maintains a persistent **Socket.io** connection. Subscribe to live platform events using `ecod.on(event, handler)`.
|
|
527
|
+
|
|
528
|
+
```typescript
|
|
529
|
+
const ecod = new Ecodrix({ apiKey: "...", clientCode: "..." });
|
|
530
|
+
|
|
531
|
+
// New incoming WhatsApp message
|
|
532
|
+
ecod.on("whatsapp.message_received", (data) => {
|
|
533
|
+
console.log(`New message from ${data.from}: ${data.body}`);
|
|
534
|
+
});
|
|
535
|
+
|
|
536
|
+
// Lead stage changed in CRM
|
|
537
|
+
ecod.on("crm.lead_updated", (data) => {
|
|
538
|
+
console.log(`Lead ${data.leadId} moved to stage: ${data.stageName}`);
|
|
539
|
+
});
|
|
540
|
+
|
|
541
|
+
// Automation or event failed — for alert pipelines
|
|
542
|
+
ecod.on("automation.failed", (data) => {
|
|
543
|
+
console.error(`Automation failed: ${data.trigger} — ${data.reason}`);
|
|
544
|
+
});
|
|
545
|
+
|
|
546
|
+
// Storage upload completed
|
|
547
|
+
ecod.on("storage.upload_confirmed", (data) => {
|
|
548
|
+
console.log(`File available at: ${data.url}`);
|
|
549
|
+
});
|
|
550
|
+
|
|
551
|
+
// Disconnect when done (e.g. server shutdown)
|
|
552
|
+
ecod.disconnect();
|
|
553
|
+
```
|
|
554
|
+
|
|
555
|
+
### Standard Event Names
|
|
556
|
+
|
|
557
|
+
| Event | Payload | Description |
|
|
558
|
+
| --------------------------- | -------------------------------- | --------------------------- |
|
|
559
|
+
| `whatsapp.message_received` | `{ from, body, conversationId }` | Inbound WhatsApp message |
|
|
560
|
+
| `whatsapp.message_sent` | `{ to, messageId }` | Outbound message delivered |
|
|
561
|
+
| `crm.lead_created` | `{ leadId, phone }` | New CRM lead created |
|
|
562
|
+
| `crm.lead_updated` | `{ leadId, stageName }` | Lead stage or field changed |
|
|
563
|
+
| `meet.scheduled` | `{ meetingId, meetLink }` | New Google Meet booked |
|
|
564
|
+
| `storage.upload_confirmed` | `{ key, url, sizeBytes }` | File upload confirmed |
|
|
565
|
+
| `automation.failed` | `{ trigger, reason, leadId }` | Automation execution failed |
|
|
566
|
+
|
|
567
|
+
---
|
|
568
|
+
|
|
569
|
+
## Error Handling
|
|
570
|
+
|
|
571
|
+
All methods throw typed errors you can catch and inspect:
|
|
572
|
+
|
|
573
|
+
```typescript
|
|
574
|
+
import {
|
|
575
|
+
Ecodrix,
|
|
576
|
+
APIError,
|
|
577
|
+
AuthenticationError,
|
|
578
|
+
RateLimitError,
|
|
579
|
+
} from "@ecodrix/erix-api";
|
|
580
|
+
|
|
581
|
+
try {
|
|
582
|
+
const { data } = await ecod.crm.leads.retrieve("non_existent_id");
|
|
583
|
+
} catch (err) {
|
|
584
|
+
if (err instanceof AuthenticationError) {
|
|
585
|
+
// 401 — invalid API key or client code
|
|
586
|
+
console.error("Check your credentials.");
|
|
587
|
+
} else if (err instanceof RateLimitError) {
|
|
588
|
+
// 429 — slow down requests
|
|
589
|
+
console.warn("Rate limit hit. Retrying after delay...");
|
|
590
|
+
} else if (err instanceof APIError) {
|
|
591
|
+
// Other HTTP errors from the API
|
|
592
|
+
console.error(`API Error [${err.status}]: ${err.message}`);
|
|
593
|
+
} else {
|
|
594
|
+
throw err; // re-throw unknown errors
|
|
595
|
+
}
|
|
596
|
+
}
|
|
597
|
+
```
|
|
598
|
+
|
|
599
|
+
### Error Classes
|
|
600
|
+
|
|
601
|
+
| Class | Status | Code | Description |
|
|
602
|
+
| --------------------- | ------ | --------------------- | ------------------------------------------ |
|
|
603
|
+
| `EcodrixError` | — | — | Base error class |
|
|
604
|
+
| `APIError` | varies | varies | Generic API error with `status` and `code` |
|
|
605
|
+
| `AuthenticationError` | 401 | `AUTH_FAILED` | Invalid API key or client code |
|
|
606
|
+
| `RateLimitError` | 429 | `RATE_LIMIT_EXCEEDED` | Too many requests |
|
|
607
|
+
|
|
608
|
+
---
|
|
609
|
+
|
|
610
|
+
## Browser / CDN Usage
|
|
611
|
+
|
|
612
|
+
For usage without a bundler (plain HTML, marketing pages):
|
|
613
|
+
|
|
614
|
+
```html
|
|
615
|
+
<!-- Via CDN (jsDelivr) -->
|
|
616
|
+
<script src="https://cdn.jsdelivr.net/npm/@ecodrix/erix-api/dist/ts/browser/index.global.js"></script>
|
|
617
|
+
<script>
|
|
618
|
+
const ecod = new Ecodrix.Ecodrix({
|
|
619
|
+
apiKey: "your_api_key",
|
|
620
|
+
clientCode: "YOUR_CLIENT_CODE",
|
|
621
|
+
});
|
|
622
|
+
|
|
623
|
+
ecod.whatsapp.messages.send({
|
|
624
|
+
to: "+919876543210",
|
|
625
|
+
text: "Hello from the browser!",
|
|
626
|
+
});
|
|
627
|
+
</script>
|
|
628
|
+
```
|
|
629
|
+
|
|
630
|
+
---
|
|
631
|
+
|
|
632
|
+
## Contributing
|
|
633
|
+
|
|
634
|
+
1. Fork the repository.
|
|
635
|
+
2. Create a feature branch: `git checkout -b feat/my-feature`
|
|
636
|
+
3. Make changes, then run `pnpm check` to validate.
|
|
637
|
+
4. Submit a Pull Request.
|
|
638
|
+
|
|
639
|
+
---
|
|
640
|
+
|
|
641
|
+
## License
|
|
642
|
+
|
|
643
|
+
[MIT](LICENSE) © 2026 [ECODrIx Team](https://ecodrix.com)
|