Skip to content

Templates

Create reusable email templates with variable substitution. Templates support HTML content with {{variable}} placeholders that are replaced at send time.

POST
/templates

Create a new email template. Templates start in draft status.

json
{
  "name": "Welcome Email",
  "subject": "Welcome to {{company_name}}, {{first_name}}!",
  "html": "<h1>Hello {{first_name}},</h1><p>Welcome to {{company_name}}.</p>",
  "text": "Hello {{first_name}}, Welcome to {{company_name}}.",
  "variables": ["first_name", "company_name"]
}
GET
/templates

List all templates with pagination.

json
{
  "templates": [
    {
      "id": "tpl_abc123def456ghi789",
      "name": "Welcome Email",
      "status": "published",
      "created_at": "2026-03-23T10:00:00.000Z",
      "updated_at": "2026-03-23T12:00:00.000Z"
    }
  ],
  "pagination": {
    "total": 12,
    "page": 1,
    "per_page": 20,
    "total_pages": 1
  }
}
GET
/templates/:id

Retrieve a single template including its full HTML content and variable list.

json
{
  "id": "tpl_abc123def456ghi789",
  "name": "Welcome Email",
  "subject": "Welcome to {{company_name}}, {{first_name}}!",
  "html": "<h1>Hello {{first_name}},</h1><p>Welcome to {{company_name}}.</p>",
  "text": "Hello {{first_name}}, Welcome to {{company_name}}.",
  "status": "published",
  "variables": ["first_name", "company_name"],
  "created_at": "2026-03-23T10:00:00.000Z",
  "updated_at": "2026-03-23T12:00:00.000Z"
}
PATCH
/templates/:id

Update a template. Published templates create a new version.

json
{
  "name": "Welcome Email v2",
  "html": "<h1>Hi {{first_name}}!</h1><p>Thanks for joining {{company_name}}.</p>"
}
DELETE
/templates/:id

Delete a template. This does not affect emails already sent using this template.

json
{
  "deleted": true
}
POST
/templates/:id/publish

Publish a draft template, making it available for sending.

json
{
  "id": "tpl_abc123def456ghi789",
  "status": "published",
  "published_at": "2026-03-23T15:00:00.000Z"
}
POST
/templates/:id/unpublish

Revert a published template back to draft status.

json
{
  "id": "tpl_abc123def456ghi789",
  "status": "draft"
}
POST
/templates/:id/duplicate

Create a copy of an existing template. The duplicate starts in draft status with '(Copy)' appended to the name.

json
{
  "id": "tpl_new_copy_456ghi789",
  "name": "Welcome Email (Copy)",
  "status": "draft",
  "created_at": "2026-03-23T16:00:00.000Z"
}
GET
/templates/presets

List available template presets from the gallery. Presets are pre-built templates you can use as a starting point.

json
{
  "presets": [
    {
      "id": 1,
      "name": "Welcome Email",
      "description": "A clean welcome email with logo and CTA",
      "subject": "Welcome!",
      "html": "<h1>Welcome</h1>...",
      "text": "Welcome..."
    },
    {
      "id": 2,
      "name": "Newsletter",
      "description": "Multi-section newsletter layout",
      "subject": "Your Weekly Update",
      "html": "<h1>Newsletter</h1>...",
      "text": "Newsletter..."
    }
  ]
}
POST
/templates/presets/:presetId/use

Create a new template from a preset. The template starts in draft status with the preset's content.

json
{
  "id": "tpl_new_from_preset",
  "name": "Welcome Email",
  "subject": "Welcome!",
  "status": "draft",
  "created_at": "2026-03-23T16:00:00.000Z"
}

Using Templates with Emails

Reference a published template by ID when sending an email. Provide the variable values to populate the placeholders:

typescript
await poststack.emails.send({
  from: 'you@yourdomain.com',
  to: ['alice@example.com'],
  template_id: 'tpl_abc123def456ghi789',
  variables: {
    first_name: 'Alice',
    company_name: 'Acme Inc',
  },
});
json
{
  "from": "you@yourdomain.com",
  "to": ["alice@example.com"],
  "template_id": "tpl_abc123def456ghi789",
  "variables": {
    "first_name": "Alice",
    "company_name": "Acme Inc"
  }
}

Conditional Blocks

Templates support flat conditional blocks for inclusion or exclusion of content based on whether a variable is truthy. Useful for optional greetings, footer lines that only appear for certain audiences, or fallback copy when a value is missing:

html
{{#if first_name}}Hi {{first_name}},{{/if}}
{{#unless first_name}}Hi there,{{/unless}}

Welcome to {{company_name}}.

{{#if support_url}}Need help? Visit {{support_url}}.{{/if}}

A variable counts as truthy when present and not the empty string, "0", or "false". Conditionals do not nest in this pass — flat use covers the common cases (greet when known, fall back when unknown, hide CTAs that lack a URL). Conditionals are evaluated before variable substitution, so the inner content can reference the same variables.

Visual Template Builder

The dashboard includes a block-based visual editor as an alternative to hand-written HTML. When you choose Visual Builder at create time, you compose the email from typed blocks — heading, paragraph, button, image, divider — and PostStack renders them to the final HTML on save. The underlying builder_blocks JSON is stored alongside the compiled HTML so the editor can round-trip without lossy re-parsing. Variable placeholders ({{first_name}}) pass through any block's text content untouched and are substituted at send time.

You can switch a template between builder_type "html" and "visual", but going visual → html is one-way: editing the HTML directly discards the block tree. Publish bumps the version; renaming does not.

React Email Components

PostStack does not run a React renderer server-side. If you author your emails as React components (for example via react-email), render to HTML at build time or in your application before sending. The TS SDK accepts plain HTML on the html field — bring your own renderer:

typescript
import { render } from '@react-email/render';
import { WelcomeEmail } from './emails/welcome';

const html = render(<WelcomeEmail name="Alice" />);

await poststack.emails.send({
  from: 'you@yourdomain.com',
  to: ['alice@example.com'],
  subject: 'Welcome',
  html,
});

This pattern keeps PostStack's surface small and the SDK runtime fast — the React renderer stays in your application's deployment, not in the email pipeline.