Skip to main content
Email templates allow you to create reusable email designs with dynamic variables that can be populated at send time.

Quick Start

Here’s how to create a template and send an email using it:
package main

import (
	"context"
	"fmt"
	"os"

	"github.com/resend/resend-go/v3"
)

func main() {
	ctx := context.Background()
	apiKey := os.Getenv("RESEND_API_KEY")

	client := resend.NewClient(apiKey)

	// Create a template
	template, err := client.Templates.Create(&resend.CreateTemplateRequest{
		Name:    "welcome-email",
		Alias:   "welcome",
		Subject: "Welcome {{{userName}}}!",
		Html:    "<h1>Hello {{{userName}}}!</h1><p>Welcome to {{{companyName}}}.</p>",
		Variables: []*resend.TemplateVariable{
			{
				Key:           "userName",
				Type:          resend.VariableTypeString,
				FallbackValue: "User",
			},
			{
				Key:           "companyName",
				Type:          resend.VariableTypeString,
				FallbackValue: "Our Company",
			},
		},
	})
	if err != nil {
		panic(err)
	}

	// Publish the template
	_, err = client.Templates.Publish(template.Id)
	if err != nil {
		panic(err)
	}

	// Send email using the template
	sent, err := client.Emails.Send(&resend.SendEmailRequest{
		To: []string{"[email protected]"},
		Template: &resend.EmailTemplate{
			Id: template.Id,
			Variables: map[string]any{
				"userName":    "Alice Johnson",
				"companyName": "Acme Corp",
			},
		},
	})
	if err != nil {
		panic(err)
	}

	fmt.Printf("Email sent: %s\n", sent.Id)
}

EmailTemplate Struct

When sending emails with templates, use the EmailTemplate struct:
id
string
required
The template ID or alias to use for this email.
variables
map[string]any
Key-value pairs to populate the template placeholders. Values can be strings, numbers, or other JSON-serializable types.
Source: emails.go:17

Creating Templates

Basic Template Creation

ctx := context.Background()

templateParams := &resend.CreateTemplateRequest{
	Name:    "user-welcome-template",
	Alias:   "welcome",
	From:    "[email protected]",
	Subject: "Welcome to {{{companyName}}}, {{{userName}}}!",
	Html: `
		<html>
			<body>
				<h1>Hello {{{userName}}}!</h1>
				<p>Welcome to {{{companyName}}}. We're excited to have you on board.</p>
				<p>You currently have {{{messageCount}}} unread messages waiting for you.</p>
			</body>
		</html>
	`,
	Text: "Hello {{{userName}}}! Welcome to {{{companyName}}}.",
	Variables: []*resend.TemplateVariable{
		{
			Key:           "userName",
			Type:          resend.VariableTypeString,
			FallbackValue: "User",
		},
		{
			Key:           "companyName",
			Type:          resend.VariableTypeString,
			FallbackValue: "Our Company",
		},
		{
			Key:           "messageCount",
			Type:          resend.VariableTypeNumber,
			FallbackValue: 0,
		},
	},
}

template, err := client.Templates.CreateWithContext(ctx, templateParams)
if err != nil {
	panic(err)
}

fmt.Printf("Created template: %s\n", template.Id)
Source: examples/send_email_with_template.go:17

CreateTemplateRequest Fields

name
string
required
The name of the template.
alias
string
A unique alias for the template. Use this to reference the template instead of its ID.
from
string
Default sender email address for this template.
subject
string
Default subject line. Can include template variables like {{{variableName}}}.
replyTo
any
Default reply-to address. Can be a string or array of strings.
html
string
required
HTML content with template variables. Use triple braces {{{variableName}}} for variables.
text
string
Plain text version with template variables.
variables
[]*TemplateVariable
Array of variable definitions used in the template.
All variables referenced in Html or Subject (e.g., {{{userName}}}) must be declared in the Variables array, or the API will return a validation error.
Source: templates.go:28

Template Variables

Each variable in a template must be defined with the TemplateVariable struct:
key
string
required
The variable name (without braces). Must match the placeholder in HTML/subject.
type
VariableType
required
Variable type: VariableTypeString or VariableTypeNumber.
fallbackValue
any
Default value used if no value is provided when sending the email.
Source: templates.go:19

Variable Types

{
    Key:           "userName",
    Type:          resend.VariableTypeString,
    FallbackValue: "Guest",
}
Use for: names, email addresses, text content, URLs

Publishing Templates

Templates must be published before they can be used:
ctx := context.Background()

// Publish by template ID
publishResp, err := client.Templates.PublishWithContext(ctx, template.Id)
if err != nil {
	panic(err)
}

fmt.Printf("Published template: %s\n", publishResp.Id)
Only published templates can be used to send emails. Unpublished templates are in draft state.
Source: examples/send_email_with_template.go:58

Sending Emails with Templates

Using Template ID

ctx := context.Background()

emailParams := &resend.SendEmailRequest{
	To: []string{"[email protected]"},
	Template: &resend.EmailTemplate{
		Id: "3a76bde0-8f64-4b48-a92f-5f650cc0319d",
		Variables: map[string]any{
			"userName":     "Alice Johnson",
			"companyName":  "Acme Corporation",
			"messageCount": 12,
		},
	},
}

sent, err := client.Emails.SendWithContext(ctx, emailParams)
if err != nil {
	panic(err)
}

fmt.Printf("Sent email: %s\n", sent.Id)
Source: examples/send_email_with_template.go:65

Using Template Alias

You can use the template’s alias instead of its ID:
emailParams := &resend.SendEmailRequest{
	To: []string{"[email protected]"},
	Template: &resend.EmailTemplate{
		Id: "welcome", // Using alias instead of ID
		Variables: map[string]any{
			"userName":     "Bob Smith",
			"companyName":  "Tech Startup Inc",
			"messageCount": 3,
		},
	},
}

sent, err := client.Emails.Send(emailParams)
Using aliases makes your code more maintainable since you don’t need to update IDs when recreating templates.
Source: examples/send_email_with_template.go:84

Overriding Template Fields

You can override template defaults when sending:
emailParams := &resend.SendEmailRequest{
	From:    "[email protected]",         // Override template's From
	To:      []string{"[email protected]"},
	Subject: "Custom Subject Override",     // Override template's Subject
	Bcc:     []string{"[email protected]"},
	ReplyTo: "[email protected]",
	Template: &resend.EmailTemplate{
		Id: template.Id,
		Variables: map[string]any{
			"userName":     "Charlie Brown",
			"companyName":  "Example LLC",
			"messageCount": 7,
		},
	},
}

sent, err := client.Emails.Send(emailParams)
Source: examples/send_email_with_template.go:103
Fields specified in SendEmailRequest take precedence over template defaults.

Managing Templates

Retrieving a Template

ctx := context.Background()

// Get by ID
template, err := client.Templates.GetWithContext(ctx, "3a76bde0-8f64-4b48-a92f-5f650cc0319d")
if err != nil {
	panic(err)
}

// Or get by alias
template, err = client.Templates.Get("welcome")
if err != nil {
	panic(err)
}

fmt.Printf("Template: %s (Status: %s)\n", template.Name, template.Status)
fmt.Printf("Variables: %d\n", len(template.Variables))

Listing Templates

ctx := context.Background()

// List all templates
listResp, err := client.Templates.ListWithContext(ctx, nil)
if err != nil {
	panic(err)
}

fmt.Printf("Found %d templates\n", len(listResp.Data))
for _, tmpl := range listResp.Data {
	fmt.Printf("- %s (alias: %s, status: %s)\n", tmpl.Name, tmpl.Alias, tmpl.Status)
}

// List with pagination
limit := 10
paginatedResp, err := client.Templates.List(&resend.ListOptions{
	Limit: &limit,
})

Updating a Template

ctx := context.Background()

updateParams := &resend.UpdateTemplateRequest{
	Name:    "Updated Welcome Template",
	Subject: "Welcome {{{userName}}} to {{{companyName}}}!",
	Html:    "<h1>Hello {{{userName}}}!</h1><p>Updated content</p>",
	Variables: []*resend.TemplateVariable{
		{
			Key:           "userName",
			Type:          resend.VariableTypeString,
			FallbackValue: "User",
		},
		{
			Key:           "companyName",
			Type:          resend.VariableTypeString,
			FallbackValue: "Our Company",
		},
	},
}

updated, err := client.Templates.UpdateWithContext(ctx, "welcome", updateParams)
if err != nil {
	panic(err)
}

fmt.Printf("Updated template: %s\n", updated.Id)
After updating a template, you must publish it again for changes to take effect in sent emails.

Duplicating a Template

ctx := context.Background()

duplicateResp, err := client.Templates.DuplicateWithContext(ctx, "welcome")
if err != nil {
	panic(err)
}

fmt.Printf("Duplicated template ID: %s\n", duplicateResp.Id)

Deleting a Template

ctx := context.Background()

removeResp, err := client.Templates.RemoveWithContext(ctx, template.Id)
if err != nil {
	panic(err)
}

if removeResp.Deleted {
	fmt.Printf("Deleted template: %s\n", removeResp.Id)
}
Source: examples/send_email_with_template.go:126

Common Use Cases

templateParams := &resend.CreateTemplateRequest{
    Name:    "welcome-email",
    Alias:   "welcome",
    Subject: "Welcome to {{{appName}}}, {{{userName}}}!",
    Html: `
        <h1>Welcome {{{userName}}}!</h1>
        <p>Thanks for joining {{{appName}}}.</p>
        <p>Get started by <a href="{{{loginUrl}}}">logging in</a>.</p>
    `,
    Variables: []*resend.TemplateVariable{
        {Key: "userName", Type: resend.VariableTypeString, FallbackValue: "there"},
        {Key: "appName", Type: resend.VariableTypeString, FallbackValue: "our app"},
        {Key: "loginUrl", Type: resend.VariableTypeString},
    },
}
templateParams := &resend.CreateTemplateRequest{
    Name:    "order-confirmation",
    Alias:   "order-confirmed",
    Subject: "Order #{{{orderNumber}}} Confirmed",
    Html: `
        <h1>Thank you for your order!</h1>
        <p>Order Number: {{{orderNumber}}}</p>
        <p>Total: ${{{orderTotal}}}</p>
        <p>Items: {{{itemCount}}}</p>
        <p><a href="{{{trackingUrl}}}">Track your order</a></p>
    `,
    Variables: []*resend.TemplateVariable{
        {Key: "orderNumber", Type: resend.VariableTypeString},
        {Key: "orderTotal", Type: resend.VariableTypeNumber},
        {Key: "itemCount", Type: resend.VariableTypeNumber},
        {Key: "trackingUrl", Type: resend.VariableTypeString},
    },
}
templateParams := &resend.CreateTemplateRequest{
    Name:    "password-reset",
    Alias:   "reset-password",
    Subject: "Reset your password",
    Html: `
        <h1>Password Reset Request</h1>
        <p>Hi {{{userName}}},</p>
        <p>Click the link below to reset your password:</p>
        <p><a href="{{{resetUrl}}}">Reset Password</a></p>
        <p>This link expires in {{{expiryMinutes}}} minutes.</p>
    `,
    Variables: []*resend.TemplateVariable{
        {Key: "userName", Type: resend.VariableTypeString},
        {Key: "resetUrl", Type: resend.VariableTypeString},
        {Key: "expiryMinutes", Type: resend.VariableTypeNumber, FallbackValue: 60},
    },
}

Best Practices

1

Declare All Variables

Always declare variables in the Variables array before using them in HTML:
// ✅ Correct - variable is declared
Html: "<p>Hello {{{userName}}}</p>",
Variables: []*resend.TemplateVariable{
    {Key: "userName", Type: resend.VariableTypeString},
}

// ❌ Wrong - will cause validation error
Html: "<p>Hello {{{userName}}}</p>",
Variables: []*resend.TemplateVariable{},
2

Use Aliases for Stability

Use template aliases instead of IDs for better code maintainability:
Template: &resend.EmailTemplate{
    Id: "welcome", // Use alias, not "3a76bde0-8f64-4b48-a92f-5f650cc0319d"
    Variables: map[string]any{...},
}
3

Provide Fallback Values

Always provide sensible fallback values for optional variables:
{
    Key:           "userName",
    Type:          resend.VariableTypeString,
    FallbackValue: "Valued Customer", // Good default
}
4

Use Triple Braces

Use triple braces {{{variable}}} for template variables to prevent HTML escaping:
Html: "<h1>Hello {{{userName}}}!</h1>" // Correct
// Not: "<h1>Hello {{userName}}!</h1>" // Wrong
5

Publish After Updates

Remember to publish templates after creating or updating them:
template, _ := client.Templates.Create(params)
client.Templates.Publish(template.Id) // Required!

Next Steps

Sending Emails

Learn the basics of sending emails

Attachments

Add attachments to template emails

Batch Emails

Send templated emails in bulk

Scheduled Emails

Schedule template emails for later

Build docs developers (and LLMs) love