npm package: @myxara/sdk-js
Description: JavaScript SDK for Myxara - Email infrastructure for AI agents
Author: Myxara
Latest version: 0.1.0

# @myxara/sdk-js

Official JavaScript/TypeScript SDK for Myxara - Email infrastructure for AI agents.

[![npm version](https://img.shields.io/npm/v/@myxara/sdk-js.svg)](https://www.npmjs.com/package/@myxara/sdk-js)
[![License: MIT](https://img.shields.io/badge/License-MIT-yellow.svg)](https://opensource.org/licenses/MIT)
[![TypeScript](https://img.shields.io/badge/TypeScript-Ready-blue.svg)](https://www.typescriptlang.org/)

## Features

- ✅ **Fully Typed** - Complete TypeScript support with detailed JSDoc
- ✅ **Automatic Retries** - Exponential backoff with jitter for failed requests
- ✅ **Rate Limiting** - Built-in rate limit detection and handling
- ✅ **Auto-pagination** - Helper methods to fetch all pages automatically
- ✅ **Webhook Helpers** - HMAC signature verification for secure webhooks
- ✅ **Error Handling** - Comprehensive error classes for type-safe error handling
- ✅ **Debug Mode** - Optional request/response logging for development
- ✅ **Dual Format** - Works with both ESM and CommonJS

## Installation

```bash
npm install @myxara/sdk-js
# or
yarn add @myxara/sdk-js
# or
bun add @myxara/sdk-js
```

## Quick Start

```typescript
import { MyxaraClient } from '@myxara/sdk-js'

// Initialize the client
const client = new MyxaraClient({
  apiKey: process.env.MYXARA_API_KEY!
})

// Create an inbox
const inbox = await client.inboxes.create({
  local_part: 'my-agent',
  name: 'Customer Support Agent'
})

console.log(`Inbox created: ${inbox.address}`)

// Send an email
const message = await client.inboxes.messages(inbox.id).send({
  to: 'customer@example.com',
  subject: 'Welcome!',
  html: '<h1>Thanks for reaching out!</h1>',
  text: 'Thanks for reaching out!'
})

console.log(`Message sent: ${message.id}`)

// List incoming messages
const messages = await client.inboxes.messages(inbox.id).list({
  direction: 'in',
  limit: 20
})

messages.data.forEach(msg => {
  console.log(`From: ${msg.from}`)
  console.log(`Subject: ${msg.subject}`)
})
```

## Usage Examples

### Managing Inboxes

```typescript
// Create an inbox
const inbox = await client.inboxes.create({
  local_part: 'support-agent',
  name: 'Support Agent'
})

// Get a specific inbox
const inbox = await client.inboxes.get('inbox_abc123')

// List all inboxes (with auto-pagination)
const allInboxes = await client.inboxes.listAll()

// List inboxes with pagination
const inboxes = await client.inboxes.list({ limit: 10, offset: 0 })

// Update an inbox
const updated = await client.inboxes.update('inbox_abc123', {
  status: 'paused'
})

// Delete an inbox
await client.inboxes.delete('inbox_abc123')
```

### Sending Emails

```typescript
// Send a simple email
await client.inboxes.messages('inbox_abc123').send({
  to: 'user@example.com',
  subject: 'Hello!',
  text: 'This is a plain text email'
})

// Send an HTML email
await client.inboxes.messages('inbox_abc123').send({
  to: 'user@example.com',
  subject: 'Welcome!',
  html: '<h1>Welcome</h1><p>Thanks for signing up!</p>',
  text: 'Welcome! Thanks for signing up!'
})

// Send with CC, BCC, and attachments
await client.inboxes.messages('inbox_abc123').send({
  to: ['user1@example.com', 'user2@example.com'],
  cc: ['manager@example.com'],
  bcc: ['archive@example.com'],
  subject: 'Team Update',
  html: '<p>Here is the latest update...</p>',
  attachments: [
    {
      filename: 'report.pdf',
      content: base64Content,
      content_type: 'application/pdf'
    }
  ]
})
```

### Reading Messages

```typescript
// List messages for an inbox
const messages = await client.inboxes.messages('inbox_abc123').list({
  direction: 'in',
  limit: 50
})

// Get all messages (auto-pagination)
const allMessages = await client.inboxes.messages('inbox_abc123').listAll()

// Get a specific message
const message = await client.inboxes.messages('inbox_abc123').get('msg_xyz')

// Get raw email content (RFC 822)
const raw = await client.inboxes.messages('inbox_abc123').getRaw('msg_xyz')

// Filter by thread
const thread = await client.inboxes.messages('inbox_abc123').list({
  thread_key: 'thread_abc'
})
```

### Managing Webhooks

```typescript
// Create a webhook
const webhook = await client.webhooks.create({
  url: 'https://api.example.com/webhooks',
  events: ['message.received', 'message.sent']
})

console.log(`Webhook secret: ${webhook.secret}`) // Save this securely!

// List webhooks
const webhooks = await client.webhooks.list()

// Update a webhook
await client.webhooks.update('webhook_abc123', {
  is_active: false
})

// Delete a webhook
await client.webhooks.delete('webhook_abc123')

// View webhook deliveries
const deliveries = await client.webhooks.listDeliveries('webhook_abc123')

// Retry a failed delivery
await client.webhooks.retryDelivery('webhook_abc123', 'delivery_xyz')
```

### Webhook Signature Verification

```typescript
import { verifyWebhookSignature, parseWebhookPayload } from '@myxara/sdk-js'
import express from 'express'

const app = express()

// Important: Use raw body for signature verification
app.use(express.json({
  verify: (req, res, buf) => {
    req.rawBody = buf.toString()
  }
}))

app.post('/webhooks', async (req, res) => {
  const signature = req.headers['x-myxara-signature']
  const rawBody = req.rawBody
  const secret = process.env.WEBHOOK_SECRET!

  // Verify signature
  const isValid = await verifyWebhookSignature(rawBody, signature, secret)
  if (!isValid) {
    return res.status(401).json({ error: 'Invalid signature' })
  }

  // Parse and validate payload
  const payload = parseWebhookPayload(req.body)

  // Handle the event
  if (payload.event === 'message.received') {
    console.log('New message:', payload.data.message.subject)
    // Process the message with your AI agent...
  }

  res.status(200).json({ received: true })
})
```

Or use the built-in webhook handler:

```typescript
import { createWebhookHandler } from '@myxara/sdk-js'
import express from 'express'

const app = express()

app.use(express.json({
  verify: (req, res, buf) => {
    req.rawBody = buf.toString()
  }
}))

app.post('/webhooks', createWebhookHandler(
  process.env.WEBHOOK_SECRET!,
  async (payload) => {
    if (payload.event === 'message.received') {
      // Process message
      console.log('New message:', payload.data.message.subject)
    }
  }
))
```

### Managing API Keys

```typescript
// Create an API key
const key = await client.apiKeys.create({
  name: 'Production Key',
  scopes: ['messages:read', 'messages:write'],
  usage_limit_per_day: 10000
})

// IMPORTANT: Save this key securely - it won't be shown again!
console.log(`API Key: ${key.key}`)

// List API keys
const keys = await client.apiKeys.list()

// Get usage statistics
const usage = await client.apiKeys.getUsage('key_abc123')
console.log(`Today: ${usage.today} calls`)
console.log(`This month: ${usage.this_month} calls`)

// Revoke an API key
await client.apiKeys.revoke('key_abc123')
```

### Error Handling

```typescript
import {
  MyxaraError,
  AuthenticationError,
  PermissionError,
  NotFoundError,
  ValidationError,
  RateLimitError
} from '@myxara/sdk-js'

try {
  await client.inboxes.get('invalid_id')
} catch (error) {
  if (error instanceof AuthenticationError) {
    console.error('Invalid API key')
  } else if (error instanceof PermissionError) {
    console.error('Insufficient permissions')
  } else if (error instanceof NotFoundError) {
    console.error('Inbox not found')
  } else if (error instanceof ValidationError) {
    console.error('Invalid input:', error.details)
  } else if (error instanceof RateLimitError) {
    console.error('Rate limit exceeded')
    console.error('Retry after:', error.retryAfter)
    console.error('Reset at:', error.resetAt)
  } else if (error instanceof MyxaraError) {
    console.error('API error:', error.message)
    console.error('Status:', error.statusCode)
    console.error('Code:', error.code)
  }
}
```

## Configuration

```typescript
const client = new MyxaraClient({
  // Required: Your API key
  apiKey: process.env.MYXARA_API_KEY!,

  // Optional: Custom API base URL
  baseUrl: 'https://api.myxara.ai',

  // Optional: Request timeout in milliseconds (default: 30000)
  timeout: 60000,

  // Optional: Enable debug logging (default: false)
  debug: true,

  // Optional: Maximum retry attempts (default: 3)
  maxRetries: 5,

  // Optional: Custom headers for all requests
  headers: {
    'X-Custom-Header': 'value'
  }
})
```

## API Reference

### Client

- `client.inboxes` - Inbox management
- `client.webhooks` - Webhook management
- `client.apiKeys` - API key management

### Inboxes

- `client.inboxes.create(data)` - Create a new inbox
- `client.inboxes.get(id)` - Get an inbox by ID
- `client.inboxes.list(params?)` - List inboxes with pagination
- `client.inboxes.listAll()` - Get all inboxes (auto-pagination)
- `client.inboxes.update(id, data)` - Update an inbox
- `client.inboxes.delete(id)` - Delete an inbox
- `client.inboxes.messages(inboxId)` - Get messages manager for an inbox

### Messages

- `client.inboxes.messages(inboxId).list(query?)` - List messages
- `client.inboxes.messages(inboxId).listAll(query?)` - Get all messages
- `client.inboxes.messages(inboxId).get(id)` - Get a message by ID
- `client.inboxes.messages(inboxId).send(request)` - Send an email
- `client.inboxes.messages(inboxId).delete(id)` - Delete a message
- `client.inboxes.messages(inboxId).getRaw(id)` - Get raw email content

### Webhooks

- `client.webhooks.create(data)` - Create a new webhook
- `client.webhooks.get(id)` - Get a webhook by ID
- `client.webhooks.list(params?)` - List webhooks with pagination
- `client.webhooks.listAll()` - Get all webhooks
- `client.webhooks.update(id, data)` - Update a webhook
- `client.webhooks.delete(id)` - Delete a webhook
- `client.webhooks.listDeliveries(webhookId, params?)` - List webhook deliveries
- `client.webhooks.getDelivery(webhookId, deliveryId)` - Get a delivery
- `client.webhooks.retryDelivery(webhookId, deliveryId)` - Retry a failed delivery

### API Keys

- `client.apiKeys.create(data)` - Create a new API key
- `client.apiKeys.get(id)` - Get an API key by ID
- `client.apiKeys.list(params?)` - List API keys with pagination
- `client.apiKeys.listAll()` - Get all API keys
- `client.apiKeys.revoke(id)` - Revoke an API key
- `client.apiKeys.getUsage(id)` - Get usage statistics

## TypeScript Support

This SDK is written in TypeScript and includes complete type definitions. All API responses, request parameters, and error types are fully typed.

```typescript
import type {
  Inbox,
  Message,
  Webhook,
  CreateInboxRequest,
  SendEmailRequest,
  PaginatedResponse
} from '@myxara/sdk-js'
```

## Contributing

Contributions are welcome! Please see our [Contributing Guide](../../CONTRIBUTING.md) for details.

## License

MIT © Myxara

## Links

- [Documentation](https://docs.myxara.ai)
- [API Reference](https://docs.myxara.ai/api)
- [GitHub](https://github.com/myxara/myxara)
- [Issues](https://github.com/myxara/myxara/issues)