Mailcraft API Reference
Complete API documentation for Mailcraft SDK.
Table of Contents
Core Types
ArchetypeName
type ArchetypeName =
| "verification"
| "welcome"
| "receipt"
| "announcement"
| "digest";
Union type representing all available email template archetypes.
RenderedEmail
type RenderedEmail = {
to: string[];
subject: string;
html: string;
text: string;
};
The output of rendering an email template. Contains ready-to-send email content.
Properties:
to- Array of recipient email addressessubject- Email subject linehtml- Full HTML email bodytext- Plain text version of email body
SendResult
type SendResult = {
id: string;
provider: string;
acceptedAt: string;
metadata?: {
messageId?: string;
sequenceToken?: string;
[key: string]: string | number | boolean | undefined;
};
};
Response from a successful email send.
Properties:
id- Unique identifier for this send (provider-specific)provider- Name of the email provider (e.g., "resend")acceptedAt- ISO 8601 timestamp when email was acceptedmetadata- Provider-specific metadata (messageId for Resend, sequenceToken for SES)
Mailcraft Class
The main SDK class for rendering and sending emails.
Constructor
new Mailcraft(brand: BrandProfile)
Initialize a Mailcraft instance with a brand profile.
Parameters:
brand- Brand profile with sender info, colors, and business details
Example:
const mailcraft = new Mailcraft({
name: "Acme Corp",
sender: {
fromEmail: "noreply@acme.com",
fromName: "Acme"
},
business: {
legalName: "Acme Corporation Inc."
}
});
render<T>(archetype: T, input: RenderInputMap[T], options?: RenderOptions): RenderedEmail
Render an email template without sending it.
Type Parameters:
T extends ArchetypeName- The archetype to render
Parameters:
archetype- Name of the archetypeinput- Typed input data for the archetypeoptions- Optional rendering options
Returns: RenderedEmail object with HTML and text
Throws: MailcraftValidationError if input validation fails, MailcraftRenderError if rendering fails
Example:
const rendered = mailcraft.render("welcome", {
to: ["user@example.com"],
title: "Welcome to Acme!",
body: "Thanks for signing up."
});
console.log(rendered.html); // Full HTML email
console.log(rendered.text); // Plain text version
async send<T>(archetype: T, input: RenderInputMap[T], adapter: SenderAdapter): Promise<SendResult>
Render and send an email in one call.
Type Parameters:
T extends ArchetypeName- The archetype to send
Parameters:
archetype- Name of the archetypeinput- Typed input data for the archetypeadapter- Email provider adapter (Resend, SES, etc.)
Returns: SendResult with provider response information
Throws: MailcraftValidationError, MailcraftRenderError, or MailcraftSendError
Example:
import { ResendAdapter } from "@mailcraft/adapters/resend";
const adapter = new ResendAdapter(process.env.RESEND_API_KEY);
const result = await mailcraft.send(
"verification",
{
to: ["user@example.com"],
code: "123456"
},
adapter
);
console.log(`Sent with message ID: ${result.metadata?.messageId}`);
Archetype Inputs
Each archetype has a specific input type, defined in RenderInputMap[T].
Common Properties
All archetype inputs include:
to: string[]- Required. Array of recipient email addressessubject?: string- Optional. Override the default subject line
VerificationInput
type VerificationInput = {
to: string[];
subject?: string;
code?: string;
link?: string;
};
Used for email verification/confirmation workflows.
Properties:
code- Verification code to displaylink- Click-through verification link
Example:
const rendered = mailcraft.render("verification", {
to: ["user@example.com"],
code: "ABC123",
link: "https://app.com/verify?token=xyz"
});
WelcomeInput
type WelcomeInput = {
to: string[];
subject?: string;
title: string;
body: string;
cta?: Cta;
};
type Cta = {
label: string;
url: string;
};
Onboarding/welcome emails for new users.
Properties:
title- Email headlinebody- Email contentcta- Optional call-to-action button with label and URL
Example:
mailcraft.render("welcome", {
to: ["user@example.com"],
title: "Welcome!",
body: "You're all set. Here's what you can do next...",
cta: { label: "Get Started", url: "https://app.com/onboard" }
});
VerificationInput
See above under VerificationInput.
ReceiptInput
type ReceiptInput = {
to: string[];
subject?: string;
receiptId: string;
currency: string;
total: string;
items: ReceiptItem[];
};
type ReceiptItem = {
name: string;
quantity: number;
amount: string;
};
Transactional receipts and invoices.
Properties:
receiptId- Unique receipt identifiercurrency- Currency code (e.g., "USD", "EUR")total- Total amount as stringitems- Array of line items with name, quantity, and amount
Example:
mailcraft.render("receipt", {
to: ["customer@example.com"],
receiptId: "RCP-2024-001",
currency: "USD",
total: "99.99",
items: [
{ name: "Premium Plan", quantity: 1, amount: "99.99" }
]
});
AnnouncementInput
type AnnouncementInput = {
to: string[];
subject?: string;
title: string;
body: string;
cta?: Cta;
};
Product announcements and feature launches.
Properties:
title- Announcement headlinebody- Announcement detailscta- Optional action button
Example:
mailcraft.render("announcement", {
to: ["users@example.com"],
title: "New Feature: Dark Mode",
body: "We've launched dark mode. Go to settings to enable it.",
cta: { label: "Try It", url: "https://app.com/settings/theme" }
});
DigestInput
type DigestInput = {
to: string[];
subject?: string;
title: string;
entries: DigestEntry[];
};
type DigestEntry = {
title: string;
body: string;
url?: string;
};
Summary/digest emails with multiple items.
Properties:
title- Digest headline (e.g., "Your Weekly Digest")entries- Array of content items with title, body, and optional URL
Example:
mailcraft.render("digest", {
to: ["user@example.com"],
title: "Your Weekly Digest",
entries: [
{
title: "Article 1",
body: "Summary of interesting article...",
url: "https://blog.com/article-1"
},
{
title: "Article 2",
body: "Another great read...",
url: "https://blog.com/article-2"
}
]
});
Brand Profile
The BrandProfile type defines visual and sender identity.
type BrandProfile = {
name: string;
visual?: {
logoUrl?: string;
primaryColor?: string;
secondaryColor?: string;
stylePreset?: "modern" | "classic" | "minimal";
};
voice?: {
descriptor?: string;
examples?: string[];
antiPatterns?: string[];
};
sender: {
fromEmail: string;
fromName?: string;
replyTo?: string;
};
business: {
legalName: string;
addressLine1?: string;
country?: string;
};
footer?: {
unsubscribeUrl?: string;
supportEmail?: string;
};
};
Required Properties:
name- Brand/product namesender.fromEmail- Email address to send from (must be verified with provider)business.legalName- Legal entity name
Optional Properties:
visual.primaryColor- Primary brand color (hex format, e.g., "#0f172a")visual.secondaryColor- Secondary background colorvisual.stylePreset- Visual style: "modern", "classic", or "minimal"sender.fromName- Display name for sendersender.replyTo- Reply-to addressfooter.supportEmail- Support contact emailfooter.unsubscribeUrl- Unsubscribe link for emails
Example:
const brand: BrandProfile = {
name: "Acme",
visual: {
primaryColor: "#ff5733",
secondaryColor: "#fff9f5",
stylePreset: "modern"
},
sender: {
fromEmail: "noreply@acme.com",
fromName: "Acme Support"
},
business: {
legalName: "Acme Inc.",
addressLine1: "123 Main St"
},
footer: {
supportEmail: "support@acme.com",
unsubscribeUrl: "https://acme.com/unsubscribe"
}
};
Adapters
Adapters handle communication with specific email providers.
SenderAdapter Interface
All adapters implement:
interface SenderAdapter {
readonly provider: string;
send(input: RenderedEmail & { from: string }): Promise<SendResult>;
}
Resend Adapter
import { ResendAdapter } from "@mailcraft/adapters/resend";
const adapter = new ResendAdapter(apiKey?: string);
Uses Resend for email delivery.
Parameters:
apiKey- Optional. Resend API key. Falls back toRESEND_API_KEYenv var or mock mode.
Mock Mode: If no API key is provided, returns mock responses for testing.
Example:
// Production with API key
const adapter = new ResendAdapter(process.env.RESEND_API_KEY);
// Or rely on environment variable
const adapter = new ResendAdapter();
// Mock mode for testing
const mockAdapter = new ResendAdapter(); // No env var = mock
SES Adapter
import { SesAdapter } from "@mailcraft/adapters/ses";
const adapter = new SesAdapter(region?: string);
Uses AWS SES for email delivery.
Parameters:
region- Optional. AWS region (e.g., "us-east-1"). Falls back toAWS_REGIONenv var or mock mode.
Mock Mode: If no region is provided, returns mock responses for testing.
AWS Credentials: Uses standard AWS SDK credential resolution (env vars, credentials file, IAM roles).
Example:
// Production with region
const adapter = new SesAdapter("us-east-1");
// Or rely on environment variable
const adapter = new SesAdapter();
// Mock mode for testing
const mockAdapter = new SesAdapter(); // No env var = mock
Error Handling
Mailcraft provides typed error classes for different failure scenarios.
MailcraftValidationError
Thrown when input validation fails.
import { MailcraftValidationError } from "@mailcraft/core";
try {
mailcraft.render("welcome", {
to: [], // Invalid: empty recipients
title: "Test"
});
} catch (error) {
if (error instanceof MailcraftValidationError) {
console.error(`Validation error: ${error.message}`);
console.error(`Code: ${error.code}`);
}
}
Properties:
message- Human-readable error descriptioncode- "MAILCRAFT_VALIDATION_ERROR"
MailcraftRenderError
Thrown when rendering fails.
import { MailcraftRenderError } from "@mailcraft/sdk";
try {
await mailcraft.send("announcement", input, adapter);
} catch (error) {
if (error instanceof MailcraftRenderError) {
console.error(`Render failed for ${error.archetype}: ${error.message}`);
}
}
Properties:
message- Error descriptioncode- "MAILCRAFT_RENDER_ERROR"archetype- The archetype that failed to render
MailcraftSendError
Thrown when sending fails (provider error, network issue, etc.).
import { MailcraftSendError, type SendErrorPayload } from "@mailcraft/sdk";
try {
await mailcraft.send("verification", input, adapter);
} catch (error) {
if (error instanceof MailcraftSendError) {
const payload: SendErrorPayload = error.payload;
console.error(`Send failed:`);
console.error(` Provider: ${payload.provider}`);
console.error(` Archetype: ${payload.archetype}`);
console.error(` Reason: ${payload.reason}`);
console.error(` Original cause:`, error.cause);
}
}
Properties:
message- Error descriptioncode- "MAILCRAFT_SEND_ERROR"archetype- The archetype that failed to sendprovider- The provider that failed (e.g., "resend")payload- Structured error information with provider, archetype, reason, and optional codecause- Original error from the provider
Error Recovery Pattern
try {
await mailcraft.send(archetype, input, adapter);
} catch (error) {
if (error instanceof MailcraftValidationError) {
// Fix input data and retry
console.error("Invalid input:", error.message);
} else if (error instanceof MailcraftRenderError) {
// Template rendering issue - may be provider/SDK bug
console.error("Rendering failed:", error.message);
} else if (error instanceof MailcraftSendError) {
// Provider-specific issue (quota, auth, network, etc.)
console.error(`${error.provider} failed: ${error.payload.reason}`);
// Implement retry logic
}
}