mailtea

package module
v0.1.0 Latest Latest
Warning

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

Go to latest
Published: Aug 27, 2026 License: MIT Imports: 15 Imported by: 0

README

mailtea-go

The official Go SDK for Mailtea — a thin, typed wrapper over the REST API.

No dependencies outside the standard library. Go 1.18 or newer.

Install

go get github.com/mailtea-app/mailtea-go@v0.1.0
import "github.com/mailtea-app/mailtea-go" // package mailtea

Usage

package main

import (
	"context"
	"fmt"
	"log"
	"os"

	"github.com/mailtea-app/mailtea-go"
)

func main() {
	client, err := mailtea.New(os.Getenv("MAILTEA_API_KEY"))
	if err != nil {
		log.Fatal(err)
	}

	ctx := context.Background()

	sent, err := client.Emails.Send(ctx, mailtea.SendEmailRequest{
		From:    "you@yourdomain.com",
		To:      []string{"recipient@example.com"},
		Subject: "Hello from Mailtea",
		HTML:    "<p>Your first email, sent with <strong>Mailtea</strong>.</p>",
	})
	if err != nil {
		log.Fatal(err)
	}
	fmt.Println(sent.ID)

	email, err := client.Emails.Get(ctx, sent.ID)
	if err != nil {
		log.Fatal(err)
	}
	fmt.Println(email.Status) // queued, sent, delivered, bounced, …
}

A single message is capped at 50 recipients combined across to + cc + bcc; the API rejects a larger one rather than accepting a send that fails downstream.

Configuration

What How
API key mailtea.New("mt_pat_…"), or mailtea.New("") to read MAILTEA_API_KEY
Base URL mailtea.New(key, mailtea.WithBaseURL("http://127.0.0.1:7787")), or MAILTEA_API_BASE_URL
Transport mailtea.New(key, mailtea.WithHTTPClient(myClient)) — anything with Do(*http.Request) (*http.Response, error)

An explicit option beats the environment variable, which beats the default (https://api.mailtea.app). New returns a *mailtea.Error with Code: "missing_api_key" when there is no key at all, rather than letting the misconfiguration surface as a 401 on your first send.

Pass a custom client to add a proxy, a timeout, retries — or, in a test, to answer without a network:

client, err := mailtea.New("mt_pat_test", mailtea.WithHTTPClient(fakeDoer{}))

API

Every method takes a context.Context first and returns (result, error).

Payloads follow the REST wire format (reply_to, scheduled_at, …). The methods below marked typed take a request struct; every other method takes mailtea.Params, a map[string]interface{} of wire-format keys. Each typed struct also has an Extra mailtea.Params field whose keys are merged over the named ones, so a field the API adds tomorrow is sendable today.

Responses that this SDK does not type are mailtea.Object — a map with typed accessors (String, Int, Bool, Object, List) and Decode(&yourStruct). List endpoints return *mailtea.List (Data []Object, plus Total/Limit/ Offset/HasMore for offset pagination or NextCursor for cursor pagination).

Method Description
Emails.Send(ctx, req) typed Send a transactional email → {ID}
Emails.Batch(ctx, reqs) typed Send up to 100 emails → {Data: [{ID}]}
Emails.Get(ctx, id) Retrieve an email and its delivery status (typed *Email)
Emails.List(ctx, params) List emails → *List
Emails.Update(ctx, id, req) typed Reschedule a scheduled email
Emails.Reschedule(ctx, id, scheduledAt) Convenience wrapper over Update
Emails.Cancel(ctx, id) Cancel a scheduled email (POST …/cancel; there is no DELETE)
Emails.Analytics(ctx, params) Aggregate transactional metrics over an optional date window
Emails.Inbound.List / Get / Reply Received emails; Reply threads by construction
Emails.Inbound.Attachments.List / Get Attachments on a received email, with signed download URLs
Contacts.Create / Upsert typed Create or update a contact (the endpoint upserts)
Contacts.Update typed Change a contact's status
Contacts.List / Get / Delete Manage audience contacts
Posts.Create(ctx, req) typed Create a newsletter post (draft, or Send: true)
Posts.Send(ctx, id, req) typed Send a draft post to the audience, now or scheduled
Posts.SendTest(ctx, id, req) typed Send a [TEST] copy → {SentTo, FailedTo}
Posts.List / Get / Update / Delete Manage posts
Segments.Create / List / Get / Update / Delete Manage audience segments
Topics.Create(ctx, req) typed Create a topic definition (opt_in / opt_out)
Topics.List / Get / Update / Delete Manage topic definitions
Senders.Create / List / Get / Update / Delete Manage named From identities (email immutable)
Assets.Upload / List / Delete The publication's image library (content accepts raw []byte)
Suppressions.List / Add / Remove Manage the team-wide do-not-send list
Suppressions.Export(ctx) Export the whole list as CSV (raw string, not JSON)
Templates.Create / List / Get / Update / Delete Manage reusable email templates
Templates.Render(ctx, params) Render a spec to HTML without saving → {html, text}
Templates.Publish / Unpublish / Duplicate Template lifecycle
Templates.Versions / RestoreVersion Design history; restoring returns the template to draft
Domains.Create / List / Get / Verify / Update / Delete Manage sending domains
Domains.Tracking.Create / List / Verify / Delete CNAME tracking sub-domains under a domain
Webhooks.Create / List / Get / Update / Delete Manage outbound event subscriptions
ContactProperties.Create / List / Update / Delete Custom contact fields (team-scoped)
APIKeys.Create / List / Revoke Manage API keys (needs settings:write)
Automations.Create / List / Get / Update / Delete Automation graphs (steps + optional connections)
Automations.Validate(ctx, params) Dry-run a graph → {valid, issues}
Automations.Activate / Pause / Archive Lifecycle (cancel_runs defaults false on pause, true on archive)
Automations.Versions / Version / Metrics Stored versions and per-step funnel counts
Automations.Test(ctx, id, params) One test run against a real contact — sends real, billed email
AutomationRuns.List / Get / Cancel Inspect and cancel runs (a run pins the version it started on)
Events.Send / List Record and list custom product events
EventDefinitions.Create / List / Get / Update / Delete The event catalog (name immutable)

Emails.Send also takes Tags, custom Headers, Attachments, and ScheduledAt. Attachments carry base64 Content; set a ContentID (plus ContentType) to embed an inline image referenced by cid: in the HTML:

_, err := client.Emails.Send(ctx, mailtea.SendEmailRequest{
	From:    "you@yourdomain.com",
	To:      []string{"recipient@example.com"},
	Subject: "Your receipt",
	HTML:    `<p>Thanks!</p><img src="cid:logo" />`,
	Tags:    []mailtea.Tag{{Name: "category", Value: "receipt"}},
	Attachments: []mailtea.Attachment{
		{Filename: "receipt.pdf", Content: pdfBase64},
		{Filename: "logo.png", Content: logoBase64, ContentType: "image/png", ContentID: "logo"}, // inline
	},
})

Webhooks

Mailtea signs every outbound webhook with Standard Webhooks. VerifyWebhookSignature checks the signature and rejects replays. Pass the raw request body — not re-serialized JSON — and the endpoint's whsec_… signing secret:

func handler(w http.ResponseWriter, r *http.Request) {
	raw, err := io.ReadAll(r.Body)
	if err != nil {
		w.WriteHeader(http.StatusBadRequest)
		return
	}

	ok := mailtea.VerifyWebhookSignature(
		signingSecret, // whsec_… returned once by Webhooks.Create
		r.Header.Get("webhook-id"),
		r.Header.Get("webhook-timestamp"),
		string(raw),
		r.Header.Get("webhook-signature"),
	)
	if !ok {
		w.WriteHeader(http.StatusUnauthorized)
		return
	}
	// … handle the event
}

SignWebhook(secret, msgID, timestamp, payload) produces the same header, handy for faking deliveries in tests. VerifyWebhookSignatureAt takes the tolerance and the current time explicitly, so a test can prove an expired delivery is rejected without waiting five minutes.

Errors

Every failure is a *mailtea.Error, reachable with errors.As:

var apiErr *mailtea.Error
if errors.As(err, &apiErr) {
	log.Printf("status=%d code=%s request_id=%s: %s",
		apiErr.Status, apiErr.Code, apiErr.RequestID, apiErr.Message)
}
Field What it carries
Status HTTP status code. 0 means the fault was on this side — a missing key, an unreachable host, an undecodable body
Message The API's own error field ("Domain is not verified"), or the client-side reason
Code The API's machine-readable code, when it sends one. Branching on this survives a copy change to Message
Details The validation issue list naming the fields that failed
RequestID The response's x-request-id — quote it in a support request
Body The raw response body, verbatim

Surfacing Message is the difference between "the send failed" and "the domain isn't verified yet".

Local development

git clone https://github.com/mailtea-app/mailtea-go
cd mailtea-go
go test ./...

The tests answer from a bundled httptest mock of the Mailtea API, so they need no API key and make no network calls. One of them checks endpoint parity with the Python SDK: every /v1/… path the reference client reaches, this one must reach too.

To run against a Mailtea on your own machine:

export MAILTEA_API_KEY="mt_pat_…"
export MAILTEA_API_BASE_URL="http://127.0.0.1:7787"

License

MIT. See LICENSE.

Documentation

Overview

Package mailtea is the official Go SDK for Mailtea — a thin, typed wrapper over the REST API at https://docs.mailtea.app/docs/api-reference.

It has no dependencies outside the standard library.

client, err := mailtea.New(os.Getenv("MAILTEA_API_KEY"))
if err != nil {
    log.Fatal(err)
}

sent, err := client.Emails.Send(ctx, mailtea.SendEmailRequest{
    From:    "you@yourdomain.com",
    To:      []string{"recipient@example.com"},
    Subject: "Hello from Mailtea",
    HTML:    "<p>Your first email.</p>",
})

Every method takes a context.Context and returns (result, error). Errors from the API are *mailtea.Error, reachable with errors.As.

Index

Constants

View Source
const DefaultBaseURL = "https://api.mailtea.app"

DefaultBaseURL is the hosted Mailtea API.

View Source
const (

	// DefaultWebhookTolerance is how far the delivery's timestamp may sit from
	// now, each way, before it is treated as a replay. Five minutes, the
	// Standard Webhooks default.
	DefaultWebhookTolerance = 5 * time.Minute
)
View Source
const Version = "0.1.0"

Version is this SDK's release. It is sent on every request as `User-Agent: mailtea-go/<Version>`, which is how a support request can be traced back to the client that made it.

The mirror repo's `v<Version>` git tag IS the Go release — pkg.go.dev indexes the tag, there is no separate registry upload — so this constant and that tag must always agree.

Variables

This section is empty.

Functions

func SignWebhook

func SignWebhook(secret, msgID string, timestamp int64, payload string) string

SignWebhook signs a payload and returns the `webhook-signature` header value in Standard Webhooks form, `v1,<base64 HMAC-SHA256>`. Useful for faking Mailtea deliveries in tests.

timestamp is Unix seconds — the same value sent in `webhook-timestamp`.

func VerifyWebhookSignature

func VerifyWebhookSignature(secret, msgID, timestamp, payload, signatureHeader string) bool

VerifyWebhookSignature checks a `webhook-signature` header against the expected HMAC.

ok := mailtea.VerifyWebhookSignature(
    signingSecret,                       // whsec_… from Webhooks.Create
    r.Header.Get("webhook-id"),
    r.Header.Get("webhook-timestamp"),
    string(rawBody),                     // exact bytes received, not re-serialized
    r.Header.Get("webhook-signature"),
)

The header may carry several space-delimited `v1,<sig>` tokens — Standard Webhooks allows key rotation, and the platform may sign one delivery with both the old and the new secret — so a match against any `v1` token passes.

It returns false when the timestamp is outside DefaultWebhookTolerance of now, which is the replay protection. The comparison is constant-time, and a bad signature is a false rather than an error.

func VerifyWebhookSignatureAt

func VerifyWebhookSignatureAt(
	secret, msgID, timestamp, payload, signatureHeader string,
	tolerance time.Duration,
	now time.Time,
) bool

VerifyWebhookSignatureAt is VerifyWebhookSignature with the tolerance and the current time supplied — the injectable form, so a test can prove that an expired timestamp is rejected without sleeping for five minutes.

Types

type APIKeysService

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

APIKeysService is the `api_keys` resource. Reach it as client.APIKeys.

Requires a token with `settings:write`. A key can never be granted scopes the calling token does not already hold.

func (*APIKeysService) Create

func (s *APIKeysService) Create(ctx context.Context, params Params) (Object, error)

Create mints an API key. The `token` is returned ONCE — store it securely.

Takes name, optional permission ("full_access" or "sending_access"), and optional domain_id.

func (*APIKeysService) List

func (s *APIKeysService) List(ctx context.Context) (*List, error)

List lists API keys. Token values are never returned.

func (*APIKeysService) Revoke

func (s *APIKeysService) Revoke(ctx context.Context, id string) (Object, error)

Revoke deletes an API key by id.

type AssetsService

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

AssetsService is the `assets` resource — a publication's image library. Reach it as client.Assets.

An email or site image block needs an absolute URL, so this is how a picture that is not already in the library gets into one. Pointing an image at a host you do not control breaks the day that host moves the file.

PNG, JPEG, GIF, WebP or SVG, 5 MB per image. The bytes are checked against the declared content_type, so a mislabelled file is rejected rather than stored.

func (*AssetsService) Delete

func (s *AssetsService) Delete(ctx context.Context, id string, params Params) (Object, error)

Delete retires an asset.

The stored file is KEPT and its URL keeps resolving, so images inside already-sent emails do not break. This hides the asset from the library — it does not remove it from any email, template or page referencing it.

func (*AssetsService) List

func (s *AssetsService) List(ctx context.Context, params Params) (*List, error)

List lists the library, newest first. Filters: publication_id (required), search (file name), limit (1-200, default 100).

func (*AssetsService) Upload

func (s *AssetsService) Upload(ctx context.Context, params Params) (Object, error)

Upload puts an image in the library and returns it, including the `url` to use as an image block's src.

Takes publication_id, content, content_type and filename. `content` may be raw []byte — base64-encoded for you — or a string that is already base64:

raw, _ := os.ReadFile("hero.png")
asset, err := client.Assets.Upload(ctx, mailtea.Params{
    "publication_id": "pub_123",
    "content":        raw,
    "content_type":   "image/png",
    "filename":       "hero.png",
})
asset.String("url")

type Attachment

type Attachment struct {
	Filename    string `json:"filename"`
	Content     string `json:"content"`
	ContentType string `json:"content_type,omitempty"`
	ContentID   string `json:"content_id,omitempty"`
}

Attachment is a file sent with an email. Content is base64. Set ContentType and a ContentID to embed an inline image referenced by `cid:` in the HTML; omit ContentID for an ordinary file attachment.

type AttachmentMeta

type AttachmentMeta struct {
	Filename    string `json:"filename"`
	ContentType string `json:"content_type"`
	Size        int64  `json:"size"`
}

AttachmentMeta describes an attachment on a retrieved email. The bytes are not returned.

type AutomationRunsService

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

AutomationRunsService is the `automation_runs` resource — one contact's journey through one automation. Reach it as client.AutomationRuns.

Runs are nested under an automation and scoped to a publication. A run PINS the automation version it started on, so Get returns the graph the run is actually executing, not the live one.

func (*AutomationRunsService) Cancel

func (s *AutomationRunsService) Cancel(ctx context.Context, automationID, runID string, params Params) (Object, error)

Cancel stops one in-flight run. Requires publication_id. A cancelled run cannot be resumed. Returns the run in full detail.

func (*AutomationRunsService) Get

func (s *AutomationRunsService) Get(ctx context.Context, automationID, runID string, params Params) (Object, error)

Get retrieves one run in full. Requires publication_id. Returns the PINNED steps/connections, the per-step step_runs, and `waiting` (resume_at / waiting_event_name) — read this rather than an event ingest's resumed_runs counter to tell whether an event actually advanced the run.

func (*AutomationRunsService) List

func (s *AutomationRunsService) List(ctx context.Context, automationID string, params Params) (*List, error)

List lists an automation's runs, cursor-paginated. Filters: publication_id (required), status (one status or a []string of them, joined for you), contact_id, is_test, limit, after. List items omit the pinned graph and the step runs; use Get for those.

A Go bool renders as "true"/"false" here, which is what the server matches `is_test` against — it 400s on anything else.

type AutomationsService

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

AutomationsService is the `automations` resource — multi-step contact journeys. Reach it as client.Automations.

Automations are scoped to a publication. An automation is a graph: `steps` (each {"key", "type", "label", "config"}) plus optional `connections` (each {"from", "to", "branch"}).

`connections` is optional: omit it and the server links the steps in array order with branch "next", rooted at the trigger. A graph containing a `condition` or `wait_for_event` step cannot be inferred that way and is rejected with `connections_required_for_branching` — send its connections explicitly.

Failures come back as coded `issues[]` rather than schema errors, and for a draft/paused/archived automation they ride along informationally instead of blocking the save.

func (*AutomationsService) Activate

func (s *AutomationsService) Activate(ctx context.Context, id string, params Params) (Object, error)

Activate starts the automation so new contacts enroll. Requires publication_id. A graph with errors is refused with 422 `automation_invalid` and the blocking issues[].

func (*AutomationsService) Archive

func (s *AutomationsService) Archive(ctx context.Context, id string, params Params) (Object, error)

Archive archives the automation. Requires publication_id (query). Optional cancel_runs — it DEFAULTS TO TRUE here, the opposite of Pause, so in-flight runs exit with `automation_archived`. Returns the automation plus canceled_runs.

func (*AutomationsService) Create

func (s *AutomationsService) Create(ctx context.Context, params Params) (Object, error)

Create adds an automation. Takes publication_id, name and steps, plus optional description, connections, reentry_policy (once/once_per_window/always — once_per_window requires reentry_window_seconds), on_step_failure and validate_only. With validate_only nothing is written and an automation_validation comes back instead. New automations start as draft — Activate starts them.

func (*AutomationsService) Delete

func (s *AutomationsService) Delete(ctx context.Context, id string, params Params) (Object, error)

Delete removes an automation. Requires publication_id. Deleting an `active` automation is a 409 `automation_active` — pause or archive it first so its in-flight runs are not dropped silently.

func (*AutomationsService) Get

func (s *AutomationsService) Get(ctx context.Context, id string, params Params) (Object, error)

Get retrieves one automation with its live graph and current issues[]. Requires publication_id.

func (*AutomationsService) List

func (s *AutomationsService) List(ctx context.Context, params Params) (*List, error)

List lists automations, cursor-paginated. Filters: publication_id (required), status (draft/active/paused/archived), limit, after. List items omit steps, connections, valid and issues — use Get for the full graph.

func (*AutomationsService) Metrics

func (s *AutomationsService) Metrics(ctx context.Context, id string, params Params) (Object, error)

Metrics returns per-step funnel counts. Filters: publication_id (required), version (omit to aggregate across ALL versions), since, until (ISO 8601). Test runs are always excluded (excludes_test_runs: true). Condition steps report branches {condition_met, condition_not_met}; wait_for_event steps {event_received, timeout}.

func (*AutomationsService) Pause

func (s *AutomationsService) Pause(ctx context.Context, id string, params Params) (Object, error)

Pause stops new enrollments. Requires publication_id (query). Optional cancel_runs — it DEFAULTS TO FALSE here, so in-flight runs keep going; pass cancel_runs true to exit them. Returns the automation plus canceled_runs.

func (*AutomationsService) Test

func (s *AutomationsService) Test(ctx context.Context, id string, params Params) (Object, error)

Test runs the automation once against a real contact. publication_id is required and is sent as a query parameter; the body takes one of contact_id or email, plus optional event_properties to seed the run's `event.*` namespace.

A test run SENDS REAL, BILLED EMAIL to that inbox — it does not bypass any send gate. It is flagged is_test and excluded from Metrics. Returns 202 with the queued run.

func (*AutomationsService) Update

func (s *AutomationsService) Update(ctx context.Context, id string, params Params) (Object, error)

Update changes an automation's name, description, steps, connections, reentry_policy, reentry_window_seconds or on_step_failure. publication_id is required and is sent as a query parameter ONLY — this endpoint rejects it in the body. The graph is replaced wholesale and cuts a new version.

validate_only returns an automation_validation and writes nothing. A graph change carrying errors saves anyway while the automation is draft/paused/archived; on an `active` one it is a 422 — pause, save, then start again.

func (*AutomationsService) Validate

func (s *AutomationsService) Validate(ctx context.Context, params Params) (Object, error)

Validate dry-runs a graph without creating anything. Takes publication_id and steps, plus optional connections. Returns {"object": "automation_validation", "valid": ..., "issues": [...]}.

func (*AutomationsService) Version

func (s *AutomationsService) Version(ctx context.Context, id string, version interface{}, params Params) (Object, error)

Version retrieves one stored version, including its steps and connections. Requires publication_id. This is the graph a run of that version is pinned to — editing the automation never rewrites it.

func (*AutomationsService) Versions

func (s *AutomationsService) Versions(ctx context.Context, id string, params Params) (Object, error)

Versions lists an automation's versions, cursor-paginated. Filters: publication_id (required), limit, after. List items carry no steps/connections — use Version for a stored graph.

type BatchResponse

type BatchResponse struct {
	Data []SendEmailResponse `json:"data"`
}

BatchResponse is what a batch send returns — one id per message, in order.

type Client

type Client struct {
	Emails            *EmailsService
	Contacts          *ContactsService
	Segments          *SegmentsService
	Topics            *TopicsService
	Posts             *PostsService
	Senders           *SendersService
	Assets            *AssetsService
	Suppressions      *SuppressionsService
	Templates         *TemplatesService
	Domains           *DomainsService
	Webhooks          *WebhooksService
	ContactProperties *ContactPropertiesService
	APIKeys           *APIKeysService
	Automations       *AutomationsService
	AutomationRuns    *AutomationRunsService
	Events            *EventsService
	EventDefinitions  *EventDefinitionsService
	// contains filtered or unexported fields
}

Client talks to one Mailtea instance with one API key. It is safe for concurrent use by multiple goroutines.

func New

func New(apiKey string, opts ...Option) (*Client, error)

New builds a client.

The API key is an mt_pat_… or mt_svc_… token. Pass it explicitly, or pass "" to read MAILTEA_API_KEY from the environment. With neither, New returns a *Error with Status 0 and Code "missing_api_key" — the misconfiguration is reported where it happened rather than as a 401 on the first send.

The base URL defaults to DefaultBaseURL, overridden by MAILTEA_API_BASE_URL and then by WithBaseURL.

func (*Client) BaseURL

func (c *Client) BaseURL() string

BaseURL reports the API this client talks to, after the environment and options have been applied.

type ContactPropertiesService

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

ContactPropertiesService is the `contact_properties` resource — custom contact fields. Reach it as client.ContactProperties.

Definitions are team-scoped: there is no publication_id here. Create takes key and type ("string" or "number").

func (*ContactPropertiesService) Create

func (s *ContactPropertiesService) Create(ctx context.Context, params Params) (Object, error)

Create adds a contact property definition.

func (*ContactPropertiesService) Delete

Delete removes a contact property definition.

func (*ContactPropertiesService) List

func (s *ContactPropertiesService) List(ctx context.Context, params Params) (*List, error)

List lists contact property definitions.

func (*ContactPropertiesService) Update

func (s *ContactPropertiesService) Update(ctx context.Context, id string, params Params) (Object, error)

Update changes a contact property definition.

type ContactsService

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

ContactsService is the `contacts` resource. Reach it as client.Contacts.

Audience resources are scoped to a publication — every call takes a publication_id.

func (*ContactsService) Create

func (s *ContactsService) Create(ctx context.Context, request CreateContactRequest) (Object, error)

Create adds a contact — or updates it if the email already exists in the publication, because the endpoint upserts. Upsert is the same call under the name of what it actually does.

func (*ContactsService) Delete

func (s *ContactsService) Delete(ctx context.Context, idOrEmail string, params Params) (Object, error)

Delete removes a contact. Requires publication_id.

func (*ContactsService) Get

func (s *ContactsService) Get(ctx context.Context, idOrEmail string, params Params) (Object, error)

Get retrieves one contact by id or by email address.

func (*ContactsService) List

func (s *ContactsService) List(ctx context.Context, params Params) (*List, error)

List lists contacts, cursor-paginated. Filters: publication_id (required), status (active/unsubscribed/suppressed), search (matches the email address), limit, after (a cursor from a previous next_cursor).

func (*ContactsService) Update

func (s *ContactsService) Update(ctx context.Context, idOrEmail string, request UpdateContactRequest) (Object, error)

Update changes a contact. The publication is sent in the query string as well as the body, which is what this endpoint reads.

func (*ContactsService) Upsert

func (s *ContactsService) Upsert(ctx context.Context, request CreateContactRequest) (Object, error)

Upsert creates the contact or updates it in place — an alias of Create, named for what POST /v1/contacts really does.

type CreateContactRequest

type CreateContactRequest struct {
	PublicationID string `json:"publication_id"`
	Email         string `json:"email"`
	Status        string `json:"status,omitempty"`

	// Extra carries wire fields this SDK version does not name yet.
	Extra Params `json:"-"`
}

CreateContactRequest is the body of POST /v1/contacts.

Status is one of "active", "unsubscribed" or "suppressed"; omit it and the server picks the default.

func (CreateContactRequest) MarshalJSON

func (r CreateContactRequest) MarshalJSON() ([]byte, error)

MarshalJSON merges Extra over the named fields.

type CreatePostRequest

type CreatePostRequest struct {
	PublicationID string `json:"publication_id"`
	Subject       string `json:"subject,omitempty"`
	Name          string `json:"name,omitempty"`
	Kind          string `json:"kind,omitempty"`

	HTML string `json:"html,omitempty"`
	Text string `json:"text,omitempty"`

	TemplateID string                 `json:"template_id,omitempty"`
	Variables  map[string]interface{} `json:"variables,omitempty"`

	From    string `json:"from,omitempty"`
	ReplyTo string `json:"reply_to,omitempty"`

	// Send delivers the post to the audience as part of creating it.
	Send bool `json:"send,omitempty"`
	// ScheduledAt, with Send, queues that delivery for later (ISO 8601).
	ScheduledAt string `json:"scheduled_at,omitempty"`

	// Extra carries wire fields this SDK version does not name yet.
	Extra Params `json:"-"`
}

CreatePostRequest is the body of POST /v1/posts.

Seed the post from a published server template with TemplateID + Variables, or pass inline HTML. Kind selects the post type ("newsletter" or "broadcast"). Set Send to deliver right after creating (or add ScheduledAt to schedule) — that requires the `issues:send` scope.

func (CreatePostRequest) MarshalJSON

func (r CreatePostRequest) MarshalJSON() ([]byte, error)

MarshalJSON merges Extra over the named fields.

type CreateTopicRequest

type CreateTopicRequest struct {
	PublicationID       string `json:"publication_id"`
	Name                string `json:"name"`
	DefaultSubscription string `json:"default_subscription"`
	Description         string `json:"description,omitempty"`
	Visibility          string `json:"visibility,omitempty"`

	// Extra carries wire fields this SDK version does not name yet.
	Extra Params `json:"-"`
}

CreateTopicRequest is the body of POST /v1/topics.

DefaultSubscription is required and is one of "opt_in" or "opt_out". Visibility defaults to "private"; "public" makes the topic appear on the reader preference page as its own subscription.

func (CreateTopicRequest) MarshalJSON

func (r CreateTopicRequest) MarshalJSON() ([]byte, error)

MarshalJSON merges Extra over the named fields.

type DomainsService

type DomainsService struct {

	// Tracking covers the CNAME tracking sub-domains under a domain.
	Tracking *TrackingDomainsService
	// contains filtered or unexported fields
}

DomainsService is the `domains` resource — email and site sending domains. Reach it as client.Domains.

Scoped to a publication. Register a domain, add the DNS `records` the response lists, then Verify it before sending from it.

func (*DomainsService) Create

func (s *DomainsService) Create(ctx context.Context, params Params) (Object, error)

Create registers a domain. The response's `records` lists the DNS records to add.

func (*DomainsService) Delete

func (s *DomainsService) Delete(ctx context.Context, id string, params Params) (Object, error)

Delete removes a domain. Requires publication_id.

func (*DomainsService) Get

func (s *DomainsService) Get(ctx context.Context, id string, params Params) (Object, error)

Get retrieves one domain. Requires publication_id.

func (*DomainsService) List

func (s *DomainsService) List(ctx context.Context, params Params) (*List, error)

List lists domains. Requires publication_id.

func (*DomainsService) Update

func (s *DomainsService) Update(ctx context.Context, id string, params Params) (Object, error)

Update changes a domain — open_tracking, click_tracking, custom_return_path and the like. publication_id travels in the query string and the body alike.

custom_return_path delegates a subdomain as the envelope sender so SPF aligns with your own domain. Mail keeps sending on the default return-path until the delegated DNS resolves.

func (*DomainsService) Verify

func (s *DomainsService) Verify(ctx context.Context, id string, params Params) (Object, error)

Verify checks a domain's DNS records; on success its status becomes "verified".

type DroppedRecipient

type DroppedRecipient struct {
	Address string `json:"address"`
	Field   string `json:"field"`
	Reason  string `json:"reason"`
}

DroppedRecipient is an address the message did not reach, and why. To/CC/BCC are what was ASKED for; a suppressed or unusable address is filtered out of the envelope but left in those fields, so without reading this a partially delivered send looks identical to a fully delivered one.

type Email

type Email struct {
	Object  string `json:"object"`
	ID      string `json:"id"`
	From    string `json:"from"`
	To      string `json:"to"`
	CC      string `json:"cc"`
	BCC     string `json:"bcc"`
	ReplyTo string `json:"reply_to"`
	Subject string `json:"subject"`
	HTML    string `json:"html"`
	Text    string `json:"text"`

	// LastEvent is where the send got to: queued, scheduled, sent, delivered,
	// delivery_delayed, bounced, complained, failed, suppressed, canceled.
	// Reading it is how you check on a send without setting up a webhook.
	LastEvent string `json:"last_event"`
	// Status is a friendly alias of LastEvent, filled in by this SDK.
	Status string `json:"status"`

	// Error is why the send failed, in neutral words — the provider's own
	// wording is never returned. Empty on every email that has not failed.
	Error string `json:"error"`

	DroppedRecipients []DroppedRecipient `json:"dropped_recipients"`

	CreatedAt   string `json:"created_at"`
	ScheduledAt string `json:"scheduled_at"`
	FailedAt    string `json:"failed_at"`
	DelayedAt   string `json:"delayed_at"`
	OpenedAt    string `json:"opened_at"`
	OpenCount   int    `json:"open_count"`
	ClickedAt   string `json:"clicked_at"`
	ClickCount  int    `json:"click_count"`

	Tags        []Tag             `json:"tags"`
	Headers     map[string]string `json:"headers"`
	Attachments []AttachmentMeta  `json:"attachments"`
}

Email is one send, as returned by Get.

type EmailsService

type EmailsService struct {

	// Inbound covers received mail: list, get, reply, and attachments.
	Inbound *InboundService
	// contains filtered or unexported fields
}

EmailsService is the `emails` resource. Reach it as client.Emails.

func (*EmailsService) Analytics

func (s *EmailsService) Analytics(ctx context.Context, params Params) (Object, error)

Analytics aggregates transactional metrics over an optional date window: totals, delivered/bounced/open/click counts, per-status counts, and rates. Optional filters: from_date, to_date (ISO 8601), clamped like List's.

func (*EmailsService) Batch

func (s *EmailsService) Batch(ctx context.Context, requests []SendEmailRequest) (*BatchResponse, error)

Batch sends up to 100 emails in one request. The body is a bare array, which is what this endpoint takes — not an object wrapping one.

func (*EmailsService) Cancel

func (s *EmailsService) Cancel(ctx context.Context, id string) (Object, error)

Cancel stops a scheduled email before it sends.

It works only while the email is still `scheduled`. Any other status — including the `queued` of an ordinary immediate send — answers 422, so treat that as "too late to stop it" rather than as a bug. There is no DELETE on emails; cancel is this POST.

The reply is `{object, id}` and nothing more — a 2xx IS the confirmation. Call Get if you want to read the resulting `canceled` status back.

func (*EmailsService) Get

func (s *EmailsService) Get(ctx context.Context, id string) (*Email, error)

Get retrieves an email with its delivery status and tracking counters.

The id goes through url.PathEscape: a real "txemail_…" passes through untouched, and an id from somewhere less trustworthy cannot walk out of the path segment it belongs in.

func (*EmailsService) List

func (s *EmailsService) List(ctx context.Context, params Params) (*List, error)

List lists emails, most recent first. Optional filters: status, tag_name, tag_value, search (substring match on recipient/sender/subject), from_date, to_date, limit, offset.

from_date is clamped to the plan's analytics retention window — 30 days on most plans, 90 on Scale and Enterprise. A value reaching further back returns data from the start of that window rather than an error, and omitting it returns the window rather than all time.

func (*EmailsService) Reschedule

func (s *EmailsService) Reschedule(ctx context.Context, id, scheduledAt string) (Object, error)

Reschedule is Update for the one case it exists for.

func (*EmailsService) Send

Send sends one transactional email, or schedules it when ScheduledAt is set.

func (*EmailsService) Update

func (s *EmailsService) Update(ctx context.Context, id string, request UpdateEmailRequest) (Object, error)

Update changes a scheduled email (currently only scheduled_at).

type Error

type Error struct {
	// Status is the HTTP status code. Zero means the failure happened on this
	// side of the wire — a missing API key, an unreachable host, a response
	// body that was not the JSON it claimed to be — so there is no status to
	// report. Branch on it before assuming the API said anything at all.
	Status int

	// Message is the API's own `error` field ("Domain is not verified",
	// "Validation failed"), or the client-side reason when Status is 0.
	Message string

	// Code is the API's machine-readable code, when it sends one (for example
	// `marketing_plan_required` on a 402, or `template_version_not_found`).
	// Branching on Code survives a copy change to Message. Empty when absent.
	Code string

	// Details is the validation issue list the API returns alongside a 400,
	// naming the fields that failed. Nil when absent. It is decoded as
	// free-form JSON because its shape varies per endpoint; use DetailsJSON to
	// print it or json.Unmarshal it into your own type.
	Details interface{}

	// RequestID is the response's `x-request-id` header — quote it in a support
	// request and the exact call can be found.
	RequestID string

	// Body is the raw response body, kept verbatim. The parsed fields above are
	// what you branch on; this is what you log when they were not enough.
	Body string
}

Error is returned whenever the Mailtea API answers with a non-2xx status, or the client is misconfigured before a request is even attempted.

Reach it with errors.As:

var apiErr *mailtea.Error
if errors.As(err, &apiErr) && apiErr.Status == 422 {
    // too late to cancel
}

func (*Error) Error

func (e *Error) Error() string

type EventDefinitionsService

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

EventDefinitionsService is the `event_definitions` resource — the catalog of event names a publication expects, with optional property schemas. Reach it as client.EventDefinitions.

Definitions are scoped to a publication. They are documentation and tooling, not a gate: Events.Send accepts an event with no definition.

func (*EventDefinitionsService) Create

func (s *EventDefinitionsService) Create(ctx context.Context, params Params) (Object, error)

Create adds an event definition. Takes publication_id and name, plus optional description and schema_json. The name is immutable once created.

func (*EventDefinitionsService) Delete

func (s *EventDefinitionsService) Delete(ctx context.Context, id string, params Params) (Object, error)

Delete removes an event definition. Requires publication_id. Events already recorded under that name are untouched.

func (*EventDefinitionsService) Get

func (s *EventDefinitionsService) Get(ctx context.Context, id string, params Params) (Object, error)

Get retrieves one definition. Requires publication_id. Adds schema_properties and inferred_properties — the latter computed on read over the last 500 events, reporting each key's type, sample count and COVERAGE. Low coverage is the trap: a condition on a key present in 3% of events will almost never match.

func (*EventDefinitionsService) List

func (s *EventDefinitionsService) List(ctx context.Context, params Params) (*List, error)

List lists event definitions, cursor-paginated. Filters: publication_id (required), limit, after. List items carry no inferred_properties — use Get for those.

func (*EventDefinitionsService) Update

func (s *EventDefinitionsService) Update(ctx context.Context, id string, params Params) (Object, error)

Update changes a definition's description or schema_json (an explicit nil clears the schema back to free-form). publication_id is required and is sent as a query parameter ONLY. `name` is immutable — sending it is a 400 `event_name_immutable`, not a silently dropped rename.

type EventsService

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

EventsService is the `events` resource — custom product events that trigger automations and resume `wait_for_event` steps. Reach it as client.Events.

Events are scoped to a publication.

func (*EventsService) List

func (s *EventsService) List(ctx context.Context, params Params) (*List, error)

List lists recorded events, cursor-paginated. Filters: publication_id (required), name, contact_id, limit, after.

func (*EventsService) Send

func (s *EventsService) Send(ctx context.Context, params Params) (Object, error)

Send records an event for a contact. Takes publication_id, name, and exactly one of contact_id or email (both is a 400 `contact_reference_conflict`, neither a 400 `contact_reference_required`). Optional: create_contact, properties, occurred_at, idempotency_key.

create_contact is OPT-IN — without it an unresolvable address is a 404 `contact_not_found` rather than a new contact.

Returns 202 with enrolled_automations and resumed_runs. A replay of the same idempotency_key returns the ORIGINAL event id with replayed: true and always reports enrolled_automations: 0, resumed_runs: 0. Note that resumed_runs: 0 on a FRESH ingest does not prove nothing matched — a run being advanced concurrently is invisible for that instant, so read the run itself (client.AutomationRuns.Get) rather than the counter.

type HTTPDoer

type HTTPDoer interface {
	Do(req *http.Request) (*http.Response, error)
}

HTTPDoer is the slice of *http.Client this SDK uses. Supply your own to add a proxy, a timeout, retries, or — in a test — to answer without a network:

client, _ := mailtea.New("mt_pat_test", mailtea.WithHTTPClient(fake))

type InboundAttachmentsService

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

InboundAttachmentsService covers attachments on a received email. Reach it as client.Emails.Inbound.Attachments. Each returned object carries a short-lived signed download_url.

func (*InboundAttachmentsService) Get

func (s *InboundAttachmentsService) Get(ctx context.Context, id, attachmentID string) (Object, error)

Get retrieves a single inbound attachment with a signed download URL.

func (*InboundAttachmentsService) List

List lists an inbound email's attachments, each with a signed download URL.

type InboundService

type InboundService struct {

	// Attachments covers the files on a received email.
	Attachments *InboundAttachmentsService
	// contains filtered or unexported fields
}

InboundService covers inbound (received) emails. Reach it as client.Emails.Inbound.

List and retrieve mail delivered to your receiving domains, download attachments, and Reply — which threads correctly by construction and reuses the transactional send pipeline. Scoped to a publication: pass publication_id to List.

func (*InboundService) Get

func (s *InboundService) Get(ctx context.Context, id string) (Object, error)

Get retrieves a single received email, including its body, headers, and attachments.

func (*InboundService) List

func (s *InboundService) List(ctx context.Context, params Params) (*List, error)

List lists received emails in a publication, most recent first, cursor-paginated. Takes publication_id, optional limit (1-100, default 20) and cursor.

func (*InboundService) Reply

func (s *InboundService) Reply(ctx context.Context, id string, params Params) (Object, error)

Reply replies to a received email. The reply target (`to`), threading headers, and the "Re: " subject default are all server-derived — pass only the content (html/text, and optionally from, subject, cc, bcc, idempotency_key). Returns the resulting transactional email's id and status.

type List

type List struct {
	Object     string   `json:"object"`
	Data       []Object `json:"data"`
	Total      int      `json:"total"`
	Limit      int      `json:"limit"`
	Offset     int      `json:"offset"`
	HasMore    bool     `json:"has_more"`
	NextCursor string   `json:"next_cursor"`
}

List is the API's standard list envelope. Offset-paginated endpoints (emails, posts) fill Total/Limit/Offset/HasMore; cursor-paginated ones (contacts, senders, templates, automations, events, …) fill NextCursor and leave Total at zero. Data holds the rows either way.

type Object

type Object map[string]interface{}

Object is a decoded JSON response. It is a plain map, so an unfamiliar or brand-new field is still readable, with typed accessors for the common reads and Decode for pulling the whole thing into a struct of your own.

func (Object) Bool

func (o Object) Bool(key string) bool

Bool returns a boolean field, or false when the key is absent or not a bool.

func (Object) Decode

func (o Object) Decode(v interface{}) error

Decode re-encodes the object and unmarshals it into v, so a caller who wants a struct does not have to reach through the map:

var domain struct {
    ID     string `json:"id"`
    Status string `json:"status"`
}
err := created.Decode(&domain)

func (Object) Float

func (o Object) Float(key string) float64

Float returns a numeric field. JSON numbers decode to float64, so this is the lossless read; Int rounds it for counters and ids.

func (Object) Int

func (o Object) Int(key string) int

Int returns a numeric field truncated to an int, or 0 when absent.

func (Object) List

func (o Object) List(key string) []Object

List returns a nested array of objects, skipping any element that is not one.

func (Object) Object

func (o Object) Object(key string) Object

Object returns a nested object field, or nil when absent or not an object.

func (Object) String

func (o Object) String(key string) string

String returns a string field, or "" when the key is absent or not a string.

type Option

type Option func(*Client)

Option configures a Client at construction.

func WithBaseURL

func WithBaseURL(baseURL string) Option

WithBaseURL points the client at a different Mailtea — a self-hosted instance, or http://127.0.0.1:7787 in local dev. An empty string is ignored, so passing os.Getenv("MAILTEA_API_BASE_URL") is safe when the variable is unset. A trailing slash is trimmed; a path prefix is kept.

func WithHTTPClient

func WithHTTPClient(doer HTTPDoer) Option

WithHTTPClient replaces the underlying HTTP client. A nil value is ignored.

type Params

type Params map[string]interface{}

Params is a free-form wire-format payload: snake_case keys exactly as the REST API names them ("reply_to", "publication_id", "scheduled_at").

The methods this SDK types explicitly — emails.Send/Batch/Update, contacts.Create/Update, posts.Create/Send/SendTest, topics.Create — take a request struct instead. Everything else takes Params, so a field added to the API is reachable the day it ships rather than the day this SDK is re-released.

type PostsService

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

PostsService is the `posts` resource — newsletter posts and issues. Reach it as client.Posts.

func (*PostsService) Create

func (s *PostsService) Create(ctx context.Context, request CreatePostRequest) (Object, error)

Create adds a newsletter post — a draft unless Send is set.

func (*PostsService) Delete

func (s *PostsService) Delete(ctx context.Context, id string, params Params) (Object, error)

Delete removes a draft post. Sent posts cannot be deleted.

func (*PostsService) Get

func (s *PostsService) Get(ctx context.Context, id string, params Params) (Object, error)

Get retrieves a post by id.

func (*PostsService) List

func (s *PostsService) List(ctx context.Context, params Params) (*List, error)

List lists posts, most recent first, offset-paginated. Takes publication_id (required) plus optional limit, offset, status and kind.

func (*PostsService) Send

func (s *PostsService) Send(ctx context.Context, id string, request SendPostRequest) (Object, error)

Send delivers a draft post to the publication's audience — immediately, or at ScheduledAt. Requires the `issues:send` scope.

func (*PostsService) SendTest

SendTest sends a TEST copy of a post to specific recipients, to check it before subscribers see it. It renders the post exactly as a subscriber would receive it and delivers a one-shot [TEST] email — it does NOT send to the audience.

func (*PostsService) Update

func (s *PostsService) Update(ctx context.Context, id string, params Params) (Object, error)

Update changes a draft post — subject, html, text, from, reply_to, name. Sent posts are immutable.

type SegmentsService

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

SegmentsService is the `segments` resource. Reach it as client.Segments.

Audience segments are scoped to a publication — pass publication_id. To clear a nullable filter on update, set it to nil explicitly (Params{"status_filter": nil} is dropped from a query but kept in a body); omit the key to leave it unchanged.

func (*SegmentsService) Create

func (s *SegmentsService) Create(ctx context.Context, params Params) (Object, error)

Create adds a segment.

func (*SegmentsService) Delete

func (s *SegmentsService) Delete(ctx context.Context, id string, params Params) (Object, error)

Delete removes a segment. Requires publication_id.

func (*SegmentsService) Get

func (s *SegmentsService) Get(ctx context.Context, id string, params Params) (Object, error)

Get retrieves one segment. Requires publication_id.

func (*SegmentsService) List

func (s *SegmentsService) List(ctx context.Context, params Params) (*List, error)

List lists segments. Requires publication_id.

func (*SegmentsService) Update

func (s *SegmentsService) Update(ctx context.Context, id string, params Params) (Object, error)

Update changes a segment. publication_id travels in the query string and the body alike.

type SendEmailRequest

type SendEmailRequest struct {
	// From is a verified sender, e.g. "Acme <hello@acme.com>".
	From string `json:"from,omitempty"`
	// SenderID selects a saved sender ("snd_…") instead of From.
	SenderID string `json:"sender_id,omitempty"`

	To      []string `json:"to"`
	Subject string   `json:"subject"`

	HTML string `json:"html,omitempty"`
	Text string `json:"text,omitempty"`
	// Template renders a published template server-side. Mutually exclusive
	// with HTML.
	Template *TemplateRef `json:"template,omitempty"`

	CC      []string `json:"cc,omitempty"`
	BCC     []string `json:"bcc,omitempty"`
	ReplyTo []string `json:"reply_to,omitempty"`

	// ScheduledAt queues the send for later, ISO 8601: "2026-09-01T09:00:00Z".
	ScheduledAt string `json:"scheduled_at,omitempty"`

	Tags    []Tag             `json:"tags,omitempty"`
	Headers map[string]string `json:"headers,omitempty"`

	Attachments []Attachment `json:"attachments,omitempty"`

	// TrackingOpen and TrackingClick opt this message out of the open pixel or
	// out of rewritten links. They are pointers because "unset" and "false" are
	// different: unset means tracked, as it always has been. A sending domain
	// with tracking switched off cannot be overridden from here — policy
	// narrows, it never widens.
	TrackingOpen  *bool `json:"tracking_open,omitempty"`
	TrackingClick *bool `json:"tracking_click,omitempty"`

	// Extra carries wire fields this SDK version does not name yet. Its keys
	// are merged over the encoded struct, so a field the API adds tomorrow is
	// sendable today.
	Extra Params `json:"-"`
}

SendEmailRequest is the body of POST /v1/emails.

Set the From with exactly one of From (a "Name <email>" string) or SenderID (a named, verified publication sender, which also supplies its default reply-to). Provide HTML/Text OR Template, never both.

To, CC and BCC are capped at 50 recipients COMBINED — the provider refuses a larger message, so the API rejects it rather than accepting a send that dies downstream where you cannot see it.

func (SendEmailRequest) MarshalJSON

func (r SendEmailRequest) MarshalJSON() ([]byte, error)

MarshalJSON merges Extra over the named fields.

type SendEmailResponse

type SendEmailResponse struct {
	Object string `json:"object"`
	ID     string `json:"id"`
}

SendEmailResponse is what a send returns: the id you look the send up by, and the id webhooks reference.

type SendPostRequest

type SendPostRequest struct {
	ScheduledAt string `json:"scheduled_at,omitempty"`

	// Extra carries wire fields this SDK version does not name yet.
	Extra Params `json:"-"`
}

SendPostRequest is the body of POST /v1/posts/{id}/send. Leave it zero to send now; set ScheduledAt (ISO 8601) to schedule.

func (SendPostRequest) MarshalJSON

func (r SendPostRequest) MarshalJSON() ([]byte, error)

MarshalJSON merges Extra over the named fields.

type SendTestPostRequest

type SendTestPostRequest struct {
	Recipients []string `json:"recipients"`
	From       string   `json:"from,omitempty"`
	ReplyTo    string   `json:"reply_to,omitempty"`

	// Extra carries wire fields this SDK version does not name yet.
	Extra Params `json:"-"`
}

SendTestPostRequest is the body of POST /v1/posts/{id}/test. Up to 10 recipients; From must use a verified domain.

func (SendTestPostRequest) MarshalJSON

func (r SendTestPostRequest) MarshalJSON() ([]byte, error)

MarshalJSON merges Extra over the named fields.

type SendTestPostResponse

type SendTestPostResponse struct {
	SentTo   []string `json:"sent_to"`
	FailedTo []string `json:"failed_to"`
}

SendTestPostResponse reports which test recipients were reached.

type SendersService

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

SendersService is the `senders` resource — named From identities. Reach it as client.Senders.

Senders are scoped to a publication. Create takes name and email (the address must live on a verified, DKIM-verified email domain), plus optional reply_to and is_default. The email is immutable, so Update only changes name, reply_to and is_default.

func (*SendersService) Create

func (s *SendersService) Create(ctx context.Context, params Params) (Object, error)

Create adds a sender.

func (*SendersService) Delete

func (s *SendersService) Delete(ctx context.Context, id string, params Params) (Object, error)

Delete removes a sender. Requires publication_id.

func (*SendersService) Get

func (s *SendersService) Get(ctx context.Context, id string, params Params) (Object, error)

Get retrieves one sender. Requires publication_id.

func (*SendersService) List

func (s *SendersService) List(ctx context.Context, params Params) (*List, error)

List lists senders, cursor-paginated. Filters: publication_id (required), limit, after (a cursor from a previous next_cursor).

func (*SendersService) Update

func (s *SendersService) Update(ctx context.Context, id string, params Params) (Object, error)

Update changes a sender's name, reply_to or is_default. publication_id is required in the body — unlike most updates, this one reads nothing from the query string.

type SuppressionsService

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

SuppressionsService is the `suppressions` resource — the team-wide do-not-send list. Reach it as client.Suppressions.

Suppressions are team-scoped: there is no publication_id here.

func (*SuppressionsService) Add

func (s *SuppressionsService) Add(ctx context.Context, params Params) (Object, error)

Add adds addresses to the suppression list. Takes emails (up to 1000) and an optional reason. Returns {"added": n}.

func (*SuppressionsService) Export

func (s *SuppressionsService) Export(ctx context.Context) (string, error)

Export returns the whole suppression list as CSV — the raw text/csv body (email,reason,source,created_at with a header row), not JSON.

func (*SuppressionsService) List

func (s *SuppressionsService) List(ctx context.Context, params Params) (*List, error)

List lists suppression entries, cursor-paginated. Optional filters: reason, q (email search), created_after, created_before, limit, starting_after (a cursor from a previous next_cursor).

func (*SuppressionsService) Remove

func (s *SuppressionsService) Remove(ctx context.Context, params Params) (Object, error)

Remove takes addresses off the suppression list. Takes emails. Returns {"removed": n}. The body travels on a DELETE, which is what this endpoint reads.

type Tag

type Tag struct {
	Name  string `json:"name"`
	Value string `json:"value"`
}

Tag is a key/value label carried with a send, for filtering and analytics later.

type TemplateRef

type TemplateRef struct {
	ID        string                 `json:"id"`
	Variables map[string]interface{} `json:"variables,omitempty"`
}

TemplateRef seeds a send from a published server-side template instead of inline HTML. Variables fill the template's placeholders.

type TemplatesService

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

TemplatesService is the `templates` resource — reusable server-side email templates. Reach it as client.Templates.

Templates are scoped to a publication (except Render, which just renders a spec). Create one from raw html, a json-render spec, or an editor_doc (a Studio editor design), then Publish it before seeding posts or emails from it.

func (*TemplatesService) Create

func (s *TemplatesService) Create(ctx context.Context, params Params) (Object, error)

Create adds a template from html, a spec, OR an editor_doc — exactly one is required, and the server renders html from an editor_doc, so do not send both. Takes publication_id and name, plus optional style_profile, mailtea_theme, global_css, category, preview_image_url, tags, description, text, subject, from, reply_to and variables.

func (*TemplatesService) Delete

func (s *TemplatesService) Delete(ctx context.Context, id string, params Params) (Object, error)

Delete removes a template. Requires publication_id.

func (*TemplatesService) Duplicate

func (s *TemplatesService) Duplicate(ctx context.Context, id string, params Params) (Object, error)

Duplicate copies a template into a new draft. Requires publication_id.

func (*TemplatesService) Get

func (s *TemplatesService) Get(ctx context.Context, id string, params Params) (Object, error)

Get retrieves one template. Requires publication_id.

func (*TemplatesService) List

func (s *TemplatesService) List(ctx context.Context, params Params) (*List, error)

List lists templates, cursor-paginated. Filters: publication_id (required), limit, after (a cursor from a previous next_cursor).

func (*TemplatesService) Publish

func (s *TemplatesService) Publish(ctx context.Context, id string, params Params) (Object, error)

Publish makes a template available to seed posts and emails. Requires publication_id.

func (*TemplatesService) Render

func (s *TemplatesService) Render(ctx context.Context, params Params) (Object, error)

Render renders a json-render `spec` (with optional `variables`) to HTML without creating a template. Returns {"html": ..., "text": ...}.

func (*TemplatesService) RestoreVersion

func (s *TemplatesService) RestoreVersion(ctx context.Context, id string, version interface{}, params Params) (Object, error)

RestoreVersion puts an older design from Versions back onto the template. Requires publication_id.

Restoring is a content write, so THE TEMPLATE RETURNS TO DRAFT — automations and the API stop sending it until Publish is called again. The reply's `unpublished` reports whether that just happened; re-publishing is the caller's job.

History is forward-only: the design being replaced is recorded as its own version first, then the restored design is appended as the new newest one. Nothing is rewound or deleted, so a restore is itself undone by restoring the entry directly above it.

Restoring the design that is already current writes nothing and returns restored: false with reason: "identical" and unpublished: false, so a no-op restore cannot unpublish a live template. A version that has aged out of retention returns a *Error with Code "template_version_not_found".

version is an int or a string — whatever Versions reported.

func (*TemplatesService) Unpublish

func (s *TemplatesService) Unpublish(ctx context.Context, id string, params Params) (Object, error)

Unpublish returns a published template to draft. published_at is kept — it records that the template was published once, not that it still is. Requires publication_id.

func (*TemplatesService) Update

func (s *TemplatesService) Update(ctx context.Context, id string, params Params) (Object, error)

Update changes a template. An editor_doc re-renders html server-side, so do not send both. global_css, category, preview_image_url, tags, text, subject, from and reply_to accept an explicit nil to clear them. publication_id is required and travels in the query string as well as the body.

func (*TemplatesService) Versions

func (s *TemplatesService) Versions(ctx context.Context, id string, params Params) (Object, error)

Versions lists a template's design history, newest first. Requires publication_id; optional limit (the server caps it at the retained maximum).

Entries are metadata only — version, origin ("edit", "publish" or "restore"), restored_from_version, format, name, sealed, is_current, created_at, updated_at and author — never the design document, which one entry alone can carry half a megabyte of. is_current marks the design the template is serving right now, which is not always the newest entry: a metadata-only update touches the template without recording a version.

The reply also carries `retention`: only the newest max_versions are kept, and consecutive edits by the same author within coalesce_window_seconds collapse into one entry.

type TopicsService

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

TopicsService is the `topics` resource — topic definitions. Reach it as client.Topics.

Topics are scoped to a publication. This manages topic definitions only; assigning topics to contacts is not yet exposed by the API.

func (*TopicsService) Create

func (s *TopicsService) Create(ctx context.Context, request CreateTopicRequest) (Object, error)

Create adds a topic definition.

func (*TopicsService) Delete

func (s *TopicsService) Delete(ctx context.Context, id string, params Params) (Object, error)

Delete removes a topic. Requires publication_id.

func (*TopicsService) Get

func (s *TopicsService) Get(ctx context.Context, id string, params Params) (Object, error)

Get retrieves one topic. Requires publication_id.

func (*TopicsService) List

func (s *TopicsService) List(ctx context.Context, params Params) (*List, error)

List lists topics. Requires publication_id.

func (*TopicsService) Update

func (s *TopicsService) Update(ctx context.Context, id string, params Params) (Object, error)

Update changes a topic. publication_id travels in the query string and the body alike.

type TrackingDomainsService

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

TrackingDomainsService covers tracking sub-domains (CNAME) under a domain — used to serve open-pixel and click-tracking links from your own domain. Reach it as client.Domains.Tracking.

func (*TrackingDomainsService) Create

func (s *TrackingDomainsService) Create(ctx context.Context, domainID string, params Params) (Object, error)

Create adds a tracking sub-domain. Takes publication_id and subdomain. The response's `records` lists the CNAME to add.

publication_id goes in the query string and only `subdomain` in the body, which is what this endpoint reads.

func (*TrackingDomainsService) Delete

func (s *TrackingDomainsService) Delete(ctx context.Context, domainID, trackingDomainID string, params Params) (Object, error)

Delete removes a tracking sub-domain. Requires publication_id.

func (*TrackingDomainsService) List

func (s *TrackingDomainsService) List(ctx context.Context, domainID string, params Params) (Object, error)

List lists a domain's tracking sub-domains. Requires publication_id.

func (*TrackingDomainsService) Verify

func (s *TrackingDomainsService) Verify(ctx context.Context, domainID, trackingDomainID string, params Params) (Object, error)

Verify checks a tracking sub-domain's CNAME. Requires publication_id.

type UpdateContactRequest

type UpdateContactRequest struct {
	PublicationID string `json:"publication_id"`
	Status        string `json:"status,omitempty"`

	// Extra carries wire fields this SDK version does not name yet.
	Extra Params `json:"-"`
}

UpdateContactRequest is the body of PATCH /v1/contacts/{id_or_email}. PublicationID is required — it goes in the query string and the body alike.

func (UpdateContactRequest) MarshalJSON

func (r UpdateContactRequest) MarshalJSON() ([]byte, error)

MarshalJSON merges Extra over the named fields.

type UpdateEmailRequest

type UpdateEmailRequest struct {
	ScheduledAt string `json:"scheduled_at,omitempty"`

	// Extra carries wire fields this SDK version does not name yet.
	Extra Params `json:"-"`
}

UpdateEmailRequest reschedules a scheduled email. ScheduledAt is currently the only field the API accepts.

func (UpdateEmailRequest) MarshalJSON

func (r UpdateEmailRequest) MarshalJSON() ([]byte, error)

MarshalJSON merges Extra over the named fields.

type WebhooksService

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

WebhooksService is the `webhooks` resource — outbound event subscriptions. Reach it as client.Webhooks.

Scoped to a publication. Create returns the signing_secret ONCE; store it and verify deliveries with VerifyWebhookSignature.

func (*WebhooksService) Create

func (s *WebhooksService) Create(ctx context.Context, params Params) (Object, error)

Create registers a webhook endpoint.

func (*WebhooksService) Delete

func (s *WebhooksService) Delete(ctx context.Context, id string, params Params) (Object, error)

Delete removes a webhook endpoint. Requires publication_id.

func (*WebhooksService) Get

func (s *WebhooksService) Get(ctx context.Context, id string, params Params) (Object, error)

Get retrieves one webhook endpoint. Requires publication_id.

func (*WebhooksService) List

func (s *WebhooksService) List(ctx context.Context, params Params) (*List, error)

List lists webhook endpoints. Requires publication_id.

func (*WebhooksService) Update

func (s *WebhooksService) Update(ctx context.Context, id string, params Params) (Object, error)

Update changes a webhook endpoint. publication_id travels in the query string and the body alike.

Jump to

Keyboard shortcuts

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