Skip to documentation

SDKs & tools

SDKs and tools

The Opensend Node SDK and MCP server for your self-hosted API.

Node SDK

@opensendcc/sdk is Opensend’s Node SDK. It needs Node.js 20 or later.

bash
pnpm add @opensendcc/sdk
typescript
import { Opensend } from "@opensendcc/sdk";

const opensend = new Opensend(process.env.OPENSEND_API_KEY!, {
  baseUrl: process.env.OPENSEND_BASE_URL!, // https://api.example.com
});

const { data, error } = await opensend.emails.send({
  from: "hello@example.com",
  to: "you@example.net",
  subject: "Welcome",
  html: "<p>Hello.</p>",
});
if (error) throw new Error(error.message);
console.log(data?.id);

Opensend is self-hosted, so there is no shared cloud API URL: always pass your installation’s API origin as baseUrl. Without arguments, new Opensend() reads OPENSEND_API_KEY and OPENSEND_BASE_URL, and it throws if there is no base URL.

OptionEnvironment variableDefault
Key (first argument)OPENSEND_API_KEYNone, required
baseUrlOPENSEND_BASE_URLNone, required
userAgentOPENSEND_USER_AGENTopensend-node:<version>

Calls resolve to { data, error, headers } and do not throw for API errors; read the rate limit headers from headers. To send React emails, also install @react-email/render; the SDK renders the react option to HTML before sending. opensend.webhooks.verify() checks webhook signatures (see verify webhook requests). Each API reference page shows the SDK call and the cURL request.

Moving an app from Resend

The SDK keeps Resend’s resource and method names, and exports Resend as an alias of Opensend. Replace the resend package with @opensendcc/sdk, change the import, and pass your installation’s base URL. The SDK never reads RESEND_API_KEY or RESEND_BASE_URL, so a leftover Resend setting can’t send your mail to Resend. The migration guide covers domains, webhooks, templates and contacts.

Where SDK and HTTP names differ

SDK options are camelCase and the wire fields are snake_case: replyTo is reply_to, scheduledAt is scheduled_at, and automation triggers use eventName for event_name. CSV imports use columnMap and onConflict and are sent as multipart form data.

A few operations need the SDK’s generic get, post, patch, and delete methods:

  • topics.list() takes no pagination options. Use opensend.get("/topics?limit=20") to page through topics.
  • topics.create() has no visibility option in its types. Set visibility with opensend.post("/topics", { … }), or over HTTP.
  • audiences is an alias for segments and calls /segments. The deprecated /audiences routes are reachable with the generic methods.

Only the documented endpoints are supported. A few SDK methods have no Opensend endpoint; for example, emails.receiving.forward(). Read compatibility for the partial operations.

Other languages

There is no Opensend SDK for other languages yet. Call the HTTP API from any server-side language: send your API key as a bearer token to your installation’s API origin.

MCP server

@opensendcc/mcp gives AI agents 101 tools for your installation’s API. It needs Node.js 22 or later. Add it to Claude Desktop (claude_desktop_config.json), Claude Code (.mcp.json) or Cursor (.cursor/mcp.json):

json
{
  "mcpServers": {
    "opensend": {
      "command": "npx",
      "args": ["-y", "@opensendcc/mcp"],
      "env": {
        "OPENSEND_API_KEY": "os_xxxxxxxx",
        "OPENSEND_BASE_URL": "https://api.example.com"
      }
    }
  }
}

To serve it over HTTP instead, run npx -y @opensendcc/mcp --http --port 3000. Each HTTP client then sends its own key as Authorization: Bearer <key>. Use a key with only the access the agent needs. For the raw API contract, give agents llms.txt.