lettr

package module
v1.6.0 Latest Latest
Warning

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

Go to latest
Published: Sep 22, 2026 License: MIT Imports: 12 Imported by: 0

README

lettr-go

The official Go SDK for the Lettr Email API. A typed client for emails, templates, domains, webhooks, audience, and campaigns.

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)
}

Methods return a wrapped response (read resp.Data) and a structured error.

Error Handling

The SDK returns typed errors you can inspect with helper predicates:

resp, err := client.Emails.Send(ctx, req)
if err != nil {
	switch {
	case lettr.IsValidationError(err):
		apiErr := err.(*lettr.Error)
		for field, messages := range apiErr.Errors {
			fmt.Printf("%s: %v\n", field, messages)
		}
	case lettr.IsUnauthorized(err):
		fmt.Println("Invalid API key")
	case lettr.IsNotFound(err):
		fmt.Println("Resource not found")
	default:
		fmt.Printf("Error: %v\n", err)
	}
}

See Error Handling for the full set of predicates.

Documentation

Full guides for every service, with complete request/response details, live in the docs:

📚 docs.lettr.com/quickstart/go

Topic Guide
Install, client, sending Quickstart
Batch sending, context & timeouts, error handling Advanced
Manage Lettr templates & merge tags Templates
Add, verify, and manage sending domains Domains
Webhook endpoints for delivery & engagement events Webhooks
Lists, contacts, topics, properties, segments Audience
List, send, and schedule campaigns Campaigns
Endpoint reference (params & schemas) API Reference

Versioning & Releases

This project follows Semantic Versioning.

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 (
	ContactStatusSubscribed   = "subscribed"
	ContactStatusUnsubscribed = "unsubscribed"
	ContactStatusBounced      = "bounced"
	ContactStatusComplained   = "complained"
	ContactStatusUnverified   = "unverified"
)

Contact subscription status values returned by the API.

View Source
const (
	TopicOptIn  = "opt_in"
	TopicOptOut = "opt_out"
)

Topic subscription states for a write request. These say what a request should *do* with a topic, and are distinct from a topic's DefaultSubscription, which describes how the topic behaves for a contact that says nothing.

TopicOptOut also cancels the auto-subscription a topic whose default is opt-out would otherwise give a newly created contact, so a create and an unsubscribe fit in one request.

View Source
const (
	BulkContactErrorMissingEmail             = "missing_email"
	BulkContactErrorInvalidEmail             = "invalid_email"
	BulkContactErrorInvalidPropertyValue     = "invalid_property_value"
	BulkContactErrorUnknownPropertyKey       = "unknown_property_key"
	BulkContactErrorUnknownList              = "unknown_list"
	BulkContactErrorUnknownTopic             = "unknown_topic"
	BulkContactErrorInvalidTopicSubscription = "invalid_topic_subscription"
)

Reasons a single row was skipped during a bulk create. These are per-row codes reported inside a 201 body — not the top-level Error.ErrorCode of a failed request.

View Source
const (
	PropertyTypeString  = "string"
	PropertyTypeNumber  = "number"
	PropertyTypeBoolean = "boolean"
	PropertyTypeDate    = "date"
	PropertyTypeJSON    = "json"
)

Data-type values for audience properties.

View Source
const (
	SegmentOperatorContains           = "contains"
	SegmentOperatorNotContains        = "not_contains"
	SegmentOperatorEquals             = "equals"
	SegmentOperatorNotEquals          = "not_equals"
	SegmentOperatorStartsWith         = "starts_with"
	SegmentOperatorNotStartsWith      = "not_starts_with"
	SegmentOperatorEndsWith           = "ends_with"
	SegmentOperatorNotEndsWith        = "not_ends_with"
	SegmentOperatorIsTrue             = "is_true"
	SegmentOperatorIsFalse            = "is_false"
	SegmentOperatorGreaterThan        = "greater_than"
	SegmentOperatorGreaterThanOrEqual = "greater_than_or_equal"
	SegmentOperatorLessThan           = "less_than"
	SegmentOperatorLessThanOrEqual    = "less_than_or_equal"
	SegmentOperatorBefore             = "before"
	SegmentOperatorAfter              = "after"
)

Segment condition operator values.

View Source
const (
	TopicDefaultSubscriptionOptIn  = "opt_in"
	TopicDefaultSubscriptionOptOut = "opt_out"
)

Default-subscription values for audience topics.

View Source
const (
	TopicVisibilityPrivate = "private"
	TopicVisibilityPublic  = "public"
)

Visibility values for audience topics.

View Source
const (
	CampaignStatusDraft     = "draft"
	CampaignStatusScheduled = "scheduled"
	CampaignStatusPreparing = "preparing"
	CampaignStatusInReview  = "in_review"
	CampaignStatusSending   = "sending"
	CampaignStatusSent      = "sent"
	CampaignStatusFailed    = "failed"
)

Campaign status values.

View Source
const (
	CampaignEventTypeInjection       = "injection"
	CampaignEventTypeDelivery        = "delivery"
	CampaignEventTypeBounce          = "bounce"
	CampaignEventTypeSpamComplaint   = "spam_complaint"
	CampaignEventTypeOpen            = "open"
	CampaignEventTypeClick           = "click"
	CampaignEventTypeListUnsubscribe = "list_unsubscribe"
)

Campaign engagement event types.

View Source
const (
	EventMessageInjection       = "message.injection"
	EventMessageDelivery        = "message.delivery"
	EventMessageBounce          = "message.bounce"
	EventMessageDelay           = "message.delay"
	EventMessageOutOfBand       = "message.out_of_band"
	EventMessageSpamComplaint   = "message.spam_complaint"
	EventMessagePolicyRejection = "message.policy_rejection"

	EventEngagementClick          = "engagement.click"
	EventEngagementOpen           = "engagement.open"
	EventEngagementInitialOpen    = "engagement.initial_open"
	EventEngagementAmpClick       = "engagement.amp_click"
	EventEngagementAmpOpen        = "engagement.amp_open"
	EventEngagementAmpInitialOpen = "engagement.amp_initial_open"

	EventGenerationFailure   = "generation.generation_failure"
	EventGenerationRejection = "generation.generation_rejection"

	EventUnsubscribeList = "unsubscribe.list_unsubscribe"
	EventUnsubscribeLink = "unsubscribe.link_unsubscribe"

	EventRelayInjection = "relay.relay_injection"
	EventRelayRejection = "relay.relay_rejection"
	EventRelayDelivery  = "relay.relay_delivery"
	EventRelayTempfail  = "relay.relay_tempfail"
	EventRelayPermfail  = "relay.relay_permfail"
)

Webhook event-type constants. The Lettr API uses namespaced strings (e.g. "message.delivery") on both request and response sides.

View Source
const ErrorCodeIdempotencyInProgress = "idempotency_in_progress"

ErrorCodeIdempotencyInProgress is sent when the original request for an Idempotency-Key is still being processed.

View Source
const ErrorCodeIdempotencyKeyConflict = "idempotency_key_conflict"

ErrorCodeIdempotencyKeyConflict is sent when an Idempotency-Key was already used with a different request payload.

View Source
const ErrorCodeResourceAlreadyExists = "resource_already_exists"

ErrorCodeResourceAlreadyExists is the machine-readable code the API sends when a create collides with an existing resource.

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

Variables

This section is empty.

Functions

func IsConflict added in v1.4.0

func IsConflict(err error) bool

IsConflict returns true if the error is a 409 Conflict error.

func IsContactAlreadyExists added in v1.4.0

func IsContactAlreadyExists(err error) bool

IsContactAlreadyExists returns true if the error is the 409 that AudienceContactService.Create returns when the email is already in the team's audience.

_, err := client.Audience.Contacts.Create(ctx, &lettr.CreateAudienceContactRequest{Email: email})
if lettr.IsContactAlreadyExists(err) {
	// Client-correctable: update the existing contact instead.
}

This is not a retryable failure. The API used to let a duplicate escape as an HTTP 500 with the misleading "send_error" code (it names email delivery, which is not involved here); a retry-on-5xx policy would retry it pointlessly. It is now a 409, and a 409 here must not be retried.

A 409 that carries no error code also counts, so the check still works against an API deployment that predates the change.

func IsIdempotencyConflict added in v1.5.0

func IsIdempotencyConflict(err error) bool

IsIdempotencyConflict reports whether err is the 409 for an Idempotency-Key reused with a different payload.

Never retry this. Two different emails were sent under one key, which is a bug on the caller's side; the same request will fail identically forever. Use a key that is unique per logical send, or send the payload the key was first used with.

func IsIdempotencyInProgress added in v1.5.0

func IsIdempotencyInProgress(err error) bool

IsIdempotencyInProgress reports whether err is the 409 for a send whose original request is still running.

Unlike IsIdempotencyConflict this one is retryable, and must be retried with the same key - a fresh key would send a second email. Wait Error.RetryAfter seconds first.

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 IsValidIdempotencyKey added in v1.5.0

func IsValidIdempotencyKey(key string) bool

IsValidIdempotencyKey reports whether a string is a usable idempotency key.

Exported so callers deriving keys from their own ids - an order number, a job id - can check before sending rather than discovering it as a 422.

func IsValidationError

func IsValidationError(err error) bool

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

Types

type AttachContactResponse added in v1.2.0

type AttachContactResponse struct {
	Message string `json:"message"`
}

AttachContactResponse is the response from attaching a contact to a list or subscribing a contact to a topic. The endpoint returns only a status message; no payload data is sent.

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 AudienceContact added in v1.2.0

type AudienceContact struct {
	ID         string                     `json:"id"`
	Email      string                     `json:"email"`
	Status     string                     `json:"status"`
	Properties ContactProperties          `json:"properties"`
	CreatedAt  string                     `json:"created_at"`
	Lists      []AudienceContactListLink  `json:"lists"`
	Topics     []AudienceContactTopicLink `json:"topics"`
}

AudienceContact represents a contact in the team's audience.

type AudienceContactListLink struct {
	ID   string `json:"id"`
	Name string `json:"name"`
}

AudienceContactListLink is a short reference to a list the contact belongs to.

type AudienceContactResponse added in v1.2.0

type AudienceContactResponse struct {
	Message string          `json:"message"`
	Data    AudienceContact `json:"data"`
}

AudienceContactResponse is the response from endpoints that return a single contact (Create, Get, Update).

type AudienceContactService added in v1.2.0

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

AudienceContactService handles communication with the audience-contact endpoints of the Lettr API.

func (*AudienceContactService) AttachToList added in v1.2.0

func (s *AudienceContactService) AttachToList(ctx context.Context, contactID, listID string) (*AttachContactResponse, error)

AttachToList adds a contact to a list. Returns 201 when the contact is newly attached or 200 when the contact was already in the list.

func (*AudienceContactService) BulkAttachToLists added in v1.2.0

BulkAttachToLists attaches every combination of contact_ids × list_ids (up to 1000 contacts × 50 lists).

func (*AudienceContactService) BulkCreate added in v1.2.0

BulkCreate creates up to 1000 contacts in a single request.

Rows that fail validation are skipped, not fatal: the call still returns HTTP 201 and reports them in Data.Errors. A nil error does not mean every row landed — check Data.HasErrors.

func (*AudienceContactService) BulkDetachFromLists added in v1.2.0

BulkDetachFromLists detaches every combination of contact_ids × list_ids.

func (*AudienceContactService) BulkSubscribeToTopics added in v1.4.0

BulkSubscribeToTopics subscribes every combination of contact_ids × topic_ids (up to 1000 contacts × 50 topics).

Pass BulkCreateAudienceContactsData.ContactIDs from a bulk create — no ID lookup needed.

func (*AudienceContactService) BulkUnsubscribeFromTopics added in v1.4.0

BulkUnsubscribeFromTopics unsubscribes every combination of contact_ids × topic_ids. Pairs that do not exist are ignored.

This is a DELETE carrying a request body, as BulkDetachFromLists already is.

func (*AudienceContactService) Create added in v1.2.0

Create creates a single contact. When params.DoubleOptIn is set, the contact is created in "unverified" status and the confirmation email is sent.

An email already in the team's audience comes back as a 409 with error code "resource_already_exists" — use IsContactAlreadyExists to detect it. That is a client-correctable condition, not an outage: do not retry it. Update the existing contact with Update, or use BulkCreate with UpdateExisting set.

func (*AudienceContactService) Delete added in v1.2.0

func (s *AudienceContactService) Delete(ctx context.Context, contactID string) error

Delete permanently deletes a contact.

func (*AudienceContactService) DetachFromList added in v1.2.0

func (s *AudienceContactService) DetachFromList(ctx context.Context, contactID, listID string) error

DetachFromList removes a contact from a list. The operation is idempotent.

func (*AudienceContactService) Get added in v1.2.0

Get retrieves a single contact by ID.

func (*AudienceContactService) List added in v1.2.0

List retrieves a paginated, filterable list of audience contacts.

Pass nil for params to use defaults.

func (*AudienceContactService) SubscribeToTopic added in v1.2.0

func (s *AudienceContactService) SubscribeToTopic(ctx context.Context, contactID, topicID string) (*AttachContactResponse, error)

SubscribeToTopic subscribes a contact to a topic. Returns 201 when the subscription is newly created or 200 when it already existed.

func (*AudienceContactService) UnsubscribeFromTopic added in v1.2.0

func (s *AudienceContactService) UnsubscribeFromTopic(ctx context.Context, contactID, topicID string) error

UnsubscribeFromTopic removes a contact's subscription from a topic. The operation is idempotent.

func (*AudienceContactService) Update added in v1.2.0

Update partially updates a contact.

type AudienceContactTopicLink struct {
	ID   string `json:"id"`
	Name string `json:"name"`
}

AudienceContactTopicLink is a short reference to a topic the contact is subscribed to.

type AudienceList added in v1.2.0

type AudienceList struct {
	ID            string `json:"id"`
	Name          string `json:"name"`
	ContactsCount int    `json:"contacts_count"`
}

AudienceList represents an audience list.

type AudienceListResponse added in v1.2.0

type AudienceListResponse struct {
	Message string       `json:"message"`
	Data    AudienceList `json:"data"`
}

AudienceListResponse is the response from endpoints that return a single audience list (Create, Get, Update).

type AudienceListService added in v1.2.0

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

AudienceListService handles communication with the audience-list endpoints of the Lettr API.

func (*AudienceListService) BulkDelete added in v1.2.0

BulkDelete deletes up to 50 audience lists in a single request.

func (*AudienceListService) Create added in v1.2.0

Create creates a new audience list.

func (*AudienceListService) Delete added in v1.2.0

func (s *AudienceListService) Delete(ctx context.Context, listID string) error

Delete permanently deletes an audience list.

func (*AudienceListService) Get added in v1.2.0

Get retrieves a single audience list by ID.

func (*AudienceListService) List added in v1.2.0

List retrieves a paginated list of audience lists.

Pass nil for params to use defaults.

func (*AudienceListService) Update added in v1.2.0

Update partially updates an audience list.

type AudienceProperty added in v1.2.0

type AudienceProperty struct {
	ID            string  `json:"id"`
	Name          string  `json:"name"`
	Type          string  `json:"type"`
	FallbackValue *string `json:"fallback_value"`
	CreatedAt     string  `json:"created_at"`
}

AudienceProperty represents a custom property definition that contacts can hold.

type AudiencePropertyResponse added in v1.2.0

type AudiencePropertyResponse struct {
	Message string           `json:"message"`
	Data    AudienceProperty `json:"data"`
}

AudiencePropertyResponse is the response from endpoints that return a single property.

type AudiencePropertyService added in v1.2.0

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

AudiencePropertyService handles communication with the audience-property endpoints of the Lettr API.

func (*AudiencePropertyService) Create added in v1.2.0

Create creates a new property definition.

func (*AudiencePropertyService) Delete added in v1.2.0

func (s *AudiencePropertyService) Delete(ctx context.Context, propertyID string) error

Delete permanently deletes a property definition.

func (*AudiencePropertyService) Get added in v1.2.0

Get retrieves a single property by ID.

func (*AudiencePropertyService) List added in v1.2.0

List retrieves a paginated list of property definitions.

Pass nil for params to use defaults.

func (*AudiencePropertyService) Update added in v1.2.0

Update updates a property's fallback value.

type AudienceSegment added in v1.2.0

type AudienceSegment struct {
	ID                  string                  `json:"id"`
	Name                string                  `json:"name"`
	ListID              *string                 `json:"list_id"`
	ListName            *string                 `json:"list_name"`
	ConditionGroups     []SegmentConditionGroup `json:"condition_groups"`
	CachedContactsCount *int                    `json:"cached_contacts_count"`
	CreatedAt           string                  `json:"created_at"`
}

AudienceSegment represents an audience segment.

type AudienceSegmentResponse added in v1.2.0

type AudienceSegmentResponse struct {
	Message string          `json:"message"`
	Data    AudienceSegment `json:"data"`
}

AudienceSegmentResponse is the response from endpoints that return a single segment.

type AudienceSegmentService added in v1.2.0

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

AudienceSegmentService handles communication with the audience-segment endpoints of the Lettr API.

func (*AudienceSegmentService) Create added in v1.2.0

Create creates a new segment.

func (*AudienceSegmentService) Delete added in v1.2.0

func (s *AudienceSegmentService) Delete(ctx context.Context, segmentID string) error

Delete permanently deletes a segment.

func (*AudienceSegmentService) Get added in v1.2.0

Get retrieves a single segment by ID.

func (*AudienceSegmentService) List added in v1.2.0

List retrieves a paginated list of segments.

Pass nil for params to use defaults.

func (*AudienceSegmentService) Update added in v1.2.0

Update partially updates a segment.

type AudienceService added in v1.2.0

type AudienceService struct {
	Lists      *AudienceListService
	Contacts   *AudienceContactService
	Topics     *AudienceTopicService
	Properties *AudiencePropertyService
	Segments   *AudienceSegmentService
}

AudienceService groups all audience-related operations under one namespace. The endpoint methods live on its sub-services: Lists, Contacts, Topics, Properties, and Segments.

Example:

lists, err := client.Audience.Lists.List(ctx, nil)
contact, err := client.Audience.Contacts.Get(ctx, "0193e6b0-9c1d-7d4f-a8f1-cef9a1b2d3e4")

type AudienceTopic added in v1.2.0

type AudienceTopic struct {
	ID                  string  `json:"id"`
	Name                string  `json:"name"`
	Description         *string `json:"description"`
	DefaultSubscription string  `json:"default_subscription"`
	Visibility          string  `json:"visibility"`
	ContactsCount       int     `json:"contacts_count"`
	CreatedAt           *string `json:"created_at"`
}

AudienceTopic represents a topic that contacts can subscribe to.

type AudienceTopicResponse added in v1.2.0

type AudienceTopicResponse struct {
	Message string        `json:"message"`
	Data    AudienceTopic `json:"data"`
}

AudienceTopicResponse is the response from endpoints that return a single topic.

type AudienceTopicService added in v1.2.0

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

AudienceTopicService handles communication with the audience-topic endpoints of the Lettr API.

func (*AudienceTopicService) Create added in v1.2.0

Create creates a new topic.

func (*AudienceTopicService) Delete added in v1.2.0

func (s *AudienceTopicService) Delete(ctx context.Context, topicID string) error

Delete permanently deletes a topic.

func (*AudienceTopicService) Get added in v1.2.0

Get retrieves a single topic by ID.

func (*AudienceTopicService) List added in v1.2.0

List retrieves a paginated list of topics.

Pass nil for params to use defaults.

func (*AudienceTopicService) Update added in v1.2.0

Update partially updates a topic.

type AudienceTopicSubscription added in v1.4.0

type AudienceTopicSubscription struct {
	ID string `json:"id"`

	// Subscription is TopicOptIn or TopicOptOut. Empty means opt-in server-side.
	Subscription string `json:"subscription,omitempty"`
}

AudienceTopicSubscription is a topic and the subscription state to apply to it. Used batch-wide on BulkCreateAudienceContactsRequest and per row on BulkAudienceContactRow. A row-level opt-out wins over a batch-level opt-in for that contact.

Build them with SubscribeTopic / UnsubscribeTopic for readability at the call site.

func SubscribeTopic added in v1.4.0

func SubscribeTopic(topicID string) AudienceTopicSubscription

SubscribeTopic returns a subscription that opts the contact in to topicID.

func UnsubscribeTopic added in v1.4.0

func UnsubscribeTopic(topicID string) AudienceTopicSubscription

UnsubscribeTopic returns a subscription that opts the contact out of topicID, including a topic that would otherwise auto-subscribe new contacts.

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 BulkAttachContactsToListsData added in v1.2.0

type BulkAttachContactsToListsData struct {
	Attached        int `json:"attached"`
	AlreadyAttached int `json:"already_attached"`
	TotalPairs      int `json:"total_pairs"`
}

BulkAttachContactsToListsData holds the counts from a bulk-attach operation.

type BulkAttachContactsToListsResponse added in v1.2.0

type BulkAttachContactsToListsResponse struct {
	Message string                        `json:"message"`
	Data    BulkAttachContactsToListsData `json:"data"`
}

BulkAttachContactsToListsResponse is the response from bulk attach.

type BulkAudienceContactError added in v1.4.0

type BulkAudienceContactError struct {
	// Index is the zero-based position of the row in the submitted slice.
	Index int `json:"index"`

	Email string `json:"email"`

	// ErrorCode is one of the BulkContactError* constants. It is a plain string
	// so a code added server-side is still readable here.
	ErrorCode string `json:"error_code"`

	Error string `json:"error"`
}

BulkAudienceContactError is a row that was skipped during a bulk create.

type BulkAudienceContactRef added in v1.4.0

type BulkAudienceContactRef struct {
	ID    string `json:"id"`
	Email string `json:"email"`

	// Created is true when this request created the contact, false when it
	// already existed.
	Created bool `json:"created"`
}

BulkAudienceContactRef identifies a contact that exists after a bulk create, so a caller can chain into the bulk list and topic endpoints without a follow-up lookup.

type BulkAudienceContactRow added in v1.4.0

type BulkAudienceContactRow struct {
	Email string `json:"email"`

	// Properties keys must each match a property defined for the team.
	Properties map[string]string `json:"properties,omitempty"`

	// ListIDs is up to 50 list IDs for this row, on top of the batch-wide ones.
	ListIDs []string `json:"list_ids,omitempty"`

	// Topics is up to 50 topic subscriptions for this row.
	Topics []AudienceTopicSubscription `json:"topics,omitempty"`
}

BulkAudienceContactRow is one contact in a bulk-create payload.

ListIDs and Topics here are applied on top of the batch-wide ones on BulkCreateAudienceContactsRequest; a Properties key here overrides the batch-wide value for the same key.

A row that fails validation is skipped rather than failing the request — it comes back in BulkCreateAudienceContactsData.Errors.

type BulkContactsListsRequest added in v1.2.0

type BulkContactsListsRequest struct {
	// ContactIDs is 1-1000 contact IDs.
	ContactIDs []string `json:"contact_ids"`
	// ListIDs is 1-50 list IDs.
	ListIDs []string `json:"list_ids"`
}

BulkContactsListsRequest is the body for bulk attach/detach between contacts and lists. Every contact × list combination is processed.

type BulkContactsTopicsRequest added in v1.4.0

type BulkContactsTopicsRequest struct {
	// ContactIDs is 1-1000 contact IDs.
	ContactIDs []string `json:"contact_ids"`
	// TopicIDs is 1-50 topic IDs.
	TopicIDs []string `json:"topic_ids"`
}

BulkContactsTopicsRequest is the body for bulk subscribe/unsubscribe between contacts and topics. Every contact × topic combination is processed.

type BulkCreateAudienceContactsData added in v1.2.0

type BulkCreateAudienceContactsData struct {
	Created        int `json:"created"`
	AlreadyExisted int `json:"already_existed"`

	// Updated counts existing contacts this request changed — properties
	// merged, a list or topic attached, or a subscription dropped.
	Updated int `json:"updated"`

	// ErrorCount is the number of skipped rows.
	ErrorCount int `json:"error_count"`

	Errors []BulkAudienceContactError `json:"errors"`

	// Contacts lists every contact that exists after the request, in
	// submission order.
	Contacts []BulkAudienceContactRef `json:"contacts"`
}

BulkCreateAudienceContactsData holds the results of a bulk-create operation.

A bulk create can partially succeed: rows that fail validation are skipped and reported in Errors while the rest of the batch is written, and the call still returns HTTP 201. A nil error from BulkCreate therefore does not mean every row landed — check HasErrors.

AlreadyExisted and Updated overlap by design. They answer different questions ("was the address already in the audience?" vs "did this request change the contact?"), so they do not sum to the row count: a contact that already existed and got attached to a list is counted in both.

func (BulkCreateAudienceContactsData) ContactIDs added in v1.4.0

func (d BulkCreateAudienceContactsData) ContactIDs() []string

ContactIDs returns the IDs of every contact that exists after the request, in submission order — ready to pass to BulkAttachToLists or BulkSubscribeToTopics.

func (BulkCreateAudienceContactsData) HasErrors added in v1.4.0

func (d BulkCreateAudienceContactsData) HasErrors() bool

HasErrors reports whether any row was skipped. Always check this — a bulk create reports partial failures in the body, not in the HTTP status.

func (BulkCreateAudienceContactsData) IDFor added in v1.4.0

IDFor looks up the ID for a submitted address, reporting whether it was found. Matching is case-insensitive because the API normalizes addresses before storing them.

type BulkCreateAudienceContactsRequest added in v1.2.0

type BulkCreateAudienceContactsRequest struct {
	// Emails is 1-1000 email addresses. They are normalized and deduplicated
	// server-side. Leave nil when using Contacts.
	Emails []string `json:"emails,omitempty"`

	// ListID is a single batch-wide list, folded into ListIDs server-side.
	ListID *string `json:"list_id,omitempty"`

	// Properties applies to every contact in the batch; a row's own key wins.
	Properties map[string]string `json:"properties,omitempty"`

	// Contacts is 1-1000 rows. Alternative to Emails.
	Contacts []BulkAudienceContactRow `json:"contacts,omitempty"`

	// ListIDs is up to 50 batch-wide lists.
	ListIDs []string `json:"list_ids,omitempty"`

	// Topics is up to 50 batch-wide topic subscriptions.
	Topics []AudienceTopicSubscription `json:"topics,omitempty"`

	// UpdateExisting merges properties into contacts that already exist
	// (submitted keys overwrite, absent keys are preserved) and allows dropping
	// a subscription via an opt-out. Defaults to false, in which case existing
	// contacts keep their properties but are still attached to the requested
	// lists. Omitted from the payload when false, so a legacy request stays
	// byte-identical on the wire.
	UpdateExisting bool `json:"update_existing,omitempty"`
}

BulkCreateAudienceContactsRequest is the body for bulk-creating contacts.

Two shapes are supported, and exactly one of them must be filled in:

  • Emails — a flat list of addresses that all share the batch-wide ListID / ListIDs, Properties and Topics. The original shape, unchanged.
  • Contacts — one BulkAudienceContactRow per contact, each with its own properties, lists and topic subscriptions.

Batch-wide ListIDs and Topics are unioned into every row; a row-level property key or opt-out wins over the batch-wide value.

type BulkCreateAudienceContactsResponse added in v1.2.0

type BulkCreateAudienceContactsResponse struct {
	Message string                         `json:"message"`
	Data    BulkCreateAudienceContactsData `json:"data"`
}

BulkCreateAudienceContactsResponse is the response from a bulk create.

type BulkDeleteAudienceListsData added in v1.2.0

type BulkDeleteAudienceListsData struct {
	Deleted int `json:"deleted"`
}

BulkDeleteAudienceListsData holds the counts from a bulk-delete operation.

type BulkDeleteAudienceListsRequest added in v1.2.0

type BulkDeleteAudienceListsRequest struct {
	// ListIDs is 1-50 list IDs to delete.
	ListIDs []string `json:"list_ids"`
}

BulkDeleteAudienceListsRequest is the body for bulk-deleting audience lists.

type BulkDeleteAudienceListsResponse added in v1.2.0

type BulkDeleteAudienceListsResponse struct {
	Message string                      `json:"message"`
	Data    BulkDeleteAudienceListsData `json:"data"`
}

BulkDeleteAudienceListsResponse is the response from a bulk delete.

type BulkDetachContactsFromListsData added in v1.2.0

type BulkDetachContactsFromListsData struct {
	Detached   int `json:"detached"`
	NotPresent int `json:"not_present"`
	TotalPairs int `json:"total_pairs"`
}

BulkDetachContactsFromListsData holds the counts from a bulk-detach operation.

type BulkDetachContactsFromListsResponse added in v1.2.0

type BulkDetachContactsFromListsResponse struct {
	Message string                          `json:"message"`
	Data    BulkDetachContactsFromListsData `json:"data"`
}

BulkDetachContactsFromListsResponse is the response from bulk detach.

type BulkSubscribeContactsToTopicsData added in v1.4.0

type BulkSubscribeContactsToTopicsData struct {
	Subscribed        int `json:"subscribed"`
	AlreadySubscribed int `json:"already_subscribed"`
	TotalPairs        int `json:"total_pairs"`
}

BulkSubscribeContactsToTopicsData holds the counts from a bulk-subscribe operation.

type BulkSubscribeContactsToTopicsResponse added in v1.4.0

type BulkSubscribeContactsToTopicsResponse struct {
	Message string                            `json:"message"`
	Data    BulkSubscribeContactsToTopicsData `json:"data"`
}

BulkSubscribeContactsToTopicsResponse is the response from a bulk subscribe.

type BulkUnsubscribeContactsFromTopicsData added in v1.4.0

type BulkUnsubscribeContactsFromTopicsData struct {
	Unsubscribed int `json:"unsubscribed"`
	TotalPairs   int `json:"total_pairs"`
}

BulkUnsubscribeContactsFromTopicsData holds the counts from a bulk-unsubscribe operation. Pairs that did not exist are ignored, so Unsubscribed can be lower than TotalPairs.

type BulkUnsubscribeContactsFromTopicsResponse added in v1.4.0

type BulkUnsubscribeContactsFromTopicsResponse struct {
	Message string                                `json:"message"`
	Data    BulkUnsubscribeContactsFromTopicsData `json:"data"`
}

BulkUnsubscribeContactsFromTopicsResponse is the response from a bulk unsubscribe.

type Campaign added in v1.3.0

type Campaign struct {
	ID              string        `json:"id"`
	Name            string        `json:"name"`
	Subject         *string       `json:"subject"`
	FromEmail       *string       `json:"from_email"`
	FromName        *string       `json:"from_name"`
	ReplyTo         *string       `json:"reply_to"`
	Status          string        `json:"status"`
	ScheduledAt     *string       `json:"scheduled_at"`
	TotalRecipients *int          `json:"total_recipients"`
	SentCount       int           `json:"sent_count"`
	SentAt          *string       `json:"sent_at"`
	CreatedAt       string        `json:"created_at"`
	Stats           CampaignStats `json:"stats"`
}

Campaign is a campaign summary with embedded engagement stats. Nullable fields are represented as pointers.

type CampaignActionResponse added in v1.3.0

type CampaignActionResponse struct {
	Message string    `json:"message"`
	Data    *Campaign `json:"data"`
}

CampaignActionResponse is the response from the send, schedule, and unschedule actions. Data carries the updated campaign on success; it is nil in the rare case the campaign cannot be re-read immediately after the action (e.g. it was concurrently deleted), in which case the server omits the key.

type CampaignDetail added in v1.3.0

type CampaignDetail struct {
	Campaign
	HTMLContent *string `json:"html_content"`
}

CampaignDetail is the full campaign representation, extending Campaign with the rendered HTML content of the campaign email.

type CampaignEvent added in v1.3.0

type CampaignEvent struct {
	EventID   string `json:"event_id"`
	EventType string `json:"event_type"`
	Email     string `json:"email"`
	Timestamp string `json:"timestamp"`
	// BounceClass is the SparkPost bounce classification code, serialised as
	// a string by the campaigns API (note this differs from EmailEvent's *int
	// BounceClass — see emails.go — which is the same underlying code but
	// kept as the type the /emails/events endpoint emits).
	BounceClass   *string `json:"bounce_class"`
	Reason        *string `json:"reason"`
	TargetLinkURL *string `json:"target_link_url"`
	UserAgent     *string `json:"user_agent"`
}

CampaignEvent is a single campaign engagement event. Fields that only apply to certain event types are represented as pointers.

type CampaignResponse added in v1.3.0

type CampaignResponse struct {
	Message string         `json:"message"`
	Data    CampaignDetail `json:"data"`
}

CampaignResponse is the response from Get, returning a single campaign with its rendered HTML content.

type CampaignService added in v1.3.0

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

CampaignService handles communication with the campaign endpoints of the Lettr API.

func (*CampaignService) Get added in v1.3.0

func (s *CampaignService) Get(ctx context.Context, campaignID string) (*CampaignResponse, error)

Get retrieves a single campaign by ID, including its rendered HTML content.

func (*CampaignService) List added in v1.3.0

List retrieves a paginated list of campaigns with embedded engagement stats.

Pass nil for params to use defaults.

func (*CampaignService) ListEvents added in v1.3.0

ListEvents retrieves a page of engagement events (opens, clicks, bounces, etc.) for a campaign using cursor-based pagination.

Pass nil for params to use defaults.

func (*CampaignService) Schedule added in v1.3.0

func (s *CampaignService) Schedule(ctx context.Context, campaignID string, params *ScheduleCampaignRequest) (*CampaignActionResponse, error)

Schedule schedules a campaign for future delivery, or reschedules one that is already scheduled. The campaign is dispatched automatically at the given time. Not available to sandbox keys.

func (*CampaignService) Send added in v1.3.0

func (s *CampaignService) Send(ctx context.Context, campaignID string) (*CampaignActionResponse, error)

Send immediately dispatches a draft campaign. The campaign must have a subject, sender email, and content. Sending is asynchronous; the campaign transitions to the "preparing" status. Not available to sandbox keys.

func (*CampaignService) Unschedule added in v1.3.0

func (s *CampaignService) Unschedule(ctx context.Context, campaignID string) (*CampaignActionResponse, error)

Unschedule cancels a scheduled send and returns the campaign to the "draft" status. The campaign must currently be scheduled. Not available to sandbox keys.

type CampaignStats added in v1.3.0

type CampaignStats struct {
	Injections     int `json:"injections"`
	Deliveries     int `json:"deliveries"`
	Bounces        int `json:"bounces"`
	SpamComplaints int `json:"spam_complaints"`
	Opens          int `json:"opens"`
	UniqueOpens    int `json:"unique_opens"`
	Clicks         int `json:"clicks"`
	UniqueClicks   int `json:"unique_clicks"`
	Unsubscribes   int `json:"unsubscribes"`
}

CampaignStats holds aggregated engagement statistics for a campaign.

type CancelScheduledResponse added in v0.2.0

type CancelScheduledResponse struct {
	Message string         `json:"message"`
	Data    ScheduledEmail `json:"data"`
}

CancelScheduledResponse is the response from cancelling a scheduled email.

type Client

type Client struct {

	// Services for different API resources.
	Emails    *EmailService
	Domains   *DomainService
	Webhooks  *WebhookService
	Templates *TemplateService
	Projects  *ProjectService
	Folders   *FolderService
	Audience  *AudienceService
	Campaigns *CampaignService
	// 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 ContactProperties added in v1.2.0

type ContactProperties map[string]string

ContactProperties holds a contact's custom property key-value pairs. It is a map[string]string with a tolerant UnmarshalJSON: when the API returns an empty associative array as `[]` (a PHP/Laravel serialization quirk for empty maps), it decodes to an empty ContactProperties instead of erroring.

func (*ContactProperties) UnmarshalJSON added in v1.2.0

func (p *ContactProperties) UnmarshalJSON(data []byte) error

UnmarshalJSON implements json.Unmarshaler. It accepts both a JSON object (`{...}`) and an empty JSON array (`[]`) for the empty-map case.

type CreateAudienceContactRequest added in v1.2.0

type CreateAudienceContactRequest struct {
	Email       string             `json:"email"`
	ListID      *string            `json:"list_id,omitempty"`
	Properties  map[string]string  `json:"properties,omitempty"`
	DoubleOptIn *DoubleOptInConfig `json:"double_opt_in,omitempty"`
}

CreateAudienceContactRequest is the body for creating a single contact.

type CreateAudienceListRequest added in v1.2.0

type CreateAudienceListRequest struct {
	// Name must be unique within the team (max 255 chars).
	Name string `json:"name"`
}

CreateAudienceListRequest is the body for creating an audience list.

type CreateAudiencePropertyRequest added in v1.2.0

type CreateAudiencePropertyRequest struct {
	Name          string  `json:"name"`
	Type          string  `json:"type"`
	FallbackValue *string `json:"fallback_value,omitempty"`
}

CreateAudiencePropertyRequest is the body for creating a property. Name must match the pattern ^[a-z][a-z0-9_]*$.

type CreateAudienceSegmentRequest added in v1.2.0

type CreateAudienceSegmentRequest struct {
	Name       string                 `json:"name"`
	ListID     *string                `json:"list_id,omitempty"`
	Conditions SegmentConditionsInput `json:"conditions"`
}

CreateAudienceSegmentRequest is the body for creating a segment.

type CreateAudienceTopicRequest added in v1.2.0

type CreateAudienceTopicRequest struct {
	Name string `json:"name"`
	// Description is optional. Set to a pointer to an empty string for empty,
	// or omit to leave unset.
	Description *string `json:"description,omitempty"`
	// DefaultSubscription defaults to "opt_in" server-side when omitted.
	DefaultSubscription string `json:"default_subscription,omitempty"`
	// Visibility defaults to "private" server-side when omitted.
	Visibility string `json:"visibility,omitempty"`
}

CreateAudienceTopicRequest is the body for creating a topic.

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"`
	Purpose           TemplatePurpose           `json:"purpose"`
	PreparationStatus TemplatePreparationStatus `json:"preparation_status"`
	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. It must belong to
	// the same module as Purpose. Discover ids with Folders.List.
	FolderID *int `json:"folder_id,omitempty"`

	// Purpose is the module to create the template in. Leave empty to let the
	// API decide, which today means transactional.
	Purpose TemplatePurpose `json:"purpose,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 CreateWebhookRequest added in v0.2.0

type CreateWebhookRequest struct {
	Name              string   `json:"name"`
	URL               string   `json:"url"`
	AuthType          string   `json:"auth_type"`
	AuthUsername      string   `json:"auth_username,omitempty"`
	AuthPassword      string   `json:"auth_password,omitempty"`
	OAuthClientID     string   `json:"oauth_client_id,omitempty"`
	OAuthClientSecret string   `json:"oauth_client_secret,omitempty"`
	OAuthTokenURL     string   `json:"oauth_token_url,omitempty"`
	EventsMode        string   `json:"events_mode"`
	Events            []string `json:"events,omitempty"`
}

CreateWebhookRequest represents the request body for creating a webhook.

type CreateWebhookResponse added in v0.2.0

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

CreateWebhookResponse is the response from creating a webhook.

type CursorPagination

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

CursorPagination holds cursor-based pagination info.

type DeleteTemplateParams added in v0.2.0

type DeleteTemplateParams struct {
	// ProjectID is the project containing the template.
	ProjectID int
}

DeleteTemplateParams contains optional query parameters for deleting a template.

type DeleteTemplateResponse added in v0.2.0

type DeleteTemplateResponse struct {
	Message string `json:"message"`
}

DeleteTemplateResponse is the response from deleting a template.

type DeleteWebhookResponse added in v0.2.0

type DeleteWebhookResponse struct {
	Message string `json:"message"`
}

DeleteWebhookResponse is the response from deleting a webhook.

type DmarcValidationResult added in v0.2.0

type DmarcValidationResult struct {
	IsValid               bool    `json:"is_valid"`
	Status                string  `json:"status"`
	FoundAtDomain         *string `json:"found_at_domain"`
	Record                *string `json:"record"`
	Policy                *string `json:"policy"`
	SubdomainPolicy       *string `json:"subdomain_policy"`
	Error                 *string `json:"error"`
	CoveredByParentPolicy bool    `json:"covered_by_parent_policy"`
}

DmarcValidationResult contains DMARC validation details.

type DnsProviderInfo added in v0.2.0

type DnsProviderInfo struct {
	Provider      string   `json:"provider"`
	ProviderLabel string   `json:"provider_label"`
	Nameservers   []string `json:"nameservers"`
	Error         *string  `json:"error"`
}

DnsProviderInfo contains detected DNS provider information for a domain.

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"`
	Headers       string `json:"headers,omitempty"`
	SigningDomain string `json:"signing_domain,omitempty"`
}

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"`
	SpfStatus       *string          `json:"spf_status"`
	DmarcStatus     *string          `json:"dmarc_status"`
	TrackingDomain  *string          `json:"tracking_domain"`
	DnsProvider     *DnsProviderInfo `json:"dns_provider"`
	IsPrimaryDomain bool             `json:"is_primary_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 DomainDnsVerificationView added in v0.2.0

type DomainDnsVerificationView struct {
	SpfRecord   *string `json:"spf_record,omitempty"`
	SpfError    *string `json:"spf_error,omitempty"`
	DkimRecord  *string `json:"dkim_record,omitempty"`
	DkimError   *string `json:"dkim_error,omitempty"`
	CnameRecord *string `json:"cname_record,omitempty"`
	CnameError  *string `json:"cname_error,omitempty"`
	DmarcRecord *string `json:"dmarc_record,omitempty"`
	DmarcError  *string `json:"dmarc_error,omitempty"`
}

DomainDnsVerificationView contains DNS verification error details.

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)

func (*DomainService) Verify added in v0.2.0

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

Verify triggers DNS record verification for a domain.

Example:

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

type DomainVerificationView added in v0.2.0

type DomainVerificationView struct {
	Domain            string                     `json:"domain"`
	DkimStatus        string                     `json:"dkim_status"`
	CnameStatus       string                     `json:"cname_status"`
	DmarcStatus       string                     `json:"dmarc_status"`
	SpfStatus         string                     `json:"spf_status"`
	IsPrimaryDomain   bool                       `json:"is_primary_domain"`
	OwnershipVerified *string                    `json:"ownership_verified"`
	Dmarc             *DmarcValidationResult     `json:"dmarc,omitempty"`
	Spf               *SpfValidationResult       `json:"spf,omitempty"`
	DNS               *DomainDnsVerificationView `json:"dns,omitempty"`
}

DomainVerificationView contains domain verification results.

type DoubleOptInConfig added in v1.2.0

type DoubleOptInConfig struct {
	From         string  `json:"from"`
	FromName     *string `json:"from_name,omitempty"`
	Subject      string  `json:"subject"`
	TemplateSlug string  `json:"template_slug"`
	RedirectURL  string  `json:"redirect_url"`
}

DoubleOptInConfig configures the confirmation email sent when a contact is created with double opt-in. When provided, the contact is created in "unverified" status until they click the confirmation link.

type EmailDetail added in v1.6.0

type EmailDetail struct {
	// TransmissionID is the provider's id, the same value that appears on
	// webhook events for this email.
	TransmissionID string       `json:"transmission_id"`
	State          string       `json:"state"`
	ScheduledAt    *string      `json:"scheduled_at"`
	From           string       `json:"from"`
	FromName       *string      `json:"from_name"`
	Subject        string       `json:"subject"`
	Recipients     []string     `json:"recipients"`
	NumRecipients  int          `json:"num_recipients"`
	Events         []EmailEvent `json:"events"`
}

EmailDetail is an already-sent email, reconstructed from its delivery events.

State here is derived from the events that arrived ("delivered", "bounced", "failed"), which is a different vocabulary from ScheduledEmail.State: that one is Lettr's own lifecycle and is known before anything is delivered.

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"`
	BounceClass           *int    `json:"bounce_class,omitempty"`
	// RcptMeta is polymorphic per spec: an object (in /emails list items)
	// or an array (in event-stream payloads like /emails/events), or null.
	// Type-assert to map[string]interface{} or []interface{} as appropriate.
	RcptMeta        interface{}      `json:"rcpt_meta"`
	TemplateID      *string          `json:"template_id,omitempty"`
	TemplateVersion *string          `json:"template_version,omitempty"`
	DelvMethod      *string          `json:"delv_method,omitempty"`
	RecvMethod      *string          `json:"recv_method,omitempty"`
	RoutingDomain   *string          `json:"routing_domain,omitempty"`
	ScheduledTime   *string          `json:"scheduled_time,omitempty"`
	CampaignID      *string          `json:"campaign_id,omitempty"`
	AbTestID        *string          `json:"ab_test_id,omitempty"`
	AbTestVersion   *string          `json:"ab_test_version,omitempty"`
	AmpEnabled      *bool            `json:"amp_enabled,omitempty"`
	RcptType        *string          `json:"rcpt_type,omitempty"`
	RcptTags        []string         `json:"rcpt_tags,omitempty"`
	IpPool          *string          `json:"ip_pool,omitempty"`
	MsgFrom         *string          `json:"msg_from,omitempty"`
	QueueTime       *int             `json:"queue_time,omitempty"`
	OutboundTls     *string          `json:"outbound_tls,omitempty"`
	InitialPixel    *bool            `json:"initial_pixel,omitempty"`
	NumRetries      *int             `json:"num_retries,omitempty"`
	DeviceToken     *string          `json:"device_token,omitempty"`
	TargetLinkURL   *string          `json:"target_link_url,omitempty"`
	TargetLinkName  *string          `json:"target_link_name,omitempty"`
	UserAgent       *string          `json:"user_agent,omitempty"`
	UserAgentParsed *UserAgentParsed `json:"user_agent_parsed,omitempty"`
	GeoIp           *GeoIp           `json:"geo_ip,omitempty"`
	IpAddress       *string          `json:"ip_address,omitempty"`
}

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) CancelScheduled added in v0.2.0

func (s *EmailService) CancelScheduled(ctx context.Context, id string) (*CancelScheduledResponse, error)

CancelScheduled cancels a scheduled email before it is sent, and returns it in its cancelled state.

Only an email still in ScheduledStateScheduled can be cancelled; past that it is with the provider, which offers no per-message recall, and the call fails with a 409.

Example:

resp, err := client.Emails.CancelScheduled(ctx, "sch_01M322YMWVCZ4RNYXHMSSMDTM1")
resp.Data.State // lettr.ScheduledStateCancelled

func (*EmailService) Get

func (s *EmailService) Get(ctx context.Context, requestID string, params *GetEmailParams) (*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", nil)

func (*EmailService) GetScheduled added in v0.2.0

func (s *EmailService) GetScheduled(ctx context.Context, id string) (*GetScheduledEmailResponse, error)

GetScheduled retrieves a scheduled email by its RequestID.

A provider transmission id stored before Lettr owned the schedule still resolves, answered from delivery events. That older shape carries no request_id, so RequestID is filled in from the id you asked about and always holds the id that addresses this email.

Example:

scheduled, err := client.Emails.GetScheduled(ctx, "sch_01M322YMWVCZ4RNYXHMSSMDTM1")

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) ListEvents added in v0.2.0

ListEvents retrieves email delivery events (opens, bounces, clicks, etc.) with optional filtering.

Pass nil for params to use defaults.

Example:

events, err := client.Emails.ListEvents(ctx, &lettr.ListEmailEventsParams{
    Events:  []string{"delivery", "bounce"},
    PerPage: 50,
})

func (*EmailService) ListScheduled added in v1.6.0

ListScheduled retrieves a paginated list of scheduled emails.

Pass nil for params to use defaults.

Example:

resp, err := client.Emails.ListScheduled(ctx, &lettr.ListScheduledEmailsParams{
    Status: lettr.ScheduledStateScheduled,
})

func (*EmailService) Schedule added in v0.2.0

Schedule queues an email for future delivery.

The delivery time must be at least 5 minutes and at most 30 days out. The response is the scheduled email itself, so there is no need to read it back to learn its state.

Example:

resp, err := client.Emails.Schedule(ctx, &lettr.ScheduleEmailRequest{
    SendEmailRequest: lettr.SendEmailRequest{
        From:    "sender@example.com",
        To:      []string{"recipient@example.com"},
        Subject: "Scheduled Hello",
        Html:    "<h1>Hello!</h1>",
    },
    ScheduledAt: "2024-12-25T10:00:00Z",
})

resp.Data.RequestID // "sch_…" — pass this to GetScheduled and CancelScheduled

func (*EmailService) Send

func (s *EmailService) Send(ctx context.Context, params *SendEmailRequest, opts ...SendOption) (*SendEmailResponse, error)

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>",
})

Pass WithIdempotencyKey to make a retry safe:

resp, err := client.Emails.Send(ctx, params,
    lettr.WithIdempotencyKey("order-confirmation-12345"))

resp.Data.Replayed // true → this replayed an earlier send

The options are variadic, so existing two-argument calls are unaffected.

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"`

	// RetryAfter is the Retry-After header in seconds, when the API sent one.
	//
	// It is what separates the retryable failures from the permanent ones:
	// idempotency_in_progress carries it and should be retried with the same
	// key, while idempotency_key_conflict does not and never will succeed.
	RetryAfter int `json:"-"`

	// 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.

func (*Error) UnmarshalJSON added in v1.2.0

func (e *Error) UnmarshalJSON(data []byte) error

UnmarshalJSON tolerates a PHP/Laravel serialization quirk where an empty associative array can come over the wire as `[]` instead of `{}`. For Error.Errors that means a 422 response with no field-level errors may carry `"errors": []`; without this tolerance the standard library would fail with "cannot unmarshal array into Go struct field … of type map[string][]string" and the SDK would surface a confusing decode error instead of the real 422.

type Folder added in v1.5.0

type Folder struct {
	ID             int             `json:"id"`
	Name           string          `json:"name"`
	ProjectID      int             `json:"project_id"`
	Purpose        TemplatePurpose `json:"purpose"`
	TemplatesCount int             `json:"templates_count"`
	CreatedAt      string          `json:"created_at"`
	UpdatedAt      string          `json:"updated_at"`
}

Folder is a folder templates are filed into.

ID is what CreateTemplateRequest.FolderID expects, so listing folders is how a caller picks where a template lands instead of hardcoding an integer read out of an app URL.

type FolderService added in v1.5.0

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

FolderService handles communication with the folder-related endpoints of the Lettr API.

Read-only: creating, renaming and deleting folders stay in the app, because deleting one moves or deletes the templates inside it.

func (*FolderService) List added in v1.5.0

List retrieves the folders templates are filed into.

Pass nil for params to use defaults.

Example:

folders, err := client.Folders.List(ctx, &lettr.ListFoldersParams{
    Purpose: lettr.PurposeCampaign,
})

type GeoIp added in v0.2.0

type GeoIp struct {
	Country    string  `json:"country,omitempty"`
	Region     string  `json:"region,omitempty"`
	City       string  `json:"city,omitempty"`
	PostalCode string  `json:"postal_code,omitempty"`
	Zip        string  `json:"zip,omitempty"`
	Latitude   float64 `json:"latitude,omitempty"`
	Longitude  float64 `json:"longitude,omitempty"`
}

GeoIp contains geolocation data derived from IP address of open/click events.

type GetDomainResponse

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

GetDomainResponse is the response from getting a single domain.

type GetEmailParams added in v0.2.0

type GetEmailParams struct {
	// From is the start date for event search range (ISO 8601). Defaults to 10 days ago.
	From string

	// To is the end date for event search range (ISO 8601). Defaults to now.
	To string
}

GetEmailParams contains optional query parameters for getting email details.

type GetEmailResponse

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

GetEmailResponse is the response from getting email details.

type GetMergeTagsData added in v0.2.0

type GetMergeTagsData struct {
	ProjectID    int        `json:"project_id"`
	TemplateSlug string     `json:"template_slug"`
	Version      int        `json:"version"`
	MergeTags    []MergeTag `json:"merge_tags"`
}

GetMergeTagsData contains merge tags for a template version.

type GetMergeTagsParams added in v0.2.0

type GetMergeTagsParams struct {
	// ProjectID is the project containing the template.
	ProjectID int

	// Version is the template version number. Uses active version if not set.
	Version int
}

GetMergeTagsParams contains optional query parameters for getting merge tags.

type GetMergeTagsResponse added in v0.2.0

type GetMergeTagsResponse struct {
	Message string           `json:"message"`
	Data    GetMergeTagsData `json:"data"`
}

GetMergeTagsResponse is the response from getting merge tags.

type GetScheduledEmailResponse added in v0.2.0

type GetScheduledEmailResponse struct {
	Message string         `json:"message"`
	Data    ScheduledEmail `json:"data"`
}

GetScheduledEmailResponse is the response from getting a scheduled email.

type GetTemplateHtmlData added in v0.2.0

type GetTemplateHtmlData struct {
	Html      string         `json:"html"`
	MergeTags []HtmlMergeTag `json:"merge_tags"`
	Subject   *string        `json:"subject,omitempty"`
}

GetTemplateHtmlData contains the HTML content and merge tags of a template.

type GetTemplateHtmlParams added in v0.2.0

type GetTemplateHtmlParams struct {
	// ProjectID is the project containing the template (required).
	ProjectID int

	// Slug is the template slug identifier (required).
	Slug string
}

GetTemplateHtmlParams contains the query parameters for getting template HTML.

type GetTemplateHtmlResponse added in v0.2.0

type GetTemplateHtmlResponse struct {
	Success bool                `json:"success"`
	Data    GetTemplateHtmlData `json:"data"`
}

GetTemplateHtmlResponse is the response from getting template HTML.

type GetTemplateParams added in v0.2.0

type GetTemplateParams struct {
	// ProjectID is the project to look in. Uses team's default if not set.
	ProjectID int
}

GetTemplateParams contains optional query parameters for getting a template.

type GetTemplateResponse added in v0.2.0

type GetTemplateResponse struct {
	Message string         `json:"message"`
	Data    TemplateDetail `json:"data"`
}

GetTemplateResponse is the response from getting a single template.

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 HtmlMergeTag added in v0.2.0

type HtmlMergeTag struct {
	Key      string `json:"key"`
	Name     string `json:"name"`
	Required bool   `json:"required"`
}

HtmlMergeTag represents a merge tag in the template HTML response. This differs from MergeTag by including a Name field.

type ListAudienceContactsData added in v1.2.0

type ListAudienceContactsData struct {
	Contacts   []AudienceContact `json:"contacts"`
	Pagination PagePagination    `json:"pagination"`
}

ListAudienceContactsData contains the paginated list of contacts.

type ListAudienceContactsParams added in v1.2.0

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

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

	// Search filters by email or contact name (max 255 chars).
	Search string

	// Status filters by contact status. Use the ContactStatus* constants.
	Status string

	// ListID filters to contacts in a specific list.
	ListID string

	// SegmentID filters to contacts matching a specific segment.
	SegmentID string
}

ListAudienceContactsParams contains the query parameters for listing contacts.

type ListAudienceContactsResponse added in v1.2.0

type ListAudienceContactsResponse struct {
	Message string                   `json:"message"`
	Data    ListAudienceContactsData `json:"data"`
}

ListAudienceContactsResponse is the response from listing audience contacts.

type ListAudienceListsData added in v1.2.0

type ListAudienceListsData struct {
	Lists      []AudienceList `json:"lists"`
	Pagination PagePagination `json:"pagination"`
}

ListAudienceListsData contains the paginated list of audience lists.

type ListAudienceListsParams added in v1.2.0

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

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

ListAudienceListsParams contains the query parameters for listing audience lists.

type ListAudienceListsResponse added in v1.2.0

type ListAudienceListsResponse struct {
	Message string                `json:"message"`
	Data    ListAudienceListsData `json:"data"`
}

ListAudienceListsResponse is the response from listing audience lists.

type ListAudiencePropertiesData added in v1.2.0

type ListAudiencePropertiesData struct {
	Properties []AudienceProperty `json:"properties"`
	Pagination PagePagination     `json:"pagination"`
}

ListAudiencePropertiesData contains the paginated list of properties.

type ListAudiencePropertiesParams added in v1.2.0

type ListAudiencePropertiesParams struct {
	PerPage int
	Page    int
}

ListAudiencePropertiesParams contains the query parameters for listing properties.

type ListAudiencePropertiesResponse added in v1.2.0

type ListAudiencePropertiesResponse struct {
	Message string                     `json:"message"`
	Data    ListAudiencePropertiesData `json:"data"`
}

ListAudiencePropertiesResponse is the response from listing properties.

type ListAudienceSegmentsData added in v1.2.0

type ListAudienceSegmentsData struct {
	Segments   []AudienceSegment `json:"segments"`
	Pagination PagePagination    `json:"pagination"`
}

ListAudienceSegmentsData contains the paginated list of segments.

type ListAudienceSegmentsParams added in v1.2.0

type ListAudienceSegmentsParams struct {
	PerPage int
	Page    int

	// ListID filters segments to those restricted to a specific list.
	ListID string
}

ListAudienceSegmentsParams contains the query parameters for listing segments.

type ListAudienceSegmentsResponse added in v1.2.0

type ListAudienceSegmentsResponse struct {
	Message string                   `json:"message"`
	Data    ListAudienceSegmentsData `json:"data"`
}

ListAudienceSegmentsResponse is the response from listing segments.

type ListAudienceTopicsData added in v1.2.0

type ListAudienceTopicsData struct {
	Topics     []AudienceTopic `json:"topics"`
	Pagination PagePagination  `json:"pagination"`
}

ListAudienceTopicsData contains the paginated list of topics.

type ListAudienceTopicsParams added in v1.2.0

type ListAudienceTopicsParams struct {
	PerPage int
	Page    int
}

ListAudienceTopicsParams contains the query parameters for listing topics.

type ListAudienceTopicsResponse added in v1.2.0

type ListAudienceTopicsResponse struct {
	Message string                 `json:"message"`
	Data    ListAudienceTopicsData `json:"data"`
}

ListAudienceTopicsResponse is the response from listing topics.

type ListCampaignEventsData added in v1.3.0

type ListCampaignEventsData struct {
	Events     []CampaignEvent `json:"events"`
	NextCursor *string         `json:"next_cursor"`
}

ListCampaignEventsData contains a page of campaign events. An empty Events slice together with a non-nil NextCursor means more pages exist; NextCursor is nil when there are no more events.

Note: this endpoint does not nest its cursor under a "pagination" envelope (and does not echo per_page) the way /emails/events does, so it cannot directly reuse CursorPagination — the wire shape genuinely differs.

type ListCampaignEventsParams added in v1.3.0

type ListCampaignEventsParams struct {
	// EventType filters by event type (e.g. CampaignEventTypeOpen). Optional.
	EventType string

	// Email filters events to a single recipient address. Optional.
	Email string

	// StartDate is the start of the date range (ISO 8601). A date-only value
	// is treated as the start of that day in UTC. Optional.
	StartDate string

	// EndDate is the end of the date range (ISO 8601). A date-only value
	// covers the whole day in UTC. Optional.
	EndDate string

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

	// Cursor is the pagination cursor returned as NextCursor by a prior call.
	Cursor string
}

ListCampaignEventsParams contains the query parameters for listing campaign engagement events.

type ListCampaignEventsResponse added in v1.3.0

type ListCampaignEventsResponse struct {
	Message string                 `json:"message"`
	Data    ListCampaignEventsData `json:"data"`
}

ListCampaignEventsResponse is the response from listing campaign events.

type ListCampaignsData added in v1.3.0

type ListCampaignsData struct {
	Campaigns  []Campaign     `json:"campaigns"`
	Pagination PagePagination `json:"pagination"`
}

ListCampaignsData contains the paginated list of campaigns.

type ListCampaignsParams added in v1.3.0

type ListCampaignsParams struct {
	// Page is the page number (default 1).
	Page int

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

	// Status filters by campaign status (e.g. CampaignStatusSent). Optional.
	Status string
}

ListCampaignsParams contains the query parameters for listing campaigns.

type ListCampaignsResponse added in v1.3.0

type ListCampaignsResponse struct {
	Message string            `json:"message"`
	Data    ListCampaignsData `json:"data"`
}

ListCampaignsResponse is the response from listing campaigns.

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 ListEmailEventsData added in v0.2.0

type ListEmailEventsData struct {
	Events ListEmailEventsEvents `json:"events"`
}

ListEmailEventsData wraps the paginated email events returned by the API.

type ListEmailEventsEvents added in v0.2.0

type ListEmailEventsEvents struct {
	Data       []EmailEvent     `json:"data"`
	TotalCount int              `json:"total_count"`
	From       string           `json:"from"`
	To         string           `json:"to"`
	Pagination CursorPagination `json:"pagination"`
}

ListEmailEventsEvents contains the paginated list of email events plus the query date range echoed back by the API.

type ListEmailEventsParams added in v0.2.0

type ListEmailEventsParams struct {
	// Events filters by event types (e.g. "delivery", "bounce", "open", "click").
	Events []string

	// Recipients filters by recipient email addresses.
	Recipients []string

	// Transmissions filters by transmission ID.
	Transmissions string

	// BounceClasses filters by bounce classification codes.
	BounceClasses []int

	// From is the start date for events (ISO 8601). Defaults to 10 days ago.
	From string

	// To is the end date for events (ISO 8601). Defaults to now.
	To string

	// PerPage is the number of events per page.
	PerPage int

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

ListEmailEventsParams contains the query parameters for listing email events.

type ListEmailEventsResponse added in v0.2.0

type ListEmailEventsResponse struct {
	Message string              `json:"message"`
	Data    ListEmailEventsData `json:"data"`
}

ListEmailEventsResponse is the response from listing email events.

type ListEmailsData

type ListEmailsData struct {
	Events ListEmailsEvents `json:"events"`
}

ListEmailsData wraps the paginated email events returned by the API.

type ListEmailsEvents added in v0.2.0

type ListEmailsEvents struct {
	Data       []EmailEvent     `json:"data"`
	TotalCount int              `json:"total_count"`
	From       string           `json:"from"`
	To         string           `json:"to"`
	Pagination CursorPagination `json:"pagination"`
}

ListEmailsEvents contains the paginated list of email events plus the query date range echoed back by the API.

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 ListFoldersData added in v1.5.0

type ListFoldersData struct {
	Folders    []Folder       `json:"folders"`
	Pagination PagePagination `json:"pagination"`
}

ListFoldersData contains the paginated list of folders.

type ListFoldersParams added in v1.5.0

type ListFoldersParams struct {
	// ProjectID is the project to list folders from. Uses the team's default
	// project if not set, the same way Templates.List resolves it.
	ProjectID int

	// Purpose narrows the list to one module. Both are returned if not set.
	Purpose TemplatePurpose

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

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

ListFoldersParams contains the query parameters for listing folders.

type ListFoldersResponse added in v1.5.0

type ListFoldersResponse struct {
	Message string          `json:"message"`
	Data    ListFoldersData `json:"data"`
}

ListFoldersResponse is the response from listing folders.

type ListProjectsData added in v0.2.0

type ListProjectsData struct {
	Projects   []Project      `json:"projects"`
	Pagination PagePagination `json:"pagination"`
}

ListProjectsData contains the paginated list of projects.

type ListProjectsParams added in v0.2.0

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

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

ListProjectsParams contains the query parameters for listing projects.

type ListProjectsResponse added in v0.2.0

type ListProjectsResponse struct {
	Message string           `json:"message"`
	Data    ListProjectsData `json:"data"`
}

ListProjectsResponse is the response from listing projects.

type ListScheduledEmailsData added in v1.6.0

type ListScheduledEmailsData struct {
	ScheduledEmails []ScheduledEmail `json:"scheduled_emails"`
	Pagination      PagePagination   `json:"pagination"`
}

ListScheduledEmailsData contains the paginated list of scheduled emails.

type ListScheduledEmailsParams added in v1.6.0

type ListScheduledEmailsParams struct {
	// Status narrows the list to one state. All states are returned if not set.
	Status ScheduledEmailState

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

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

ListScheduledEmailsParams contains the query parameters for listing scheduled emails.

type ListScheduledEmailsResponse added in v1.6.0

type ListScheduledEmailsResponse struct {
	Message string                  `json:"message"`
	Data    ListScheduledEmailsData `json:"data"`
}

ListScheduledEmailsResponse is the response from listing scheduled 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

	// FolderID narrows the list to one folder of that project. Discover ids
	// with Folders.List.
	//
	// One PerPage=100 call reconciles a whole bulk import instead of a detail
	// call per template, each of which drags the full HTML payload against the
	// same rate limit.
	//
	// A folder that is not in the resolved project is a 404, not an empty
	// list, so a typo cannot be misread as "nothing is there yet".
	FolderID int

	// Purpose narrows the list to one module. Both are returned if not set.
	Purpose TemplatePurpose

	// 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"`
	Type     string          `json:"type,omitempty"`
	Children []MergeTagChild `json:"children,omitempty"`
}

MergeTag represents a merge tag extracted from template content.

type MergeTagChild added in v0.2.0

type MergeTagChild struct {
	Key  string `json:"key"`
	Type string `json:"type,omitempty"`
}

MergeTagChild represents a child merge tag within a loop block.

type NullString added in v1.2.0

type NullString struct {
	String string
	// Valid indicates whether String is the value to send. When false, the
	// NullString marshals to JSON null regardless of String.
	Valid bool
}

NullString lets PATCH callers distinguish three intents for a nullable string field on the wire. Field names and zero-value semantics mirror database/sql's NullString: the zero value is null.

  • nil *NullString → omit the field entirely (server keeps the existing value)
  • &NullString{} → send JSON null (server clears the field)
  • &NullString{Valid: true, String: "x"} → send the JSON string "x" (use NewNullString as shorthand)

Plain Go *string + ,omitempty cannot represent the three states because the json package treats a nil pointer the same as a missing field. NullString fills that gap for the audience PATCH endpoints where the API distinguishes "field omitted" (no change) from "field is null" (clear).

func NewNullString added in v1.2.0

func NewNullString(s string) *NullString

NewNullString returns a NullString that marshals to the given JSON string. It is shorthand for &NullString{Valid: true, String: s}.

func (*NullString) MarshalJSON added in v1.2.0

func (n *NullString) MarshalJSON() ([]byte, error)

MarshalJSON implements json.Marshaler.

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 Project added in v0.2.0

type Project struct {
	ID        int     `json:"id"`
	Name      string  `json:"name"`
	TeamID    int     `json:"team_id"`
	CreatedAt string  `json:"created_at"`
	UpdatedAt string  `json:"updated_at"`
	Emoji     *string `json:"emoji"`
}

Project represents a project.

type ProjectService added in v0.2.0

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

ProjectService handles communication with the project-related endpoints of the Lettr API.

func (*ProjectService) List added in v0.2.0

List retrieves a paginated list of projects associated with the team.

Pass nil for params to use defaults.

Example:

projects, err := client.Projects.List(ctx, nil)

type ScheduleCampaignRequest added in v1.3.0

type ScheduleCampaignRequest struct {
	// ScheduledAt is the future delivery time (ISO 8601). Include a timezone
	// offset (e.g. "+02:00" or "Z"); a value without an offset is interpreted
	// as UTC. Must be in the future.
	ScheduledAt string `json:"scheduled_at"`
}

ScheduleCampaignRequest is the body for scheduling a campaign.

type ScheduleEmailRequest added in v0.2.0

type ScheduleEmailRequest struct {
	SendEmailRequest

	// ScheduledAt is the time to send the email (ISO 8601).
	// Must be at least 5 minutes in the future and at most 30 days.
	ScheduledAt string `json:"scheduled_at"`
}

ScheduleEmailRequest represents the request body for scheduling an email for future delivery.

type ScheduleEmailResponse added in v0.2.0

type ScheduleEmailResponse struct {
	Message string         `json:"message"`
	Data    ScheduledEmail `json:"data"`
}

ScheduleEmailResponse is the response from scheduling an email.

type ScheduledEmail added in v1.6.0

type ScheduledEmail struct {
	RequestID      string              `json:"request_id"`
	TransmissionID *string             `json:"transmission_id"`
	State          ScheduledEmailState `json:"state"`

	// ScheduledAt is the delivery time (ISO 8601). It is nil only on the
	// legacy read path described on GetScheduled.
	ScheduledAt *string `json:"scheduled_at"`

	From          string   `json:"from"`
	FromName      *string  `json:"from_name"`
	Subject       *string  `json:"subject"`
	Recipients    []string `json:"recipients"`
	NumRecipients int      `json:"num_recipients"`

	// Accepted and Rejected are the provider's counts once the email has been
	// sent, and before that describe what Lettr took on for delivery — so a
	// cancelled email reads back as 0 accepted, not 1.
	Accepted int `json:"accepted"`
	Rejected int `json:"rejected"`

	Tag *string `json:"tag"`

	// FailureReason is set only in ScheduledStateFailed.
	FailureReason *string `json:"failure_reason"`

	// Events are the delivery events, which only exist once the email has been
	// handed over.
	Events []EmailEvent `json:"events"`
}

ScheduledEmail is an email Lettr is holding until its delivery time.

It carries two ids, and they are not interchangeable:

  • RequestID ("sch_…") is Lettr's own id. It is what GetScheduled and CancelScheduled take.
  • TransmissionID is the provider's id, nil until the email is actually handed over. It is the value webhook events carry, so it is what correlates this email with the webhooks it produces.

type ScheduledEmailState added in v1.6.0

type ScheduledEmailState string

ScheduledEmailState is the lifecycle of a scheduled email.

Lettr holds the email in its own store until it is due, so these states are Lettr's and are authoritative from the moment of scheduling. The provider never sees a future-dated message, which is why a cancelled email can be told apart from one that never existed.

const (
	// ScheduledStateScheduled is waiting for its delivery time. The only state
	// CancelScheduled accepts.
	ScheduledStateScheduled ScheduledEmailState = "scheduled"

	// ScheduledStateSending is being handed to the provider right now.
	ScheduledStateSending ScheduledEmailState = "sending"

	// ScheduledStateSent has been handed over. TransmissionID is set from here
	// on, and delivery detail comes from the events API.
	ScheduledStateSent ScheduledEmailState = "sent"

	// ScheduledStateCancelled was cancelled before hand-off, so nothing was sent.
	ScheduledStateCancelled ScheduledEmailState = "cancelled"

	// ScheduledStateFailed gave up trying to hand the email over. FailureReason
	// says why.
	ScheduledStateFailed ScheduledEmailState = "failed"

	// The states below are the provider's, not Lettr's. GetScheduled reports
	// them only on the legacy read path, which answers from delivery events in
	// the provider's own vocabulary - never for a sch_ id.
	//
	// Deprecated: legacy provider state, from a numeric transmission id.
	ScheduledStateSubmitted ScheduledEmailState = "submitted"
	// Deprecated: legacy provider state, from a numeric transmission id.
	ScheduledStateGenerating ScheduledEmailState = "generating"
	// Deprecated: legacy provider state, from a numeric transmission id.
	ScheduledStateDelivered ScheduledEmailState = "delivered"
	// Deprecated: legacy provider state, from a numeric transmission id.
	ScheduledStateBounced ScheduledEmailState = "bounced"
)

func (ScheduledEmailState) IsCancellable added in v1.6.0

func (s ScheduledEmailState) IsCancellable() bool

IsCancellable reports whether CancelScheduled would still be honoured.

Once the email is with the provider there is no per-message recall, so cancelling anything past "scheduled" returns a 409 rather than stopping it.

type ScheduledTransmission deprecated added in v0.2.0

type ScheduledTransmission = ScheduledEmail

ScheduledTransmission is the former name of ScheduledEmail.

Deprecated: renamed to ScheduledEmail. If you used it for Emails.Get rather than the scheduled endpoints, that response now has its own type, EmailDetail.

type SegmentCondition added in v1.2.0

type SegmentCondition struct {
	Field    string  `json:"field"`
	Operator string  `json:"operator"`
	Value    *string `json:"value,omitempty"`
}

SegmentCondition is a single field/operator/value match. Value is optional and not required when Operator is "is_true" or "is_false".

type SegmentConditionGroup added in v1.2.0

type SegmentConditionGroup struct {
	Conditions []SegmentCondition `json:"conditions"`
}

SegmentConditionGroup is a set of conditions joined by OR. Multiple groups within a segment are joined by AND, i.e. (A OR B) AND (C OR D).

type SegmentConditionsInput added in v1.2.0

type SegmentConditionsInput struct {
	Groups []SegmentConditionGroup `json:"groups"`
}

SegmentConditionsInput is the request-side wrapper for segment conditions.

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"`

	// Replayed is true when this response replayed an earlier send under the
	// same idempotency key - no second email went out. It is still a success.
	//
	// Read from the Idempotency-Replayed response header rather than the body,
	// so it is only ever set when WithIdempotencyKey was used.
	Replayed bool `json:"-"`
}

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"`

	// InlineCss enables inlining CSS styles in HTML content.
	InlineCss *bool `json:"inline_css,omitempty"`

	// PerformSubstitutions enables variable substitutions in content.
	PerformSubstitutions *bool `json:"perform_substitutions,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"`

	// Cc is the list of carbon copy recipient email addresses (optional).
	Cc []string `json:"cc,omitempty"`

	// Bcc is the list of blind carbon copy recipient email addresses (optional).
	Bcc []string `json:"bcc,omitempty"`

	// Subject is the email subject line (required unless using template_slug).
	Subject string `json:"subject,omitempty"`

	// 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"`

	// AmpHtml is the AMP HTML content for supported email clients (optional).
	AmpHtml string `json:"amp_html,omitempty"`

	// ReplyTo is the reply-to email address (optional).
	ReplyTo string `json:"reply_to,omitempty"`

	// ReplyToName is the reply-to display name (optional).
	ReplyToName string `json:"reply_to_name,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]string `json:"substitution_data,omitempty"`

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

	// Tag is a tag for tracking and analytics (optional).
	Tag string `json:"tag,omitempty"`

	// Headers contains custom email headers (up to 10, optional).
	Headers map[string]string `json:"headers,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 SendOption added in v1.5.0

type SendOption func(*sendConfig)

SendOption configures a single Send call.

func WithIdempotencyKey added in v1.5.0

func WithIdempotencyKey(key string) SendOption

WithIdempotencyKey sends the given Idempotency-Key with the request.

Reuse the key when you retry and the API returns the original result instead of delivering a second email, with SendEmailData.Replayed set.

You choose the key; the SDK never generates one. It only works if both attempts use the same value, and the SDK does not retry - one Send is one HTTP request - so the retry is yours, and only you know that two calls are the same logical send. A key generated inside Send would differ on every attempt and protect nothing while looking like it did.

The key must be 1-255 characters of [A-Za-z0-9._-]; Send returns an error before making a request if it is not.

type SpfValidationResult added in v0.2.0

type SpfValidationResult struct {
	IsValid           bool    `json:"is_valid"`
	Status            string  `json:"status"`
	Record            *string `json:"record"`
	Error             *string `json:"error"`
	IncludesSparkpost bool    `json:"includes_sparkpost"`
}

SpfValidationResult contains SPF validation details.

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"`
	Purpose           TemplatePurpose           `json:"purpose"`
	PreparationStatus TemplatePreparationStatus `json:"preparation_status"`
	CreatedAt         string                    `json:"created_at"`
	UpdatedAt         string                    `json:"updated_at"`
}

Template represents an email template.

type TemplateDetail added in v0.2.0

type TemplateDetail struct {
	ID                int                       `json:"id"`
	Name              string                    `json:"name"`
	Slug              string                    `json:"slug"`
	ProjectID         int                       `json:"project_id"`
	FolderID          int                       `json:"folder_id"`
	Purpose           TemplatePurpose           `json:"purpose"`
	PreparationStatus TemplatePreparationStatus `json:"preparation_status"`
	ActiveVersion     *int                      `json:"active_version"`
	VersionsCount     int                       `json:"versions_count"`
	Html              string                    `json:"html,omitempty"`
	Json              string                    `json:"json,omitempty"`
	CreatedAt         string                    `json:"created_at"`
	UpdatedAt         string                    `json:"updated_at"`
}

TemplateDetail represents detailed information about a template, including version info and content.

type TemplatePreparationStatus added in v1.5.0

type TemplatePreparationStatus string

TemplatePreparationStatus is how far a template has got through preparation.

Creating or updating a template through the API defers image migration and HTML rendering to a background job. On a create with JSON there is no HTML at all until it finishes; on an update the previous render stays in place, so the template is still sendable but is serving the old content.

const (
	PreparationPending TemplatePreparationStatus = "pending"
	PreparationReady   TemplatePreparationStatus = "ready"
	PreparationFailed  TemplatePreparationStatus = "failed"
)

func (TemplatePreparationStatus) Settled added in v1.5.0

func (s TemplatePreparationStatus) Settled() bool

Settled reports whether the content you last sent is the content that will go out.

Deliberately not named Ready: this is not the same question as "can I send this". A template being prepared after an update keeps its previous render and stays sendable.

An empty status - from an API deployment that predates the field - counts as settled, because there every template with HTML was simply usable. Treating it as pending would make an old API look like a stalled queue.

type TemplatePurpose added in v1.5.0

type TemplatePurpose string

TemplatePurpose is the module a template belongs to.

The two do not mix: only campaign templates can be picked by the campaign builder, and only transactional ones can be sent as single emails.

const (
	PurposeTransactional TemplatePurpose = "transactional"
	PurposeCampaign      TemplatePurpose = "campaign"
)

func (TemplatePurpose) IsCampaign added in v1.5.0

func (p TemplatePurpose) IsCampaign() bool

IsCampaign reports whether the template belongs to the campaign module.

An empty purpose - from an API deployment that predates the field - counts as transactional, which is what such a template was.

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) Delete added in v0.2.0

Delete permanently removes a template.

Pass nil for params to use the team's default project.

Example:

resp, err := client.Templates.Delete(ctx, "welcome-email", nil)

func (*TemplateService) Get added in v0.2.0

Get retrieves details of a single template by its slug.

Pass nil for params to use the team's default project.

Example:

template, err := client.Templates.Get(ctx, "welcome-email", nil)

func (*TemplateService) GetHtml added in v0.2.0

GetHtml retrieves the rendered HTML content of a template.

Example:

html, err := client.Templates.GetHtml(ctx, &lettr.GetTemplateHtmlParams{
    ProjectID: 1,
    Slug:      "welcome-email",
})

func (*TemplateService) GetMergeTags added in v0.2.0

func (s *TemplateService) GetMergeTags(ctx context.Context, slug string, params *GetMergeTagsParams) (*GetMergeTagsResponse, error)

GetMergeTags retrieves the merge tags for a template.

Pass nil for params to use defaults (team's default project, active version).

Example:

tags, err := client.Templates.GetMergeTags(ctx, "welcome-email", nil)

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)

func (*TemplateService) Update added in v0.2.0

Update modifies an existing template's name or content.

Example:

updated, err := client.Templates.Update(ctx, "welcome-email", &lettr.UpdateTemplateRequest{
    Html: "<h1>Updated Hello {{FIRST_NAME}}!</h1>",
})

type UpdateAudienceContactRequest added in v1.2.0

type UpdateAudienceContactRequest struct {
	Email      string             `json:"email,omitempty"`
	Status     string             `json:"status,omitempty"`
	Properties map[string]*string `json:"properties,omitempty"`
}

UpdateAudienceContactRequest is the body for partially updating a contact. A property set to a nil pointer in Properties is sent as JSON null and removes that property from the contact server-side.

type UpdateAudienceListRequest added in v1.2.0

type UpdateAudienceListRequest struct {
	Name string `json:"name,omitempty"`
}

UpdateAudienceListRequest is the body for partially updating an audience list.

type UpdateAudiencePropertyRequest added in v1.2.0

type UpdateAudiencePropertyRequest struct {
	FallbackValue *NullString `json:"fallback_value,omitempty"`
}

UpdateAudiencePropertyRequest is the body for updating a property's fallback value. The name and type fields are immutable.

FallbackValue is a nullable PATCH field: leave it nil to omit, NewNullString("x") to replace, or &NullString{} (zero value) to clear the existing fallback server-side.

type UpdateAudienceSegmentRequest added in v1.2.0

type UpdateAudienceSegmentRequest struct {
	Name       string                  `json:"name,omitempty"`
	ListID     *NullString             `json:"list_id,omitempty"`
	Conditions *SegmentConditionsInput `json:"conditions,omitempty"`
}

UpdateAudienceSegmentRequest is the body for partially updating a segment.

ListID is a nullable PATCH field: leave it nil to omit, NewNullString(uuid) to restrict, or &NullString{} (zero value) to clear the list restriction (so the segment matches across all lists).

type UpdateAudienceTopicRequest added in v1.2.0

type UpdateAudienceTopicRequest struct {
	Name        string      `json:"name,omitempty"`
	Description *NullString `json:"description,omitempty"`
	Visibility  string      `json:"visibility,omitempty"`
}

UpdateAudienceTopicRequest is the body for partially updating a topic. The default_subscription field is immutable and cannot be sent.

Description is a nullable PATCH field: leave it nil to omit, NewNullString("x") to replace, or &NullString{} (zero value) to clear the existing description server-side.

type UpdateTemplateData added in v0.2.0

type UpdateTemplateData 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"`
	UpdatedAt     string     `json:"updated_at"`
}

UpdateTemplateData contains the result of updating a template.

type UpdateTemplateRequest added in v0.2.0

type UpdateTemplateRequest struct {
	// Name is the new name for the template.
	Name string `json:"name,omitempty"`

	// Html is new HTML content (creates a new active version).
	Html string `json:"html,omitempty"`

	// Json is new Topol editor JSON content (creates a new active version).
	Json string `json:"json,omitempty"`

	// ProjectID is the project containing the template.
	ProjectID *int `json:"project_id,omitempty"`
}

UpdateTemplateRequest represents the request body for updating a template.

type UpdateTemplateResponse added in v0.2.0

type UpdateTemplateResponse struct {
	Message string             `json:"message"`
	Data    UpdateTemplateData `json:"data"`
}

UpdateTemplateResponse is the response from updating a template.

type UpdateWebhookRequest added in v0.2.0

type UpdateWebhookRequest struct {
	Name string `json:"name,omitempty"`
	// URL is the destination endpoint for webhook deliveries.
	URL string `json:"url,omitempty"`
	// Deprecated: use URL instead. Target is retained for backwards compatibility
	// and will be removed in a future major release.
	Target            string   `json:"target,omitempty"`
	AuthType          string   `json:"auth_type,omitempty"`
	AuthUsername      string   `json:"auth_username,omitempty"`
	AuthPassword      string   `json:"auth_password,omitempty"`
	OAuthClientID     string   `json:"oauth_client_id,omitempty"`
	OAuthClientSecret string   `json:"oauth_client_secret,omitempty"`
	OAuthTokenURL     string   `json:"oauth_token_url,omitempty"`
	Events            []string `json:"events,omitempty"`
	Active            *bool    `json:"active,omitempty"`
}

UpdateWebhookRequest represents the request body for updating a webhook.

type UpdateWebhookResponse added in v0.2.0

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

UpdateWebhookResponse is the response from updating a webhook.

type UserAgentParsed added in v0.2.0

type UserAgentParsed struct {
	AgentFamily  string `json:"agent_family,omitempty"`
	OsFamily     string `json:"os_family,omitempty"`
	OsVersion    string `json:"os_version,omitempty"`
	DeviceFamily string `json:"device_family,omitempty"`
	DeviceBrand  string `json:"device_brand,omitempty"`
	IsMobile     bool   `json:"is_mobile,omitempty"`
	IsProxy      bool   `json:"is_proxy,omitempty"`
	IsPrefetched bool   `json:"is_prefetched,omitempty"`
}

UserAgentParsed contains parsed user agent information from open/click events.

type VerifyDomainResponse added in v0.2.0

type VerifyDomainResponse struct {
	Message string                 `json:"message"`
	Data    DomainVerificationView `json:"data"`
}

VerifyDomainResponse is the response from verifying a domain.

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) Create added in v0.2.0

Create creates a new webhook for event notifications.

Event names use the namespaced form ("message.delivery", "engagement.click", etc.) — see the Event* constants in this package.

Example:

webhook, err := client.Webhooks.Create(ctx, &lettr.CreateWebhookRequest{
    Name:       "My Webhook",
    URL:        "https://example.com/webhook",
    AuthType:   "none",
    EventsMode: "selected",
    Events: []string{
        lettr.EventMessageDelivery,
        lettr.EventMessageBounce,
    },
})

func (*WebhookService) Delete added in v0.2.0

func (s *WebhookService) Delete(ctx context.Context, webhookID string) (*DeleteWebhookResponse, error)

Delete removes a webhook.

Example:

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

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)

func (*WebhookService) Update added in v0.2.0

func (s *WebhookService) Update(ctx context.Context, webhookID string, params *UpdateWebhookRequest) (*UpdateWebhookResponse, error)

Update modifies an existing webhook's settings.

Use the URL field for the destination endpoint; the Target field is deprecated and retained only for backwards compatibility.

Example:

active := false
updated, err := client.Webhooks.Update(ctx, "webhook-abc123", &lettr.UpdateWebhookRequest{
    URL:    "https://example.com/new-webhook",
    Active: &active,
})

Jump to

Keyboard shortcuts

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