lumail
v0.1.5
Published
Lumail SDK and CLI - email marketing platform
Maintainers
Readme
Lumail
TypeScript SDK and CLI for the Lumail email marketing platform.
Manage subscribers, send campaigns, trigger transactional emails, and more — all from code.
Install
npm install lumail
# or
pnpm add lumailQuick Start
import { Lumail } from "lumail";
const lumail = new Lumail({
apiKey: "lum_your_api_key", // Get yours at lumail.io/settings
});
// Add a subscriber
const { subscriber } = await lumail.subscribers.create({
email: "[email protected]",
name: "John Doe",
tags: ["newsletter", "welcome"],
});
// Send a transactional email
await lumail.emails.send({
to: "[email protected]",
from: "[email protected]",
subject: "Welcome!",
content: "Thanks for signing up.",
contentType: "MARKDOWN",
});Authentication
Get your API key from your Lumail settings page, then pass it to the constructor:
const lumail = new Lumail({ apiKey: "lum_..." });Resources
Subscribers
// List subscribers (with cursor pagination)
const { subscribers, nextCursor } = await lumail.subscribers.list({
tag: "newsletter",
status: "SUBSCRIBED",
limit: 50,
});
// Get a subscriber by ID or email
const { subscriber } = await lumail.subscribers.get("[email protected]");
// Create a subscriber
const { subscriber } = await lumail.subscribers.create({
email: "[email protected]",
name: "John Doe",
phone: "+1234567890",
tags: ["newsletter"],
fields: { company: "Acme" },
triggerWorkflows: true,
});
// Update a subscriber
await lumail.subscribers.update("[email protected]", {
name: "John D.",
fields: { company: "New Corp" },
});
// Delete a subscriber
await lumail.subscribers.delete("[email protected]");
// Unsubscribe
await lumail.subscribers.unsubscribe("[email protected]");
// Manage tags
await lumail.subscribers.addTags("[email protected]", ["vip", "early-adopter"]);
await lumail.subscribers.removeTags("[email protected]", ["early-adopter"]);
// List subscriber events
const { events } = await lumail.subscribers.listEvents("[email protected]", {
eventTypes: ["EMAIL_OPENED", "EMAIL_CLICKED"],
order: "desc",
take: 20,
});Campaigns
// List campaigns
const { campaigns } = await lumail.campaigns.list({
status: "DRAFT",
limit: 10,
});
// Create a campaign
const { campaign } = await lumail.campaigns.create({
subject: "March Newsletter",
name: "march-2026",
preview: "What's new this month",
contentType: "MARKDOWN",
content: "# Hello\n\nHere's what's new...",
});
// Get a campaign
const { campaign } = await lumail.campaigns.get("campaign_id");
// Update a campaign
await lumail.campaigns.update("campaign_id", {
subject: "Updated Subject",
});
// Send immediately
await lumail.campaigns.send("campaign_id");
// Schedule for later
await lumail.campaigns.send("campaign_id", {
scheduledAt: "2026-04-10T09:00:00Z",
timezone: "Europe/Paris",
});
// Delete a campaign
await lumail.campaigns.delete("campaign_id");Emails
// Send a transactional email
await lumail.emails.send({
to: "[email protected]",
from: "[email protected]",
subject: "Your invoice",
content: "<h1>Invoice #123</h1><p>Amount: $99</p>",
contentType: "HTML",
replyTo: "[email protected]",
transactional: true,
tracking: { open: true, links: true },
});
// Verify an email address
const result = await lumail.emails.verify({
email: "[email protected]",
});
if (result.success) {
console.log("Email is valid", result.warnings);
} else {
console.log(result.code, result.error, result.suggestion);
}Tags
// List all tags
const { tags } = await lumail.tags.list();
// Create a tag
const { tag } = await lumail.tags.create({ name: "vip" });
// Get a tag (includes subscriber count)
const { tag } = await lumail.tags.get("vip");
// Update a tag
await lumail.tags.update("vip", { name: "VIP Customers" });Events
// Create a custom event
await lumail.events.create({
eventType: "SUBSCRIBER_PAYMENT",
subscriber: "[email protected]",
data: { amount: 99, currency: "USD", plan: "pro" },
});Tools (v2)
AI-powered tools for email marketing.
// List available tools
const { tools } = await lumail.tools.list();
// Get tool details
const { tool } = await lumail.tools.get("generate-subject-line");
// Run a tool
const result = await lumail.tools.run("generate-subject-line", {
topic: "Spring sale announcement",
tone: "excited",
});Error Handling
The SDK throws typed errors you can catch individually:
import {
Lumail,
LumailAuthenticationError,
LumailValidationError,
LumailNotFoundError,
LumailRateLimitError,
LumailPaymentRequiredError,
} from "lumail";
try {
await lumail.subscribers.get("[email protected]");
} catch (error) {
if (error instanceof LumailNotFoundError) {
console.log("Subscriber not found");
} else if (error instanceof LumailAuthenticationError) {
console.log("Invalid API key");
} else if (error instanceof LumailRateLimitError) {
console.log(`Rate limited, retry after ${error.retryAfter}ms`);
} else if (error instanceof LumailValidationError) {
console.log(`Bad request: ${error.message}`);
} else if (error instanceof LumailPaymentRequiredError) {
console.log("Plan limit reached — upgrade at lumail.io/billing");
}
}All errors extend LumailError which includes status and code properties.
The client automatically retries idempotent requests (GET, PUT, DELETE) on rate-limit (429) and network errors with exponential backoff.
lumail.emails.verify() returns a discriminated union:
type VerifyEmailResponse =
| { success: true; warnings?: string[] }
| {
success: false;
error: string;
code:
| "invalid_format"
| "disposable_email"
| "spam_domain"
| "invalid_domain"
| "test_email"
| "internal_error";
suggestion?: string;
warnings?: string[];
};CLI
The package also ships a CLI:
npx lumail --helpRequirements
- Node.js 18+ (uses native
fetch) - An API key from lumail.io
License
MIT
