npm package: @interxact/sdk
Description: Official SDK for Interxact Messaging API - Send emails and WhatsApp messages
Latest version: 1.0.6

# @interxact/sdk

<div align="center">

![Version](https://img.shields.io/badge/version-1.0.3-blue.svg)
![License](https://img.shields.io/badge/license-MIT-green.svg)
![TypeScript](https://img.shields.io/badge/TypeScript-Ready-blue.svg)
![Node.js](https://img.shields.io/badge/Node.js-18%2B-green.svg)

**Official TypeScript SDK for Interxact Messaging API**

Send emails, WhatsApp messages, and manage contacts and companies programmatically with a clean, type-safe API.

[Features](#features) • [Installation](#installation) • [Quick Start](#quick-start) • [Documentation](#api-reference) • [Examples](#examples)

</div>

---

## Features

- 📧 **Email Messaging** - Send transactional emails and template-based emails
- 💬 **WhatsApp Integration** - Send text messages and WhatsApp templates
- 👥 **Contact Management** - Full CRUD operations for contacts
- 🏢 **Company Management** - Full CRUD operations for companies
- 📋 **Template Management** - List and use email and WhatsApp templates with variable information
- 🔒 **Type-Safe** - Full TypeScript support with comprehensive type definitions
- 🌐 **Universal** - Works in both Node.js and browser environments
- ⚡ **Lightweight** - Zero dependencies, uses native fetch API
- 🛡️ **Error Handling** - Comprehensive error handling with custom error classes

## Installation

```bash
npm install @interxact/sdk
```

```bash
yarn add @interxact/sdk
```

```bash
pnpm add @interxact/sdk
```

## Quick Start

```typescript
import { InterxactClient } from '@interxact/sdk';

// Initialize the client
const client = new InterxactClient(process.env.INTERXACT_API_KEY!);

// Send an email
await client.sendMessage.email({
  to: 'recipient@example.com',
  from: 'sender@example.com',
  subject: 'Hello World',
  body: 'This is a test email',
});

// Send a WhatsApp message
await client.sendMessage.whatsapp({
  to: '+1234567890',
  message: 'Hello from Interxact!',
});

// List contacts
const contacts = await client.contact.list({ limit: 10 });

// List templates
const templates = await client.listTemplates('all');
```

## Authentication

You need an API key to use this SDK. Get your API key from the [Interxact Dashboard](https://app.interxact.com).

API keys are in the format: `clientId:secret`

### Using Environment Variables (Recommended)

Store your API key securely in an environment variable:

```bash
# .env file
INTERXACT_API_KEY=ix_abc123:your-secret-key
```

```typescript
import { InterxactClient } from '@interxact/sdk';

const apiKey = process.env.INTERXACT_API_KEY;
if (!apiKey) {
  throw new Error('INTERXACT_API_KEY environment variable is required');
}

const client = new InterxactClient(apiKey);
```

### Direct API Key

You can also pass the API key directly (not recommended for production):

```typescript
const client = new InterxactClient('ix_abc123:your-secret-key');
```

> **⚠️ Security Note:** Never commit API keys to version control. Always use environment variables or secure secret management systems.

## API Reference

### 📧 Messaging

#### Send Transactional Email

Send a plain text or HTML email with optional attachments.

```typescript
await client.sendMessage.email({
  to: 'recipient@example.com',
  from: 'sender@example.com',
  subject: 'Email Subject',
  body: 'Plain text body',
  html: '<h1>HTML body</h1>', // Optional
  fromName: 'Sender Name', // Optional
  replyTo: 'reply@example.com', // Optional
  contactId: 'contact-id', // Optional, link to contact
  files: [ // Optional attachments
    {
      buffer: 'base64-encoded-file-content',
      originalname: 'document.pdf',
      mimetype: 'application/pdf',
      size: 1024,
    },
  ],
});
```

**Required Fields:**
- `to` - Recipient email address
- `from` - Sender email address (must be verified)
- `subject` - Email subject line
- `body` OR `html` - Email content (at least one required)

**Optional Fields:**
- `fromName` - Sender display name
- `replyTo` - Reply-to email address
- `contactId` - Contact ID to link this email
- `files` - Array of file attachments (base64 encoded)

#### Send Email Using Template

Send an email using a pre-configured template with variable substitution.

```typescript
await client.sendMessage.emailTemplate({
  templateId: 'template-id',
  to: 'recipient@example.com', // OR use contactId
  from: 'sender@example.com',
  variables: {
    firstName: 'John',
    lastName: 'Doe',
    company: 'Acme Corp',
  },
  fromName: 'Sender Name', // Optional
  replyTo: 'reply@example.com', // Optional
  subject: 'Custom Subject', // Optional, overrides template subject
});
```

**Required Fields:**
- `templateId` - Template ID to use
- `from` - Sender email address
- `to` OR `contactId` - Recipient (use one, not both)

**Optional Fields:**
- `variables` - Object with template variables for personalization
- `fromName` - Sender display name
- `replyTo` - Reply-to email address
- `subject` - Override template subject

### 💬 WhatsApp

#### Send WhatsApp Message

Send a text or media WhatsApp message.

```typescript
await client.sendMessage.whatsapp({
  to: '+1234567890', // Phone number with country code
  message: 'Hello from Interxact!',
  type: 'text', // Optional, default: 'text'
  conversationId: 'conversation-id', // Optional
  file: { // Optional file attachment
    buffer: 'base64-encoded-file',
    originalname: 'image.jpg',
    mimetype: 'image/jpeg',
    size: 1024,
  },
});
```

**Required Fields:**
- `to` - Recipient phone number (with country code, e.g., '+1234567890')
- `message` - Message text (required for text messages)

**Optional Fields:**
- `type` - Message type (`'text' | 'image' | 'video' | 'audio' | 'document'`)
- `mediaData` - Media data for non-text messages
- `conversationId` - Conversation ID to link this message
- `file` - File attachment

#### Send WhatsApp Template

Send a WhatsApp message using an approved template.

```typescript
await client.sendMessage.whatsappTemplate({
  to: '+1234567890',
  templateName: 'welcome_template',
  language: 'en_US', // Optional, default: 'en_US'
  variables: {
    '1': 'John',
    '2': 'Acme Corp',
  },
  components: [ // Optional template components
    {
      type: 'header',
      parameters: [
        { type: 'text', text: 'Welcome' },
      ],
    },
    {
      type: 'body',
      parameters: [
        { type: 'text', text: 'John' },
      ],
    },
  ],
  mediaIds: { // Optional media IDs
    header: 'media-id-123',
  },
});
```

**Required Fields:**
- `to` - Recipient phone number (with country code)
- `templateName` - Name of approved template

**Optional Fields:**
- `language` - Template language code (default: 'en_US')
- `variables` - Variables for template personalization
- `components` - Template components (header, body, buttons)
- `mediaIds` - Media IDs for template media

### 👥 Contact Management

#### List Contacts

Get a paginated list of contacts with optional filters.

```typescript
// Get all contacts (default limit: 10)
const result = await client.contact.list();

// Get contacts with filters
const filteredContacts = await client.contact.list({
  limit: 20,
  search: 'john',
  tags: 'vip,customer',
  status: 'active',
  sort: 'asc',
  cursor: 'next-page-cursor', // For pagination
});
```

**Response:**
```typescript
{
  contacts: [
    {
      _id: 'contact-id',
      email: ['user@example.com'],
      firstName: 'John',
      lastName: 'Doe',
      phone: ['+1234567890'],
      company: 'Acme Inc',
      companyRef: '507f1f77bcf86cd799439011',
      tags: ['customer', 'vip'],
      // ... other fields
    },
  ],
  hasMore: true,
  nextCursor: 'cursor-string',
  totalCount: 100,
}
```

**Filter Options:**
- `listId` - Filter by list ID
- `limit` - Maximum number of contacts (default: 10)
- `sort` - Sort order: `'asc'` or `'desc'` (default: `'desc'`)
- `search` - Search query for firstName, lastName, email, or phone
- `tags` - Filter by tags (comma-separated)
- `status` - Filter by status
- `company` - Filter by company name
- `cursor` - Cursor for pagination

#### Get Contact by ID

Retrieve a specific contact by its ID.

```typescript
const contact = await client.contact.get('contact-id');
```

#### Create Contact

Create a new contact with all relevant information.

```typescript
const newContact = await client.contact.create({
  email: 'user@example.com',
  firstName: 'John',
  lastName: 'Doe',
  phone: '+1234567890',
  company: 'Acme Inc',
  companyRef: '507f1f77bcf86cd799439011', // Company ID to link contact to a Company record
  position: 'Software Engineer',
  tags: ['customer', 'vip'],
  notes: 'Important customer',
  country: 'US',
  website: 'https://example.com',
  subscribedToEmail: true,
  subscribedToWhatsApp: true,
  subscribedToSMS: false,
  customFields: {
    customField1: 'value1',
  },
});
```

**Required Fields:**
- `email` OR `phone` - At least one is required

**Optional Fields:**
- `email` - Contact email(s) - can be string or array
- `firstName` - First name
- `lastName` - Last name
- `phone` - Phone number(s) - can be string or array
- `company` - Company name (string)
- `companyRef` - Company ID reference (links contact to a Company record)
- `position` - Job position
- `tags` - Array of tags
- `notes` - Notes to add to the contact
- `country` - Country code
- `website` - Website URL
- `list` or `listId` - List ID or name
- `subscribedToSMS` - Subscribe to SMS (default: false)
- `subscribedToEmail` - Subscribe to email (default: false)
- `subscribedToWhatsApp` - Subscribe to WhatsApp (default: false)
- `customFields` - Custom fields object

#### Update Contact

Update an existing contact's information.

```typescript
const updatedContact = await client.contact.update('contact-id', {
  firstName: 'Jane',
  lastName: 'Smith',
  company: 'New Company',
  companyRef: '507f1f77bcf86cd799439011', // Link to a Company record
  tags: ['updated-tag', 'customer'],
});
```

#### Delete Contact

Delete a contact by ID.

```typescript
const result = await client.contact.delete('contact-id');
// { success: true, deletedCount: 1 }
```

#### Bulk Delete Contacts

Delete multiple contacts at once.

```typescript
const result = await client.contact.bulkDelete({
  contactIds: ['id1', 'id2', 'id3'],
});
// { success: true, deletedCount: 3 }
```

### 🏢 Company Management

#### List Companies

Get a paginated list of companies with optional filters.

```typescript
// Get all companies (default limit: 50)
const result = await client.company.list();

// Get companies with filters
const filteredCompanies = await client.company.list({
  limit: 20,
  search: 'acme',
  industry: 'Technology',
  size: '50-100',
  sort: 'asc',
  cursor: 'next-page-cursor', // For pagination
});
```

**Response:**
```typescript
{
  companies: [
    {
      _id: 'company-id',
      name: 'Acme Inc',
      domain: 'acme.com',
      industry: 'Technology',
      size: '50-100',
      website: 'https://acme.com',
      tags: ['enterprise', 'saas'],
      contactsCount: 25,
      dealsTotalValue: 50000,
      // ... other fields
    },
  ],
  hasMore: true,
  nextCursor: 'cursor-string',
  totalCount: 100,
}
```

**Filter Options:**
- `limit` - Maximum number of companies (default: 50)
- `sort` - Sort order: `'asc'` or `'desc'` (default: `'desc'`)
- `search` - Search query for name or domain
- `industry` - Filter by industry
- `size` - Filter by company size
- `cursor` - Cursor for pagination

#### Get Company by ID

Retrieve a specific company by its ID.

```typescript
const company = await client.company.get('company-id');
```

#### Create Company

Create a new company with all relevant information.

```typescript
const newCompany = await client.company.create({
  name: 'Acme Inc', // Required
  domain: 'acme.com',
  industry: 'Technology',
  size: '50-100',
  website: 'https://acme.com',
  address: '123 Main St',
  description: 'Leading technology company',
  tags: ['enterprise', 'saas'],
  linkedinUrl: 'https://linkedin.com/company/acme',
  twitterUrl: 'https://twitter.com/acme',
  techStack: ['React', 'Node.js'],
  revenue: '$10M',
  foundedYear: 2020,
  customFields: {
    customField1: 'value1',
  },
});
```

**Required Fields:**
- `name` - Company name

**Optional Fields:**
- `domain` - Company domain
- `industry` - Industry
- `size` - Company size
- `website` - Website URL
- `address` - Address
- `description` - Description
- `tags` - Array of tags
- `logoUrl` - Logo URL
- `linkedinUrl` - LinkedIn URL
- `twitterUrl` - Twitter URL
- `facebookUrl` - Facebook URL
- `techStack` - Tech stack array
- `fundingInfo` - Funding information
- `revenue` - Revenue
- `foundedYear` - Founded year
- `headquarters` - Headquarters location
- `keyPeople` - Array of key people
- `recentNews` - Array of recent news
- `competitors` - Array of competitors
- `customFields` - Custom fields object

#### Update Company

Update an existing company's information.

```typescript
const updatedCompany = await client.company.update('company-id', {
  name: 'New Company Name',
  industry: 'New Industry',
  size: '100-500',
  tags: ['updated-tag', 'enterprise'],
});
```

#### Delete Company

Delete a company by ID.

```typescript
const result = await client.company.delete('company-id');
// { success: true, deletedCount: 1 }
```

### 📋 Templates

#### List Available Templates

Get a list of available email and WhatsApp templates.

```typescript
// Get all templates
const templates = await client.listTemplates('all');

// Get only email templates
const emailTemplates = await client.listTemplates('email');

// Get only WhatsApp templates
const whatsappTemplates = await client.listTemplates('whatsapp');
```

**Response:**
```typescript
{
  email: [
    {
      id: 'template-id',
      name: 'Welcome Email',
      subject: 'Welcome to our platform',
      sampleData: { firstName: 'John', company: 'Acme' },
      variables: ['firstName', 'company'],
    },
  ],
  whatsapp: [
    {
      name: 'welcome_template',
      language: 'en_US',
      category: 'UTILITY',
      components: [
        {
          type: 'BODY',
          text: 'Hello {{1}}, welcome to {{2}}!',
        },
      ],
      sampleData: { '1': 'John', '2': 'Acme' },
      variables: ['1', '2'],
    },
  ],
}
```

**Template Fields:**
- `variables` - Array of variable keys/numbers found in the template
- `components` - Full component structure (WhatsApp templates only)
- `sampleData` - Example data showing available variables

## Configuration

### Custom Base URL

For development or testing, you can use a custom base URL:

```typescript
const client = new InterxactClient('clientId:secret', {
  baseURL: 'http://localhost:3000/api/v1/public',
});
```

### Request Timeout

Set a custom timeout for requests (default: 30000ms):

```typescript
const client = new InterxactClient('clientId:secret', {
  timeout: 60000, // 60 seconds
});
```

## Error Handling

The SDK throws custom error classes for different error scenarios:

```typescript
import {
  InterxactError,
  AuthenticationError,
  PermissionError,
  ValidationError,
  RateLimitError,
  ServerError,
  NetworkError,
} from '@interxact/sdk';

try {
  await client.sendMessage.email({ /* ... */ });
} catch (error) {
  if (error instanceof AuthenticationError) {
    console.error('Invalid API key:', error.message);
  } else if (error instanceof PermissionError) {
    console.error('Insufficient permissions:', error.message);
  } else if (error instanceof ValidationError) {
    console.error('Invalid request:', error.message);
  } else if (error instanceof RateLimitError) {
    console.error('Rate limit exceeded:', error.message);
  } else if (error instanceof NetworkError) {
    console.error('Network error:', error.message);
  } else if (error instanceof ServerError) {
    console.error('Server error:', error.message);
  } else {
    console.error('Unknown error:', error);
  }
}
```

### Error Types

| Error Class | Status Code | Description |
|------------|------------|-------------|
| `AuthenticationError` | 401 | Invalid, expired, or revoked API key |
| `PermissionError` | 403 | API key doesn't have required permissions |
| `ValidationError` | 400 | Invalid request parameters |
| `RateLimitError` | 429 | API rate limit exceeded |
| `ServerError` | 500+ | Server-side error |
| `NetworkError` | - | Network request failed or timed out |

## TypeScript Support

The SDK is written in TypeScript and provides full type definitions:

```typescript
import {
  InterxactClient,
  SendEmailOptions,
  SendWhatsAppOptions,
  CreateContactOptions,
  Contact,
} from '@interxact/sdk';

const emailOptions: SendEmailOptions = {
  to: 'recipient@example.com',
  from: 'sender@example.com',
  subject: 'Test',
  body: 'Test email',
};

await client.sendMessage.email(emailOptions);
```

## Browser & Node.js Compatibility

The SDK works in both browser and Node.js environments:

- **Node.js**: Requires Node.js 18+ (uses native `fetch`)
- **Browser**: Works in all modern browsers

> **Note:** For older Node.js versions (< 18), you may need a `fetch` polyfill like `node-fetch`.

## Examples

### Complete Example: Send Email with Attachment

```typescript
import { InterxactClient } from '@interxact/sdk';

const client = new InterxactClient(process.env.INTERXACT_API_KEY!);

// In browser
const fileInput = document.querySelector('input[type="file"]');
const file = fileInput.files[0];
const reader = new FileReader();

reader.onload = async () => {
  const base64 = reader.result as string;
  const base64Content = base64.split(',')[1]; // Remove data URL prefix

  await client.sendMessage.email({
    to: 'recipient@example.com',
    from: 'sender@example.com',
    subject: 'Email with attachment',
    body: 'Please find attached.',
    files: [
      {
        buffer: base64Content,
        originalname: file.name,
        mimetype: file.type,
        size: file.size,
      },
    ],
  });
};

reader.readAsDataURL(file);
```

### Complete Example: Send Personalized Email Template

```typescript
await client.sendMessage.emailTemplate({
  templateId: 'welcome-email-template',
  to: 'newuser@example.com',
  from: 'noreply@example.com',
  variables: {
    firstName: 'John',
    lastName: 'Doe',
    company: 'Acme Corp',
  },
});
```

### Complete Example: Send WhatsApp Template

```typescript
await client.sendMessage.whatsappTemplate({
  to: '+1234567890',
  templateName: 'order_confirmation',
  language: 'en_US',
  variables: {
    '1': 'ORD-12345',
    '2': '$99.99',
  },
});
```

### Complete Example: Contact Management Workflow

```typescript
// Create a contact
const contact = await client.contact.create({
  email: 'user@example.com',
  firstName: 'John',
  lastName: 'Doe',
  phone: '+1234567890',
  company: 'Acme Inc',
  companyRef: '507f1f77bcf86cd799439011',
  tags: ['customer'],
  subscribedToEmail: true,
});

// Update the contact
const updated = await client.contact.update(contact._id, {
  tags: ['customer', 'vip'],
  company: 'New Company',
  companyRef: '507f1f77bcf86cd799439012',
});

// List contacts with filters
const contacts = await client.contact.list({
  search: 'john',
  tags: 'vip',
  limit: 20,
});

// Delete contact
await client.contact.delete(contact._id);
```

### Complete Example: Company Management Workflow

```typescript
// Create a company
const company = await client.company.create({
  name: 'Acme Inc',
  domain: 'acme.com',
  industry: 'Technology',
  size: '50-100',
  website: 'https://acme.com',
  tags: ['enterprise', 'saas'],
  linkedinUrl: 'https://linkedin.com/company/acme',
});

// Update the company
const updated = await client.company.update(company._id, {
  size: '100-500',
  tags: ['enterprise', 'saas', 'unicorn'],
  revenue: '$50M',
});

// List companies with filters
const companies = await client.company.list({
  search: 'acme',
  industry: 'Technology',
  limit: 20,
});

// Get company by ID
const companyDetails = await client.company.get(company._id);

// Delete company
await client.company.delete(company._id);
```

## API Permissions

Your API key must have the appropriate permissions to use different SDK features:

**Messaging:**
- `message.send` - Required for sending emails and WhatsApp messages

**Contacts:**
- `contact.read` - Required for listing and reading contacts
- `contact.create` - Required for creating contacts
- `contact.update` - Required for updating contacts
- `contact.delete` - Required for deleting contacts

**Companies:**
- `company.read` - Required for listing and reading companies
- `company.create` - Required for creating companies
- `company.update` - Required for updating companies
- `company.delete` - Required for deleting companies

You can manage API keys and permissions in the [Interxact Dashboard](https://app.interxact.com).

## Rate Limiting

The API has rate limits per API key. If you exceed the limit, a `RateLimitError` will be thrown. Check the error response for retry information.

## Contributing

Contributions are welcome! Please feel free to submit a Pull Request.

## Support

- 📖 [Documentation](https://app.interxact.com/docs)
- 💬 [Support](https://app.interxact.com/support)
- 🐛 [Report Issues](https://github.com/interxact/sdk/issues)

## Changelog

### [1.0.3] - 2026-02-11

#### Added
- 🏢 **Company Management API** - Full CRUD operations for companies
  - `client.company.list()` - List companies with filters (search, industry, size, pagination)
  - `client.company.get(id)` - Get company by ID
  - `client.company.create(options)` - Create a new company
  - `client.company.update(id, options)` - Update an existing company
  - `client.company.delete(id)` - Delete a company
- 📋 **Enhanced Template API** - Templates now include variable information
  - Templates return `variables` array showing available template variables
  - WhatsApp templates include `components` structure
  - Email templates include `sampleData` for variable examples
- 🔍 **Source Tracking** - All API calls are tagged with source (`sdk` vs `api`)
  - Requests from SDK automatically include `X-Interxact-Source: sdk` header
  - Source is visible in developer logs and webhook events
- 👥 **Contact Company Linking** - Contacts can now be linked to companies via `companyRef`
  - `companyRef` field added to contact create and update operations
  - Links contacts to Company records for better relationship management

#### Changed
- `client.listTemplates()` moved from `client.sendMessage.listTemplates()` to direct client method
- Template responses now include `variables`, `components`, and `sampleData` fields

### [1.0.1] - 2026-02-11

#### Added
- 👥 **Contact Management API** - Full CRUD operations for contacts
  - `client.contact.list()` - List contacts with filters
  - `client.contact.get(id)` - Get contact by ID
  - `client.contact.create(options)` - Create a new contact
  - `client.contact.update(id, options)` - Update an existing contact
  - `client.contact.delete(id)` - Delete a contact
  - `client.contact.bulkDelete(options)` - Bulk delete contacts
- 📋 **Template Listing API**
  - `client.listTemplates(channel)` - List available email and WhatsApp templates
  - Supports filtering by channel: `'email'`, `'whatsapp'`, or `'all'`

### [1.0.0] - 2026-02-11

#### Added
- 🎉 **Initial Release**
- 📧 **Email Messaging**
  - `client.sendMessage.email()` - Send transactional emails
  - `client.sendMessage.emailTemplate()` - Send emails using templates
- 💬 **WhatsApp Messaging**
  - `client.sendMessage.whatsapp()` - Send WhatsApp messages
  - `client.sendMessage.whatsappTemplate()` - Send WhatsApp templates
- 🔒 **Authentication** - API key authentication with `clientId:secret` format
- 🛡️ **Error Handling** - Custom error classes for different error scenarios
- 📝 **TypeScript Support** - Full type definitions for all API methods
- ⚙️ **Configuration** - Customizable base URL and request timeout

---

**Legend:**
- 🎉 Major features
- ✨ New features
- 🐛 Bug fixes
- 🔧 Improvements
- 📝 Documentation
- 🔒 Security

## License

MIT License - see [LICENSE](LICENSE) file for details.

---

<div align="center">

Made with ❤️ by the Interxact team

[Website](https://interxact.com) • [Dashboard](https://app.interxact.com) • [Documentation](https://app.interxact.com/docs)

</div>