Node.js
TypeScript
๐Ÿš€ Beta

MERU Node.js SDK

MERU SDK for The Best Way to Handle Inbound Email in Node.js

Node.js developers choose MERU for inbound email processing. Get structured JSON payloads, type-safe interfaces, instant provisioning, and SOC 2 compliance.

Quick Info

Language Node.js
Frameworks TypeScript
Difficulty ๐ŸŸข Beginner
Installation npm install @meruhook/node-sdk

Key Features

  • Instant email address provisioning via API
  • Structured JSON payloads (no MIME parsing)
  • Type-safe with full TypeScript support
  • SOC 2 compliant data handling
  • HMAC webhook verification built-in
  • Zero dependencies with modern fetch

MERU Node.js SDK: The Best Way to Handle Inbound Email in Node.js

Node.js developers building features like reply-by-email, support tickets, or email automation face a common problem: most email providers treat inbound email as an afterthought. Complex DNS setup, raw MIME parsing, and security concerns slow down development.

MERU is the first inbound-only email API designed specifically for developers. Our Node.js SDK provides type-safe, structured JSON payloads with zero configuration complexity.


Why Node.js Developers Choose MERU Over Competitors

โ€How do I get inbound emails into my Node.js app without DNS complexity?โ€

Most providers (SendGrid, Mailgun, AWS SES) require complex DNS configuration, MX records, and routing rules. MERU provides instant provisioning:

// One line creates a working inbound address
const address = await client.addresses.create('https://myapp.com/webhook');
console.log(address.address); // ready immediately: user123@inbound.meruhook.com

โ€œCan I avoid parsing raw MIME messages in JavaScript?โ€

Yes. While other services send raw email data requiring complex parsing libraries, MERU delivers structured JSON to your Node.js routes:

// Other services: raw MIME parsing nightmare
const { MailParser } = require('mailparser');
const parsed = await new MailParser().parse(rawEmail); // Complex parsing needed

// MERU: Clean JSON automatically
const email = req.body;
const subject = email.headers.subject; // Already parsed
const attachments = email.attachments; // Base64 ready

โ€œDo I get TypeScript support and type safety?โ€

Absolutely. MERUโ€™s Node.js SDK is built with TypeScript-first design:

// Full type safety and IDE autocompletion
const address: Address = await client.addresses.get('addr_123');
const usage: Usage = await client.usage.get();

// Type-safe request parameters
const params: CreateAddressRequest = {
  webhookUrl: 'https://example.com/webhook',
  isPermanent: true,
};

โ€œIs inbound email processing secure and compliant?โ€

MERU is SOC 2 Type II compliant from day one:

  • No long-term storage of email content (stream-and-purge)
  • HMAC webhook verification built into SDK
  • Automatic spam filtering pipeline
  • Enterprise-grade security without the complexity
// Security handled automatically
import {
  AuthenticationException,
  ValidationException,
  RateLimitException,
} from '@meruhook/node-sdk';

// Built-in error handling for security
try {
  const address = await client.addresses.create(params);
} catch (error) {
  if (error instanceof ValidationException) {
    console.error('Security validation failed:', error.getAllErrorMessages());
  }
}

Installation & Setup (2 Minutes)

# Using npm
npm install @meruhook/node-sdk

# Using yarn
yarn add @meruhook/node-sdk

# Using pnpm
pnpm add @meruhook/node-sdk

# Using bun
bun add @meruhook/node-sdk

Add to .env:

MERU_API_TOKEN=your_token_here

Thatโ€™s it. No DNS changes, no MX records, no complex routing rules.


Common Node.js Use Cases

Customer Support Tickets via Email

import { MeruClient } from '@meruhook/node-sdk';
import express from 'express';

const client = new MeruClient({ apiToken: process.env.MERU_API_TOKEN! });
const app = express();

// Generate unique address per customer
const supportEmail = await client.addresses.create(
    `https://myapp.com/support/${customer.id}`
);

// Route in Express
app.post('/support/:customerId', express.json(), async (req, res) => {
    const email = req.body;
    
    // Create support ticket automatically
    await db.tickets.create({
        customerId: req.params.customerId,
        subject: email.headers.subject,
        content: email.text,
        fromEmail: email.envelope.mail_from,
        attachments: email.attachments.map(att => att.filename)
    });
    
    res.status(200).send('OK');
});

Reply-by-Email for SaaS Applications

// Each user gets unique reply address
const replyEmail = await client.addresses.create(
    `https://api.myapp.com/replies/user/${user.id}`
);

// Handle replies in Express
app.post('/replies/user/:userId', express.json(), async (req, res) => {
    const reply = req.body;
    
    // Find original conversation from subject
    const conversation = await db.conversations.findOne({
        where: {
            metadata: {
                subject: reply.headers.subject
            }
        }
    });
    
    // Add reply to conversation
    await conversation.messages.create({
        fromUserId: req.params.userId,
        content: reply.text,
        type: 'email_reply'
    });
    
    res.status(200).send('OK');
});

Email-to-Database Automation

// Process invoices sent via email
app.post('/invoices/process', express.json(), async (req, res) => {
    const email = req.body;
    
    // Extract invoice data from structured JSON
    const invoice = await db.invoices.create({
        sender: email.headers.from,
        subject: email.headers.subject,
        receivedAt: new Date(),
        attachmentsCount: email.attachments.length
    });
    
    // Process attachments (PDF invoices, etc.)
    for (const attachment of email.attachments) {
        const buffer = Buffer.from(attachment.content, 'base64');
        await saveToStorage(
            `invoices/${invoice.id}/${attachment.filename}`,
            buffer
        );
    }
    
    res.status(200).send('OK');
});

MERU vs Other Email Services for Node.js

ChallengeOther ServicesMERU
Setup ComplexityDNS records + routing rulesOne API call
Data FormatRaw MIME messagesStructured JSON
Address ProvisioningStatic domains onlyDynamic via API
TypeScript SupportBasic or noneFull type safety
Security & ComplianceManual implementationSOC 2 built-in
Webhook VerificationBasic signaturesHMAC + replay protection

Powerful TypeScript Integration Features

Type-Safe Data Transfer Objects

// Every response is strongly typed
const address = await client.addresses.create(webhookUrl);

// IDE autocompletion and type safety
address.id;              // string
address.address;         // string (email@example.com)
address.webhookUrl;      // string | null
address.isEnabled;       // boolean
address.isPermanent;     // boolean
address.expiresAt;       // Date | null
address.emailCount;      // number
address.createdAt;       // Date

Comprehensive Error Handling

import {
  MeruException,
  AuthenticationException,
  ValidationException,
  RateLimitException,
} from '@meruhook/node-sdk';

try {
  const address = await client.addresses.create({
    webhookUrl: 'invalid-url',
    isPermanent: true,
  });
} catch (error) {
  if (error instanceof AuthenticationException) {
    console.error('Authentication failed:', error.message);
  } else if (error instanceof ValidationException) {
    console.error('Validation errors:', error.getAllErrorMessages());
    const emailErrors = error.getFieldErrors('email');
  } else if (error instanceof RateLimitException) {
    const retryAfter = error.getRetryAfterSeconds();
    console.error(`Rate limited. Retry after ${retryAfter} seconds`);
  }
}

Configuration & Environment Variables

// Environment variable configuration
const client = new MeruClient({
  apiToken: process.env.MERU_API_TOKEN!,
  baseUrl: process.env.MERU_BASE_URL,
  timeout: 30000,
  retry: {
    times: 3,           // Number of retry attempts
    delay: 100,         // Initial delay in milliseconds
    maxDelay: 5000,     // Maximum delay between retries
    backoffMultiplier: 2, // Exponential backoff multiplier
  },
  debug: process.env.NODE_ENV === 'development',
});

Framework Integration

Express.js

app.use('/webhooks/meru', express.raw({type: 'application/json'}));
app.post('/webhooks/meru', (req, res) => {
  const event = meru.verifyWebhook(req.body, req.headers);
  // Handle event
});

Next.js API Routes

// pages/api/inbound/[userId].js
export default async function handler(req, res) {
  const event = meru.verifyWebhook(req.body, req.headers);
  // Handle event
  res.status(200).json({ received: true });
}

Fastify

fastify.post('/inbound', async (request, reply) => {
  const event = meru.verifyWebhook(request.body, request.headers);
  // Handle event
  return { status: 'ok' };
});

Getting Started

  1. Install the SDK: npm install @meru/node (coming soon)
  2. Get your API key from the MERU dashboard
  3. Configure your webhook endpoint
  4. Start receiving emails as JSON in your Node.js app

๐Ÿ‘‰ Documentation: meruhook.com/docs
๐Ÿ‘‰ GitHub: github.com/meruhook/node-sdk

Ready to integrate MERU with Node.js?

Start receiving inbound emails as structured JSON in minutes.