Email Templates API

Notify's template system lets you define reusable, structured email templates that support dynamic content through variables. This guide, specifically, explains how to create and manage templates using our API if you'd rather not use the drag-and-drop editor.


Template Structure

A template object consists of the following fields:

  • Label: A unique identifier used to reference the template (e.g., welcome-email)
  • Subject: The subject line of the email
  • Blocks: An array of content blocks (e.g., headers, paragraphs, buttons) that make up the email body
  • Variables: Dynamic placeholders (e.g., {name}) that are replaced with recipient-specific values at send time

Creating Templates via API


curl -X POST https://notify.cx/api/public/v1/templates \
  -H "Content-Type: application/json" \
  -H "x-api-key: your_api_key" \
  -d '{
    "label": "welcome-email",
    "subject": "Welcome to our service!",
    "blocks": [
      {
        "type": "header",
        "content": "Welcome, {name}!"
      },
      {
        "type": "paragraph",
        "content": "We're excited to have you join us. Your account is now active."
      },
      {
        "type": "button",
        "content": "Visit Dashboard",
        "style": {
          "color": "#ffffff",
          "backgroundColor": "#007bff",
          "href": "https://example.com/dashboard"
        }
      }
    ]
  }'
// Using fetch
const response = await fetch('https://notify.cx/api/public/v1/templates', {
  method: 'POST',
  headers: {
    'Content-Type': 'application/json',
    'x-api-key': 'your_api_key'
  },
  body: JSON.stringify({
    label: 'welcome-email',
    subject: 'Welcome to our service!',
    blocks: [
      {
        type: 'header',
        content: 'Welcome, {name}!'
      },
      {
        type: 'paragraph',
        content: 'We\'re excited to have you join us. Your account is now active.'
      },
      {
        type: 'button',
        content: 'Visit Dashboard',
        style: {
          color: '#ffffff',
          backgroundColor: '#007bff',
          href: 'https://example.com/dashboard'
        }
      }
    ]
  })
});

const data = await response.json();
console.log(data);

Block Types

Templates support various content block types:

Block TypeDescription
headerLarge, prominent text for headings
subheaderSmaller heading text
paragraphStandard text block
buttonClickable button with custom styling
imageImage with optional alt text
dividerHorizontal line separator
spacerVertical space between blocks
codeFormatted code block
quoteStyled quotation

Block Type Structures

Each block type has a specific structure:

Header (mainHeading)
{
  "type": "mainHeading",
  "content": "Compelling headline here."
}
Subheader (subHeading)
{
  "type": "subHeading",
  "content": "A brief, engaging subheading for more context"
}
Paragraph
{
  "type": "paragraph",
  "content": {
    "text": "Start writing your email content here. This is a placeholder text to help you get started. You can edit or delete this paragraph as needed. Use this space to communicate your message clearly, whether it's a product update, a welcome note, or an important notification.",
    "inlineLinks": [
      {
        "text": "Use this space to communicate",
        "url": "https://example.com",
        "startIndex": 140,
        "endIndex": 169
      }
    ]
  }
}

inlineLinks allows hyperlinking specific ranges within the paragraph text, defined by character indexes. The original text remains unmodified, and links are applied during rendering.

Image
{
  "type": "image",
  "content": {
    "url": "https://example.com/image.jpg",
    "alt": "Sample image description"
  }
}
Button/CTA
{
  "type": "cta",
  "content": {
    "text": "Call to Action",
    "url": "https://example.com"
  }
}
List
{
  "type": "list",
  "content": [
    { "text": "Bullet Point 1", "inlineLinks": [] },
    { "text": "Bullet Point 2", "inlineLinks": [] },
    { "text": "Bullet Point 3", "inlineLinks": [] }
  ]
}
Quote
{
  "type": "quote",
  "content": "This is a quote."
}
Divider
{
  "type": "divider",
  "content": ""
}
Footer
{
  "type": "footer",
  "content": "Best regards,\n{company_name}\n\nHave questions? Contact us at {contact_email}."
}
Code Snippet
{
  "type": "codeSnippet",
  "content": "function example() {\n  return 'Hello world';\n}"
}
Hyperlink
{
  "type": "hyperlink",
  "content": {
    "text": "Visit our website",
    "url": "https://example.com"
  }
}
Link Hub
{
  "type": "linkHub",
  "content": {
    "label1": "FAQ",
    "link1": "https://example.com/faq",
    "label2": "Preferences",
    "link2": "https://example.com/preferences",
    "label3": "Privacy Policy",
    "link3": "https://example.com/privacy"
  }
}
Social Links
{
  "type": "socials",
  "content": {
    "twitter": "https://twitter.com/example",
    "linkedin": "https://linkedin.com/in/example",
    "github": "https://github.com/example",
    "instagram": "https://instagram.com/example"
  }
}
YouTube Embed
{
  "type": "youtube",
  "content": {
    "title": "Sample Video",
    "url": "https://www.youtube.com/watch?v=dQw4w9WgXcQ"
  }
}

Composite Block Types

You can also create composite blocks that combine multiple elements:

CTA with Text
{
  "type": "cta-with-text",
  "content": {
    "text": "Nulla neque dolor, sagittis eget, iaculis quis, molestie non, velit.",
    "label": "Your Link Here",
    "url": "https://example.com"
  }
}

Variables

Variables are specified using curly braces: {variable_name}. When you send an email using a template, you'll provide values for these variables.

Retrieving Templates


List All Templates

curl -X GET https://notify.cx/api/public/v1/templates \
  -H "x-api-key: your_api_key"
// Using fetch
const response = await fetch('https://notify.cx/api/public/v1/templates', {
  method: 'GET',
  headers: {
    'x-api-key': 'your_api_key'
  }
});

const data = await response.json();
console.log(data);

You can add pagination parameters:

  • ?page=2 (default: 1)
  • ?limit=50 (default: 20, max: 100)

Get Template by ID

curl -X GET https://notify.cx/api/public/v1/templates/template_id \
  -H "x-api-key: your_api_key"
// Using fetch
const response = await fetch('https://notify.cx/api/public/v1/templates/template_id', {
  method: 'GET',
  headers: {
    'x-api-key': 'your_api_key'
  }
});

const data = await response.json();
console.log(data);

Get Template by Label

curl -X GET https://notify.cx/api/public/v1/templates/by-label/welcome-email \
  -H "x-api-key: your_api_key"
// Using fetch
const response = await fetch('https://notify.cx/api/public/v1/templates/by-label/welcome-email', {
  method: 'GET',
  headers: {
    'x-api-key': 'your_api_key'
  }
});

const data = await response.json();
console.log(data);

Render Template Preview


You can retrieve a rendered HTML preview of a template by adding the render=true parameter to the GET request.

curl -X GET https://notify.cx/api/public/v1/templates/template_id?render=true \
  -H "x-api-key: your_api_key"
// Using fetch
const response = await fetch('https://notify.cx/api/public/v1/templates/template_id?render=true', {
  method: 'GET',
  headers: {
    'x-api-key': 'your_api_key'
  }
});

const data = await response.json();
console.log(data);

Or by label:

curl -X GET https://notify.cx/api/public/v1/templates/by-label/welcome-email?render=true \
  -H "x-api-key: your_api_key"
// Using fetch
const response = await fetch('https://notify.cx/api/public/v1/templates/by-label/welcome-email?render=true', {
  method: 'GET',
  headers: {
    'x-api-key': 'your_api_key'
  }
});

const data = await response.json();
console.log(data);

Updating Templates


Update Template by ID

curl -X PUT https://notify.cx/api/public/v1/templates/template_id \
  -H "Content-Type: application/json" \
  -H "x-api-key: your_api_key" \
  -d '{
    "subject": "Updated Subject Line",
    "blocks": [
      {
        "type": "header",
        "content": "Updated Header Content"
      },
      {
        "type": "paragraph",
        "content": "Updated paragraph content with {variable}."
      }
    ]
  }'
// Using fetch
const response = await fetch('https://notify.cx/api/public/v1/templates/template_id', {
  method: 'PUT',
  headers: {
    'Content-Type': 'application/json',
    'x-api-key': 'your_api_key'
  },
  body: JSON.stringify({
    subject: 'Updated Subject Line',
    blocks: [
      {
        type: 'header',
        content: 'Updated Header Content'
      },
      {
        type: 'paragraph',
        content: 'Updated paragraph content with {variable}.'
      }
    ]
  })
});

const data = await response.json();
console.log(data);

Update Template by Label

curl -X PUT https://notify.cx/api/public/v1/templates/by-label/welcome-email \
  -H "Content-Type: application/json" \
  -H "x-api-key: your_api_key" \
  -d '{
    "subject": "Updated Subject Line",
    "blocks": [
      {
        "type": "header",
        "content": "Updated Header Content"
      },
      {
        "type": "paragraph",
        "content": "Updated paragraph content with {variable}."
      }
    ]
  }'
// Using fetch
const response = await fetch('https://notify.cx/api/public/v1/templates/by-label/welcome-email', {
  method: 'PUT',
  headers: {
    'Content-Type': 'application/json',
    'x-api-key': 'your_api_key'
  },
  body: JSON.stringify({
    subject: 'Updated Subject Line',
    blocks: [
      {
        type: 'header',
        content: 'Updated Header Content'
      },
      {
        type: 'paragraph',
        content: 'Updated paragraph content with {variable}.'
      }
    ]
  })
});

const data = await response.json();
console.log(data);

When updating a template, you only need to include the fields you want to change. The label cannot be changed via the update endpoints.

Deleting Templates


Delete Template by ID

curl -X DELETE https://notify.cx/api/public/v1/templates/template_id \
  -H "x-api-key: your_api_key"
// Using fetch
const response = await fetch('https://notify.cx/api/public/v1/templates/template_id', {
  method: 'DELETE',
  headers: {
    'x-api-key': 'your_api_key'
  }
});

const data = await response.json();
console.log(data);

Delete Template by Label

curl -X DELETE https://notify.cx/api/public/v1/templates/by-label/welcome-email \
  -H "x-api-key: your_api_key"
// Using fetch
const response = await fetch('https://notify.cx/api/public/v1/templates/by-label/welcome-email', {
  method: 'DELETE',
  headers: {
    'x-api-key': 'your_api_key'
  }
});

const data = await response.json();
console.log(data);

Response Structure


All API endpoints return responses in a consistent format:

Success Response

{
  "success": true,
  "data": {
    // Endpoint-specific data
  },
  "meta": {
    // Optional metadata (e.g., pagination info)
  }
}

Error Response

{
  "success": false,
  "error": "Human-readable error message",
  "code": "ERROR_CODE"
}

Common error codes:

Error CodeDescription
API_KEY_MISSINGAPI key not provided in request header
INVALID_API_KEYThe provided API key is invalid or revoked
TEMPLATE_NOT_FOUNDThe requested template does not exist
INVALID_REQUEST_DATAThe request body contains invalid data
DUPLICATE_LABELA template with the provided label already exists

Template Best Practices

  1. Use meaningful labels that describe the template's purpose
  2. Document your variables to make it easier for team members to use templates
  3. Test templates with different variable values to ensure they render correctly
  4. Group related templates with consistent naming conventions

Next Steps