JSPM

  • Created
  • Published
  • Downloads 401
  • Score
    100M100P100Q110221F
  • License MIT

Official Isomorphic SDK for the ECODrIx platform. Native support for WhatsApp, CRM, Storage, and Meetings across TS, JS, Python, and Java.

Package Exports

  • @ecodrix/erix-api

Readme

@ecodrix/erix-api

NPM Version License: MIT TypeScript OpenAPI

The official, isomorphic SDK for the ECODrIx platform.

Manage WhatsApp conversations, CRM leads, file storage, and Google Meet appointments — all from a single, type-safe library.


Table of Contents


Installation

# pnpm (recommended)
pnpm add @ecodrix/erix-api

# npm
npm install @ecodrix/erix-api

# yarn
yarn add @ecodrix/erix-api

Requires: Node.js >= 18


Quick Start

import { Ecodrix } from "@ecodrix/erix-api";

const ecod = new Ecodrix({
  apiKey: "your_api_key",
  clientCode: "YOUR_CLIENT_CODE", // Your tenant ID
});

// Send a WhatsApp message
await ecod.whatsapp.messages.send({
  to: "+919876543210",
  text: "Hello from ECODrIx!",
});

// Create a CRM lead
const lead = await ecod.crm.leads.create({
  firstName: "Jhon",
  phone: "+919876543210",
  source: "website",
});

console.log(lead.data.id);

Configuration

Pass an options object to new Ecodrix(options):

Option Type Required Default Description
apiKey string ✅ Yes Your ECOD Platform API key
clientCode string Recommended Your tenant ID (scopes all requests)
baseUrl string No https://api.ecodrix.com Override the API base URL (e.g. for local dev)
socketUrl string No Same as baseUrl Override the Socket.io server URL
const ecod = new Ecodrix({
  apiKey: process.env.ECOD_API_KEY!,
  clientCode: process.env.ECOD_CLIENT_CODE,
  baseUrl: "http://localhost:4000", // For local development
});

Resources

Every resource follows the same predictable CRUD interface:

Method Description
.create(params) Create a new record
.list(params?) List records with optional filters
.retrieve(id) Get a single record by ID
.update(id, params) Update a record
.delete(id) Delete or cancel a record

WhatsApp

Access via ecod.whatsapp.

ecod.whatsapp.messages

Send a text message

await ecod.whatsapp.messages.send({
  to: "+919876543210",
  text: "Your appointment is confirmed!",
});

Send a media message (image, video, document, audio)

await ecod.whatsapp.messages.send({
  to: "+919876543210",
  mediaUrl: "https://cdn.ecodrix.com/invoice.pdf",
  mediaType: "document",
  filename: "invoice.pdf",
});

Send a pre-approved template message

await ecod.whatsapp.messages.sendTemplate({
  to: "+919876543210",
  templateName: "appointment_reminder",
  language: "en_US",
  variables: ["Dhanesh", "Tomorrow 10AM"],
});

Send a Meta-approved direct template (Bypass queues)

Use this specifically to dispatch high-priority utility templates containing dynamic variable maps.

const { messageId } = await ecod.whatsapp.sendTemplate({
  phone: "+919876543210",
  templateName: "payment_confirmation",
  variables: {
    name: "Dhanesh",
    amount: "₹1,500",
  },
});

Mark a conversation as read

await ecod.whatsapp.messages.markRead("conversation_id");

ecod.whatsapp.conversations

// List conversations (cursor-based pagination)
const { data } = await ecod.whatsapp.conversations.list({ limit: 20 });

// Get a specific conversation
const conv = await ecod.whatsapp.conversations.retrieve("conversation_id");

// Archive a conversation
await ecod.whatsapp.conversations.delete("conversation_id");

CRM — Leads

Access via ecod.crm.leads.

Create a Lead

const { data: lead } = await ecod.crm.leads.create({
  firstName: "Dhanesh",
  lastName: "Kumar",
  phone: "+919876543210",
  email: "dhanesh@example.com",
  source: "website", // 'website' | 'whatsapp' | 'direct' | ...
  metadata: {
    utmSource: "google",
  },
});

List Leads (with filters)

const { data: leads } = await ecod.crm.leads.list({
  status: "new", // filter by status
  source: "whatsapp",
  page: 1,
  limit: 25,
});

(See Enterprise Capabilities for efficient auto-pagination or bulk-creation tricks like listAutoPaging and createMany).

Retrieve a Lead by ID

const { data: lead } = await ecod.crm.leads.retrieve("lead_id");

Update a Lead

await ecod.crm.leads.update("lead_id", {
  email: "new@email.com",
  metadata: { score: 95 },
});

Delete / Archive a Lead

await ecod.crm.leads.delete("lead_id");

Meetings

Access via ecod.meet. Backed by Google Meet.

Schedule a Meeting

const { data: meeting } = await ecod.meet.create({
  leadId: "lead_id",
  participantName: "Dhanesh Kumar",
  participantPhone: "+919876543210",
  startTime: "2026-04-10T10:00:00.000Z",
  endTime: "2026-04-10T10:30:00.000Z",
});

console.log(meeting.meetLink); // → https://meet.google.com/abc-defg-hij

List Meetings

const { data: meetings } = await ecod.meet.list({ status: "scheduled" });

Retrieve a Meeting

const { data } = await ecod.meet.retrieve("meeting_id");

Reschedule a Meeting

await ecod.meet.update("meeting_id", {
  startTime: "2026-04-11T11:00:00.000Z",
  endTime: "2026-04-11T11:30:00.000Z",
});

Cancel a Meeting

await ecod.meet.delete("meeting_id");

Storage

Access via ecod.storage. Powered by Cloudflare R2.

Upload a File (Elite Helper)

This single call handles the entire R2 presigned-URL orchestration for you:

  1. Requests a presigned PUT URL from the backend.
  2. Uploads the file directly to R2 (no proxy overhead).
  3. Confirms the upload with the backend.
// Node.js: from a Buffer
import { readFileSync } from "fs";

const fileBuffer = readFileSync("./contract.pdf");
const { data } = await ecod.storage.upload(fileBuffer, {
  folder: "customer_documents",
  filename: "contract.pdf",
  contentType: "application/pdf",
});

console.log(data.url); // → https://cdn.ecodrix.com/customer_documents/contract.pdf

// Browser: from an <input> file
const file = document.getElementById("file-input").files[0];
const { data } = await ecod.storage.upload(file, {
  folder: "avatars",
  filename: file.name,
  contentType: file.type,
});
  filename: "dhanesh.png",
  contentType: "image/png"
});

console.log(data.url);
// -> https://cdn.ecodrix.com/avatars/dhanesh.png

Get a Presigned URL for Private Assets

const { data } = await ecod.media.getDownloadUrl("confidential/contract.pdf");

Monitor Quota & Usage

const { data: usage } = await ecod.media.getUsage();
console.log(`${usage.usedMB} MB used of ${usage.limitMB} MB`);

Email

Access via ecod.email.

Send an Email Campaign

Dispatch an HTML email campaign to a given array of recipients. Powered by Ecodrix or AWS SES depending on tenant configuration.

const { success } = await ecod.email.sendEmailCampaign({
  subject: "Summer Subscription Discount!",
  recipients: ["user@example.com", "lead@example.com"],
  html: "<h1>Get 20% off all plans today!</h1>",
});

Send a Test Email

Send a system verification email to validate SMTP configuration for your tenant.

const { success } = await ecod.email.sendTestEmail("admin@example.com");

Events & Workflows

Access via ecod.events. Programmatically integrate the CRM's automation engine with your external apps.

Retrieve Global Triggers

Fetch all active automation triggers belonging to the current tenant.

const { data: triggers } = await ecod.events.list();

Register a Custom Event Definition

Register a new entry point that you want to show up in the CRM Automation Builder.

await ecod.events.assign({
  name: "cart_abandoned",
  displayName: "Shopping Cart Abandoned",
  pipelineId: "pipeline_123" /* Auto map leads to this pipeline */,
});

Emit a Payload / Trigger Workflow

Inject generic data into the EventBus to fire customized automation rules.

await ecod.events.trigger({
  trigger: "cart_abandoned",
  phone: "+919876543210", // Primary matching key
  variables: { items: "T-Shirt, Mug", total: "₹850" },
  createLeadIfMissing: true, // Upsert lead if it's a new customer
});

Notifications & Logs

Access via ecod.notifications. View automation and webhook audit logs.

List Automation Execution Logs

const { data: logs } = await ecod.notifications.listLogs({
  trigger: "lead_created",
  status: "failed", // filter to only failed automations
  startDate: "2026-04-01",
  endDate: "2026-04-30",
  limit: 50,
});

Retrieve a Specific Log

const { data: log } = await ecod.notifications.retrieveLog("log_id");

Get Automation Stats Summary

const { data: stats } = await ecod.notifications.getStats({
  startDate: "2026-04-01",
  endDate: "2026-04-30",
});

List Provider Callback Logs (Webhooks)

const { data: callbacks } = await ecod.notifications.listCallbacks({
  limit: 20,
});

Enterprise Capabilities

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.

Auto-Paginating Iterators

To rapidly ingest records without manually iterating pages, use standard Node.js for await loops. The SDK controls memory buffers and page fetching dynamically.

// Look how beautiful this developer experience is:
for await (const lead of ecod.crm.leads.listAutoPaging({ status: "won" })) {
  await syncToMyDatabase(lead);
}

Bulk Data Chunking

Need to insert 5,000 leads at once but worried about network congestion or rate limits? createMany automatically chunks arrays into concurrent streams.

// The users array chunked into safe parallel batched requests
const results = await ecod.crm.leads.createMany(massiveArrayOfLeads, 100);
console.log(`Successfully ingested ${results.length} leads.`);

Idempotency Keys

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."

await ecod.email.sendEmailCampaign(
  { subject: "Promo", recipients: ["user@example.com"] },
  { idempotencyKey: "promo_campaign_uuid_123_abc" },
);

Webhook Signature Verification

Verify cryptographic webhook payloads issued by the ECODrIx platform reliably in Node environments, mitigating spoofing attacks seamlessly.

app.post(
  "/api/webhooks",
  express.raw({ type: "application/json" }),
  async (req, res) => {
    try {
      const event = await ecod.webhooks.constructEvent(
        req.body.toString(),
        req.headers["x-ecodrix-signature"],
        "whsec_your_secret_key",
      );
      console.log("Verified event received:", event);
    } catch (err) {
      return res.status(400).send(`Invalid signature: ${err.message}`);
    }
  },
);

Raw Execution Engine

Need to execute an experimental, undocumented, or beta endpoint but still want full authentication mapping, global headers, and intelligent retries?

// Bypass strictly typed resources with full network resiliency
const customData = await ecod.request("POST", "/api/saas/beta-feature-route", {
  experimentalFlag: true,
});

Real-time Events

The SDK maintains a persistent Socket.io connection. Subscribe to live platform events using ecod.on(event, handler).

const ecod = new Ecodrix({ apiKey: "...", clientCode: "..." });

// New incoming WhatsApp message
ecod.on("whatsapp.message_received", (data) => {
  console.log(`New message from ${data.from}: ${data.body}`);
});

// Lead stage changed in CRM
ecod.on("crm.lead_updated", (data) => {
  console.log(`Lead ${data.leadId} moved to stage: ${data.stageName}`);
});

// Automation or event failed — for alert pipelines
ecod.on("automation.failed", (data) => {
  console.error(`Automation failed: ${data.trigger}${data.reason}`);
});

// Storage upload completed
ecod.on("storage.upload_confirmed", (data) => {
  console.log(`File available at: ${data.url}`);
});

// Disconnect when done (e.g. server shutdown)
ecod.disconnect();

Standard Event Names

Event Payload Description
whatsapp.message_received { from, body, conversationId } Inbound WhatsApp message
whatsapp.message_sent { to, messageId } Outbound message delivered
crm.lead_created { leadId, phone } New CRM lead created
crm.lead_updated { leadId, stageName } Lead stage or field changed
meet.scheduled { meetingId, meetLink } New Google Meet booked
storage.upload_confirmed { key, url, sizeBytes } File upload confirmed
automation.failed { trigger, reason, leadId } Automation execution failed

Error Handling

All methods throw typed errors you can catch and inspect:

import {
  Ecodrix,
  APIError,
  AuthenticationError,
  RateLimitError,
} from "@ecodrix/erix-api";

try {
  const { data } = await ecod.crm.leads.retrieve("non_existent_id");
} catch (err) {
  if (err instanceof AuthenticationError) {
    // 401 — invalid API key or client code
    console.error("Check your credentials.");
  } else if (err instanceof RateLimitError) {
    // 429 — slow down requests
    console.warn("Rate limit hit. Retrying after delay...");
  } else if (err instanceof APIError) {
    // Other HTTP errors from the API
    console.error(`API Error [${err.status}]: ${err.message}`);
  } else {
    throw err; // re-throw unknown errors
  }
}

Error Classes

Class Status Code Description
EcodrixError Base error class
APIError varies varies Generic API error with status and code
AuthenticationError 401 AUTH_FAILED Invalid API key or client code
RateLimitError 429 RATE_LIMIT_EXCEEDED Too many requests

Browser / CDN Usage

For usage without a bundler (plain HTML, marketing pages):

<!-- Via CDN (jsDelivr) -->
<script src="https://cdn.jsdelivr.net/npm/@ecodrix/erix-api/dist/ts/browser/index.global.js"></script>
<script>
  const ecod = new Ecodrix.Ecodrix({
    apiKey: "your_api_key",
    clientCode: "YOUR_CLIENT_CODE",
  });

  ecod.whatsapp.messages.send({
    to: "+919876543210",
    text: "Hello from the browser!",
  });
</script>

Contributing

  1. Fork the repository.
  2. Create a feature branch: git checkout -b feat/my-feature
  3. Make changes, then run pnpm check to validate.
  4. Submit a Pull Request.

License

MIT © 2026 ECODrIx Team