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 addresses
  • subject - Email subject line
  • html - Full HTML email body
  • text - 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 accepted
  • metadata - 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 archetype
  • input - Typed input data for the archetype
  • options - 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 archetype
  • input - Typed input data for the archetype
  • adapter - 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 addresses
  • subject?: 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 display
  • link - 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 headline
  • body - Email content
  • cta - 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 identifier
  • currency - Currency code (e.g., "USD", "EUR")
  • total - Total amount as string
  • items - 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 headline
  • body - Announcement details
  • cta - 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 name
  • sender.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 color
  • visual.stylePreset - Visual style: "modern", "classic", or "minimal"
  • sender.fromName - Display name for sender
  • sender.replyTo - Reply-to address
  • footer.supportEmail - Support contact email
  • footer.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 to RESEND_API_KEY env 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 to AWS_REGION env 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 description
  • code - "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 description
  • code - "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 description
  • code - "MAILCRAFT_SEND_ERROR"
  • archetype - The archetype that failed to send
  • provider - The provider that failed (e.g., "resend")
  • payload - Structured error information with provider, archetype, reason, and optional code
  • cause - 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
  }
}

See Also