Skip to main content

Transactional Emails

Transactional emails are triggered programmatically for individual users—order confirmations, password resets, account notifications, and other time-sensitive communications.

Transactional vs Marketing

TransactionalMarketing
Triggered by user actionSent to segments
One recipient at a timeMultiple recipients
Time-sensitiveCan be scheduled
Expected by userPromotional
Higher deliverabilityMay be filtered
Examples of transactional emails:
  • Order confirmation
  • Shipping notification
  • Password reset
  • Account verification
  • Payment receipt
  • Security alert

Two Sending Modes

Create reusable templates in the dashboard, send via API using the template slug.
curl -X POST "https://api.sequenzy.com/api/v1/transactional/send" \
  -H "Authorization: Bearer YOUR_API_KEY" \
  -H "Content-Type: application/json" \
  -d '{
    "to": "[email protected]",
    "slug": "order-confirmation",
    "variables": {
      "orderNumber": "ORD-12345",
      "total": "$99.99",
      "deliveryDate": "January 20, 2024"
    }
  }'
Benefits:
  • Non-developers can edit templates
  • Consistent branding
  • Version control in dashboard
  • Analytics per template

2. Direct Mode

Send email content directly without a pre-created template.
curl -X POST "https://api.sequenzy.com/api/v1/transactional/send" \
  -H "Authorization: Bearer YOUR_API_KEY" \
  -H "Content-Type: application/json" \
  -d '{
    "to": "[email protected]",
    "subject": "Your Order #{{orderNumber}}",
    "body": "<h1>Thank you for your order!</h1><p>Order: {{orderNumber}}</p>",
    "variables": {
      "orderNumber": "ORD-12345"
    }
  }'
Use cases:
  • Dynamic content generated by your app
  • One-off emails that don’t need templates
  • Testing and development

Creating Templates

In the Dashboard

  1. Go to Transactional in your dashboard
  2. Click Create Template
  3. Enter a slug (URL-friendly identifier)
  4. Design your email with the visual editor
  5. Add variable placeholders where needed
  6. Save and activate

Template Slugs

Slugs are unique identifiers for your templates:
order-confirmation
password-reset
welcome-email
invoice-reminder
shipping-update
Slugs are auto-generated from the template name but can be customized. They cannot be changed after creation.

Variables

Variables let you personalize transactional emails.

Syntax

<p>Hello {{FIRST_NAME}},</p>
<p>Your order {{orderNumber}} has shipped!</p>

With Defaults

Provide fallback values for missing variables:
<p>Hello {{FIRST_NAME|Customer}},</p>
If FIRST_NAME is empty, “Customer” is used.

System Variables

These are automatically available:
VariableSource
{{NAME}}Subscriber full name
{{FIRST_NAME}}Subscriber first name
{{LAST_NAME}}Subscriber last name
{{EMAIL}}Subscriber email

Custom Attributes

Any subscriber custom attributes are available:
<p>Your plan: {{plan}}</p>
<p>Account ID: {{userId}}</p>

Passed Variables

Variables passed in the API request:
{
  "variables": {
    "orderNumber": "ORD-123",
    "total": "$99.99"
  }
}
<p>Order: {{orderNumber}}</p>
<p>Total: {{total}}</p>

API Reference

Send Email

POST /api/v1/transactional/send
Template mode:
{
  "to": "[email protected]",
  "slug": "template-slug",
  "variables": {
    "key": "value"
  }
}
Direct mode:
{
  "to": "[email protected]",
  "subject": "Email Subject",
  "body": "<html>Email content</html>",
  "variables": {
    "key": "value"
  }
}
Response:
{
  "success": true,
  "data": {
    "jobId": "job_abc123",
    "email": "[email protected]"
  }
}

List Templates

GET /api/v1/transactional
Response:
{
  "success": true,
  "data": [
    {
      "id": "trans_abc123",
      "slug": "order-confirmation",
      "name": "Order Confirmation",
      "subject": "Your Order #{{orderNumber}}",
      "enabled": true
    }
  ]
}

Get Template Details

GET /api/v1/transactional/:slug
Response:
{
  "success": true,
  "data": {
    "id": "trans_abc123",
    "slug": "order-confirmation",
    "name": "Order Confirmation",
    "subject": "Your Order #{{orderNumber}}",
    "body": "<html>...</html>",
    "enabled": true,
    "variables": ["orderNumber", "total", "items"]
  }
}

Auto-Creation

When you send to an email that doesn’t exist:
  1. A new subscriber is created automatically
  2. Status is set to active
  3. Custom attributes from variables are saved (if applicable)
This makes integration seamless—no need to create subscribers first.

Error Handling

Common Errors

ErrorCauseSolution
Template not foundInvalid slugCheck slug spelling
Template disabledTemplate is deactivatedEnable in dashboard
Missing required fieldsNo to, slug/subjectInclude required fields
Missing variablesTemplate has unfilled variablesPass all required variables
No sender configuredNo sender profileSet up sender in dashboard
Sending pausedAccount sending is pausedCheck sending status

Response Codes

CodeDescription
200Email queued successfully
400Validation error
401Invalid API key
404Template not found
500Server error

Best Practices

1. Use Templates

Templates are easier to maintain and update:
✓ Template: Update once, affects all future sends
✗ Direct: Must update every code path that sends email

2. Handle Variables Gracefully

Always provide defaults or check for required variables:
<!-- Good: Has default -->
<p>Hi {{FIRST_NAME|there}},</p>

<!-- Better: Check in template -->
{{#if firstName}}
<p>Hi {{firstName}},</p>
{{else}}
<p>Hi there,</p>
{{/if}}

3. Log Job IDs

Save the returned job ID for debugging:
const response = await sendTransactional({
  to: user.email,
  slug: "order-confirmation",
  variables: { orderNumber: order.id },
});

await saveToDatabase({
  orderId: order.id,
  emailJobId: response.data.jobId,
});

4. Use Meaningful Slugs

✓ "order-confirmation"
✓ "password-reset"
✓ "trial-expiring-reminder"

✗ "email1"
✗ "template_2024_01"

5. Test in Development

Use test emails before production:
const to =
  process.env.NODE_ENV === "development"
    ? "[email protected]"
    : user.email;

Integration Examples

Order Confirmation

async function sendOrderConfirmation(order) {
  await fetch("https://api.sequenzy.com/api/v1/transactional/send", {
    method: "POST",
    headers: {
      Authorization: `Bearer ${process.env.SEQUENZY_API_KEY}`,
      "Content-Type": "application/json",
    },
    body: JSON.stringify({
      to: order.customerEmail,
      slug: "order-confirmation",
      variables: {
        orderNumber: order.id,
        total: formatCurrency(order.total),
        items: order.items.map((i) => i.name).join(", "),
        shippingAddress: formatAddress(order.shippingAddress),
        estimatedDelivery: formatDate(order.estimatedDelivery),
      },
    }),
  });
}

Password Reset

async function sendPasswordReset(email, resetToken) {
  const resetUrl = `${APP_URL}/reset-password?token=${resetToken}`;

  await fetch("https://api.sequenzy.com/api/v1/transactional/send", {
    method: "POST",
    headers: {
      Authorization: `Bearer ${process.env.SEQUENZY_API_KEY}`,
      "Content-Type": "application/json",
    },
    body: JSON.stringify({
      to: email,
      slug: "password-reset",
      variables: {
        resetUrl,
        expiresIn: "24 hours",
      },
    }),
  });
}

Welcome Email

async function sendWelcome(user) {
  await fetch("https://api.sequenzy.com/api/v1/transactional/send", {
    method: "POST",
    headers: {
      Authorization: `Bearer ${process.env.SEQUENZY_API_KEY}`,
      "Content-Type": "application/json",
    },
    body: JSON.stringify({
      to: user.email,
      slug: "welcome",
      variables: {
        firstName: user.firstName,
        dashboardUrl: `${APP_URL}/dashboard`,
        docsUrl: `${APP_URL}/docs`,
      },
    }),
  });
}