npm package: @inbounter/node
Description: Inbounter Node.js SDK - Official SDK for AI agent inboxes (email, SMS), Shield Mode, routing, and webhooks
Author: Inbounter
Latest version: 1.0.0

<p align="center">
  <picture>
    <source media="(prefers-color-scheme: dark)" srcset="https://inbounter.com/logos/inbounter_light.svg" />
    <source media="(prefers-color-scheme: light)" srcset="https://inbounter.com/logos/inbounter_dark.svg" />
    <img src="https://inbounter.com/logos/inbounter_dark.svg" alt="Inbounter" width="300" />
  </picture>
</p>

<p align="center">
  <b>Official TypeScript / Node.js SDK for <a href="https://inbounter.com">Inbounter</a></b><br/>
  Secure inbox infrastructure for AI agents — email, SMS, smart routing, and Shield Mode.
</p>

<p align="center">
  <a href="https://www.npmjs.com/package/@inbounter/node">
    <img src="https://img.shields.io/npm/v/@inbounter/node.svg?style=flat-square" alt="NPM Version" />
  </a>
  <a href="https://github.com/inbounter/inbounter-node/blob/main/LICENSE">
    <img src="https://img.shields.io/github/license/inbounter/inbounter-node.svg?style=flat-square" alt="License" />
  </a>
</p>

# Inbounter Node.js SDK

## What is Inbounter?

**Inbounter** is infrastructure that gives AI agents their own inboxes — email, SMS, and more — with built-in security and smart routing.

- 📬 **Inboxes** — Provision dedicated email & SMS inboxes for AI agents
- 🛡️ **Shield Mode** — Block spam, phishing, and unwanted messages automatically
- 🔀 **Smart Routing** — Route inbound messages with filters, AI extraction, and webhooks
- 📨 **Outbound** — Send emails and SMS directly from agent inboxes
- 🔗 **Webhooks** — Real-time event notifications for contacts, messages, and more
- 💳 **Credits** — Usage-based billing with auto-replenish

> [Get your API key](https://inbounter.com)

## Installation

```bash
npm install @inbounter/server
# or
yarn add @inbounter/server
# or
pnpm add @inbounter/server
```

## Quick Start

```typescript
import { Inbounter, SourceType, TransformationType } from "@inbounter/server";

const inbounter = new Inbounter("your-api-key");

// Set workspace for workspace-scoped operations
inbounter.setWorkspaceId("wks_abc123");

// Create an inbox + provision an email source
const inbox = await inbounter.inboxes.create({
  name: "support-agent",
  sourceType: SourceType.EMAIL,
  domain: "agents.yourdomain.com",
  provisionSource: true,
  shieldEnabled: true,
});

// Add a route with AI extraction
const scope = inbounter.routes.scopeForInbox(inbox.id);
const route = await inbounter.routes.create(scope, {
  name: "Lead router",
  enabled: true,
});

await inbounter.routes.createTransformation(route.id, {
  type: TransformationType.AI_EXTRACT,
  outputKey: "lead",
  config: {
    fields: [
      { name: "company", description: "Company name", type: "string" },
      { name: "budget", description: "Budget amount", type: "number" },
    ],
  },
});
```

## Usage with Next.js

### Server Actions

```typescript
// app/actions.ts
"use server";

import { Inbounter, WebhookEvent } from "@inbounter/server";

const inbounter = new Inbounter(process.env.INBOUNTER_API_KEY!);
inbounter.setWorkspaceId(process.env.INBOUNTER_WORKSPACE_ID!);

export async function createWebhook(url: string) {
  return await inbounter.webhooks.create({
    url,
    events: [WebhookEvent.CONTACT_CREATED],
  });
}
```

### API Routes

```typescript
// app/api/webhooks/route.ts
import { Inbounter } from "@inbounter/server";
import { NextRequest, NextResponse } from "next/server";

const inbounter = new Inbounter(process.env.INBOUNTER_API_KEY!);

export async function POST(request: NextRequest) {
  const { url, events } = await request.json();

  const webhook = await inbounter.webhooks.create({
    url,
    events,
  });

  return NextResponse.json({ webhook });
}
```

## API Reference

### Webhooks

Manage webhook subscriptions for receiving real-time events.

```typescript
// Create a webhook
const webhook = await inbounter.webhooks.create({
  url: "https://example.com/webhooks/contacts",
  events: ["CONTACT_CREATED", "CONTACT_UPDATED"],
  token: "optional-secret-token", // Optional: auto-generated if not provided
});

// Get a webhook
const webhook = await inbounter.webhooks.get("webhook-id");

// Update a webhook
const updated = await inbounter.webhooks.update("webhook-id", {
  events: ["CONTACT_CREATED"],
  status: "ACTIVE",
});

// List webhooks
const { items, cursor, hasMore } = await inbounter.webhooks.list({
  limit: 20,
  status: "ACTIVE",
});

// Pause a webhook
await inbounter.webhooks.pause("webhook-id", "Maintenance");

// Resume a webhook
await inbounter.webhooks.resume("webhook-id");

// Test a webhook
const result = await inbounter.webhooks.test("webhook-id");

// Delete a webhook
await inbounter.webhooks.delete("webhook-id");
```

#### Webhook Events

| Event | Description |
|-------|-------------|
| `CONTACT_CREATED` | A new contact was created |
| `CONTACT_UPDATED` | A contact was updated |
| `CONTACT_DELETED` | A contact was deleted |
| `CONTACT_PROPERTY_UPDATED` | A contact property was updated |
| `CONTACT_TAG_ADDED` | A tag was added to a contact |
| `CONTACT_TAG_REMOVED` | A tag was removed from a contact |
| `CONTACT_UNSUBSCRIBED` | A contact unsubscribed |
| `CONTACT_RESUBSCRIBED` | A contact resubscribed |
| `WORKSPACE_BANNED` | Workspace was banned |
| `WORKSPACE_SENDING_EMAILS_PAUSED` | Email sending was paused |
| `WORKSPACE_TEAM_MEMBER_JOINED` | A team member joined |
| `TESTING_CONNECTION` | Test webhook event |

### Sources (Inbound Email/SMS)

Manage inbound message sources for receiving emails and SMS.

```typescript
// Set workspace ID first
inbounter.setWorkspaceId("wks_abc123");

// Create an email source
const source = await inbounter.sources.create({
  type: "EMAIL",
  address: "support@yourdomain.com",
  name: "Support Inbox",
  settings: {
    autoReply: {
      enabled: true,
      message: "Thanks for reaching out! We'll respond shortly.",
    },
  },
});

// Get a source
const source = await inbounter.sources.get("source-id");

// Update a source
const updated = await inbounter.sources.update("source-id", {
  name: "Updated Name",
  settings: {
    autoReply: { enabled: false },
  },
});

// List sources
const { items, cursor, hasMore } = await inbounter.sources.list({
  type: "EMAIL",
  status: "ACTIVE",
});

// Verify a source (check DNS records)
const verified = await inbounter.sources.verify("source-id");

// Delete a source
await inbounter.sources.delete("source-id");
```

### Messages

Access inbound messages received by your sources.

```typescript
// Set workspace ID first
inbounter.setWorkspaceId("wks_abc123");

// Get a specific message with full details (route runs + deliveries)
const { message, routeRuns, deliveries } = await inbounter.messages.get("message-id");

// List messages by source
const { items, cursor, hasMore } = await inbounter.messages.listBySource(
  "source-id",
  {
    limit: 20,
    status: "DELIVERED",
  }
);

// List all messages in workspace
const messages = await inbounter.messages.list({
  startDate: "2024-01-01",
  endDate: "2024-01-31",
});

// Retry a specific failed delivery
// First, get the message details to find the failed delivery
const details = await inbounter.messages.get("message-id");
const failedDelivery = details.deliveries.find(d => d.status === "FAILED");
if (failedDelivery) {
  await inbounter.messages.retryDelivery("message-id", failedDelivery.id);
}
```

### Inboxes (Agent-first)

```typescript
// Create inbox + SMS source
const inbox = await inbounter.inboxes.create({
  name: "ops-agent",
  sourceType: "SMS",
  address: "+14155551234",
  sourceSettings: {
    twilioPhoneNumberSid: "PNxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx",
  },
  provisionSource: true,
});

// List inboxes
const inboxes = await inbounter.inboxes.list({ limit: 20 });

// Shield mode update
await inbounter.inboxes.update(inbox.id, {
  shieldEnabled: true,
  shieldRules: [
    { action: "ALLOW", pattern: "@openai.com" },
    { action: "REJECT", pattern: "*" },
  ],
});

// Inbox analytics
const stats = await inbounter.inboxes.getStats(inbox.id);

// Inbox messages, search, threads
const messages = await inbounter.inboxes.listMessages(inbox.id, { limit: 20 });
const search = await inbounter.inboxes.searchMessages(inbox.id, {
  q: "urgent outage",
  mode: "semantic",
});
const threads = await inbounter.inboxes.listThreads(inbox.id, { limit: 20 });
```

### Smart Routing

```typescript
const scope = inbounter.routes.scopeForInbox("ibx_123");

const route = await inbounter.routes.create(scope, {
  name: "Primary Router",
  enabled: true,
});

await inbounter.routes.createFilter(route.id, {
  field: "from",
  operator: "contains",
  value: "@customer.com",
});

await inbounter.routes.createTransformation(route.id, {
  type: "AI_EXTRACT",
  outputKey: "structured",
  config: {
    fields: [
      { name: "intent", description: "User intent", type: "string" },
      { name: "priority", description: "Priority 1-5", type: "number" },
    ],
  },
});

await inbounter.routes.createDestination(scope, route.id, {
  type: "WEBHOOK",
  name: "Agent Webhook",
  config: { url: "https://example.com/agent/inbound" },
});
```

### Outbound from Inbox

```typescript
await inbounter.inboxes.sendEmail("ibx_123", {
  to: "customer@example.com",
  subject: "Re: Your request",
  markdown: "Thanks, we received your message.",
  idempotencyKey: "reply-123",
});

await inbounter.inboxes.sendBatch("ibx_123", {
  messages: [
    {
      to: "a@example.com",
      subject: "Update A",
      text: "A",
    },
    {
      to: "b@example.com",
      subject: "Update B",
      text: "B",
    },
  ],
});
```

### Credits

```typescript
const credits = await inbounter.credits.get({ ledgerLimit: 25 });

await inbounter.credits.update({
  autoReplenishEnabled: true,
  autoReplenishThreshold: 2000,
  autoReplenishAmount: 10000,
});
```

## Configuration

```typescript
const inbounter = new Inbounter("your-api-key", {
  baseUrl: "https://api.inbounter.com", // default
  timeout: 30000, // 30 seconds
  maxRetries: 3,
  apiVersion: "v1",
});

// Set workspace ID for workspace-scoped operations
inbounter.setWorkspaceId("wks_abc123");

// Enable debug mode
inbounter.setDebugMode(true);

// Set custom headers
inbounter.setHeader("X-Custom-Header", "value");
```

## Error Handling

```typescript
import {
  Inbounter,
  InbounterError,
  AuthenticationError,
  RateLimitError,
  ValidationError,
} from "@inbounter/server";

try {
  await inbounter.webhooks.create({ url: "invalid" });
} catch (error) {
  if (error instanceof AuthenticationError) {
    console.error("Invalid API key");
  } else if (error instanceof RateLimitError) {
    console.error("Rate limited, retry after:", error.retryAfter);
  } else if (error instanceof ValidationError) {
    console.error("Validation error:", error.message);
  } else if (error instanceof InbounterError) {
    console.error("API error:", error.message, error.code);
  }
}
```

## TypeScript Support

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

```typescript
import type {
  // Webhooks
  Webhook,
  WebhookCreateOptions,
  WebhookEvent,
  WebhookStatus,
  // Sources
  Source,
  SourceType,
  SourceStatus,
  // Messages
  Message,
  MessageStatus,
  EmailPayload,
  SmsPayload,
} from "@inbounter/server";
```

## Singleton Pattern

For convenience, you can also use the singleton pattern:

```typescript
import { init, getClient } from "@inbounter/server";

// Initialize once (e.g., in your app's entry point)
init("your-api-key", { timeout: 60000 });

// Use anywhere in your app
const client = getClient();
await client.webhooks.list();
```

## Documentation

Full API reference → **<https://inbounter.com/docs>**

## Contributing

We ❤️ PRs!

1. **Fork** → `git checkout -b feat/awesome`
2. Add tests & docs
3. **PR** against `main`

## License

[MIT](LICENSE)