loops

package module
v0.1.3 Latest Latest
Warning

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

Go to latest
Published: May 5, 2026 License: MIT Imports: 8 Imported by: 0

README

loops-go

Go Reference

Go SDK for the Loops API.

Install

go get github.com/loops-so/loops-go

Quickstart

package main

import (
    "log"

    loops "github.com/loops-so/loops-go"
)

func main() {
    client := loops.NewClient("YOUR_API_KEY")

    err := client.SendEvent(loops.SendEventRequest{
        Email:     "user@example.com",
        EventName: "signup",
        EventProperties: map[string]any{
            "plan": "pro",
        },
    })
    if err != nil {
        log.Fatal(err)
    }
}

Client options

client := loops.NewClient("YOUR_API_KEY",
    loops.WithBaseURL("https://app.loops.so/api/v1"),
    loops.WithHTTPClient(myHTTPClient),
    loops.WithUserAgent("my-app/1.0"),
    loops.WithLogger(os.Stderr), // verbose request/response logging
)

Supported endpoints

  • API key — GetAPIKey
  • Contacts — CreateContact, UpdateContact, DeleteContact, FindContacts, CheckContactSuppression, RemoveContactSuppression
  • Contact properties — ListContactProperties, CreateContactProperty
  • Mailing lists — ListMailingLists
  • Events — SendEvent
  • Transactional — SendTransactional, ListTransactional
  • Email messages — GetEmailMessage, UpdateEmailMessage
  • Campaigns — CreateCampaign, UpdateCampaign, GetCampaign, ListCampaigns
  • Components — GetComponent, ListComponents
  • Themes — GetTheme, ListThemes

Full reference: pkg.go.dev/github.com/loops-so/loops-go.

Errors

API errors are returned as *loops.APIError with StatusCode and Message:

if err := client.SendEvent(req); err != nil {
    var apiErr *loops.APIError
    if errors.As(err, &apiErr) {
        log.Printf("loops api error %d: %s", apiErr.StatusCode, apiErr.Message)
    }
    return err
}

Retries

Requests are automatically retried with exponential backoff and jitter on 429 and 5xx responses (up to 2 retries).

Idempotency

SendEvent and SendTransactional accept an IdempotencyKey field, which is sent as the Idempotency-Key header.

Pagination

ListTransactional and ListCampaigns return a single page of results along with a *Pagination value. Pass a PaginationParams to control page size and cursor:

items, page, err := client.ListTransactional(loops.PaginationParams{PerPage: "50"})
if err != nil {
    log.Fatal(err)
}
// page.NextCursor is "" when there are no more pages.

To fetch every page, use the generic Paginate helper:

all, err := loops.Paginate(func(cursor string) ([]loops.TransactionalEmail, *loops.Pagination, error) {
    return client.ListTransactional(loops.PaginationParams{Cursor: cursor})
})

License

MIT

Documentation

Index

Constants

View Source
const (
	DefaultBaseURL = "https://app.loops.so/api/v1"
)
View Source
const Version string = "0.1.0"

Variables

This section is empty.

Functions

func Paginate

func Paginate[T any](fetch func(cursor string) ([]T, *Pagination, error)) ([]T, error)

Types

type APIError

type APIError struct {
	StatusCode int
	Message    string
}

func (*APIError) Error

func (e *APIError) Error() string

type APIKeyResponse

type APIKeyResponse struct {
	TeamName string `json:"teamName"`
}

type Attachment

type Attachment struct {
	Filename    string `json:"filename"`
	ContentType string `json:"contentType"`
	Data        string `json:"data"`
}

type Campaign

type Campaign struct {
	CampaignID     string  `json:"campaignId"`
	EmailMessageID *string `json:"emailMessageId"`
	Name           string  `json:"name"`
	Status         string  `json:"status"`
	CreatedAt      string  `json:"createdAt"`
	UpdatedAt      string  `json:"updatedAt"`
}

type CampaignCreateResponse

type CampaignCreateResponse struct {
	Campaign
	EmailMessageContentRevisionID *string `json:"emailMessageContentRevisionId"`
}

type CampaignListItem

type CampaignListItem struct {
	CampaignID     string  `json:"campaignId"`
	EmailMessageID *string `json:"emailMessageId"`
	Name           string  `json:"name"`
	Subject        string  `json:"subject"`
	Status         string  `json:"status"`
	CreatedAt      string  `json:"createdAt"`
	UpdatedAt      string  `json:"updatedAt"`
}

type Client

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

func NewClient

func NewClient(apiKey string, opts ...Option) *Client

func (*Client) CheckContactSuppression

func (c *Client) CheckContactSuppression(email, userID string) (*ContactSuppression, error)

func (*Client) CreateCampaign

func (c *Client) CreateCampaign(req CreateCampaignRequest) (*CampaignCreateResponse, error)

func (*Client) CreateContact

func (c *Client) CreateContact(req CreateContactRequest) (string, error)

func (*Client) CreateContactProperty

func (c *Client) CreateContactProperty(name, propType string) error

func (*Client) DeleteContact

func (c *Client) DeleteContact(email, userID string) error

func (*Client) FindContacts

func (c *Client) FindContacts(params FindContactParams) ([]Contact, error)

func (*Client) GetAPIKey

func (c *Client) GetAPIKey() (*APIKeyResponse, error)

func (*Client) GetCampaign

func (c *Client) GetCampaign(id string) (*Campaign, error)

func (*Client) GetComponent added in v0.1.2

func (c *Client) GetComponent(id string) (*Component, error)

func (*Client) GetEmailMessage

func (c *Client) GetEmailMessage(id string) (*EmailMessage, error)

func (*Client) GetTheme added in v0.1.3

func (c *Client) GetTheme(id string) (*Theme, error)

func (*Client) ListCampaigns

func (c *Client) ListCampaigns(params PaginationParams) ([]CampaignListItem, *Pagination, error)

func (*Client) ListComponents added in v0.1.2

func (c *Client) ListComponents(params PaginationParams) ([]Component, *Pagination, error)

func (*Client) ListContactProperties

func (c *Client) ListContactProperties(customOnly bool) ([]ContactProperty, error)

func (*Client) ListMailingLists

func (c *Client) ListMailingLists() ([]MailingList, error)

func (*Client) ListThemes added in v0.1.3

func (c *Client) ListThemes(params PaginationParams) ([]Theme, *Pagination, error)

func (*Client) ListTransactional

func (c *Client) ListTransactional(params PaginationParams) ([]TransactionalEmail, *Pagination, error)

func (*Client) RemoveContactSuppression

func (c *Client) RemoveContactSuppression(email, userID string) (*ContactSuppressionRemoval, error)

func (*Client) SendEvent

func (c *Client) SendEvent(req SendEventRequest) error

func (*Client) SendTransactional

func (c *Client) SendTransactional(req SendTransactionalRequest) error

func (*Client) UpdateCampaign

func (c *Client) UpdateCampaign(id string, req UpdateCampaignRequest) (*Campaign, error)

func (*Client) UpdateContact

func (c *Client) UpdateContact(req UpdateContactRequest) error

func (*Client) UpdateEmailMessage

func (c *Client) UpdateEmailMessage(id string, req UpdateEmailMessageRequest) (*EmailMessage, error)

type Component added in v0.1.2

type Component struct {
	ComponentID string `json:"componentId"`
	Name        string `json:"name"`
	LMX         string `json:"lmx"`
}

type Contact

type Contact struct {
	ID           string          `json:"id"`
	Email        string          `json:"email"`
	FirstName    *string         `json:"firstName"`
	LastName     *string         `json:"lastName"`
	Source       string          `json:"source"`
	Subscribed   bool            `json:"subscribed"`
	UserGroup    string          `json:"userGroup"`
	UserID       *string         `json:"userId"`
	MailingLists map[string]bool `json:"mailingLists"`
	OptInStatus  *string         `json:"optInStatus"`
	Custom       map[string]any  `json:"-"`
}

func (Contact) MarshalJSON

func (c Contact) MarshalJSON() ([]byte, error)

func (*Contact) UnmarshalJSON

func (c *Contact) UnmarshalJSON(data []byte) error

type ContactProperty

type ContactProperty struct {
	Key   string `json:"key"`
	Label string `json:"label"`
	Type  string `json:"type"`
}

type ContactSuppression

type ContactSuppression struct {
	Contact struct {
		ID     string  `json:"id"`
		Email  string  `json:"email"`
		UserID *string `json:"userId"`
	} `json:"contact"`
	IsSuppressed bool `json:"isSuppressed"`
	RemovalQuota struct {
		Limit     int `json:"limit"`
		Remaining int `json:"remaining"`
	} `json:"removalQuota"`
}

type ContactSuppressionRemoval

type ContactSuppressionRemoval struct {
	Success      bool   `json:"success"`
	Message      string `json:"message"`
	RemovalQuota struct {
		Limit     int `json:"limit"`
		Remaining int `json:"remaining"`
	} `json:"removalQuota"`
}

type CreateCampaignRequest

type CreateCampaignRequest struct {
	Name string `json:"name"`
}

type CreateContactRequest

type CreateContactRequest struct {
	Email             string
	FirstName         string
	LastName          string
	Source            string
	Subscribed        *bool
	UserGroup         string
	UserID            string
	MailingLists      map[string]bool
	ContactProperties map[string]any
}

type EmailMessage

type EmailMessage struct {
	EmailMessageID    string       `json:"emailMessageId"`
	CampaignID        *string      `json:"campaignId"`
	Subject           string       `json:"subject"`
	PreviewText       string       `json:"previewText"`
	FromName          string       `json:"fromName"`
	FromEmail         string       `json:"fromEmail"`
	ReplyToEmail      string       `json:"replyToEmail"`
	LMX               string       `json:"lmx"`
	ContentRevisionID *string      `json:"contentRevisionId"`
	UpdatedAt         string       `json:"updatedAt"`
	Warnings          []LmxWarning `json:"warnings,omitempty"`
}

type EmailMessageFields

type EmailMessageFields struct {
	Subject      string `json:"subject,omitempty"`
	PreviewText  string `json:"previewText,omitempty"`
	FromName     string `json:"fromName,omitempty"`
	FromEmail    string `json:"fromEmail,omitempty"`
	ReplyToEmail string `json:"replyToEmail,omitempty"`
	LMX          string `json:"lmx,omitempty"`
}

type FindContactParams

type FindContactParams struct {
	Email  string
	UserID string
}

type LmxWarning

type LmxWarning struct {
	Rule     string `json:"rule"`
	Severity string `json:"severity"`
	Message  string `json:"message"`
	Path     string `json:"path,omitempty"`
}

type MailingList

type MailingList struct {
	ID          string `json:"id"`
	Name        string `json:"name"`
	Description string `json:"description"`
	IsPublic    bool   `json:"isPublic"`
}

type Option

type Option func(*Client)

func WithBaseURL

func WithBaseURL(u string) Option

func WithHTTPClient

func WithHTTPClient(h *http.Client) Option

func WithLogger

func WithLogger(w io.Writer) Option

func WithUserAgent

func WithUserAgent(ua string) Option

type Pagination

type Pagination struct {
	TotalResults    int    `json:"totalResults"`
	ReturnedResults int    `json:"returnedResults"`
	PerPage         int    `json:"perPage"`
	TotalPages      int    `json:"totalPages"`
	NextCursor      string `json:"nextCursor"`
	NextPage        string `json:"nextPage"`
}

type PaginationParams

type PaginationParams struct {
	PerPage string
	Cursor  string
}

type SendEventRequest

type SendEventRequest struct {
	Email             string          `json:"-"`
	UserID            string          `json:"-"`
	EventName         string          `json:"-"`
	EventProperties   map[string]any  `json:"-"`
	MailingLists      map[string]bool `json:"-"`
	ContactProperties map[string]any  `json:"-"`
	IdempotencyKey    string          `json:"-"`
}

type SendTransactionalRequest

type SendTransactionalRequest struct {
	Email           string         `json:"email"`
	TransactionalID string         `json:"transactionalId"`
	AddToAudience   *bool          `json:"addToAudience,omitempty"`
	DataVariables   map[string]any `json:"dataVariables,omitempty"`
	Attachments     []Attachment   `json:"attachments,omitempty"`
	IdempotencyKey  string         `json:"-"`
}

type Theme added in v0.1.3

type Theme struct {
	ThemeID   string      `json:"themeId"`
	Name      string      `json:"name"`
	Styles    ThemeStyles `json:"styles"`
	IsDefault bool        `json:"isDefault"`
	CreatedAt string      `json:"createdAt"`
	UpdatedAt string      `json:"updatedAt"`
}

type ThemeStyles added in v0.1.3

type ThemeStyles struct {
	BackgroundColor       string  `json:"backgroundColor"`
	BackgroundXPadding    float64 `json:"backgroundXPadding"`
	BackgroundYPadding    float64 `json:"backgroundYPadding"`
	BodyColor             string  `json:"bodyColor"`
	BodyXPadding          float64 `json:"bodyXPadding"`
	BodyYPadding          float64 `json:"bodyYPadding"`
	BodyFontFamily        string  `json:"bodyFontFamily"`
	BodyFontCategory      string  `json:"bodyFontCategory"`
	BorderColor           string  `json:"borderColor"`
	BorderWidth           float64 `json:"borderWidth"`
	BorderRadius          float64 `json:"borderRadius"`
	ButtonBodyColor       string  `json:"buttonBodyColor"`
	ButtonBodyXPadding    float64 `json:"buttonBodyXPadding"`
	ButtonBodyYPadding    float64 `json:"buttonBodyYPadding"`
	ButtonBorderColor     string  `json:"buttonBorderColor"`
	ButtonBorderWidth     float64 `json:"buttonBorderWidth"`
	ButtonBorderRadius    float64 `json:"buttonBorderRadius"`
	ButtonTextColor       string  `json:"buttonTextColor"`
	ButtonTextFormat      float64 `json:"buttonTextFormat"`
	ButtonTextFontSize    float64 `json:"buttonTextFontSize"`
	DividerColor          string  `json:"dividerColor"`
	DividerBorderWidth    float64 `json:"dividerBorderWidth"`
	TextBaseColor         string  `json:"textBaseColor"`
	TextBaseFontSize      float64 `json:"textBaseFontSize"`
	TextBaseLineHeight    float64 `json:"textBaseLineHeight"`
	TextBaseLetterSpacing float64 `json:"textBaseLetterSpacing"`
	TextLinkColor         string  `json:"textLinkColor"`
	Heading1Color         string  `json:"heading1Color"`
	Heading1FontSize      float64 `json:"heading1FontSize"`
	Heading1LineHeight    float64 `json:"heading1LineHeight"`
	Heading1LetterSpacing float64 `json:"heading1LetterSpacing"`
	Heading2Color         string  `json:"heading2Color"`
	Heading2FontSize      float64 `json:"heading2FontSize"`
	Heading2LineHeight    float64 `json:"heading2LineHeight"`
	Heading2LetterSpacing float64 `json:"heading2LetterSpacing"`
	Heading3Color         string  `json:"heading3Color"`
	Heading3FontSize      float64 `json:"heading3FontSize"`
	Heading3LineHeight    float64 `json:"heading3LineHeight"`
	Heading3LetterSpacing float64 `json:"heading3LetterSpacing"`
}

type TransactionalEmail

type TransactionalEmail struct {
	ID            string   `json:"id"`
	Name          string   `json:"name"`
	LastUpdated   string   `json:"lastUpdated"`
	DataVariables []string `json:"dataVariables"`
}

type UpdateCampaignRequest

type UpdateCampaignRequest struct {
	Name string `json:"name"`
}

type UpdateContactRequest

type UpdateContactRequest struct {
	Email             string
	UserID            string
	FirstName         string
	LastName          string
	Subscribed        *bool
	UserGroup         string
	MailingLists      map[string]bool
	ContactProperties map[string]any
}

type UpdateEmailMessageRequest

type UpdateEmailMessageRequest struct {
	EmailMessageFields
	Set                map[string]bool
	ExpectedRevisionID string
}

Jump to

Keyboard shortcuts

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