Skip to main content
The Resend Go SDK provides multiple methods for sending emails with support for text, HTML, headers, tags, and more.

Quick Start

Here’s a simple example to send your first email:
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)

	params := &resend.SendEmailRequest{
		To:      []string{"[email protected]"},
		From:    "[email protected]",
		Subject: "Hello from Golang",
		Text:    "hello world",
	}

	sent, err := client.Emails.Send(params)
	if err != nil {
		panic(err)
	}

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

Send Methods

The SDK provides three methods for sending emails, each with different levels of control:
// Simple send without context
sent, err := client.Emails.Send(params)
if err != nil {
	panic(err)
}
Use SendWithContext when you need timeout or cancellation control. Use SendWithOptions when you need idempotency guarantees for retry logic.

SendEmailRequest Fields

The SendEmailRequest struct supports the following fields:
from
string
required
The sender email address. Must be a verified domain.
to
[]string
required
Array of recipient email addresses.
subject
string
required
The email subject line.
text
string
Plain text version of the email content.
html
string
HTML version of the email content.
cc
[]string
Array of CC recipient email addresses.
bcc
[]string
Array of BCC recipient email addresses.
replyTo
string
Reply-to email address.
headers
map[string]string
Custom email headers as key-value pairs.
tags
[]Tag
Custom metadata tags for categorizing and tracking emails.
attachments
[]*Attachment
Array of file attachments. See Attachments guide.
scheduledAt
string
ISO 8601 datetime to schedule email delivery. See Scheduled Emails guide.
template
*EmailTemplate
Template configuration for sending template-based emails. See Email Templates guide.

Sending Text and HTML Emails

params := &resend.SendEmailRequest{
    To:      []string{"[email protected]"},
    From:    "[email protected]",
    Subject: "Welcome!",
    Text:    "Welcome to our platform. We're excited to have you!",
}

sent, err := client.Emails.Send(params)

Using CC, BCC, and Reply-To

params := &resend.SendEmailRequest{
	To:      []string{"[email protected]"},
	From:    "[email protected]",
	Subject: "Hello from Golang",
	Text:    "hello world",
	Cc:      []string{"[email protected]"},
	Bcc:     []string{"[email protected]"},
	ReplyTo: "[email protected]",
}

sent, err := client.Emails.Send(params)

Adding Custom Headers

You can include custom headers for advanced email routing or tracking:
params := &resend.SendEmailRequest{
	To:      []string{"[email protected]"},
	From:    "[email protected]",
	Subject: "Custom Headers Example",
	Text:    "This email includes custom headers.",
	Headers: map[string]string{
		"X-Custom-Header": "custom-value",
		"X-Priority":      "high",
		"X-Entity-Ref-ID": "12345",
	},
}

sent, err := client.Emails.Send(params)
Some header names are reserved and cannot be overridden (e.g., From, To, Subject).

Using Tags for Categorization

Tags allow you to add custom metadata to emails for categorization, filtering, and analytics:
params := &resend.SendEmailRequest{
	To:      []string{"[email protected]"},
	From:    "[email protected]",
	Subject: "Your Order Confirmation",
	Html:    "<p>Thank you for your order!</p>",
	Tags: []resend.Tag{
		{
			Name:  "category",
			Value: "order_confirmation",
		},
		{
			Name:  "customer_id",
			Value: "cus_123456",
		},
	},
}

sent, err := client.Emails.Send(params)
Use tags to segment your email analytics and track performance by category, user segment, or campaign.

Idempotency Keys

Idempotency keys prevent duplicate email sends when retrying failed requests:
ctx := context.Background()

params := &resend.SendEmailRequest{
	To:      []string{"[email protected]"},
	From:    "[email protected]",
	Subject: "Order Confirmation #12345",
	Text:    "Your order has been confirmed.",
}

options := &resend.SendEmailOptions{
	IdempotencyKey: "order-12345-confirmation",
}

// This will only send once, even if called multiple times
sent, err := client.Emails.SendWithOptions(ctx, params, options)
if err != nil {
	panic(err)
}
Idempotency keys are valid for 24 hours. Multiple requests with the same key within this window will return the same response without sending duplicate emails.

Retrieving Sent Emails

You can retrieve details about a sent email using its ID:
ctx := context.Background()

// Get email by ID
email, err := client.Emails.GetWithContext(ctx, "49a3999c-0ce1-4ea6-ab68-afcd6dc2e794")
if err != nil {
	panic(err)
}

fmt.Printf("Email ID: %s\n", email.Id)
fmt.Printf("Subject: %s\n", email.Subject)
fmt.Printf("To: %v\n", email.To)
fmt.Printf("From: %s\n", email.From)
fmt.Printf("Created At: %s\n", email.CreatedAt)
fmt.Printf("Last Event: %s\n", email.LastEvent)
Source: emails.go:315

Listing Emails

Retrieve a list of recently sent emails:
ctx := context.Background()

listResp, err := client.Emails.ListWithContext(ctx)
if err != nil {
    panic(err)
}

fmt.Printf("Found %d emails\n", len(listResp.Data))
fmt.Printf("Has more: %v\n", listResp.HasMore)

for _, email := range listResp.Data {
    fmt.Printf("- ID: %s, Subject: %s\n", email.Id, email.Subject)
}
Source: examples/send_email.go:53

Error Handling

Always check for errors when sending emails:
params := &resend.SendEmailRequest{
	To:      []string{"[email protected]"},
	From:    "[email protected]",
	Subject: "Test Email",
	Text:    "This is a test.",
}

sent, err := client.Emails.Send(params)
if err != nil {
	// Handle rate limit errors
	if errors.Is(err, resend.ErrRateLimit) {
		if rateLimitErr, ok := err.(*resend.RateLimitError); ok {
			fmt.Printf("Rate limit exceeded. Retry after: %s seconds\n", rateLimitErr.RetryAfter)
		}
		return
	}
	
	// Handle other errors
	fmt.Printf("Failed to send email: %v\n", err)
	return
}

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

Best Practices

1

Use Context

Always use SendWithContext in production to enable timeout and cancellation control:
ctx, cancel := context.WithTimeout(context.Background(), 10*time.Second)
defer cancel()

sent, err := client.Emails.SendWithContext(ctx, params)
2

Provide Both Text and HTML

Include both Text and Html versions for better email client compatibility:
params := &resend.SendEmailRequest{
    // ... other fields
    Text: "Plain text version",
    Html: "<p>HTML version</p>",
}
3

Use Idempotency Keys

Use idempotency keys for critical transactional emails to prevent duplicates:
options := &resend.SendEmailOptions{
    IdempotencyKey: fmt.Sprintf("order-%s-confirmation", orderID),
}
4

Add Tags for Analytics

Use tags to categorize emails for better analytics and reporting:
Tags: []resend.Tag{
    {Name: "category", Value: "transactional"},
    {Name: "type", Value: "order_confirmation"},
}
5

Handle Rate Limits

Implement proper error handling for rate limits with exponential backoff:
if errors.Is(err, resend.ErrRateLimit) {
    // Implement retry logic with backoff
}

Next Steps

Email Templates

Learn how to use reusable email templates

Attachments

Add file attachments to your emails

Batch Emails

Send multiple emails in a single request

Scheduled Emails

Schedule emails for future delivery

Build docs developers (and LLMs) love