lettr

package module
v0.1.0 Latest Latest
Warning

This package is not in the latest version of its module.

Go to latest
Published: Feb 7, 2026 License: MIT Imports: 10 Imported by: 0

README

lettr-go

The official Go SDK for the Lettr Email API for Artisans. Send transactional emails with tracking, attachments, and template support.

Installation

go get github.com/lettr-com/lettr-go

Requires Go 1.21 or later.

Quick Start

package main

import (
	"context"
	"fmt"
	"log"

	lettr "github.com/lettr-com/lettr-go"
)

func main() {
	client := lettr.NewClient("your-api-key")

	resp, err := client.Emails.Send(context.Background(), &lettr.SendEmailRequest{
		From:    "sender@example.com",
		To:      []string{"recipient@example.com"},
		Subject: "Hello from Lettr",
		Html:    "<h1>Hello!</h1>",
	})
	if err != nil {
		log.Fatal(err)
	}

	fmt.Printf("Email sent! Request ID: %s\n", resp.Data.RequestID)
}

Usage

Create a Client
// Default client (30s timeout)
client := lettr.NewClient("your-api-key")

// Custom HTTP client
client := lettr.NewClientWithHTTPClient("your-api-key", &http.Client{
    Timeout: 60 * time.Second,
})
Send an Email
resp, err := client.Emails.Send(ctx, &lettr.SendEmailRequest{
    From:     "sender@example.com",
    FromName: "Sender Name",
    To:       []string{"recipient@example.com"},
    Subject:  "Welcome to Lettr",
    Html:     "<h1>Welcome!</h1>",
    Text:     "Welcome!",
    Options: &lettr.SendEmailOptions{
        ClickTracking: boolPtr(true),
        OpenTracking:  boolPtr(true),
    },
})
Send with Template
resp, err := client.Emails.Send(ctx, &lettr.SendEmailRequest{
    From:         "hello@example.com",
    To:           []string{"john@example.com"},
    Subject:      "Welcome, {{first_name}}!",
    TemplateSlug: "welcome-email",
    SubstitutionData: map[string]interface{}{
        "first_name": "John",
        "company":    "Acme Inc",
    },
})
Send with Attachments
resp, err := client.Emails.Send(ctx, &lettr.SendEmailRequest{
    From:    "billing@example.com",
    To:      []string{"customer@example.com"},
    Subject: "Your Invoice",
    Html:    "<p>Please find your invoice attached.</p>",
    Attachments: []lettr.Attachment{
        {
            Name: "invoice.pdf",
            Type: "application/pdf",
            Data: base64EncodedContent,
        },
    },
})
List Sent Emails
emails, err := client.Emails.List(ctx, &lettr.ListEmailsParams{
    PerPage:    10,
    Recipients: "user@example.com",
    From:       "2024-01-01",
    To:         "2024-01-31",
})

for _, email := range emails.Data.Results {
    fmt.Printf("%s -> %s: %s\n", email.FriendlyFrom, email.RcptTo, email.Subject)
}

// Paginate with cursor
if emails.Data.Pagination.NextCursor != nil {
    nextPage, err := client.Emails.List(ctx, &lettr.ListEmailsParams{
        Cursor: *emails.Data.Pagination.NextCursor,
    })
}
Get Email Details
details, err := client.Emails.Get(ctx, "request-id-from-send")

for _, event := range details.Data.Results {
    fmt.Printf("[%s] %s at %s\n", event.Type, event.RcptTo, event.Timestamp)
}
Domains
// List all domains
domains, err := client.Domains.List(ctx)

// Get domain details (including DNS records)
domain, err := client.Domains.Get(ctx, "example.com")

// Register a new domain
created, err := client.Domains.Create(ctx, &lettr.CreateDomainRequest{
    Domain: "example.com",
})

// Delete a domain
err := client.Domains.Delete(ctx, "example.com")
Webhooks
// List all webhooks
webhooks, err := client.Webhooks.List(ctx)

// Get webhook details
webhook, err := client.Webhooks.Get(ctx, "webhook-id")
Templates
// List templates
templates, err := client.Templates.List(ctx, &lettr.ListTemplatesParams{
    ProjectID: 5,
    PerPage:   10,
    Page:      1,
})

// Create a template
template, err := client.Templates.Create(ctx, &lettr.CreateTemplateRequest{
    Name: "Welcome Email",
    Html: "<h1>Hello {{FIRST_NAME}}!</h1>",
})
System
// Health check (no auth required)
health, err := client.HealthCheck(ctx)

// Validate API key
auth, err := client.ValidateAPIKey(ctx)
fmt.Printf("Team ID: %d\n", auth.Data.TeamID)

Error Handling

The SDK returns structured errors with HTTP status codes and API error codes:

resp, err := client.Emails.Send(ctx, &lettr.SendEmailRequest{})
if err != nil {
    // Check specific error types
    if lettr.IsValidationError(err) {
        apiErr := err.(*lettr.Error)
        for field, messages := range apiErr.Errors {
            fmt.Printf("%s: %v\n", field, messages)
        }
    } else if lettr.IsUnauthorized(err) {
        fmt.Println("Invalid API key")
    } else if lettr.IsNotFound(err) {
        fmt.Println("Resource not found")
    } else {
        fmt.Printf("Error: %v\n", err)
    }
}

License

MIT

Documentation

Overview

Package lettr provides a Go client for the Lettr Email API.

Create a client with your API key, then use the service objects to interact with the API:

client := lettr.NewClient("your-api-key")
sent, err := client.Emails.Send(ctx, &lettr.SendEmailRequest{
    From:    "sender@example.com",
    To:      []string{"recipient@example.com"},
    Subject: "Hello from Lettr",
    Html:    "<h1>Hello!</h1>",
})

Index

Constants

View Source
const (
	// Version is the current version of this SDK.
	Version = "0.1.0"
)

Variables

This section is empty.

Functions

func IsNotFound

func IsNotFound(err error) bool

IsNotFound returns true if the error is a 404 Not Found error.

func IsUnauthorized

func IsUnauthorized(err error) bool

IsUnauthorized returns true if the error is a 401 Unauthorized error.

func IsValidationError

func IsValidationError(err error) bool

IsValidationError returns true if the error is a 422 Validation Error.

Types

type Attachment

type Attachment struct {
	// Name is the filename of the attachment.
	Name string `json:"name"`

	// Type is the MIME type of the attachment (e.g. "application/pdf").
	Type string `json:"type"`

	// Data is the base64-encoded content of the attachment.
	Data string `json:"data"`
}

Attachment represents a file attachment on an email.

type AuthCheckData

type AuthCheckData struct {
	TeamID    int    `json:"team_id"`
	Timestamp string `json:"timestamp"`
}

AuthCheckData contains the auth check details.

type AuthCheckResponse

type AuthCheckResponse struct {
	Message string        `json:"message"`
	Data    AuthCheckData `json:"data"`
}

AuthCheckResponse is the response from the auth check endpoint.

type Client

type Client struct {

	// Services for different API resources.
	Emails    *EmailService
	Domains   *DomainService
	Webhooks  *WebhookService
	Templates *TemplateService
	// contains filtered or unexported fields
}

Client manages communication with the Lettr API.

func NewClient

func NewClient(apiKey string) *Client

NewClient creates a new Lettr API client with the given API key. It uses a default HTTP client with a 30-second timeout.

func NewClientWithHTTPClient

func NewClientWithHTTPClient(apiKey string, httpClient *http.Client) *Client

NewClientWithHTTPClient creates a new Lettr API client with a custom HTTP client. This is useful for testing or for configuring custom timeouts and transports.

func (*Client) HealthCheck

func (c *Client) HealthCheck(ctx context.Context) (*HealthCheckResponse, error)

HealthCheck verifies that the Lettr API is reachable.

func (*Client) SetBaseURL

func (c *Client) SetBaseURL(rawURL string) error

SetBaseURL overrides the default base URL. Useful for testing against a mock server.

func (*Client) ValidateAPIKey

func (c *Client) ValidateAPIKey(ctx context.Context) (*AuthCheckResponse, error)

ValidateAPIKey checks whether the configured API key is valid and returns the associated team information.

type CreateDomainData

type CreateDomainData struct {
	Domain      string      `json:"domain"`
	Status      string      `json:"status"`
	StatusLabel string      `json:"status_label"`
	DKIM        *DomainDKIM `json:"dkim"`
}

CreateDomainData contains the result of creating a domain.

type CreateDomainRequest

type CreateDomainRequest struct {
	// Domain is the domain name to register (e.g. "example.com").
	Domain string `json:"domain"`
}

CreateDomainRequest represents the request body for creating a domain.

type CreateDomainResponse

type CreateDomainResponse struct {
	Message string           `json:"message"`
	Data    CreateDomainData `json:"data"`
}

CreateDomainResponse is the response from creating a domain.

type CreateTemplateData

type CreateTemplateData struct {
	ID            int        `json:"id"`
	Name          string     `json:"name"`
	Slug          string     `json:"slug"`
	ProjectID     int        `json:"project_id"`
	FolderID      int        `json:"folder_id"`
	ActiveVersion int        `json:"active_version"`
	MergeTags     []MergeTag `json:"merge_tags"`
	CreatedAt     string     `json:"created_at"`
}

CreateTemplateData contains the result of creating a template.

type CreateTemplateRequest

type CreateTemplateRequest struct {
	// Name is the template name (required).
	Name string `json:"name"`

	// Html is the HTML content for the template. Mutually exclusive with Json.
	Html string `json:"html,omitempty"`

	// Json is the Topol editor JSON content. Mutually exclusive with Html.
	Json string `json:"json,omitempty"`

	// ProjectID specifies which project to create the template in.
	ProjectID *int `json:"project_id,omitempty"`

	// FolderID specifies which folder within the project.
	FolderID *int `json:"folder_id,omitempty"`
}

CreateTemplateRequest represents the request body for creating a template.

type CreateTemplateResponse

type CreateTemplateResponse struct {
	Message string             `json:"message"`
	Data    CreateTemplateData `json:"data"`
}

CreateTemplateResponse is the response from creating a template.

type CursorPagination

type CursorPagination struct {
	NextCursor *string `json:"next_cursor"`
	PerPage    int     `json:"per_page"`
}

CursorPagination holds cursor-based pagination info.

type Domain

type Domain struct {
	Domain      string  `json:"domain"`
	Status      string  `json:"status"`
	StatusLabel string  `json:"status_label"`
	CanSend     bool    `json:"can_send"`
	CnameStatus *string `json:"cname_status"`
	DkimStatus  *string `json:"dkim_status"`
	CreatedAt   string  `json:"created_at"`
	UpdatedAt   string  `json:"updated_at"`
}

Domain represents a sending domain.

type DomainDKIM

type DomainDKIM struct {
	Selector string `json:"selector"`
	Public   string `json:"public"`
}

DomainDKIM contains the DKIM DNS record details.

type DomainDNS

type DomainDNS struct {
	DKIM *DomainDKIM `json:"dkim"`
}

DomainDNS contains the DNS records for a domain.

type DomainDetail

type DomainDetail struct {
	Domain         string     `json:"domain"`
	Status         string     `json:"status"`
	StatusLabel    string     `json:"status_label"`
	CanSend        bool       `json:"can_send"`
	CnameStatus    *string    `json:"cname_status"`
	DkimStatus     *string    `json:"dkim_status"`
	TrackingDomain *string    `json:"tracking_domain"`
	DNS            *DomainDNS `json:"dns"`
	CreatedAt      string     `json:"created_at"`
	UpdatedAt      string     `json:"updated_at"`
}

DomainDetail represents detailed information about a sending domain, including DNS records and tracking domain configuration.

type DomainService

type DomainService struct {
	// contains filtered or unexported fields
}

DomainService handles communication with the domain-related endpoints of the Lettr API.

func (*DomainService) Create

Create registers a new sending domain with your account. The domain will start in a pending state until verified.

Example:

created, err := client.Domains.Create(ctx, &lettr.CreateDomainRequest{
    Domain: "example.com",
})

func (*DomainService) Delete

func (s *DomainService) Delete(ctx context.Context, domain string) error

Delete removes a sending domain. The domain will no longer be available for sending emails.

Example:

err := client.Domains.Delete(ctx, "example.com")

func (*DomainService) Get

func (s *DomainService) Get(ctx context.Context, domain string) (*GetDomainResponse, error)

Get retrieves details of a single sending domain including DNS records.

Example:

domain, err := client.Domains.Get(ctx, "example.com")

func (*DomainService) List

List retrieves all sending domains registered with your account.

Example:

domains, err := client.Domains.List(ctx)

type EmailEvent

type EmailEvent struct {
	EventID               string                 `json:"event_id"`
	Type                  string                 `json:"type,omitempty"`
	Timestamp             string                 `json:"timestamp"`
	RequestID             string                 `json:"request_id"`
	MessageID             string                 `json:"message_id"`
	Subject               string                 `json:"subject"`
	FriendlyFrom          string                 `json:"friendly_from"`
	SendingDomain         string                 `json:"sending_domain"`
	RcptTo                string                 `json:"rcpt_to"`
	RawRcptTo             string                 `json:"raw_rcpt_to"`
	RecipientDomain       string                 `json:"recipient_domain"`
	MailboxProvider       string                 `json:"mailbox_provider"`
	MailboxProviderRegion string                 `json:"mailbox_provider_region"`
	SendingIP             string                 `json:"sending_ip"`
	ClickTracking         bool                   `json:"click_tracking"`
	OpenTracking          bool                   `json:"open_tracking"`
	Transactional         bool                   `json:"transactional"`
	MsgSize               int                    `json:"msg_size"`
	InjectionTime         string                 `json:"injection_time"`
	Reason                *string                `json:"reason"`
	RawReason             *string                `json:"raw_reason"`
	ErrorCode             *string                `json:"error_code"`
	RcptMeta              map[string]interface{} `json:"rcpt_meta"`
}

EmailEvent represents a single event in an email's lifecycle (injection, delivery, bounce, open, click, etc).

type EmailService

type EmailService struct {
	// contains filtered or unexported fields
}

EmailService handles communication with the email-related endpoints of the Lettr API.

func (*EmailService) Get

func (s *EmailService) Get(ctx context.Context, requestID string) (*GetEmailResponse, error)

Get retrieves all events for a specific email by its request ID (the transmission ID returned when sending).

Example:

details, err := client.Emails.Get(ctx, "12345678901234567890")

func (*EmailService) List

List retrieves a paginated list of sent emails.

Pass nil for params to use defaults.

Example:

emails, err := client.Emails.List(ctx, &lettr.ListEmailsParams{
    PerPage: 10,
})

func (*EmailService) Send

Send sends an email with the given parameters.

Example:

resp, err := client.Emails.Send(ctx, &lettr.SendEmailRequest{
    From:    "sender@example.com",
    To:      []string{"recipient@example.com"},
    Subject: "Hello from Lettr",
    Html:    "<h1>Hello!</h1>",
})

type Error

type Error struct {
	// StatusCode is the HTTP status code of the response.
	StatusCode int `json:"-"`

	// Message is a human-readable error message.
	Message string `json:"message"`

	// ErrorCode is a machine-readable error code (e.g. "validation_error", "not_found").
	ErrorCode string `json:"error_code,omitempty"`

	// Errors contains field-level validation errors (for 422 responses).
	Errors map[string][]string `json:"errors,omitempty"`
}

Error represents an error returned by the Lettr API.

func (*Error) Error

func (e *Error) Error() string

Error implements the error interface.

type GetDomainResponse

type GetDomainResponse struct {
	Message string       `json:"message"`
	Data    DomainDetail `json:"data"`
}

GetDomainResponse is the response from getting a single domain.

type GetEmailData

type GetEmailData struct {
	Results    []EmailEvent `json:"results"`
	TotalCount int          `json:"total_count"`
}

GetEmailData contains the events for a specific email.

type GetEmailResponse

type GetEmailResponse struct {
	Message string       `json:"message"`
	Data    GetEmailData `json:"data"`
}

GetEmailResponse is the response from getting email details.

type GetWebhookResponse

type GetWebhookResponse struct {
	Message string  `json:"message"`
	Data    Webhook `json:"data"`
}

GetWebhookResponse is the response from getting a single webhook.

type HealthCheckData

type HealthCheckData struct {
	Status    string `json:"status"`
	Timestamp string `json:"timestamp"`
}

HealthCheckData contains the health check status information.

type HealthCheckResponse

type HealthCheckResponse struct {
	Message string          `json:"message"`
	Data    HealthCheckData `json:"data"`
}

HealthCheckResponse is the response from the health check endpoint.

type ListDomainsData

type ListDomainsData struct {
	Domains []Domain `json:"domains"`
}

ListDomainsData contains the list of domains.

type ListDomainsResponse

type ListDomainsResponse struct {
	Message string          `json:"message"`
	Data    ListDomainsData `json:"data"`
}

ListDomainsResponse is the response from listing domains.

type ListEmailsData

type ListEmailsData struct {
	Results    []EmailEvent     `json:"results"`
	TotalCount int              `json:"total_count"`
	Pagination CursorPagination `json:"pagination"`
}

ListEmailsData contains the paginated list of email events.

type ListEmailsParams

type ListEmailsParams struct {
	// PerPage is the number of results per page (1-100, default 25).
	PerPage int

	// Cursor is the pagination cursor from a previous response.
	Cursor string

	// Recipients filters by recipient email address.
	Recipients string

	// From filters emails sent on or after this date (ISO 8601, e.g. "2024-01-15").
	From string

	// To filters emails sent on or before this date (ISO 8601, e.g. "2024-01-31").
	To string
}

ListEmailsParams contains the query parameters for listing emails.

type ListEmailsResponse

type ListEmailsResponse struct {
	Message string         `json:"message"`
	Data    ListEmailsData `json:"data"`
}

ListEmailsResponse is the response from listing emails.

type ListTemplatesData

type ListTemplatesData struct {
	Templates  []Template     `json:"templates"`
	Pagination PagePagination `json:"pagination"`
}

ListTemplatesData contains the paginated list of templates.

type ListTemplatesParams

type ListTemplatesParams struct {
	// ProjectID is the project to retrieve templates from. Uses the team's
	// default project if not set.
	ProjectID int

	// PerPage is the number of results per page (1-100, default 25).
	PerPage int

	// Page is the page number (default 1).
	Page int
}

ListTemplatesParams contains the query parameters for listing templates.

type ListTemplatesResponse

type ListTemplatesResponse struct {
	Message string            `json:"message"`
	Data    ListTemplatesData `json:"data"`
}

ListTemplatesResponse is the response from listing templates.

type ListWebhooksData

type ListWebhooksData struct {
	Webhooks []Webhook `json:"webhooks"`
}

ListWebhooksData contains the list of webhooks.

type ListWebhooksResponse

type ListWebhooksResponse struct {
	Message string           `json:"message"`
	Data    ListWebhooksData `json:"data"`
}

ListWebhooksResponse is the response from listing webhooks.

type MergeTag

type MergeTag struct {
	Key      string `json:"key"`
	Required bool   `json:"required"`
}

MergeTag represents a merge tag extracted from template content.

type PagePagination

type PagePagination struct {
	Total       int `json:"total"`
	PerPage     int `json:"per_page"`
	CurrentPage int `json:"current_page"`
	LastPage    int `json:"last_page"`
}

PagePagination holds page-based pagination info.

type SendEmailData

type SendEmailData struct {
	// RequestID is the unique transmission ID for the sent email.
	RequestID string `json:"request_id"`

	// Accepted is the number of recipients that were accepted.
	Accepted int `json:"accepted"`

	// Rejected is the number of recipients that were rejected.
	Rejected int `json:"rejected"`
}

SendEmailData contains the result of a send operation.

type SendEmailOptions

type SendEmailOptions struct {
	// ClickTracking enables or disables click tracking.
	ClickTracking *bool `json:"click_tracking,omitempty"`

	// OpenTracking enables or disables open tracking.
	OpenTracking *bool `json:"open_tracking,omitempty"`

	// Transactional marks the email as transactional.
	Transactional *bool `json:"transactional,omitempty"`
}

SendEmailOptions contains optional send settings.

type SendEmailRequest

type SendEmailRequest struct {
	// From is the sender email address (required).
	From string `json:"from"`

	// FromName is the sender display name (optional).
	FromName string `json:"from_name,omitempty"`

	// To is the list of recipient email addresses (required, max 50).
	To []string `json:"to"`

	// Subject is the email subject line (required).
	Subject string `json:"subject"`

	// Html is the HTML body content. At least one of Html or Text is required.
	Html string `json:"html,omitempty"`

	// Text is the plain text body content. At least one of Html or Text is required.
	Text string `json:"text,omitempty"`

	// TemplateSlug is the slug of a pre-defined template to use.
	TemplateSlug string `json:"template_slug,omitempty"`

	// TemplateVersion is the specific version of the template to use.
	TemplateVersion *int `json:"template_version,omitempty"`

	// ProjectID is the project to source the template from.
	ProjectID *int `json:"project_id,omitempty"`

	// Attachments is a list of file attachments (base64-encoded).
	Attachments []Attachment `json:"attachments,omitempty"`

	// SubstitutionData contains key-value pairs for template variable replacement.
	SubstitutionData map[string]interface{} `json:"substitution_data,omitempty"`

	// Metadata contains custom key-value pairs stored with the email.
	Metadata map[string]interface{} `json:"metadata,omitempty"`

	// Options contains tracking and delivery options.
	Options *SendEmailOptions `json:"options,omitempty"`
}

SendEmailRequest represents the request body for sending an email.

type SendEmailResponse

type SendEmailResponse struct {
	Message string        `json:"message"`
	Data    SendEmailData `json:"data"`
}

SendEmailResponse is the response from sending an email.

type Template

type Template struct {
	ID        int    `json:"id"`
	Name      string `json:"name"`
	Slug      string `json:"slug"`
	ProjectID int    `json:"project_id"`
	FolderID  int    `json:"folder_id"`
	CreatedAt string `json:"created_at"`
	UpdatedAt string `json:"updated_at"`
}

Template represents an email template.

type TemplateService

type TemplateService struct {
	// contains filtered or unexported fields
}

TemplateService handles communication with the template-related endpoints of the Lettr API.

func (*TemplateService) Create

Create creates a new email template with HTML or Topol JSON content.

Example:

template, err := client.Templates.Create(ctx, &lettr.CreateTemplateRequest{
    Name: "Welcome Email",
    Html: "<h1>Hello {{FIRST_NAME}}!</h1>",
})

func (*TemplateService) List

List retrieves a paginated list of email templates.

Pass nil for params to use defaults.

Example:

templates, err := client.Templates.List(ctx, nil)

type Webhook

type Webhook struct {
	ID                 string   `json:"id"`
	Name               string   `json:"name"`
	URL                string   `json:"url"`
	Enabled            bool     `json:"enabled"`
	EventTypes         []string `json:"event_types"`
	AuthType           string   `json:"auth_type"`
	HasAuthCredentials bool     `json:"has_auth_credentials"`
	LastSuccessfulAt   *string  `json:"last_successful_at"`
	LastFailureAt      *string  `json:"last_failure_at"`
	LastStatus         *string  `json:"last_status"`
}

Webhook represents a webhook configuration.

type WebhookService

type WebhookService struct {
	// contains filtered or unexported fields
}

WebhookService handles communication with the webhook-related endpoints of the Lettr API.

func (*WebhookService) Get

func (s *WebhookService) Get(ctx context.Context, webhookID string) (*GetWebhookResponse, error)

Get retrieves details of a single webhook.

Example:

webhook, err := client.Webhooks.Get(ctx, "webhook-abc123")

func (*WebhookService) List

List retrieves all webhooks configured for your account.

Example:

webhooks, err := client.Webhooks.List(ctx)

Jump to

Keyboard shortcuts

? : This menu
/ : Search site
f or F : Jump to
y or Y : Canonical URL