bird

package module
v0.32.0 Latest Latest
Warning

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

Go to latest
Published: Aug 18, 2026 License: MIT Imports: 24 Imported by: 0

README

Bird Go SDK

The official Go SDK for the Bird API: email, SMS, WhatsApp, verification, and Realtime, over one typed client.

go get github.com/messagebird/bird-sdk-go

Requires Go 1.24+.

This SDK is generated from Bird's public OpenAPI bundle inside Bird's internal monorepo, which is the single source of truth; this repository tracks tagged releases. Generation runs in the monorepo, so make generate won't work from a clone here — see CONTRIBUTING.md.

Overview

bird.NewClient(option.WithAPIKey(...)) returns a client whose region is inferred from the API key's prefix (bk_{region}_…); pass option.WithBaseURL or option.WithRegion to override. From there:

  • client.EmailSend, Get, List (auto-paginating; ListPage for manual cursors).
  • client.SmsSend (free text or a stored template), SendBatch, Get, List (auto-paginating; ListPage for manual cursors). client.SmsTemplates (List, Get) browses the templates a send can name.
  • client.WhatsappSend (template messages), Get, List (auto-paginating; ListPage for manual cursors), ListEvents (a message's delivery timeline). Browse your workspace's approved templates in the Bird dashboard.
  • client.VerifyVerifications.Create (send a one-time passcode) and Verifications.Check (validate the code a recipient submitted).
  • client.RealtimePublish, PublishBatch, plus Channels (List, Get, Members) and Members.Disconnect. Every call takes the Realtime app id and needs the app's own credentials on top of the API key: option.WithRealtimeCredentials(key, secret), at construction or per call.
  • client.ContactsCreate, Get, Update, Delete, Batch, List (auto-paginating). client.Audiences groups them (Create, Get, Update, Delete, List, plus ListContacts, AddContacts, RemoveContacts, RemoveContact), and client.ContactProperties defines the fields a contact carries (Create, Get, Update, List, Archive, Unarchive).
  • client.DomainsCreate, Get, Update, Delete, List, and Verify (check a sending domain's DNS).
  • client.WebhooksUnwrap (verify a signed event into a typed value).
  • Typed errors. A failure is a *bird.APIError (or a richer *bird.RateLimitError / *bird.ValidationError) you branch on with errors.As. Transient failures (timeouts, 429, 5xx) are retried automatically with a reused idempotency key.
  • Options configure the client and override per call (option.WithEmailDefaults, WithTimeout, WithIdempotencyKey, …).
  • client.Get/Post/Put/Patch/Delete reach endpoints outside the curated surface.

Examples

Runnable, per-method examples live in example_test.go and render under each method on pkg.go.dev: sending (simple and rich), error handling, get, pagination, channel defaults, the webhook receiver, and the escape hatch.

Design

The wire types and a low-level client are generated from the OpenAPI spec into internal/oapi; this package is the hand-written idiomatic layer on top.

Documentation

Overview

Code generated by surface-gen; DO NOT EDIT.

Package bird is the official Go SDK for the Bird API.

It covers email, SMS, WhatsApp, verification, and Realtime on one typed client, and offers a curated resource surface, a typed error hierarchy, context cancellation, functional options, safe retries with reused idempotency keys, range-over-func pagination, and webhook verification.

client, err := bird.NewClient(option.WithAPIKey(os.Getenv("BIRD_API_KEY")))
if err != nil { ... }
msg, err := client.Email.Send(ctx, bird.EmailSendParams{
	From: "hello@acme.com", To: []string{"customer@example.com"},
	Subject: "Welcome", HTML: "<h1>Hi</h1>",
})

Code generated by surface-gen; DO NOT EDIT.

Code generated by surface-gen; DO NOT EDIT.

Code generated by surface-gen; DO NOT EDIT.

Code generated by surface-gen; DO NOT EDIT.

Code generated by surface-gen; DO NOT EDIT.

Code generated by surface-gen; DO NOT EDIT.

Code generated by surface-gen; DO NOT EDIT.

Code generated by surface-gen; DO NOT EDIT.

Code generated by surface-gen; DO NOT EDIT.

Code generated by surface-gen; DO NOT EDIT.

Code generated by surface-gen; DO NOT EDIT.

Code generated by surface-gen; DO NOT EDIT.

Code generated by surface-gen; DO NOT EDIT.

Code generated by surface-gen; DO NOT EDIT.

Code generated by surface-gen; DO NOT EDIT.

Code generated by surface-gen; DO NOT EDIT.

Code generated by surface-gen; DO NOT EDIT.

Code generated by surface-gen; DO NOT EDIT.

Example

Example constructs a client and sends an email. The region is taken from the API key's prefix; pass option.WithBaseURL or option.WithRegion to override.

package main

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

	bird "github.com/messagebird/bird-sdk-go"
	"github.com/messagebird/bird-sdk-go/option"
)

func main() {
	client, err := bird.NewClient(option.WithAPIKey(os.Getenv("BIRD_API_KEY")))
	if err != nil {
		log.Fatal(err)
	}
	msg, err := client.Email.Send(context.Background(), bird.EmailSendParams{
		From:    "onboarding@messagebird.dev",
		To:      []string{"delivered@messagebird.dev"},
		Subject: "Hello from Bird",
		HTML:    "<p>My first Bird email.</p>",
	})
	if err != nil {
		log.Fatal(err)
	}
	fmt.Println(msg.Id)
}

Index

Examples

Constants

View Source
const (
	ErrorTypeBadRequest         = apierror.ErrorTypeBadRequest
	ErrorTypeAuth               = apierror.ErrorTypeAuth
	ErrorTypeBilling            = apierror.ErrorTypeBilling
	ErrorTypePermission         = apierror.ErrorTypePermission
	ErrorTypeNotFound           = apierror.ErrorTypeNotFound
	ErrorTypeConflict           = apierror.ErrorTypeConflict
	ErrorTypePrecondition       = apierror.ErrorTypePrecondition
	ErrorTypePayloadTooLarge    = apierror.ErrorTypePayloadTooLarge
	ErrorTypeMisdirected        = apierror.ErrorTypeMisdirected
	ErrorTypeValidation         = apierror.ErrorTypeValidation
	ErrorTypeRateLimit          = apierror.ErrorTypeRateLimit
	ErrorTypeInternal           = apierror.ErrorTypeInternal
	ErrorTypeNotImplemented     = apierror.ErrorTypeNotImplemented
	ErrorTypeServiceUnavailable = apierror.ErrorTypeServiceUnavailable
)

ErrorType values — the coarse categories clients branch on.

View Source
const (
	EventTypeDomainFailed                 = oapi.EventTypeDomainFailed
	EventTypeDomainVerified               = oapi.EventTypeDomainVerified
	EventTypeEmailAccepted                = oapi.EventTypeEmailAccepted
	EventTypeEmailBounced                 = oapi.EventTypeEmailBounced
	EventTypeEmailCanceled                = oapi.EventTypeEmailCanceled
	EventTypeEmailClicked                 = oapi.EventTypeEmailClicked
	EventTypeEmailComplained              = oapi.EventTypeEmailComplained
	EventTypeEmailDeferred                = oapi.EventTypeEmailDeferred
	EventTypeEmailDelivered               = oapi.EventTypeEmailDelivered
	EventTypeEmailListUnsubscribed        = oapi.EventTypeEmailListUnsubscribed
	EventTypeEmailMailboxMessageDelivered = oapi.EventTypeEmailMailboxMessageDelivered
	EventTypeEmailMailboxMessageFailed    = oapi.EventTypeEmailMailboxMessageFailed
	EventTypeEmailMailboxMessageReceived  = oapi.EventTypeEmailMailboxMessageReceived
	EventTypeEmailMailboxMessageSent      = oapi.EventTypeEmailMailboxMessageSent
	EventTypeEmailMailboxSuspended        = oapi.EventTypeEmailMailboxSuspended
	EventTypeEmailMailboxThreadCreated    = oapi.EventTypeEmailMailboxThreadCreated
	EventTypeEmailOpened                  = oapi.EventTypeEmailOpened
	EventTypeEmailOutOfBandBounce         = oapi.EventTypeEmailOutOfBandBounce
	EventTypeEmailProcessed               = oapi.EventTypeEmailProcessed
	EventTypeEmailReceived                = oapi.EventTypeEmailReceived
	EventTypeEmailRejected                = oapi.EventTypeEmailRejected
	EventTypeEmailScheduled               = oapi.EventTypeEmailScheduled
	EventTypeEmailSuppressionCreated      = oapi.EventTypeEmailSuppressionCreated
	EventTypeEmailUnsubscribed            = oapi.EventTypeEmailUnsubscribed
	EventTypeSmsAccepted                  = oapi.EventTypeSmsAccepted
	EventTypeSmsDelivered                 = oapi.EventTypeSmsDelivered
	EventTypeSmsExpired                   = oapi.EventTypeSmsExpired
	EventTypeSmsFailed                    = oapi.EventTypeSmsFailed
	EventTypeSmsReceived                  = oapi.EventTypeSmsReceived
	EventTypeSmsRejected                  = oapi.EventTypeSmsRejected
	EventTypeSmsSent                      = oapi.EventTypeSmsSent
	EventTypeSmsUndelivered               = oapi.EventTypeSmsUndelivered
	EventTypeVerifyAttemptDelivered       = oapi.EventTypeVerifyAttemptDelivered
	EventTypeVerifyAttemptSent            = oapi.EventTypeVerifyAttemptSent
	EventTypeVerifyAttemptUndelivered     = oapi.EventTypeVerifyAttemptUndelivered
	EventTypeVerifyVerificationCreated    = oapi.EventTypeVerifyVerificationCreated
	EventTypeVerifyVerificationVerified   = oapi.EventTypeVerifyVerificationVerified
	EventTypeVoiceCallAnswered            = oapi.EventTypeVoiceCallAnswered
	EventTypeVoiceCallEnded               = oapi.EventTypeVoiceCallEnded
	EventTypeVoiceCallInitiated           = oapi.EventTypeVoiceCallInitiated
	EventTypeWhatsappAccepted             = oapi.EventTypeWhatsappAccepted
	EventTypeWhatsappDelivered            = oapi.EventTypeWhatsappDelivered
	EventTypeWhatsappFailed               = oapi.EventTypeWhatsappFailed
	EventTypeWhatsappRead                 = oapi.EventTypeWhatsappRead
	EventTypeWhatsappRejected             = oapi.EventTypeWhatsappRejected
	EventTypeWhatsappSent                 = oapi.EventTypeWhatsappSent
)

Webhook event types known at this SDK version. WebhookEventType is an open string on the wire: a value added by a newer server flows through Unwrap unchanged, so switch on these constants with a default branch.

View Source
const (
	EmailEventTypeEmailAccepted         = oapi.EmailEventTypeEmailAccepted
	EmailEventTypeEmailBounced          = oapi.EmailEventTypeEmailBounced
	EmailEventTypeEmailCanceled         = oapi.EmailEventTypeEmailCanceled
	EmailEventTypeEmailClicked          = oapi.EmailEventTypeEmailClicked
	EmailEventTypeEmailComplained       = oapi.EmailEventTypeEmailComplained
	EmailEventTypeEmailDeferred         = oapi.EmailEventTypeEmailDeferred
	EmailEventTypeEmailDelivered        = oapi.EmailEventTypeEmailDelivered
	EmailEventTypeEmailListUnsubscribed = oapi.EmailEventTypeEmailListUnsubscribed
	EmailEventTypeEmailOpened           = oapi.EmailEventTypeEmailOpened
	EmailEventTypeEmailOutOfBandBounce  = oapi.EmailEventTypeEmailOutOfBandBounce
	EmailEventTypeEmailProcessed        = oapi.EmailEventTypeEmailProcessed
	EmailEventTypeEmailRejected         = oapi.EmailEventTypeEmailRejected
	EmailEventTypeEmailScheduled        = oapi.EmailEventTypeEmailScheduled
	EmailEventTypeEmailUnsubscribed     = oapi.EmailEventTypeEmailUnsubscribed
)
View Source
const (
	EmailLookupFlagDisposable   = oapi.EmailLookupFlagDisposable
	EmailLookupFlagFreeProvider = oapi.EmailLookupFlagFreeProvider
	EmailLookupFlagRole         = oapi.EmailLookupFlagRole
)
View Source
const (
	EmailLookupReasonInvalidDomain    = oapi.EmailLookupReasonInvalidDomain
	EmailLookupReasonInvalidRecipient = oapi.EmailLookupReasonInvalidRecipient
	EmailLookupReasonInvalidSyntax    = oapi.EmailLookupReasonInvalidSyntax
)
View Source
const (
	EmailLookupResultNeutral       = oapi.EmailLookupResultNeutral
	EmailLookupResultRisky         = oapi.EmailLookupResultRisky
	EmailLookupResultTypo          = oapi.EmailLookupResultTypo
	EmailLookupResultUndeliverable = oapi.EmailLookupResultUndeliverable
	EmailLookupResultValid         = oapi.EmailLookupResultValid
)
View Source
const (
	LookupPropertyStatusInconclusive = oapi.LookupPropertyStatusInconclusive
	LookupPropertyStatusOk           = oapi.LookupPropertyStatusOk
	LookupPropertyStatusUnavailable  = oapi.LookupPropertyStatusUnavailable
)
View Source
const (
	SMSErrorCodeBlockedByCarrier    = oapi.SMSErrorCodeBlockedByCarrier
	SMSErrorCodeBlockedByRecipient  = oapi.SMSErrorCodeBlockedByRecipient
	SMSErrorCodeContentRejected     = oapi.SMSErrorCodeContentRejected
	SMSErrorCodeInsufficientBalance = oapi.SMSErrorCodeInsufficientBalance
	SMSErrorCodeInvalidDestination  = oapi.SMSErrorCodeInvalidDestination
	SMSErrorCodeLandlineUnreachable = oapi.SMSErrorCodeLandlineUnreachable
	SMSErrorCodeProviderUnavailable = oapi.SMSErrorCodeProviderUnavailable
	SMSErrorCodeRecipientOptedOut   = oapi.SMSErrorCodeRecipientOptedOut
	SMSErrorCodeSenderUnregistered  = oapi.SMSErrorCodeSenderUnregistered
	SMSErrorCodeUnknown             = oapi.SMSErrorCodeUnknown
	SMSErrorCodeUnreachable         = oapi.SMSErrorCodeUnreachable
)
View Source
const (
	TemplateLanguageStatusDraft      = oapi.TemplateLanguageStatusDraft
	TemplateLanguageStatusLive       = oapi.TemplateLanguageStatusLive
	TemplateLanguageStatusSuperseded = oapi.TemplateLanguageStatusSuperseded
)
View Source
const (
	TemplateStatusActive   = oapi.TemplateStatusActive
	TemplateStatusDraft    = oapi.TemplateStatusDraft
	TemplateStatusInactive = oapi.TemplateStatusInactive
	TemplateStatusPending  = oapi.TemplateStatusPending
	TemplateStatusRejected = oapi.TemplateStatusRejected
)
View Source
const (
	VerificationAttemptFailureReasonCarrierRejected    = oapi.VerificationAttemptFailureReasonCarrierRejected
	VerificationAttemptFailureReasonChannelDisabled    = oapi.VerificationAttemptFailureReasonChannelDisabled
	VerificationAttemptFailureReasonChannelUnavailable = oapi.VerificationAttemptFailureReasonChannelUnavailable
	VerificationAttemptFailureReasonDeliveryTimeout    = oapi.VerificationAttemptFailureReasonDeliveryTimeout
	VerificationAttemptFailureReasonHardBounce         = oapi.VerificationAttemptFailureReasonHardBounce
	VerificationAttemptFailureReasonSoftBounce         = oapi.VerificationAttemptFailureReasonSoftBounce
	VerificationAttemptFailureReasonUndelivered        = oapi.VerificationAttemptFailureReasonUndelivered
)
View Source
const (
	VerificationChannelEmail    = oapi.VerificationChannelEmail
	VerificationChannelSms      = oapi.VerificationChannelSms
	VerificationChannelTelegram = oapi.VerificationChannelTelegram
	VerificationChannelWhatsapp = oapi.VerificationChannelWhatsapp
)
View Source
const (
	VerificationTerminalReasonAttemptsExhausted = oapi.VerificationTerminalReasonAttemptsExhausted
	VerificationTerminalReasonTtlElapsed        = oapi.VerificationTerminalReasonTtlElapsed
)
View Source
const (
	WhatsAppErrorCodeInsufficientBalance  = oapi.WhatsAppErrorCodeInsufficientBalance
	WhatsAppErrorCodeInternalError        = oapi.WhatsAppErrorCodeInternalError
	WhatsAppErrorCodePriceNotFound        = oapi.WhatsAppErrorCodePriceNotFound
	WhatsAppErrorCodeRateLimited          = oapi.WhatsAppErrorCodeRateLimited
	WhatsAppErrorCodeRecipientSuppressed  = oapi.WhatsAppErrorCodeRecipientSuppressed
	WhatsAppErrorCodeServiceWindowExpired = oapi.WhatsAppErrorCodeServiceWindowExpired
	WhatsAppErrorCodeUndeliverable        = oapi.WhatsAppErrorCodeUndeliverable
)
View Source
const (
	WhatsAppEventTypeWhatsappAccepted  = oapi.WhatsAppEventTypeWhatsappAccepted
	WhatsAppEventTypeWhatsappDelivered = oapi.WhatsAppEventTypeWhatsappDelivered
	WhatsAppEventTypeWhatsappFailed    = oapi.WhatsAppEventTypeWhatsappFailed
	WhatsAppEventTypeWhatsappRead      = oapi.WhatsAppEventTypeWhatsappRead
	WhatsAppEventTypeWhatsappRejected  = oapi.WhatsAppEventTypeWhatsappRejected
	WhatsAppEventTypeWhatsappSent      = oapi.WhatsAppEventTypeWhatsappSent
)
View Source
const (
	WhatsAppTemplateCategoryAuthentication = oapi.WhatsAppTemplateCategoryAuthentication
	WhatsAppTemplateCategoryMarketing      = oapi.WhatsAppTemplateCategoryMarketing
	WhatsAppTemplateCategoryUtility        = oapi.WhatsAppTemplateCategoryUtility
)
View Source
const (
	WhatsAppTemplateParameterTypeDocument = oapi.WhatsAppTemplateParameterTypeDocument
	WhatsAppTemplateParameterTypeGif      = oapi.WhatsAppTemplateParameterTypeGif
	WhatsAppTemplateParameterTypeImage    = oapi.WhatsAppTemplateParameterTypeImage
	WhatsAppTemplateParameterTypeLocation = oapi.WhatsAppTemplateParameterTypeLocation
	WhatsAppTemplateParameterTypeText     = oapi.WhatsAppTemplateParameterTypeText
	WhatsAppTemplateParameterTypeVideo    = oapi.WhatsAppTemplateParameterTypeVideo
)
View Source
const (
	LookupFlagPorted = oapi.LookupFlagPorted
)

Variables

This section is empty.

Functions

func Bool

func Bool(v bool) *bool

Bool returns a pointer to v.

func Email added in v0.22.0

func Email(v string) *openapi_types.Email

Email returns a pointer to v as an email-typed field. A schema's `format: email` property is its own type on the wire, so bird.String does not fit one and Ptr needs the conversion spelled out:

bird.VerificationTo{Email: bird.Email("user@example.com")}

func Int

func Int(v int) *int

Int returns a pointer to v.

func Ptr

func Ptr[T any](v T) *T

Ptr returns a pointer to v, for setting optional pointer fields inline. Bool, String, Int, and Email are typed shorthands for the common cases:

bird.EmailSendParams{TrackOpens: bird.Bool(false)}

func String

func String(v string) *string

String returns a pointer to v.

Types

type APIError

type APIError = apierror.APIError

The SDK error model, re-exported from internal/apierror so these names are the semver-locked public surface. Catch *APIError (via errors.As) to handle any server error; the variants carry extra data. Transport failures with no HTTP response are *ConnectionError / *TimeoutError; a bad webhook signature is *WebhookVerificationError.

type Audience added in v0.4.0

type Audience = oapi.Audience

Audience is a static audience of contacts; AudienceList is a page of audiences. AudienceMember pairs a contact with the time it joined; AudienceMemberList is a page of members.

type AudienceAddContactsParams added in v0.4.0

type AudienceAddContactsParams struct {
	// Contacts to add to the audience. Adding a contact that is already a member has no effect and keeps its original join time. Duplicate IDs in the list are collapsed. If any ID does not exist in the workspace, the whole request fails with a validation error and no contacts are added.
	ContactIDs []string
}

AudienceAddContactsParams is the request body for add_contacts.

type AudienceCreateParams added in v0.4.0

type AudienceCreateParams struct {
	// Display name for the audience.
	Name string
	// Longer description of who this audience is.
	Description string
	// How the audience's recipients are determined. `static` is an explicit member list you manage by adding and removing contacts.
	Type *AudienceCreateRequestType
}

AudienceCreateParams is the request body for create.

type AudienceCreateRequestType added in v0.14.0

type AudienceCreateRequestType = oapi.AudienceCreateRequestType

type AudienceList added in v0.4.0

type AudienceList = oapi.AudienceList

Audience is a static audience of contacts; AudienceList is a page of audiences. AudienceMember pairs a contact with the time it joined; AudienceMemberList is a page of members.

type AudienceListContactsParams added in v0.4.0

type AudienceListContactsParams struct {
	// Case-insensitive substring match against the member's email address or phone number (digits of the international form).
	Q string
	// Maximum number of items to return per page.
	Limit int
}

AudienceListContactsParams filters the list. Zero-value fields are omitted.

type AudienceListParams added in v0.4.0

type AudienceListParams struct {
	// Case-insensitive substring match against the audience's name.
	Q string
	// Maximum number of items to return per page.
	Limit int
}

AudienceListParams filters the list. Zero-value fields are omitted.

type AudienceMember added in v0.4.0

type AudienceMember = oapi.AudienceMember

Audience is a static audience of contacts; AudienceList is a page of audiences. AudienceMember pairs a contact with the time it joined; AudienceMemberList is a page of members.

type AudienceMemberList added in v0.4.0

type AudienceMemberList = oapi.AudienceMemberList

Audience is a static audience of contacts; AudienceList is a page of audiences. AudienceMember pairs a contact with the time it joined; AudienceMemberList is a page of members.

type AudienceRemoveContactsParams added in v0.4.0

type AudienceRemoveContactsParams struct {
	// Contacts to remove from the audience. Removing a contact that is not a member has no effect. Duplicate IDs in the list are collapsed. If any ID does not exist in the workspace, the whole request fails with a validation error and no memberships are removed.
	ContactIDs []string
}

AudienceRemoveContactsParams is the request body for remove_contacts.

type AudienceUpdateParams added in v0.4.0

type AudienceUpdateParams struct {
	// New display name for the audience. Omit to keep the current name. The name cannot be cleared, and a whitespace-only value returns a validation error.
	Name string
	// Longer description of who this audience is. Set to null to clear.
	Description Nullable[string]
}

AudienceUpdateParams is the request body for update.

type AudiencesService added in v0.4.0

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

AudiencesService manages static audiences and their contact membership: create, read, update, delete, list, and add/remove contacts. Reach it via Client.Audiences.

func (*AudiencesService) AddContacts added in v0.4.0

func (s *AudiencesService) AddContacts(ctx context.Context, audienceId string, params AudienceAddContactsParams, opts ...option.RequestOption) error

AddContacts Add up to 1,000 existing contacts to a static audience by ID. Fails entirely if any contact ID does not exist. To add contacts you have not created yet, use `contacts.batch` with `audience_ids` instead: it matches or creates each contact by email address and assigns it to the audience in one call.

Example

AddContacts adds up to 1,000 existing contacts to a static audience.

package main

import (
	"context"
	"log"
	"os"

	bird "github.com/messagebird/bird-sdk-go"
	"github.com/messagebird/bird-sdk-go/option"
)

func main() {
	client, err := bird.NewClient(option.WithAPIKey(os.Getenv("BIRD_API_KEY")))
	if err != nil {
		log.Fatal(err)
	}
	err = client.Audiences.AddContacts(context.Background(), "adn_123", bird.AudienceAddContactsParams{
		ContactIDs: []string{"con_1", "con_2"},
	})
	if err != nil {
		log.Fatal(err)
	}
}

func (*AudiencesService) Create added in v0.4.0

Create Create an audience in the workspace. New audiences start empty; add contacts with `audiences.add_contacts` or `contacts.batch`. Only static audiences can be created today.

Example
package main

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

	bird "github.com/messagebird/bird-sdk-go"
	"github.com/messagebird/bird-sdk-go/option"
)

func main() {
	client, err := bird.NewClient(option.WithAPIKey(os.Getenv("BIRD_API_KEY")))
	if err != nil {
		log.Fatal(err)
	}
	audience, err := client.Audiences.Create(context.Background(), bird.AudienceCreateParams{
		Name: "Newsletter subscribers",
	})
	if err != nil {
		log.Fatal(err)
	}
	fmt.Println(audience.Id)
}

func (*AudiencesService) Delete added in v0.4.0

func (s *AudiencesService) Delete(ctx context.Context, audienceId string, opts ...option.RequestOption) error

Delete Delete an audience and its memberships; contacts themselves are not deleted. Fails while a broadcast targeting the audience is scheduled, accepted, sending, or canceling.

Example

Delete removes an audience. The contacts themselves are not deleted.

package main

import (
	"context"
	"log"
	"os"

	bird "github.com/messagebird/bird-sdk-go"
	"github.com/messagebird/bird-sdk-go/option"
)

func main() {
	client, err := bird.NewClient(option.WithAPIKey(os.Getenv("BIRD_API_KEY")))
	if err != nil {
		log.Fatal(err)
	}
	if err := client.Audiences.Delete(context.Background(), "adn_123"); err != nil {
		log.Fatal(err)
	}
}

func (*AudiencesService) Get added in v0.4.0

func (s *AudiencesService) Get(ctx context.Context, audienceId string, opts ...option.RequestOption) (*Audience, error)

Get Get a single audience by ID: name, description, and type. Members are listed separately with `audiences.list_contacts`.

Example

Get returns a single audience by id.

package main

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

	bird "github.com/messagebird/bird-sdk-go"
	"github.com/messagebird/bird-sdk-go/option"
)

func main() {
	client, err := bird.NewClient(option.WithAPIKey(os.Getenv("BIRD_API_KEY")))
	if err != nil {
		log.Fatal(err)
	}
	audience, err := client.Audiences.Get(context.Background(), "adn_123")
	if err != nil {
		log.Fatal(err)
	}
	fmt.Println(audience.Name)
}

func (*AudiencesService) List added in v0.4.0

List List the workspace's audiences as a cursor page, newest first. Filter by name substring with `q`. Range over it; the second value is non-nil only on the iteration where a fetch failed.

Example

List auto-paginates: it lazily fetches each page and yields every matching audience across all of them.

package main

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

	bird "github.com/messagebird/bird-sdk-go"
	"github.com/messagebird/bird-sdk-go/option"
)

func main() {
	client, err := bird.NewClient(option.WithAPIKey(os.Getenv("BIRD_API_KEY")))
	if err != nil {
		log.Fatal(err)
	}
	for audience, err := range client.Audiences.List(context.Background(), bird.AudienceListParams{Limit: 50}) {
		if err != nil {
			log.Fatal(err)
		}
		fmt.Println(audience.Id, audience.Name)
	}
}

func (*AudiencesService) ListContacts added in v0.4.0

func (s *AudiencesService) ListContacts(ctx context.Context, audienceId string, params AudienceListContactsParams, opts ...option.RequestOption) iter.Seq2[*AudienceMember, error]

ListContacts List the contacts in a static audience by ID, as a cursor page ordered by when each contact joined (most recent first). Each entry pairs the contact with its join time. Range over it; the second value is non-nil only on the iteration where a fetch failed.

Example

ListContacts auto-paginates: it lazily fetches each page and yields every member of the audience across all of them.

package main

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

	bird "github.com/messagebird/bird-sdk-go"
	"github.com/messagebird/bird-sdk-go/option"
)

func main() {
	client, err := bird.NewClient(option.WithAPIKey(os.Getenv("BIRD_API_KEY")))
	if err != nil {
		log.Fatal(err)
	}
	for member, err := range client.Audiences.ListContacts(context.Background(), "adn_123", bird.AudienceListContactsParams{Limit: 50}) {
		if err != nil {
			log.Fatal(err)
		}
		fmt.Println(member.Contact.Id, member.Contact.Email)
	}
}

func (*AudiencesService) ListContactsPage added in v0.4.0

func (s *AudiencesService) ListContactsPage(ctx context.Context, audienceId string, params AudienceListContactsParams, startingAfter string, opts ...option.RequestOption) (*AudienceMemberList, error)

ListContactsPage fetches one page of results. Pass the previous page's NextCursor as startingAfter to advance; "" starts from the first page.

func (*AudiencesService) ListPage added in v0.4.0

func (s *AudiencesService) ListPage(ctx context.Context, params AudienceListParams, startingAfter string, opts ...option.RequestOption) (*AudienceList, error)

ListPage fetches one page of results. Pass the previous page's NextCursor as startingAfter to advance; "" starts from the first page.

func (*AudiencesService) RemoveContact added in v0.4.0

func (s *AudiencesService) RemoveContact(ctx context.Context, audienceId string, contactId string, opts ...option.RequestOption) error

RemoveContact Remove one contact's membership from an audience. The contact itself is not deleted and stays a member of any other audiences.

Example

RemoveContact removes one contact's membership in an audience. The contact itself is not deleted and remains a member of any other audiences.

package main

import (
	"context"
	"log"
	"os"

	bird "github.com/messagebird/bird-sdk-go"
	"github.com/messagebird/bird-sdk-go/option"
)

func main() {
	client, err := bird.NewClient(option.WithAPIKey(os.Getenv("BIRD_API_KEY")))
	if err != nil {
		log.Fatal(err)
	}
	if err := client.Audiences.RemoveContact(context.Background(), "adn_123", "con_1"); err != nil {
		log.Fatal(err)
	}
}

func (*AudiencesService) RemoveContacts added in v0.4.0

func (s *AudiencesService) RemoveContacts(ctx context.Context, audienceId string, params AudienceRemoveContactsParams, opts ...option.RequestOption) error

RemoveContacts Remove up to 1,000 contacts from a static audience by ID. Fails entirely if any contact ID does not exist; contacts are not deleted.

Example

RemoveContacts removes up to 1,000 contacts from a static audience. The contacts themselves are not deleted.

package main

import (
	"context"
	"log"
	"os"

	bird "github.com/messagebird/bird-sdk-go"
	"github.com/messagebird/bird-sdk-go/option"
)

func main() {
	client, err := bird.NewClient(option.WithAPIKey(os.Getenv("BIRD_API_KEY")))
	if err != nil {
		log.Fatal(err)
	}
	err = client.Audiences.RemoveContacts(context.Background(), "adn_123", bird.AudienceRemoveContactsParams{
		ContactIDs: []string{"con_1", "con_2"},
	})
	if err != nil {
		log.Fatal(err)
	}
}

func (*AudiencesService) Update added in v0.4.0

func (s *AudiencesService) Update(ctx context.Context, audienceId string, params AudienceUpdateParams, opts ...option.RequestOption) (*Audience, error)

Update Update an audience's name or description. Omitted fields are unchanged; a null description clears it.

Example

Update changes only the fields set in params; every other field is left unchanged.

package main

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

	bird "github.com/messagebird/bird-sdk-go"
	"github.com/messagebird/bird-sdk-go/option"
)

func main() {
	client, err := bird.NewClient(option.WithAPIKey(os.Getenv("BIRD_API_KEY")))
	if err != nil {
		log.Fatal(err)
	}
	// Rename the audience and clear its description (Null sends an explicit JSON
	// null). Omit a field to leave it unchanged; bird.Value(...) sets a new value.
	audience, err := client.Audiences.Update(context.Background(), "adn_123", bird.AudienceUpdateParams{
		Name:        "Renamed",
		Description: bird.Null[string](),
	})
	if err != nil {
		log.Fatal(err)
	}
	fmt.Println(audience.Id)
}

type Category

type Category = oapi.EmailMessageCategory

Category classifies a send's suppression policy.

const (
	CategoryTransactional Category = "transactional"
	CategoryMarketing     Category = "marketing"
)

type Client

type Client struct {
	Email             *EmailService
	Sms               *SmsService
	SmsTemplates      *SmsTemplatesService
	Whatsapp          *WhatsappService
	Voice             *VoiceService
	Verify            *VerifyService
	Webhooks          *WebhookService
	Contacts          *ContactsService
	Audiences         *AudiencesService
	ContactProperties *ContactPropertiesService
	Domains           *DomainsService
	Realtime          *RealtimeService
	Lookup            *LookupService
	// contains filtered or unexported fields
}

Client is the entry point to the SDK. Construct it with NewClient and reach the API through its resource fields.

func NewClient

func NewClient(opts ...option.RequestOption) (*Client, error)

NewClient builds a Client. An API key is required (option.WithAPIKey); the base URL is derived from the key's region prefix unless option.WithBaseURL or option.WithRegion is given.

func (*Client) Delete

func (c *Client) Delete(ctx context.Context, path string, out any, opts ...option.RequestOption) error

func (*Client) Do

func (c *Client) Do(ctx context.Context, method, path string, body, out any, opts ...option.RequestOption) error

Do is the low-level call the verb methods build on: it marshals body as JSON (when non-nil), runs the request lifecycle, and decodes a 2xx body into out (when non-nil).

func (*Client) Get

func (c *Client) Get(ctx context.Context, path string, out any, opts ...option.RequestOption) error

Get, Post, Put, Patch, and Delete are the escape hatch for endpoints outside the curated surface. They run through the same auth, retry, idempotency, and base-URL handling as the typed methods. body (if non-nil) is sent as JSON; a 2xx response is decoded into out (if non-nil).

var out SuppressionList
err := client.Get(ctx, "/v1/email/suppressions", &out)
Example

The verb methods reach endpoints outside the curated surface, decoding the response into a value you provide.

package main

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

	bird "github.com/messagebird/bird-sdk-go"
	"github.com/messagebird/bird-sdk-go/option"
)

func main() {
	client, err := bird.NewClient(option.WithAPIKey(os.Getenv("BIRD_API_KEY")))
	if err != nil {
		log.Fatal(err)
	}
	var out struct {
		Data []struct {
			Recipient string `json:"recipient"`
		} `json:"data"`
	}
	if err := client.Get(context.Background(), "/v1/email/suppressions", &out); err != nil {
		log.Fatal(err)
	}
	fmt.Println(len(out.Data))
}

func (*Client) Patch

func (c *Client) Patch(ctx context.Context, path string, body, out any, opts ...option.RequestOption) error

func (*Client) Post

func (c *Client) Post(ctx context.Context, path string, body, out any, opts ...option.RequestOption) error

func (*Client) Put

func (c *Client) Put(ctx context.Context, path string, body, out any, opts ...option.RequestOption) error

type ConnectionError

type ConnectionError = apierror.ConnectionError

The SDK error model, re-exported from internal/apierror so these names are the semver-locked public surface. Catch *APIError (via errors.As) to handle any server error; the variants carry extra data. Transport failures with no HTTP response are *ConnectionError / *TimeoutError; a bad webhook signature is *WebhookVerificationError.

type Contact added in v0.4.0

type Contact = oapi.Contact

Contact is a workspace contact; ContactList is a page of contacts; ContactUpsertResult is the result of a bulk upsert, with one ContactUpsertResultItem per submitted contact in submission order.

type ContactBatchParams added in v0.4.0

type ContactBatchParams struct {
	// Contacts to create or update, matched automatically against every identifier an entry supplies. Existing contacts are updated with the fields each entry supplies; omitted fields keep their stored values, so an entry can set fields but never clear them. Unmatched entries create contacts.
	Contacts []ContactCreateRequest
	// Audiences every contact in this request is added to. Contacts that are already members are left in place. Every listed audience must exist, or the whole request fails with a validation error and nothing is written.
	AudienceIDs []string
	// Optional. Forces every entry to be matched to an existing contact by this one field, which every entry must then carry. When omitted, each entry is matched automatically against every identifier it supplies: no match creates a contact, one match updates it, and an entry whose identifiers belong to more than one contact fails with an error naming each.
	MatchOn *ContactMatchKey
	// How a supplied `data` object is applied to an existing contact. `merge` (the default) merges the supplied keys onto the contact's stored custom values, and a key with a `null` value deletes that one key. `replace` overwrites the whole stored `data` map with the supplied one. In both modes a contact that omits `data` keeps its stored values unchanged, so an import that touches one attribute never wipes the others.
	DataMode *ContactUpsertRequestDataMode
}

ContactBatchParams is the request body for batch.

type ContactCreateParams added in v0.4.0

type ContactCreateParams struct {
	// The contact's email address. Trimmed and lowercased before it is stored and checked for uniqueness. Unique within the workspace. Supply an email address, a phone number, or both.
	Email string
	// The contact's phone number in E.164 format, including the leading `+` and country code. Spaces and punctuation are accepted and stripped; the number is stored in its canonical form, which may differ from what you send, and is unique within the workspace. An empty string is treated as if the field were omitted. Supply an email address, a phone number, or both.
	PhoneNumber string
	// The contact's first name.
	FirstName string
	// The contact's last name.
	LastName string
	// Your own identifier for this contact, such as a user ID in your system. Unique within the workspace when set.
	ExternalID string
	// Custom property values for this contact. Each key must be a property created via the contact properties API, and each value must be a string, number, boolean, or RFC 3339 datetime matching the property's declared type (strings up to 500 characters); a null value is ignored. Unregistered or archived keys are rejected with a validation error. Total size is capped at 2 KB serialized.
	Data map[string]any
}

ContactCreateParams is the request body for create.

type ContactCreateRequest added in v0.16.0

type ContactCreateRequest = oapi.ContactCreateRequest

type ContactIdentifierFilter added in v0.27.0

type ContactIdentifierFilter = oapi.ContactIdentifierFilter

ContactIdentifierFilter is which identifier a contact has on file, used by the read filters.

type ContactList added in v0.4.0

type ContactList = oapi.ContactList

Contact is a workspace contact; ContactList is a page of contacts; ContactUpsertResult is the result of a bulk upsert, with one ContactUpsertResultItem per submitted contact in submission order.

type ContactListParams added in v0.4.0

type ContactListParams struct {
	// Return the contact with exactly this email address (case-insensitive). Email is unique within a workspace, so this matches at most one contact. An empty value is a validation error, never an unfiltered page.
	Email string
	// Return the contacts with exactly this phone number in international E.164 form. Repeat the parameter to match any of up to 50 numbers, and set `limit` to at least the number of values you pass: `limit` defaults to 25, and a page cut short by it looks exactly like numbers that matched nothing. Different identifier parameters still combine with AND, so `phone_number=a&phone_number=b&email=c` asks for a contact whose phone number is `a` or `b` and whose email is `c`. Encode the leading plus sign as `%2B` (an unencoded `+` arrives as a space and is rejected). Phone numbers are unique within a workspace, so each value matches at most one contact. Non-canonical forms of the same number match the contact they canonicalize to; a value that is not a phone number shape, or an empty value, is a validation error, never an unfiltered page.
	PhoneNumber []string
	// Return the contact with exactly this external_id (your own identifier for the contact). Unique within a workspace, so this matches at most one contact. An empty value is a validation error, never an unfiltered page.
	ExternalID string
	// Case-insensitive substring match against the contact's email address, first name, last name, or phone number. Phone matching is over the digits of the international form, so a full pasted number, a formatted number, or trailing digits all match; a national form with a leading trunk zero does not.
	Q string
	// Filter to contacts that have a specific identifier on file.
	Identifier ContactIdentifierFilter
	// Maximum number of items to return per page.
	Limit int
	// When true, the response includes a `total` field with the total number of items matching the request's filters across all pages.
	IncludeTotal bool
}

ContactListParams filters the list. Zero-value fields are omitted.

type ContactMatchKey added in v0.24.0

type ContactMatchKey = oapi.ContactMatchKey

type ContactPropertiesService added in v0.4.0

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

ContactPropertiesService manages workspace contact properties: create, read, update, list, archive, and unarchive. Reach it via Client.ContactProperties.

func (*ContactPropertiesService) Archive added in v0.4.0

func (s *ContactPropertiesService) Archive(ctx context.Context, propertyId string, opts ...option.RequestOption) (*ContactProperty, error)

Archive Archive a contact property: the key is rejected in new contact writes and stops rendering in templates, while stored values remain readable. The key stays reserved and counts toward the 200-property limit; reverse with `contact_properties.unarchive`.

Example

Archive archives a contact property: the key stops being accepted in new contact writes, but every value already stored on contacts is preserved.

package main

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

	bird "github.com/messagebird/bird-sdk-go"
	"github.com/messagebird/bird-sdk-go/option"
)

func main() {
	client, err := bird.NewClient(option.WithAPIKey(os.Getenv("BIRD_API_KEY")))
	if err != nil {
		log.Fatal(err)
	}
	property, err := client.ContactProperties.Archive(context.Background(), "prp_123")
	if err != nil {
		log.Fatal(err)
	}
	fmt.Println(property.Archived)
}

func (*ContactPropertiesService) Create added in v0.4.0

Create Define a custom contact property (key + value type) that becomes available in contact data and as a broadcast template variable. The key and type cannot change after creation; a workspace holds at most 200 properties, archived included.

Example
package main

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

	bird "github.com/messagebird/bird-sdk-go"
	"github.com/messagebird/bird-sdk-go/option"
)

func main() {
	client, err := bird.NewClient(option.WithAPIKey(os.Getenv("BIRD_API_KEY")))
	if err != nil {
		log.Fatal(err)
	}
	property, err := client.ContactProperties.Create(context.Background(), bird.ContactPropertyCreateParams{
		Key:  "plan",
		Type: "string",
	})
	if err != nil {
		log.Fatal(err)
	}
	fmt.Println(property.Id)
}

func (*ContactPropertiesService) Get added in v0.4.0

Get Get a single contact property by ID: key, type, fallback value, and archived state.

Example

Get returns a single contact property by id.

package main

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

	bird "github.com/messagebird/bird-sdk-go"
	"github.com/messagebird/bird-sdk-go/option"
)

func main() {
	client, err := bird.NewClient(option.WithAPIKey(os.Getenv("BIRD_API_KEY")))
	if err != nil {
		log.Fatal(err)
	}
	property, err := client.ContactProperties.Get(context.Background(), "prp_123")
	if err != nil {
		log.Fatal(err)
	}
	fmt.Println(property.Key)
}

func (*ContactPropertiesService) List added in v0.4.0

List List the workspace's contact properties as a cursor page, newest first. Archived properties are included, marked by their archived flag. Range over it; the second value is non-nil only on the iteration where a fetch failed.

Example

List auto-paginates: it lazily fetches each page and yields every matching contact property across all of them.

package main

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

	bird "github.com/messagebird/bird-sdk-go"
	"github.com/messagebird/bird-sdk-go/option"
)

func main() {
	client, err := bird.NewClient(option.WithAPIKey(os.Getenv("BIRD_API_KEY")))
	if err != nil {
		log.Fatal(err)
	}
	for property, err := range client.ContactProperties.List(context.Background(), bird.ContactPropertyListParams{Limit: 50}) {
		if err != nil {
			log.Fatal(err)
		}
		fmt.Println(property.Id, property.Key)
	}
}

func (*ContactPropertiesService) ListPage added in v0.4.0

ListPage fetches one page of results. Pass the previous page's NextCursor as startingAfter to advance; "" starts from the first page.

func (*ContactPropertiesService) Unarchive added in v0.4.0

func (s *ContactPropertiesService) Unarchive(ctx context.Context, propertyId string, opts ...option.RequestOption) (*ContactProperty, error)

Unarchive Reactivate an archived contact property so its key is accepted in contact writes and renders in templates again. Fails with a conflict if the property is not archived.

Example

Unarchive reactivates an archived contact property.

package main

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

	bird "github.com/messagebird/bird-sdk-go"
	"github.com/messagebird/bird-sdk-go/option"
)

func main() {
	client, err := bird.NewClient(option.WithAPIKey(os.Getenv("BIRD_API_KEY")))
	if err != nil {
		log.Fatal(err)
	}
	property, err := client.ContactProperties.Unarchive(context.Background(), "prp_123")
	if err != nil {
		log.Fatal(err)
	}
	fmt.Println(property.Archived)
}

func (*ContactPropertiesService) Update added in v0.4.0

Update Update a contact property's fallback value. Only the fallback value can change; the key and type are fixed at creation, so a different key or type needs a new property.

Example

Update changes a contact property's fallback value.

package main

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

	bird "github.com/messagebird/bird-sdk-go"
	"github.com/messagebird/bird-sdk-go/option"
)

func main() {
	client, err := bird.NewClient(option.WithAPIKey(os.Getenv("BIRD_API_KEY")))
	if err != nil {
		log.Fatal(err)
	}
	property, err := client.ContactProperties.Update(context.Background(), "prp_123", bird.ContactPropertyUpdateParams{
		FallbackValue: "free",
	})
	if err != nil {
		log.Fatal(err)
	}
	fmt.Println(property.Id)
}

type ContactProperty added in v0.4.0

type ContactProperty = oapi.ContactProperty

ContactProperty is a custom contact property definition; ContactPropertyList is a page of properties.

type ContactPropertyCreateParams added in v0.4.0

type ContactPropertyCreateParams struct {
	// The property key, used as the key in contact data and as the attribute in the `bird.contact.<key>` broadcast template variable. Lowercase letters, digits, and underscores, starting with a letter. Cannot be changed after creation.
	Key string
	// The value type every contact must use for a property. Cannot be changed after creation. `datetime` values are RFC 3339 timestamps with an explicit offset (for example `2024-01-15T09:30:00Z` or `2024-01-15T11:30:00+02:00`); a bare date or a time with no offset is rejected. The value is normalized to UTC with second precision on write, so `2024-01-15T11:30:00+02:00` is stored and returned as `2024-01-15T09:30:00Z`, and any fractional seconds are dropped.
	Type ContactPropertyType
	// Default used when a contact has no value for this property and the template does not supply an inline fallback. A string, number, boolean, or RFC 3339 datetime matching the declared type (strings up to 500 characters), or null for no fallback; a value of another type returns a validation error.
	FallbackValue any
}

ContactPropertyCreateParams is the request body for create.

type ContactPropertyList added in v0.4.0

type ContactPropertyList = oapi.ContactPropertyList

ContactProperty is a custom contact property definition; ContactPropertyList is a page of properties.

type ContactPropertyListParams added in v0.4.0

type ContactPropertyListParams struct {
	// Maximum number of items to return per page.
	Limit int
}

ContactPropertyListParams filters the list. Zero-value fields are omitted.

type ContactPropertyType added in v0.16.0

type ContactPropertyType = oapi.ContactPropertyType

type ContactPropertyUpdateParams added in v0.4.0

type ContactPropertyUpdateParams struct {
	// Default used when a contact has no value for this property and the template does not supply an inline fallback. A string, number, boolean, or RFC 3339 datetime matching the declared type (strings up to 500 characters); a value of another type returns a validation error. Set to null to remove the fallback.
	FallbackValue any
}

ContactPropertyUpdateParams is the request body for update.

type ContactUpdateParams added in v0.4.0

type ContactUpdateParams struct {
	// New email address for the contact. Trimmed and lowercased before it is stored and checked for uniqueness. Must not be in use by another contact in the workspace. Omit to keep the current address; set to null to remove it, as long as the contact keeps at least one identifier.
	Email Nullable[string]
	// New phone number for the contact, in E.164 format with the leading `+` and country code. Spaces and punctuation are accepted and stripped. Stored in its canonical form, which may differ from what you send, and unique within the workspace. Omit to keep the current number; set to null to remove it, as long as the contact keeps at least one identifier. An empty string behaves as null.
	PhoneNumber Nullable[string]
	// The contact's first name. Set to null to clear.
	FirstName Nullable[string]
	// The contact's last name. Set to null to clear.
	LastName Nullable[string]
	// Your own identifier for this contact. Unique within the workspace when set. Set to null to clear.
	ExternalID Nullable[string]
	// Custom property values to change, merged into the contact's existing data. Keys you supply are set, keys set to null are removed, and keys you omit are left unchanged. Each key must be a property created via the contact properties API, and each value must be a string, number, boolean, or RFC 3339 datetime matching the property's declared type (strings up to 500 characters); writing an unregistered or archived key returns a validation error. The merged result is capped at 2 KB serialized.
	Data map[string]any
}

ContactUpdateParams is the request body for update.

type ContactUpsertRequestDataMode added in v0.16.0

type ContactUpsertRequestDataMode = oapi.ContactUpsertRequestDataMode

type ContactUpsertResult added in v0.4.0

type ContactUpsertResult = oapi.ContactUpsertResult

Contact is a workspace contact; ContactList is a page of contacts; ContactUpsertResult is the result of a bulk upsert, with one ContactUpsertResultItem per submitted contact in submission order.

type ContactUpsertResultItem added in v0.4.0

type ContactUpsertResultItem = oapi.ContactUpsertResultItem

Contact is a workspace contact; ContactList is a page of contacts; ContactUpsertResult is the result of a bulk upsert, with one ContactUpsertResultItem per submitted contact in submission order.

type ContactsService added in v0.4.0

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

ContactsService manages workspace contacts: create, read, update, delete, bulk upsert, and list. Reach it via Client.Contacts.

func (*ContactsService) Batch added in v0.4.0

Batch Create or update up to 1,000 contacts in one request, each entry matched automatically against every identifier it supplies (email, phone_number, external_id) or, with match_on, by that one field only, and optionally add them all to one or more audiences. Per-contact results are returned in submission order.

Example

Batch creates or updates several contacts, matched by email address, in one request.

package main

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

	openapi_types "github.com/oapi-codegen/runtime/types"

	bird "github.com/messagebird/bird-sdk-go"
	"github.com/messagebird/bird-sdk-go/option"
)

func main() {
	client, err := bird.NewClient(option.WithAPIKey(os.Getenv("BIRD_API_KEY")))
	if err != nil {
		log.Fatal(err)
	}
	result, err := client.Contacts.Batch(context.Background(), bird.ContactBatchParams{
		Contacts: []bird.ContactCreateRequest{
			{Email: bird.Ptr(openapi_types.Email("a@x.com"))},
		},
	})
	if err != nil {
		log.Fatal(err)
	}
	for _, item := range result.Data {
		email := ""
		if item.Entry.Email != nil {
			email = *item.Entry.Email
		}
		fmt.Println(email, item.Status)
	}
}

func (*ContactsService) Create added in v0.4.0

Create Create a contact identified by an email address, an E.164 phone number, or both. Fails with a conflict if the email, phone_number, or external_id is already used by another contact. For bulk import or create-or-update semantics use `contacts.batch`.

Example

Create a contact. Unset optional fields are omitted from the request.

package main

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

	bird "github.com/messagebird/bird-sdk-go"
	"github.com/messagebird/bird-sdk-go/option"
)

func main() {
	client, err := bird.NewClient(option.WithAPIKey(os.Getenv("BIRD_API_KEY")))
	if err != nil {
		log.Fatal(err)
	}
	contact, err := client.Contacts.Create(context.Background(), bird.ContactCreateParams{
		Email:     "jane@acme.com",
		FirstName: "Jane",
	})
	if err != nil {
		log.Fatal(err)
	}
	fmt.Println(contact.Id)
}

func (*ContactsService) Delete added in v0.4.0

func (s *ContactsService) Delete(ctx context.Context, contactId string, opts ...option.RequestOption) error

Delete Delete a contact and remove it from every audience it belongs to. Suppression records for the address are unaffected.

Example

Delete removes a contact.

package main

import (
	"context"
	"log"
	"os"

	bird "github.com/messagebird/bird-sdk-go"
	"github.com/messagebird/bird-sdk-go/option"
)

func main() {
	client, err := bird.NewClient(option.WithAPIKey(os.Getenv("BIRD_API_KEY")))
	if err != nil {
		log.Fatal(err)
	}
	if err := client.Contacts.Delete(context.Background(), "con_123"); err != nil {
		log.Fatal(err)
	}
}

func (*ContactsService) Get added in v0.4.0

func (s *ContactsService) Get(ctx context.Context, contactId string, opts ...option.RequestOption) (*Contact, error)

Get Get a single contact by ID (`con_`-prefixed). Look up an ID by exact email, phone_number, or external_id with `contacts.list`.

Example

Get returns a single contact by id.

package main

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

	bird "github.com/messagebird/bird-sdk-go"
	"github.com/messagebird/bird-sdk-go/option"
)

func main() {
	client, err := bird.NewClient(option.WithAPIKey(os.Getenv("BIRD_API_KEY")))
	if err != nil {
		log.Fatal(err)
	}
	contact, err := client.Contacts.Get(context.Background(), "con_123")
	if err != nil {
		log.Fatal(err)
	}
	fmt.Println(contact.Email)
}

func (*ContactsService) List added in v0.4.0

List List the workspace's contacts as a cursor page, newest first. Look one up by exact email, phone_number, or external_id, repeating phone_number to resolve up to 50 numbers in one call (raise limit to match), or search by email, name, or phone substring. Pass include_total for a total count. Range over it; the second value is non-nil only on the iteration where a fetch failed.

Example

List auto-paginates: it lazily fetches each page and yields every matching contact across all of them.

package main

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

	bird "github.com/messagebird/bird-sdk-go"
	"github.com/messagebird/bird-sdk-go/option"
)

func main() {
	client, err := bird.NewClient(option.WithAPIKey(os.Getenv("BIRD_API_KEY")))
	if err != nil {
		log.Fatal(err)
	}
	for contact, err := range client.Contacts.List(context.Background(), bird.ContactListParams{Limit: 50}) {
		if err != nil {
			log.Fatal(err)
		}
		fmt.Println(contact.Id, contact.Email)
	}
}

func (*ContactsService) ListPage added in v0.4.0

func (s *ContactsService) ListPage(ctx context.Context, params ContactListParams, startingAfter string, opts ...option.RequestOption) (*ContactList, error)

ListPage fetches one page of results. Pass the previous page's NextCursor as startingAfter to advance; "" starts from the first page.

func (*ContactsService) Update added in v0.4.0

func (s *ContactsService) Update(ctx context.Context, contactId string, params ContactUpdateParams, opts ...option.RequestOption) (*Contact, error)

Update Update a contact's name, external_id, email, phone_number, or custom data. Only supplied fields change; custom data keys are merged, with null removing a key. A contact keeps at least one identifier: clearing both email and phone_number is rejected.

Example

Update changes only the fields set in params; every other field is left unchanged.

package main

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

	bird "github.com/messagebird/bird-sdk-go"
	"github.com/messagebird/bird-sdk-go/option"
)

func main() {
	client, err := bird.NewClient(option.WithAPIKey(os.Getenv("BIRD_API_KEY")))
	if err != nil {
		log.Fatal(err)
	}
	// Set the first name and clear the last name (Null sends an explicit JSON
	// null); omit a field to leave it unchanged.
	contact, err := client.Contacts.Update(context.Background(), "con_123", bird.ContactUpdateParams{
		FirstName: bird.Value("Jane"),
		LastName:  bird.Null[string](),
	})
	if err != nil {
		log.Fatal(err)
	}
	fmt.Println(contact.Id)
}

type DNSRecord added in v0.8.0

type DNSRecord = oapi.DNSRecord

Domain is a sending domain with its DNS records and per-capability status; DomainList is a page of domains. DNSRecord is one required DNS record and its verification state; DomainDKIM is the domain's active DKIM signing configuration; DomainCapabilities is the per-capability readiness breakdown. The write-side *Config aliases accompany DomainCreateParams / DomainUpdateParams.

type Domain added in v0.8.0

type Domain = oapi.Domain

Domain is a sending domain with its DNS records and per-capability status; DomainList is a page of domains. DNSRecord is one required DNS record and its verification state; DomainDKIM is the domain's active DKIM signing configuration; DomainCapabilities is the per-capability readiness breakdown. The write-side *Config aliases accompany DomainCreateParams / DomainUpdateParams.

type DomainCapabilities added in v0.8.0

type DomainCapabilities = oapi.DomainCapabilities

Domain is a sending domain with its DNS records and per-capability status; DomainList is a page of domains. DNSRecord is one required DNS record and its verification state; DomainDKIM is the domain's active DKIM signing configuration; DomainCapabilities is the per-capability readiness breakdown. The write-side *Config aliases accompany DomainCreateParams / DomainUpdateParams.

type DomainCapability added in v0.8.0

type DomainCapability = oapi.DomainCapability

Domain is a sending domain with its DNS records and per-capability status; DomainList is a page of domains. DNSRecord is one required DNS record and its verification state; DomainDKIM is the domain's active DKIM signing configuration; DomainCapabilities is the per-capability readiness breakdown. The write-side *Config aliases accompany DomainCreateParams / DomainUpdateParams.

type DomainCreateParams added in v0.8.0

type DomainCreateParams struct {
	// The domain you will send from — the domain of your `from` addresses. Use a dedicated subdomain (e.g. `mail.acme.com`) rather than your registered domain so sending reputation stays separate from other services on the domain.
	Domain string
	// Return-path (bounce) domain configuration. The return-path domain receives bounce and complaint notifications for mail sent from this domain and is what mailbox providers check for SPF. Provide only the name part; Bird adds the sending domain automatically.
	ReturnPath *DomainReturnPathConfig
	// Tracking domain configuration for branded open and click tracking URLs. Provide only the name part; Bird adds the sending domain automatically. A domain created with no tracking configuration defaults to the name `links`. Tracked links are served over HTTPS once the tracking record verifies.
	Tracking *DomainTrackingConfig
	// DKIM signing configuration.
	Dkim *DomainDKIMConfig
	// Per-domain behavior toggles. Changes apply immediately to new sends.
	Settings *DomainSettings
}

DomainCreateParams is the request body for create.

type DomainDKIM added in v0.8.0

type DomainDKIM = oapi.DomainDKIM

Domain is a sending domain with its DNS records and per-capability status; DomainList is a page of domains. DNSRecord is one required DNS record and its verification state; DomainDKIM is the domain's active DKIM signing configuration; DomainCapabilities is the per-capability readiness breakdown. The write-side *Config aliases accompany DomainCreateParams / DomainUpdateParams.

type DomainDKIMConfig added in v0.8.0

type DomainDKIMConfig = oapi.DomainDKIMConfig

type DomainDKIMConfigMode added in v0.15.0

type DomainDKIMConfigMode = oapi.DomainDKIMConfigMode
const (
	DomainDKIMConfigModeTxt       DomainDKIMConfigMode = "txt"
	DomainDKIMConfigModeDelegated DomainDKIMConfigMode = "delegated"
)

type DomainFailedEvent

type DomainFailedEvent = oapi.EventDomainFailed

Webhook event payloads, returned by Event.AsAny. Type-switch on these.

type DomainInboundConfig added in v0.8.0

type DomainInboundConfig = oapi.DomainInboundConfig

type DomainList added in v0.8.0

type DomainList = oapi.DomainList

Domain is a sending domain with its DNS records and per-capability status; DomainList is a page of domains. DNSRecord is one required DNS record and its verification state; DomainDKIM is the domain's active DKIM signing configuration; DomainCapabilities is the per-capability readiness breakdown. The write-side *Config aliases accompany DomainCreateParams / DomainUpdateParams.

type DomainListParams added in v0.8.0

type DomainListParams struct {
	// Substring match against the domain name (case-insensitive).
	Name string
	// Field to sort by.
	Sort string
	// Sort direction. Defaults to `desc` (newest/largest first).
	Order string
	// Maximum number of items to return per page.
	Limit int
	// When true, the response includes a `total` field with the total number of items matching the request's filters across all pages.
	IncludeTotal bool
}

DomainListParams filters the list. Zero-value fields are omitted.

type DomainReturnPathConfig added in v0.8.0

type DomainReturnPathConfig = oapi.DomainReturnPathConfig

type DomainSettings added in v0.8.0

type DomainSettings = oapi.DomainSettings

type DomainStatus added in v0.8.0

type DomainStatus = oapi.DomainStatus

Domain is a sending domain with its DNS records and per-capability status; DomainList is a page of domains. DNSRecord is one required DNS record and its verification state; DomainDKIM is the domain's active DKIM signing configuration; DomainCapabilities is the per-capability readiness breakdown. The write-side *Config aliases accompany DomainCreateParams / DomainUpdateParams.

type DomainTrackingConfig added in v0.8.0

type DomainTrackingConfig = oapi.DomainTrackingConfig

type DomainUpdateParams added in v0.8.0

type DomainUpdateParams struct {
	// Per-domain behavior toggles. Changes apply immediately to new sends.
	Settings *DomainSettings
	// Change the return-path name part. Cannot be removed — the return-path is required for sending.
	ReturnPath *DomainReturnPathConfig
	// Set or change the tracking name part, or remove tracking by passing null. Removal requires `click_tracking` and `open_tracking` to be disabled first, and returns `409` otherwise. After removal, links in previously sent email keep resolving while the tracking records are reported as `deprecated`.
	Tracking Nullable[DomainTrackingConfig]
	// Change how the DKIM key is published. The current key keeps signing until the new configuration verifies, so mail is never sent unsigned during the transition.
	Dkim *DomainDKIMConfig
	// Enable or disable receiving on this domain. Enabling claims the domain for inbound and moves `capabilities.inbound.status` from `not_configured` to `pending`, then `verified` once the MX records resolve to Bird. The MX records to publish are always present under `dns_records` (`purpose: inbound_mx`) as a regional reference, so their presence does not mean receiving is on — a domain still needs enabling whenever `capabilities.inbound.status` is `not_configured`. Enabling requires the domain's DKIM to be verified first (ownership proof): a fresh enable on a domain whose DKIM is not verified returns `422` `E05019` and claims nothing. A domain already receiving inbound for another organization returns `422` `E05018`.
	Inbound *DomainInboundConfig
}

DomainUpdateParams is the request body for update.

type DomainVerifiedEvent

type DomainVerifiedEvent = oapi.EventDomainVerified

Webhook event payloads, returned by Event.AsAny. Type-switch on these.

type DomainsService added in v0.8.0

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

DomainsService manages sending domains: register, read, update, delete, list, and verify. Reach it via Client.Domains. Register a domain, publish the DNS records it returns, then call Verify until it is usable as a sender.

func (*DomainsService) Create added in v0.8.0

func (s *DomainsService) Create(ctx context.Context, params DomainCreateParams, opts ...option.RequestOption) (*Domain, error)

Create Register a new sending domain and get the DNS records to publish. Verification is a second step: the records go live at the DNS provider, then email_domains_verify confirms them. Propagation takes minutes to hours, so the first verify often still reports unverified and a later one succeeds.

Example

Register a sending domain. It returns in "pending" with the DNS records to publish; call Verify once they are in place.

package main

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

	bird "github.com/messagebird/bird-sdk-go"
	"github.com/messagebird/bird-sdk-go/option"
)

func main() {
	client, err := bird.NewClient(option.WithAPIKey(os.Getenv("BIRD_API_KEY")))
	if err != nil {
		log.Fatal(err)
	}
	domain, err := client.Domains.Create(context.Background(), bird.DomainCreateParams{
		Domain: "mail.acme.com",
	})
	if err != nil {
		log.Fatal(err)
	}
	fmt.Println(domain.Id, *domain.Status)
}

func (*DomainsService) Delete added in v0.8.0

func (s *DomainsService) Delete(ctx context.Context, domainId string, opts ...option.RequestOption) error

Delete Delete a sending domain by id. Revokes its sender authorization: new sends from the domain are rejected afterward, while historical statistics and events for past sends are preserved. Destructive.

Example

Delete removes a sending domain.

package main

import (
	"context"
	"log"
	"os"

	bird "github.com/messagebird/bird-sdk-go"
	"github.com/messagebird/bird-sdk-go/option"
)

func main() {
	client, err := bird.NewClient(option.WithAPIKey(os.Getenv("BIRD_API_KEY")))
	if err != nil {
		log.Fatal(err)
	}
	if err := client.Domains.Delete(context.Background(), "dom_123"); err != nil {
		log.Fatal(err)
	}
}

func (*DomainsService) Get added in v0.8.0

func (s *DomainsService) Get(ctx context.Context, domainId string, opts ...option.RequestOption) (*Domain, error)

Get Fetch one sending domain: verification status and the DNS records with their individual verification states.

Example

Get returns a single sending domain by id, with its DNS records.

package main

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

	bird "github.com/messagebird/bird-sdk-go"
	"github.com/messagebird/bird-sdk-go/option"
)

func main() {
	client, err := bird.NewClient(option.WithAPIKey(os.Getenv("BIRD_API_KEY")))
	if err != nil {
		log.Fatal(err)
	}
	domain, err := client.Domains.Get(context.Background(), "dom_123")
	if err != nil {
		log.Fatal(err)
	}
	fmt.Println(*domain.Domain)
}

func (*DomainsService) List added in v0.8.0

List List the workspace's sending domains with their verification status, as a cursor page. Range over it; the second value is non-nil only on the iteration where a fetch failed.

Example

List auto-paginates: it lazily fetches each page and yields every sending domain across all of them.

package main

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

	bird "github.com/messagebird/bird-sdk-go"
	"github.com/messagebird/bird-sdk-go/option"
)

func main() {
	client, err := bird.NewClient(option.WithAPIKey(os.Getenv("BIRD_API_KEY")))
	if err != nil {
		log.Fatal(err)
	}
	for domain, err := range client.Domains.List(context.Background(), bird.DomainListParams{Limit: 50}) {
		if err != nil {
			log.Fatal(err)
		}
		fmt.Println(domain.Id, *domain.Status)
	}
}

func (*DomainsService) ListPage added in v0.8.0

func (s *DomainsService) ListPage(ctx context.Context, params DomainListParams, startingAfter string, opts ...option.RequestOption) (*DomainList, error)

ListPage fetches one page of results. Pass the previous page's NextCursor as startingAfter to advance; "" starts from the first page.

func (*DomainsService) Update added in v0.8.0

func (s *DomainsService) Update(ctx context.Context, domainId string, params DomainUpdateParams, opts ...option.RequestOption) (*Domain, error)

Update Update a sending domain's tracking and inbound configuration. Tracking: click_tracking and open_tracking apply immediately to new sends, and the tracking domain can be set, changed, or removed (the name part only, and the sending domain is appended for you). Enabling either toggle with no tracking domain configured returns 409, and removing the tracking domain while either toggle is still on also returns 409. Tracking-domain changes on a verified domain are staged behind DNS verification, so the current config keeps serving until the new records verify. Inbound receiving: inbound.enabled starts or stops receiving mail for the domain. Enabling requires the domain's DKIM to be verified first (a fresh enable on an unverified domain returns 422), and a domain already receiving inbound for another organization returns 422. The MX records to publish are always listed in dns_records regardless, so receiving starts only once inbound.enabled is set, even when those records are already published.

Example

Update edits a sending domain. Only the fields you set change.

package main

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

	bird "github.com/messagebird/bird-sdk-go"
	"github.com/messagebird/bird-sdk-go/option"
)

func main() {
	client, err := bird.NewClient(option.WithAPIKey(os.Getenv("BIRD_API_KEY")))
	if err != nil {
		log.Fatal(err)
	}
	domain, err := client.Domains.Update(context.Background(), "dom_123", bird.DomainUpdateParams{
		Settings: &bird.DomainSettings{ClickTracking: bird.Bool(true), OpenTracking: bird.Bool(true)},
		Tracking: bird.Value(bird.DomainTrackingConfig{Name: "links"}),
	})
	if err != nil {
		log.Fatal(err)
	}
	fmt.Println(domain.Id)
}

func (*DomainsService) Verify added in v0.8.0

func (s *DomainsService) Verify(ctx context.Context, domainId string, opts ...option.RequestOption) (*Domain, error)

Verify Trigger a DNS verification check for a sending domain and return the refreshed domain with per-record results. Safe to repeat while waiting for DNS propagation.

Example

Verify triggers a fresh DNS check and returns the refreshed domain. Safe to repeat while waiting for DNS to propagate.

package main

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

	bird "github.com/messagebird/bird-sdk-go"
	"github.com/messagebird/bird-sdk-go/option"
)

func main() {
	client, err := bird.NewClient(option.WithAPIKey(os.Getenv("BIRD_API_KEY")))
	if err != nil {
		log.Fatal(err)
	}
	domain, err := client.Domains.Verify(context.Background(), "dom_123")
	if err != nil {
		log.Fatal(err)
	}
	fmt.Println(*domain.Status)
}

type EmailAcceptedEvent

type EmailAcceptedEvent = oapi.EventEmailAccepted

Webhook event payloads, returned by Event.AsAny. Type-switch on these.

type EmailAttachment

type EmailAttachment = oapi.EmailAttachment

EmailAttachment is a file attachment on a send.

type EmailBatch added in v0.2.0

type EmailBatch = oapi.EmailMessageBatchResponse

EmailBatch is the result of a batch send: one item per submitted message, in submission order.

type EmailBatchItem added in v0.2.0

type EmailBatchItem = oapi.EmailMessageBatchItem

EmailBatchItem is a single message's entry in a batch send result.

type EmailBouncedEvent

type EmailBouncedEvent = oapi.EventEmailBounced

Webhook event payloads, returned by Event.AsAny. Type-switch on these.

type EmailClickedEvent

type EmailClickedEvent = oapi.EventEmailClicked

Webhook event payloads, returned by Event.AsAny. Type-switch on these.

type EmailComplainedEvent

type EmailComplainedEvent = oapi.EventEmailComplained

Webhook event payloads, returned by Event.AsAny. Type-switch on these.

type EmailDefaults

type EmailDefaults = requestconfig.EmailDefaults

EmailDefaults are values applied to an email send when the per-send params leave the field unset. Configure with option.WithEmailDefaults.

Example

EmailDefaults set common send fields once; a per-send value always wins.

package main

import (
	"context"
	"log"
	"os"

	bird "github.com/messagebird/bird-sdk-go"
	"github.com/messagebird/bird-sdk-go/option"
)

func main() {
	client, err := bird.NewClient(
		option.WithAPIKey(os.Getenv("BIRD_API_KEY")),
		option.WithEmailDefaults(bird.EmailDefaults{
			From:     "hello@acme.com",
			Category: bird.CategoryTransactional,
		}),
	)
	if err != nil {
		log.Fatal(err)
	}
	// From is filled from the default.
	if _, err := client.Email.Send(context.Background(), bird.EmailSendParams{
		To: []string{"customer@example.com"}, Subject: "Hi", HTML: "<p>hi</p>",
	}); err != nil {
		log.Fatal(err)
	}
}

type EmailDeferredEvent

type EmailDeferredEvent = oapi.EventEmailDeferred

Webhook event payloads, returned by Event.AsAny. Type-switch on these.

type EmailDeliveredEvent

type EmailDeliveredEvent = oapi.EventEmailDelivered

Webhook event payloads, returned by Event.AsAny. Type-switch on these.

type EmailEngagementSortMetric added in v0.16.0

type EmailEngagementSortMetric = oapi.EmailEngagementSortMetric

EmailEngagementSortMetric is the engagement metric a breakdown sorts by.

type EmailEventType added in v0.19.0

type EmailEventType = oapi.EmailEventType

EmailEventType is an open string on the wire: a value added by a newer server deserializes unchanged, so compare against the EmailEventType* constants with a default branch rather than treating the set as closed.

type EmailLabelsUpdate added in v0.16.0

type EmailLabelsUpdate = oapi.EmailLabelsUpdate

type EmailListParams

type EmailListParams struct {
	// Maximum number of items to return per page.
	Limit int
	// Return only resources created at or after this timestamp (inclusive lower bound). Combine with `created_before` to filter to a time window. RFC 3339 / ISO 8601 with timezone.
	CreatedAfter time.Time
	// Return only resources created strictly before this timestamp (exclusive upper bound). Combine with `created_after` to filter to a time window. RFC 3339 / ISO 8601 with timezone.
	CreatedBefore time.Time
	// Filter by aggregate delivery status.
	Status EmailMessageStatus
	// Filter by tag. Accepts `name` to match any message carrying that tag name, or `name:value` to match a specific tag pair (for example `category:welcome`). Repeat the parameter to add more tags. A message must match every tag listed to be returned.
	Tag []string
	// Filter by category.
	Category EmailMessageCategory
	// Filter by recipient address. Exact match against any `to`/`cc`/`bcc` recipient on the message. The address is normalized to lowercase before comparison.
	To string
	// Filter by sender address. Exact match against the message `from` field. The address is normalized to lowercase before comparison.
	From string
}

EmailListParams filters the list. Zero-value fields are omitted.

type EmailListUnsubscribedEvent

type EmailListUnsubscribedEvent = oapi.EventEmailListUnsubscribed

Webhook event payloads, returned by Event.AsAny. Type-switch on these.

type EmailLookup added in v0.31.0

type EmailLookup = oapi.EmailLookup

PhoneNumberLookup is what we know about a phone number; EmailLookup is the verdict on an email address. Every block a phone lookup carries reports its own status, so a partial answer is visible rather than silent.

type EmailLookupFlag added in v0.31.0

type EmailLookupFlag = oapi.EmailLookupFlag

EmailLookupFlag is an open string on the wire: a value added by a newer server deserializes unchanged, so compare against the EmailLookupFlag* constants with a default branch rather than treating the set as closed.

type EmailLookupReason added in v0.31.0

type EmailLookupReason = oapi.EmailLookupReason

EmailLookupReason is an open string on the wire: a value added by a newer server deserializes unchanged, so compare against the EmailLookupReason* constants with a default branch rather than treating the set as closed.

type EmailLookupResult added in v0.31.0

type EmailLookupResult = oapi.EmailLookupResult

EmailLookupResult is an open string on the wire: a value added by a newer server deserializes unchanged, so compare against the EmailLookupResult* constants with a default branch rather than treating the set as closed.

type EmailMailboxLabelList added in v0.12.0

type EmailMailboxLabelList = oapi.EmailMailboxLabelList

EmailMailboxLabelList is the list of labels available in a mailbox.

type EmailMailboxProviderSortMetric added in v0.16.0

type EmailMailboxProviderSortMetric = oapi.EmailMailboxProviderSortMetric

EmailMailboxProviderSortMetric is the metric a mailbox-provider breakdown sorts by.

type EmailMailboxesCreateParams added in v0.17.0

type EmailMailboxesCreateParams struct {
	// The local part of the mailbox address (the part before `@`). Letters, digits, dots, underscores, and hyphens. Stored lowercase. On the shared `inbox.ai` domain, separators must sit between letters or digits (no leading, trailing, or repeated separators), reserved names such as `postmaster` or `abuse` are unavailable, and choosing your own local part uses one of your plan's custom-handle allowance slots (generated addresses are always available). Omit it and we generate a random local part.
	LocalPart string
	// The domain the address lives under. Defaults to `inbox.ai`, our shared mailbox domain, where creating the mailbox claims the address for your organization: first come, first served, and permanently reserved to your organization even after the mailbox is deleted. May instead name one of your own domains that is enabled for receiving email.
	Domain string
	// Display name used as the sender name on mail from this mailbox.
	DisplayName string
	// Default Reply-To address stamped on mail sent from this mailbox.
	DefaultReplyTo string
	// Which inbound mail the mailbox accepts: - `open`: Accepts everything not blocked by a rule. - `replies_only`: Accepts only replies to messages this mailbox has sent. A reply must match a message the mailbox sent. Landing in an existing thread by itself does not count. - `allowlist`: Accepts only senders matching an allow rule. - `drop`: Stores nothing.
	ReceivePolicy *MailboxCreateReceivePolicy
	// How long the mailbox remembers message metadata and extracted text. Original rendered source is always available for 30 days regardless of tier.
	RetentionTier *MailboxCreateRetentionTier
	// Your own key/value data to attach to the mailbox. Up to 2 KB. Keys starting with `__bird` are reserved.
	Metadata map[string]any
}

EmailMailboxesCreateParams is the request body for create.

type EmailMailboxesListParams added in v0.17.0

type EmailMailboxesListParams struct {
	// Filter to the mailbox with exactly this address.
	Address string
	// Case-insensitive search matching the mailbox's address or display name (substring).
	Q string
	// Filter by lifecycle state.
	State string
	// Filter to mailboxes whose address is on this domain.
	Domain string
	// Include mailboxes deleted within their 30-day restore window. Defaults to false, so only active and suspended mailboxes are returned. A deleted mailbox has a non-null `deleted_at`.
	IncludeDeleted bool
	// Maximum number of items to return per page.
	Limit int
}

EmailMailboxesListParams filters the list. Zero-value fields are omitted.

type EmailMailboxesMessagesCreateParams added in v0.17.0

type EmailMailboxesMessagesCreateParams struct {
	To       []string // required; plain address or "Name <addr>"
	Subject  string   // required
	HTML     string
	Text     string
	CC       []string
	BCC      []string
	ReplyTo  []string
	Category string // marketing | transactional
	Metadata map[string]any
}

EmailMailboxesMessagesCreateParams sends a new message from the mailbox.

type EmailMailboxesMessagesService added in v0.17.0

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

EmailMailboxesMessagesService sends messages from a mailbox's own address. Reach it via Client.Email.Mailboxes.Messages.

func (*EmailMailboxesMessagesService) Create added in v0.17.0

Compose sends a new email from the mailbox's own address, starting a new conversation. Retried safely with a reused idempotency key.

Example
package main

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

	bird "github.com/messagebird/bird-sdk-go"
	"github.com/messagebird/bird-sdk-go/option"
)

func main() {
	client, err := bird.NewClient(option.WithAPIKey(os.Getenv("BIRD_API_KEY")))
	if err != nil {
		log.Fatal(err)
	}
	msg, err := client.Email.Mailboxes.Messages.Create(context.Background(), "mbx_123", bird.EmailMailboxesMessagesCreateParams{
		To:      []string{"customer@example.com"},
		Subject: "Following up",
		HTML:    "<p>Hi, just checking in.</p>",
	})
	if err != nil {
		log.Fatal(err)
	}
	fmt.Println(msg.Id)
}

type EmailMailboxesReceiveRulesCreateParams added in v0.17.0

type EmailMailboxesReceiveRulesCreateParams struct {
	// What the rule does when it matches. Block rules always win. To flip an entry's action, delete the existing rule and re-create it.
	Action ReceiveRuleCreateAction
	// The sender address (`alice@example.com`) or domain (`example.com`) to match. Domains also match their subdomains. Stored lowercase.
	Entry string
	// Your own note about why the rule exists.
	Note string
}

EmailMailboxesReceiveRulesCreateParams is the request body for create.

type EmailMailboxesReceiveRulesListParams added in v0.17.0

type EmailMailboxesReceiveRulesListParams struct {
	// Filter by rule action.
	Action string
	// Maximum number of items to return per page.
	Limit int
}

EmailMailboxesReceiveRulesListParams filters the list. Zero-value fields are omitted.

type EmailMailboxesReceiveRulesService added in v0.17.0

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

EmailMailboxesReceiveRulesService manages per-sender allow/block rules on a mailbox. Reach it via Client.Email.Mailboxes.ReceiveRules.

func (*EmailMailboxesReceiveRulesService) Create added in v0.17.0

Create Add an allow or block rule for a sender address or domain to a mailbox. Block always wins. Up to 200 rules per mailbox.

Example
package main

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

	bird "github.com/messagebird/bird-sdk-go"
	"github.com/messagebird/bird-sdk-go/option"
)

func main() {
	client, err := bird.NewClient(option.WithAPIKey(os.Getenv("BIRD_API_KEY")))
	if err != nil {
		log.Fatal(err)
	}
	rule, err := client.Email.Mailboxes.ReceiveRules.Create(context.Background(), "mbx_123", bird.EmailMailboxesReceiveRulesCreateParams{
		Action: "block",
		Entry:  "spam.example.com",
	})
	if err != nil {
		log.Fatal(err)
	}
	fmt.Println(rule.Id)
}

func (*EmailMailboxesReceiveRulesService) Delete added in v0.17.0

func (s *EmailMailboxesReceiveRulesService) Delete(ctx context.Context, mailboxId string, ruleId string, opts ...option.RequestOption) error

Delete Remove a receive rule from a mailbox. Rules have no update operation, so a rule's allow or block action cannot be changed after it is created.

Example
package main

import (
	"context"
	"log"
	"os"

	bird "github.com/messagebird/bird-sdk-go"
	"github.com/messagebird/bird-sdk-go/option"
)

func main() {
	client, err := bird.NewClient(option.WithAPIKey(os.Getenv("BIRD_API_KEY")))
	if err != nil {
		log.Fatal(err)
	}
	if err := client.Email.Mailboxes.ReceiveRules.Delete(context.Background(), "mbx_123", "erl_456"); err != nil {
		log.Fatal(err)
	}
}

func (*EmailMailboxesReceiveRulesService) List added in v0.17.0

List List a mailbox's allow/block receive rules as a cursor page, oldest first. Filter by action. Range over it; the second value is non-nil only on the iteration where a fetch failed.

Example
package main

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

	bird "github.com/messagebird/bird-sdk-go"
	"github.com/messagebird/bird-sdk-go/option"
)

func main() {
	client, err := bird.NewClient(option.WithAPIKey(os.Getenv("BIRD_API_KEY")))
	if err != nil {
		log.Fatal(err)
	}
	for rule, err := range client.Email.Mailboxes.ReceiveRules.List(context.Background(), "mbx_123", bird.EmailMailboxesReceiveRulesListParams{}) {
		if err != nil {
			log.Fatal(err)
		}
		fmt.Println(rule.Id, rule.Action, rule.Entry)
	}
}

func (*EmailMailboxesReceiveRulesService) ListPage added in v0.17.0

ListPage fetches one page of results. Pass the previous page's NextCursor as startingAfter to advance; "" starts from the first page.

type EmailMailboxesService added in v0.17.0

type EmailMailboxesService struct {

	// Messages sends new messages from the mailbox's own address.
	Messages *EmailMailboxesMessagesService

	// ReceiveRules manages per-sender allow/block rules on the mailbox.
	ReceiveRules *EmailMailboxesReceiveRulesService
	// contains filtered or unexported fields
}

EmailMailboxesService manages agent mailboxes — durable inboxes on inbox.ai or your own domain that receive, store, and send email. Reach it via Client.Email.Mailboxes.

func (*EmailMailboxesService) Create added in v0.17.0

Create Create a mailbox: a durable agent identity that owns an email address, groups mail into conversations, and remembers conversations for its retention tier.

Example
package main

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

	bird "github.com/messagebird/bird-sdk-go"
	"github.com/messagebird/bird-sdk-go/option"
)

func main() {
	client, err := bird.NewClient(option.WithAPIKey(os.Getenv("BIRD_API_KEY")))
	if err != nil {
		log.Fatal(err)
	}
	mailbox, err := client.Email.Mailboxes.Create(context.Background(), bird.EmailMailboxesCreateParams{
		DisplayName: "Support",
	})
	if err != nil {
		log.Fatal(err)
	}
	fmt.Println(mailbox.Id, *mailbox.Address)
}

func (*EmailMailboxesService) Delete added in v0.17.0

func (s *EmailMailboxesService) Delete(ctx context.Context, mailboxId string, opts ...option.RequestOption) error

Delete Delete a mailbox. The address stops receiving immediately and is quarantined. The mailbox and its remembered messages stay restorable for 30 days through the restore endpoint, then are permanently deleted.

Example
package main

import (
	"context"
	"log"
	"os"

	bird "github.com/messagebird/bird-sdk-go"
	"github.com/messagebird/bird-sdk-go/option"
)

func main() {
	client, err := bird.NewClient(option.WithAPIKey(os.Getenv("BIRD_API_KEY")))
	if err != nil {
		log.Fatal(err)
	}
	if err := client.Email.Mailboxes.Delete(context.Background(), "mbx_123"); err != nil {
		log.Fatal(err)
	}
}

func (*EmailMailboxesService) Get added in v0.17.0

func (s *EmailMailboxesService) Get(ctx context.Context, mailboxId string, opts ...option.RequestOption) (*Mailbox, error)

Get Read one mailbox by ID. A mailbox deleted within its 30-day restore window is still returned, with a non-null `deleted_at`. Once that window closes it is gone and this returns 404.

Example
package main

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

	bird "github.com/messagebird/bird-sdk-go"
	"github.com/messagebird/bird-sdk-go/option"
)

func main() {
	client, err := bird.NewClient(option.WithAPIKey(os.Getenv("BIRD_API_KEY")))
	if err != nil {
		log.Fatal(err)
	}
	mailbox, err := client.Email.Mailboxes.Get(context.Background(), "mbx_123")
	if err != nil {
		log.Fatal(err)
	}
	fmt.Println(*mailbox.Address)
}

func (*EmailMailboxesService) Labels added in v0.17.0

Labels List the labels available in a mailbox: the built-in system labels (inbox, archive, spam, blocked, sent, trash, unread) plus every custom label in use.

Example
package main

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

	bird "github.com/messagebird/bird-sdk-go"
	"github.com/messagebird/bird-sdk-go/option"
)

func main() {
	client, err := bird.NewClient(option.WithAPIKey(os.Getenv("BIRD_API_KEY")))
	if err != nil {
		log.Fatal(err)
	}
	labels, err := client.Email.Mailboxes.Labels(context.Background(), "mbx_123")
	if err != nil {
		log.Fatal(err)
	}
	for _, l := range labels.Data {
		fmt.Println(l.Name)
	}
}

func (*EmailMailboxesService) List added in v0.17.0

List List the workspace's mailboxes as a cursor page, newest first. Search addresses and display names with q, or filter by exact address, state, or domain. Range over it; the second value is non-nil only on the iteration where a fetch failed.

Example

List auto-paginates across all mailboxes in the workspace.

package main

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

	bird "github.com/messagebird/bird-sdk-go"
	"github.com/messagebird/bird-sdk-go/option"
)

func main() {
	client, err := bird.NewClient(option.WithAPIKey(os.Getenv("BIRD_API_KEY")))
	if err != nil {
		log.Fatal(err)
	}
	for mailbox, err := range client.Email.Mailboxes.List(context.Background(), bird.EmailMailboxesListParams{}) {
		if err != nil {
			log.Fatal(err)
		}
		fmt.Println(mailbox.Id)
	}
}

func (*EmailMailboxesService) ListPage added in v0.17.0

func (s *EmailMailboxesService) ListPage(ctx context.Context, params EmailMailboxesListParams, startingAfter string, opts ...option.RequestOption) (*MailboxList, error)

ListPage fetches one page of results. Pass the previous page's NextCursor as startingAfter to advance; "" starts from the first page.

func (*EmailMailboxesService) Restore added in v0.17.0

func (s *EmailMailboxesService) Restore(ctx context.Context, mailboxId string, opts ...option.RequestOption) (*Mailbox, error)

Restore Restore a mailbox deleted less than 30 days ago: the address starts receiving again and the remembered messages are back. Past the window the mailbox is permanently deleted and returns 404. A mailbox that is not deleted returns 409.

Example
package main

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

	bird "github.com/messagebird/bird-sdk-go"
	"github.com/messagebird/bird-sdk-go/option"
)

func main() {
	client, err := bird.NewClient(option.WithAPIKey(os.Getenv("BIRD_API_KEY")))
	if err != nil {
		log.Fatal(err)
	}
	mailbox, err := client.Email.Mailboxes.Restore(context.Background(), "mbx_123")
	if err != nil {
		log.Fatal(err)
	}
	fmt.Println(mailbox.Id)
}

func (*EmailMailboxesService) Resume added in v0.17.0

func (s *EmailMailboxesService) Resume(ctx context.Context, mailboxId string, opts ...option.RequestOption) (*Mailbox, error)

Resume Resume a suspended mailbox so it can send and receive again and its conversations become visible. Fails if your plan does not have room for another active mailbox (or another custom inbox.ai handle). Delete an active mailbox or upgrade first. A mailbox that is not suspended returns 409.

Example
package main

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

	bird "github.com/messagebird/bird-sdk-go"
	"github.com/messagebird/bird-sdk-go/option"
)

func main() {
	client, err := bird.NewClient(option.WithAPIKey(os.Getenv("BIRD_API_KEY")))
	if err != nil {
		log.Fatal(err)
	}
	mailbox, err := client.Email.Mailboxes.Resume(context.Background(), "mbx_123")
	if err != nil {
		log.Fatal(err)
	}
	fmt.Println(mailbox.Id)
}

func (*EmailMailboxesService) Stats added in v0.17.0

Stats Read a mailbox's sent and received email statistics over a window: a period summary plus a bucketed series. Rows are bucketed by event time rather than send time, so engagement that arrived during the period for messages sent earlier is counted here. Both window bounds must use the same form, calendar days or RFC 3339 instants, matching the granularity.

Example
package main

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

	bird "github.com/messagebird/bird-sdk-go"
	"github.com/messagebird/bird-sdk-go/option"
)

func main() {
	client, err := bird.NewClient(option.WithAPIKey(os.Getenv("BIRD_API_KEY")))
	if err != nil {
		log.Fatal(err)
	}
	stats, err := client.Email.Mailboxes.Stats(context.Background(), "mbx_123", bird.EmailMailboxesStatsParams{})
	if err != nil {
		log.Fatal(err)
	}
	if stats.Summary != nil {
		if d := stats.Summary.Delivery; d != nil {
			fmt.Println(d.Delivered, d.Bounced)
		}
	}
}

func (*EmailMailboxesService) Update added in v0.17.0

Update Update a mailbox's display name, reply-to, receive policy, retention tier, IP pool, or metadata. Lowering the retention tier requires `confirm=true` when it would delete remembered messages older than the new cutoff.

Example
package main

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

	bird "github.com/messagebird/bird-sdk-go"
	"github.com/messagebird/bird-sdk-go/option"
)

func main() {
	client, err := bird.NewClient(option.WithAPIKey(os.Getenv("BIRD_API_KEY")))
	if err != nil {
		log.Fatal(err)
	}
	mailbox, err := client.Email.Mailboxes.Update(context.Background(), "mbx_123", bird.EmailMailboxesUpdateParams{
		DisplayName: bird.Value("Sales"),
	})
	if err != nil {
		log.Fatal(err)
	}
	fmt.Println(mailbox.Id)
}

type EmailMailboxesStatsParams added in v0.17.0

type EmailMailboxesStatsParams struct {
	// Inclusive start of the window: a calendar day (YYYY-MM-DD, `day` granularity only) or an RFC 3339 instant rounded down to the hour (`hour` granularity only). Interpreted in `timezone`, or in UTC when `timezone` is omitted. A numeric UTC offset is rejected when `timezone` is set; use a calendar day or a `Z` (UTC) instant. Must use the same form as `to`. Defaults to 30 days before `to` at `day` granularity and 7 days before `to` at `hour`, when omitted.
	From string
	// Inclusive end of the window: a calendar day (YYYY-MM-DD, `day` granularity only) or an RFC 3339 instant rounded down to the hour (`hour` granularity only). Interpreted in `timezone`, or in UTC when `timezone` is omitted. A numeric UTC offset is rejected when `timezone` is set; use a calendar day or a `Z` (UTC) instant. Must use the same form as `from`. Defaults to today (day) or the current hour (hour) in that timezone when omitted. Window may not exceed 365 days at `day` or 30 days at `hour` granularity.
	To string
	// IANA timezone identifier (for example `Asia/Kathmandu`) to report in; defaults to UTC. Day and hour boundaries and the default window when `from` and `to` are omitted both follow it, so a calendar-day `from` or `to` names a local day. A `from` or `to` carrying its own UTC offset is rejected while this is set: pass a calendar day or a `Z` instant.
	Timezone string
	// Granularity of the series: `day` (default) or `hour`. Echoed back as `period.grain`.
	Granularity string
}

EmailMailboxesStatsParams filters the stats read.

type EmailMailboxesUpdateParams added in v0.17.0

type EmailMailboxesUpdateParams struct {
	// Display name used as the sender name on mail from this mailbox. Null clears it.
	DisplayName Nullable[string]
	// Default Reply-To address stamped on mail sent from this mailbox. Null clears it.
	DefaultReplyTo Nullable[string]
	// Which inbound mail the mailbox accepts.
	ReceivePolicy *MailboxUpdateReceivePolicy
	// How long the mailbox remembers message metadata and extracted text. Lowering the tier deletes remembered messages older than the new horizon, and requires `confirm=true` when that would happen.
	RetentionTier *MailboxUpdateRetentionTier
	// Replaces the mailbox's key/value data. Up to 2 KB. Keys starting with `__bird` are reserved.
	Metadata map[string]any
	// Set to `true` when lowering `retention_tier` would delete remembered messages older than the new cutoff. The request is rejected without it in that case.
	Confirm bool
}

EmailMailboxesUpdateParams is the request body for update.

type EmailMessage

type EmailMessage = oapi.EmailMessage

EmailMessage is a sent message with aggregate delivery status.

type EmailMessageCategory added in v0.16.0

type EmailMessageCategory = oapi.EmailMessageCategory

EmailMessageCategory is an alias of Category, used by the read filters.

type EmailMessageList

type EmailMessageList = oapi.EmailMessageList

EmailMessageList is one page of messages plus its pagination cursors.

type EmailMessageStatus added in v0.16.0

type EmailMessageStatus = oapi.EmailMessageStatus

EmailMessageStatus is an alias of EmailStatus, used by the read filters.

type EmailOpenedEvent

type EmailOpenedEvent = oapi.EventEmailOpened

Webhook event payloads, returned by Event.AsAny. Type-switch on these.

type EmailOutOfBandBounceEvent

type EmailOutOfBandBounceEvent = oapi.EventEmailOutOfBandBounce

Webhook event payloads, returned by Event.AsAny. Type-switch on these.

type EmailProcessedEvent

type EmailProcessedEvent = oapi.EventEmailProcessed

Webhook event payloads, returned by Event.AsAny. Type-switch on these.

type EmailReceivedEvent

type EmailReceivedEvent = oapi.EventEmailReceived

Webhook event payloads, returned by Event.AsAny. Type-switch on these.

type EmailRejectedEvent

type EmailRejectedEvent = oapi.EventEmailRejected

Webhook event payloads, returned by Event.AsAny. Type-switch on these.

type EmailSendBatchParams added in v0.2.0

type EmailSendBatchParams struct {
	Messages []EmailSendParams
}

EmailSendBatchParams is a batch of email sends submitted in one request. Each Message is an individual send; the whole batch is validated before any item is queued. The result preserves submission order.

type EmailSendParams

type EmailSendParams struct {
	From        string            // sender; bare address or "Name <addr>" form; must be on a verified domain
	To          []string          // primary recipients; each may be bare or "Name <addr>" form
	Cc          []string          // optional; same syntax as To
	Bcc         []string          // optional; same syntax as To
	ReplyTo     []string          // optional Reply-To; same syntax as To
	Subject     string            // subject line
	HTML        string            // HTML body; at least one of HTML or Text is required
	Text        string            // plain-text body
	Tags        []EmailTag        // structured {name,value} labels for filtering and analytics
	Metadata    map[string]any    // arbitrary JSON, echoed on reads and in webhook payloads
	Headers     map[string]string // custom email headers
	Attachments []EmailAttachment // file attachments
	Category    Category          // transactional (default) or marketing
	IpPoolId    string            // IP pool ID (ipp_…); workspace default when empty
	// TrackOpens and TrackClicks are pointers because the server default is
	// true — a nil leaves the default, false explicitly disables tracking.
	TrackOpens  *bool
	TrackClicks *bool
	// Template, when set, sends a published template in place of inline content:
	// leave Subject/HTML/Text empty (the template supplies them) and personalize
	// with Parameters. The value is the template's ID (`emt_…`) or its slug handle.
	Template string
	// Language selects which of the template's languages to send, as a BCP-47 tag
	// (e.g. "en", "pt-BR"). Template sends only. Omit it to send the template's
	// default language, unless the template's language_source_required is true, in
	// which case a send naming none is rejected. A language the template doesn't
	// carry is resolved by the template's own on_missing_language setting
	// (fallback to the closest match, or fail the send).
	Language string
	// Parameters holds template variables rendered into the subject and
	// body at send time; works with both inline content and a Template.
	Parameters map[string]any
	// ScheduledAt holds the message until a future instant instead of sending
	// it immediately: at least 30 seconds and at most 30 days ahead, and
	// mutually exclusive with Template. Only a single send accepts it; a batch
	// item that sets one is rejected with a 422.
	ScheduledAt time.Time
}

EmailSendParams is an email send. Optional fields are omitted from the request when left at their zero value.

Address fields (From, To, Cc, Bcc, ReplyTo) accept either a bare email address or RFC 5322 mailbox syntax with a display name: "Support Team <support@example.com>".

type EmailService

type EmailService struct {

	// Stats reads aggregated delivery and engagement statistics.
	Stats *EmailStatsService

	// Mailboxes manages durable agent mailboxes that receive, store, and send email.
	Mailboxes *EmailMailboxesService

	// Threads reads and manages email conversations across every mailbox.
	Threads *EmailThreadsService
	// contains filtered or unexported fields
}

EmailService sends and reads email messages. Reach it via Client.Email.

func (*EmailService) Cancel added in v0.4.1

func (s *EmailService) Cancel(ctx context.Context, messageId string, opts ...option.RequestOption) error

Cancel Cancel a scheduled email before it sends. Only works while the message's `status` is still `scheduled`. Once it starts sending, or was already canceled, the call returns a conflict error. Canceling does not return consumed scheduled-send quota.

Example

Cancel stops a message that has not left yet — a scheduled send before its send time, or a queued one still awaiting delivery.

package main

import (
	"context"
	"log"
	"os"

	bird "github.com/messagebird/bird-sdk-go"
	"github.com/messagebird/bird-sdk-go/option"
)

func main() {
	client, err := bird.NewClient(option.WithAPIKey(os.Getenv("BIRD_API_KEY")))
	if err != nil {
		log.Fatal(err)
	}
	if err := client.Email.Cancel(context.Background(), "em_abc123"); err != nil {
		log.Fatal(err)
	}
}

func (*EmailService) Get

func (s *EmailService) Get(ctx context.Context, messageId string, opts ...option.RequestOption) (*EmailMessage, error)

Get Fetch one email message by `id`, with aggregate delivery status and per-state recipient counts. The message body (`html`, `text`) is not returned. Per-recipient delivery statuses and the event log are separate sub-resources: `GET /v1/email/messages/{message_id}/recipients` and `GET /v1/email/messages/{message_id}/events`.

Example
package main

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

	bird "github.com/messagebird/bird-sdk-go"
	"github.com/messagebird/bird-sdk-go/option"
)

func main() {
	client, err := bird.NewClient(option.WithAPIKey(os.Getenv("BIRD_API_KEY")))
	if err != nil {
		log.Fatal(err)
	}
	msg, err := client.Email.Get(context.Background(), "em_abc123")
	if err != nil {
		log.Fatal(err)
	}
	fmt.Println(*msg.Status, *msg.DeliveredCount)
}

func (*EmailService) List

List List sent email messages, newest first, as a cursor page (`{data, next_cursor, …}`). Pass `next_cursor` back as `starting_after` to fetch the next page. Filter by creation time with the half-open range `created_after` (inclusive) and `created_before` (exclusive). For a single UTC day, `created_after` is that day at 00:00:00Z and `created_before` is the next day at 00:00:00Z. Range over it; the second value is non-nil only on the iteration where a fetch failed.

Example

List auto-paginates: it lazily fetches each page and yields every matching message across all of them.

package main

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

	bird "github.com/messagebird/bird-sdk-go"
	"github.com/messagebird/bird-sdk-go/option"
)

func main() {
	client, err := bird.NewClient(option.WithAPIKey(os.Getenv("BIRD_API_KEY")))
	if err != nil {
		log.Fatal(err)
	}
	for msg, err := range client.Email.List(context.Background(), bird.EmailListParams{Status: bird.EmailStatusBounced}) {
		if err != nil {
			log.Fatal(err)
		}
		fmt.Println(msg.Id)
	}
	page, err := client.Email.ListPage(context.Background(), bird.EmailListParams{}, "")
	if err != nil {
		log.Fatal(err)
	}
	fmt.Println(len(page.Data)) // page.NextCursor carries the next starting_after
}

func (*EmailService) ListPage

func (s *EmailService) ListPage(ctx context.Context, params EmailListParams, startingAfter string, opts ...option.RequestOption) (*EmailMessageList, error)

ListPage fetches one page of results. Pass the previous page's NextCursor as startingAfter to advance; "" starts from the first page.

func (*EmailService) Send

Send delivers an email and returns the created message. Sends are retried safely: a single idempotency key is reused across attempts, so a retry never double-delivers. Provide your own key with option.WithIdempotencyKey.

Example
package main

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

	bird "github.com/messagebird/bird-sdk-go"
	"github.com/messagebird/bird-sdk-go/option"
)

func main() {
	client, err := bird.NewClient(option.WithAPIKey(os.Getenv("BIRD_API_KEY")))
	if err != nil {
		log.Fatal(err)
	}
	msg, err := client.Email.Send(context.Background(), bird.EmailSendParams{
		From:    "onboarding@messagebird.dev",
		To:      []string{"delivered@messagebird.dev"},
		Subject: "Hello from Bird",
		HTML:    "<p>My first Bird email.</p>",
	})
	if err != nil {
		log.Fatal(err)
	}
	fmt.Println(msg.Id, *msg.Status)
}
Example (Bounce)

Sending to the sandbox bounce address, which hard-bounces every time. The tag and metadata are what make the resulting event findable in the logs.

package main

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

	bird "github.com/messagebird/bird-sdk-go"
	"github.com/messagebird/bird-sdk-go/option"
)

func main() {
	client, err := bird.NewClient(option.WithAPIKey(os.Getenv("BIRD_API_KEY")))
	if err != nil {
		log.Fatal(err)
	}
	msg, err := client.Email.Send(context.Background(), bird.EmailSendParams{
		From:     "onboarding@messagebird.dev",
		To:       []string{"bounce+signup-flow@messagebird.dev"},
		Subject:  "Sandbox bounce test",
		HTML:     "<p>This message will hard-bounce.</p>",
		Tags:     []bird.Tag{{Name: "flow", Value: "signup"}},
		Metadata: map[string]any{"test_run": "docs-capture-1"},
	})
	if err != nil {
		log.Fatal(err)
	}
	fmt.Println(msg.Id, *msg.Status)
}
Example (DisplayNames)

Send with display names: "Name <addr>" syntax in From and To.

package main

import (
	"context"
	"log"
	"os"

	bird "github.com/messagebird/bird-sdk-go"
	"github.com/messagebird/bird-sdk-go/option"
)

func main() {
	client, err := bird.NewClient(option.WithAPIKey(os.Getenv("BIRD_API_KEY")))
	if err != nil {
		log.Fatal(err)
	}
	_, err = client.Email.Send(context.Background(), bird.EmailSendParams{
		From:    "Bird Support <support@acme.com>",
		To:      []string{"Jane Doe <jane@example.com>", "bob@example.com"},
		Subject: "Your order is confirmed",
		HTML:    "<p>Thanks for your order!</p>",
	})
	if err != nil {
		log.Fatal(err)
	}
}
Example (Errors)

Branch on the typed error hierarchy. The SDK already retries transient failures (timeouts, 429, 5xx), so a returned error is terminal — most callers just propagate it; branch only to act on a category.

package main

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

	bird "github.com/messagebird/bird-sdk-go"
	"github.com/messagebird/bird-sdk-go/option"
)

func main() {
	client, err := bird.NewClient(option.WithAPIKey(os.Getenv("BIRD_API_KEY")))
	if err != nil {
		log.Fatal(err)
	}
	_, err = client.Email.Send(context.Background(), bird.EmailSendParams{
		From: "onboarding@messagebird.dev", To: []string{"delivered@messagebird.dev"}, Subject: "Hello from Bird", HTML: "<p>My first Bird email.</p>",
	})
	if err != nil {
		var rle *bird.RateLimitError
		var ve *bird.ValidationError
		var ae *bird.APIError
		switch {
		case errors.As(err, &rle):
			fmt.Println("rate limited; retry after", rle.RetryAfter)
		case errors.As(err, &ve):
			for _, d := range ve.Details {
				fmt.Printf("%s: %s\n", d.Param, d.Message)
			}
		case errors.As(err, &ae):
			fmt.Printf("API error %s (status %d, request %s)\n", ae.Code, ae.StatusCode, ae.RequestID)
		default:
			log.Print(err) // transport: *bird.ConnectionError or *bird.TimeoutError
		}
	}
}
Example (Rich)
package main

import (
	"context"
	"log"
	"os"

	bird "github.com/messagebird/bird-sdk-go"
	"github.com/messagebird/bird-sdk-go/option"
)

func main() {
	client, err := bird.NewClient(option.WithAPIKey(os.Getenv("BIRD_API_KEY")))
	if err != nil {
		log.Fatal(err)
	}
	_, err = client.Email.Send(context.Background(), bird.EmailSendParams{
		From:        "hello@acme.com",
		To:          []string{"a@example.com", "b@example.com"},
		Cc:          []string{"manager@example.com"},
		ReplyTo:     []string{"support@acme.com"},
		Subject:     "Your March invoice",
		HTML:        "<p>Attached.</p>",
		Tags:        []bird.EmailTag{{Name: "category", Value: "billing"}},
		Metadata:    map[string]any{"invoice_id": "inv_123"},
		TrackClicks: bird.Bool(false),
	}, option.WithIdempotencyKey("invoice-march/cust_1"))
	if err != nil {
		log.Fatal(err)
	}
}
Example (Template)

A richer send: cc/bcc, reply-to, tags, metadata, opt-out of click tracking, and an idempotency key (safe to retry — the server dedupes). Send a published template in place of inline content. The template supplies the subject and bodies; Parameters fills its variables.

package main

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

	bird "github.com/messagebird/bird-sdk-go"
	"github.com/messagebird/bird-sdk-go/option"
)

func main() {
	client, err := bird.NewClient(option.WithAPIKey(os.Getenv("BIRD_API_KEY")))
	if err != nil {
		log.Fatal(err)
	}
	msg, err := client.Email.Send(context.Background(), bird.EmailSendParams{
		From:       "onboarding@messagebird.dev",
		To:         []string{"delivered@messagebird.dev"},
		Category:   "transactional",
		Template:   "welcome-email",
		Parameters: map[string]any{"first_name": "Jane"},
	})
	if err != nil {
		log.Fatal(err)
	}
	fmt.Println(msg.Id, *msg.Status)
}

func (*EmailService) SendBatch added in v0.2.0

func (s *EmailService) SendBatch(ctx context.Context, params EmailSendBatchParams, opts ...option.RequestOption) (*EmailBatch, error)

SendBatch queues multiple emails in one request and returns one result item per submitted message, in submission order. The whole batch is validated before any item is queued. Like Send, the batch is retried safely: a single idempotency key is reused across attempts, so a retry never double-delivers. Provide your own key with option.WithIdempotencyKey.

Example

SendBatch queues several emails in one request and returns one result item per message, in submission order.

package main

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

	bird "github.com/messagebird/bird-sdk-go"
	"github.com/messagebird/bird-sdk-go/option"
)

func main() {
	client, err := bird.NewClient(option.WithAPIKey(os.Getenv("BIRD_API_KEY")))
	if err != nil {
		log.Fatal(err)
	}
	batch, err := client.Email.SendBatch(context.Background(), bird.EmailSendBatchParams{
		Messages: []bird.EmailSendParams{
			{
				From:    "onboarding@messagebird.dev",
				To:      []string{"alice@example.com"},
				Subject: "Hello, Alice",
				HTML:    "<p>Welcome!</p>",
			},
			{
				From:    "onboarding@messagebird.dev",
				To:      []string{"bob@example.com"},
				Subject: "Hello, Bob",
				HTML:    "<p>Welcome!</p>",
			},
		},
	})
	if err != nil {
		log.Fatal(err)
	}
	for _, item := range batch.Data {
		fmt.Println(item.Id)
	}
}

type EmailStatsByBounceCodeParams added in v0.10.0

type EmailStatsByBounceCodeParams struct {
	// Start date (inclusive) in YYYY-MM-DD, interpreted as a calendar day in `timezone` (a UTC day when `timezone` is omitted). Defaults to 30 days before `to` when omitted.
	From time.Time
	// End date (inclusive) in YYYY-MM-DD, interpreted as a calendar day in `timezone` (a UTC day when `timezone` is omitted). Defaults to today in that timezone when omitted. Window may not exceed 365 days.
	To time.Time
	// IANA timezone identifier (for example `Asia/Kathmandu`) to report in; defaults to UTC. Day and hour boundaries and the default window when `from` and `to` are omitted both follow it, so a calendar-day `from` or `to` names a local day. A `from` or `to` carrying its own UTC offset is rejected while this is set: pass a calendar day or a `Z` instant.
	Timezone string
	// Not supported on breakdown endpoints. Supplying it returns 422. To compare categories, use `GET /v1/email/stats/categories`. The summary, daily, and hourly statistics accept `category` as a filter.
	Category string
	// Metric to rank rows by, applied descending. It defaults to `bounced`. Only the bounce counts are sortable here, because this breakdown has no rate fields.
	Sort string
	// Maximum number of bounce-code rows to return, ranked by the `sort` field descending.
	Limit int
}

EmailStatsByBounceCodeParams filters the by_bounce_code read.

type EmailStatsByBounceCodeResponse added in v0.10.0

type EmailStatsByBounceCodeResponse = oapi.EmailStatsByBounceCodeResponse

Email statistics responses, returned by the Client.Email.Stats methods. Each is the read-side body for one breakdown.

type EmailStatsByBroadcastParams added in v0.10.0

type EmailStatsByBroadcastParams struct {
	// Start date (inclusive) in YYYY-MM-DD, UTC. Defaults to 30 days before `to` when omitted.
	From time.Time
	// End date (inclusive) in YYYY-MM-DD, UTC. Defaults to today (UTC) when omitted. Window may not exceed 365 days.
	To time.Time
	// Not supported on breakdown endpoints. Supplying it returns a 422. To compare categories, use `GET /v1/email/stats/categories`. The summary, daily, and hourly statistics accept `category` as a filter.
	Category string
	// Metric to rank rows by, applied descending. Any count or rate in the response may be used; rows whose rate is undefined (zero denominator) sort last. Defaults to `processed`.
	Sort EmailStatsSortMetric
	// Maximum number of broadcast rows to return, ranked by the `sort` field descending.
	Limit int
}

EmailStatsByBroadcastParams filters the by_broadcast read.

type EmailStatsByBroadcastResponse added in v0.10.0

type EmailStatsByBroadcastResponse = oapi.EmailStatsByBroadcastResponse

Email statistics responses, returned by the Client.Email.Stats methods. Each is the read-side body for one breakdown.

type EmailStatsByCategoryParams added in v0.10.0

type EmailStatsByCategoryParams struct {
	// Start date (inclusive) in YYYY-MM-DD, interpreted as a calendar day in `timezone` (a UTC day when `timezone` is omitted). It defaults to 30 days before `to` when you leave it out. When `include_trend=true` and `trend_grain=hourly`, that default tightens to 29 days before `to` instead, so the defaulted window still fits inside the 720-hour trend cap.
	From time.Time
	// End date (inclusive) in YYYY-MM-DD, interpreted as a calendar day in `timezone` (a UTC day when `timezone` is omitted). Defaults to today in that timezone when omitted. Window may not exceed 365 days.
	To time.Time
	// IANA timezone identifier (for example `Asia/Kathmandu`) to report in; defaults to UTC. Day and hour boundaries and the default window when `from` and `to` are omitted both follow it, so a calendar-day `from` or `to` names a local day. A `from` or `to` carrying its own UTC offset is rejected while this is set: pass a calendar day or a `Z` instant.
	Timezone string
	// Metric to rank rows by, applied descending. Any count or rate in the response can be used. A row whose rate is undefined because its denominator is zero sorts last. It defaults to `processed`.
	Sort EmailStatsSortMetric
	// Maximum number of category rows to return, ranked by the `sort` field descending.
	Limit int
	// When true, each row also gets a `trend` array: a short per-bucket series showing that category's delivery and engagement rates over the window. This only works when `limit` is 50 or fewer and the window is at most 90 days for `trend_grain=daily` or 720 hours for `trend_grain=hourly`. Ask for more and you get a 422. When you leave `from` out and use `trend_grain=hourly`, the default window tightens to 29 days before `to` (720 hours total), so a request built entirely from defaults always fits inside the cap.
	IncludeTrend bool
	// Bucket grain for the `trend` series. Has no effect unless `include_trend=true`.
	TrendGrain StatsTrendGrain
}

EmailStatsByCategoryParams filters the by_category read.

type EmailStatsByCategoryResponse added in v0.10.0

type EmailStatsByCategoryResponse = oapi.EmailStatsByCategoryResponse

Email statistics responses, returned by the Client.Email.Stats methods. Each is the read-side body for one breakdown.

type EmailStatsByClientParams added in v0.10.0

type EmailStatsByClientParams struct {
	// Start date (inclusive) in YYYY-MM-DD, interpreted as a calendar day in `timezone` (a UTC day when `timezone` is omitted). Defaults to 30 days before `to` when omitted.
	From time.Time
	// End date (inclusive) in YYYY-MM-DD, interpreted as a calendar day in `timezone` (a UTC day when `timezone` is omitted). Defaults to today in that timezone when omitted. Window may not exceed 365 days.
	To time.Time
	// IANA timezone identifier (for example `Asia/Kathmandu`) to report in; defaults to UTC. Day and hour boundaries and the default window when `from` and `to` are omitted both follow it, so a calendar-day `from` or `to` names a local day. A `from` or `to` carrying its own UTC offset is rejected while this is set: pass a calendar day or a `Z` instant.
	Timezone string
	// Not supported on breakdown endpoints; supplying it returns 422. To compare categories use `GET /v1/email/stats/categories`; the summary, daily, and hourly statistics accept `category` as a filter.
	Category string
	// Which reading-environment facet to group rows by. `email_client` (default) groups by mail client; `os` groups by operating system; `device_type` groups by device type. Each row populates the chosen facet and leaves the other two null.
	GroupBy string
	// Metric to rank rows by, applied descending. It defaults to `unique_opens`. Only engagement counts are sortable. This breakdown has no rates.
	Sort EmailEngagementSortMetric
	// Maximum number of client rows to return, ranked by the `sort` field descending.
	Limit int
}

EmailStatsByClientParams filters the by_client read.

type EmailStatsByClientResponse added in v0.10.0

type EmailStatsByClientResponse = oapi.EmailStatsByClientResponse

Email statistics responses, returned by the Client.Email.Stats methods. Each is the read-side body for one breakdown.

type EmailStatsByComplaintTypeParams added in v0.10.0

type EmailStatsByComplaintTypeParams struct {
	// Start date (inclusive) in YYYY-MM-DD, interpreted as a calendar day in `timezone` (a UTC day when `timezone` is omitted). Defaults to 30 days before `to` when omitted.
	From time.Time
	// End date (inclusive) in YYYY-MM-DD, interpreted as a calendar day in `timezone` (a UTC day when `timezone` is omitted). Defaults to today in that timezone when omitted. Window may not exceed 365 days.
	To time.Time
	// IANA timezone identifier (for example `Asia/Kathmandu`) to report in; defaults to UTC. Day and hour boundaries and the default window when `from` and `to` are omitted both follow it, so a calendar-day `from` or `to` names a local day. A `from` or `to` carrying its own UTC offset is rejected while this is set: pass a calendar day or a `Z` instant.
	Timezone string
	// Not supported on breakdown endpoints. Supplying it returns 422. To compare categories, use `GET /v1/email/stats/categories`. The summary, daily, and hourly statistics accept `category` as a filter.
	Category string
	// Metric to rank rows by, applied descending. It defaults to `complained`, the only sortable metric for this breakdown.
	Sort string
	// Maximum number of complaint-type rows to return, ranked by `complained` descending.
	Limit int
}

EmailStatsByComplaintTypeParams filters the by_complaint_type read.

type EmailStatsByComplaintTypeResponse added in v0.10.0

type EmailStatsByComplaintTypeResponse = oapi.EmailStatsByComplaintTypeResponse

Email statistics responses, returned by the Client.Email.Stats methods. Each is the read-side body for one breakdown.

type EmailStatsByLocationParams added in v0.10.0

type EmailStatsByLocationParams struct {
	// Start date (inclusive) in YYYY-MM-DD, interpreted as a calendar day in `timezone` (a UTC day when `timezone` is omitted). Defaults to 30 days before `to` when omitted.
	From time.Time
	// End date (inclusive) in YYYY-MM-DD, interpreted as a calendar day in `timezone` (a UTC day when `timezone` is omitted). Defaults to today in that timezone when omitted. Window may not exceed 365 days.
	To time.Time
	// IANA timezone identifier (for example `Asia/Kathmandu`) to report in; defaults to UTC. Day and hour boundaries and the default window when `from` and `to` are omitted both follow it, so a calendar-day `from` or `to` names a local day. A `from` or `to` carrying its own UTC offset is rejected while this is set: pass a calendar day or a `Z` instant.
	Timezone string
	// Not supported on breakdown endpoints; supplying it returns 422. To compare categories use `GET /v1/email/stats/categories`; the summary, daily, and hourly statistics accept `category` as a filter.
	Category string
	// Location granularity for each row. `country` (default) groups by country; `region` groups by region within country; `city` groups by city within region. Each row reports the location hierarchy down to the chosen level.
	GroupBy string
	// Metric to rank rows by, applied descending. It defaults to `unique_opens`. Only engagement counts are sortable. This breakdown has no rates.
	Sort EmailEngagementSortMetric
	// Maximum number of location rows to return, ranked by the `sort` field descending.
	Limit int
}

EmailStatsByLocationParams filters the by_location read.

type EmailStatsByLocationResponse added in v0.10.0

type EmailStatsByLocationResponse = oapi.EmailStatsByLocationResponse

Email statistics responses, returned by the Client.Email.Stats methods. Each is the read-side body for one breakdown.

type EmailStatsByMailboxProviderParams added in v0.10.0

type EmailStatsByMailboxProviderParams struct {
	// Start date (inclusive) in YYYY-MM-DD, interpreted as a calendar day in `timezone` (a UTC day when `timezone` is omitted). It defaults to 30 days before `to` when you leave it out. When `include_trend=true` and `trend_grain=hourly`, that default tightens to 29 days before `to` instead, so the defaulted window still fits inside the 720-hour trend cap.
	From time.Time
	// End date (inclusive) in YYYY-MM-DD, interpreted as a calendar day in `timezone` (a UTC day when `timezone` is omitted). Defaults to today in that timezone when omitted. Window may not exceed 365 days.
	To time.Time
	// IANA timezone identifier (for example `Asia/Kathmandu`) to report in; defaults to UTC. Day and hour boundaries and the default window when `from` and `to` are omitted both follow it, so a calendar-day `from` or `to` names a local day. A `from` or `to` carrying its own UTC offset is rejected while this is set: pass a calendar day or a `Z` instant.
	Timezone string
	// Not supported on breakdown endpoints; supplying it returns 422. To compare categories use `GET /v1/email/stats/categories`; the summary, daily, and hourly statistics accept `category` as a filter.
	Category string
	// Metric to rank rows by, applied descending. Any count or rate in the response can be used. A row whose rate is undefined because its denominator is zero sorts last. It defaults to `delivered`. `processed`, `rejected`, and `oob_bounces` are not part of this breakdown's rows, so they are not sortable here.
	Sort EmailMailboxProviderSortMetric
	// Maximum number of mailbox-provider rows to return, ranked by the `sort` field descending.
	Limit int
	// When true, each row also gets a `trend` array: a short per-bucket series showing that provider's delivery and engagement rates over the window. This only works when `limit` is 50 or fewer and the window is at most 90 days for `trend_grain=daily` or 720 hours for `trend_grain=hourly`. Ask for more and you get a 422. When you leave `from` out and use `trend_grain=hourly`, the default window tightens to 29 days before `to` (720 hours total), so a request built entirely from defaults always fits inside the cap.
	IncludeTrend bool
	// Bucket grain for the `trend` series. Has no effect unless `include_trend=true`.
	TrendGrain StatsTrendGrain
}

EmailStatsByMailboxProviderParams filters the by_mailbox_provider read.

type EmailStatsByMailboxProviderRegionParams added in v0.10.0

type EmailStatsByMailboxProviderRegionParams struct {
	// Start date (inclusive) in YYYY-MM-DD, interpreted as a calendar day in `timezone` (a UTC day when `timezone` is omitted). It defaults to 30 days before `to` when you leave it out. When `include_trend=true` and `trend_grain=hourly`, that default tightens to 29 days before `to` instead, so the defaulted window still fits inside the 720-hour trend cap.
	From time.Time
	// End date (inclusive) in YYYY-MM-DD, interpreted as a calendar day in `timezone` (a UTC day when `timezone` is omitted). Defaults to today in that timezone when omitted. Window may not exceed 365 days.
	To time.Time
	// IANA timezone identifier (for example `Asia/Kathmandu`) to report in; defaults to UTC. Day and hour boundaries and the default window when `from` and `to` are omitted both follow it, so a calendar-day `from` or `to` names a local day. A `from` or `to` carrying its own UTC offset is rejected while this is set: pass a calendar day or a `Z` instant.
	Timezone string
	// Not supported on breakdown endpoints. Supplying it returns 422. To compare categories, use `GET /v1/email/stats/categories`. The summary, daily, and hourly statistics accept `category` as a filter.
	Category string
	// Metric to rank rows by, applied descending. Any count or rate in the response can be used. A row whose rate is undefined because its denominator is zero sorts last. It defaults to `delivered`. `processed`, `rejected`, and `oob_bounces` are not part of this breakdown's rows, so they are not sortable here.
	Sort EmailMailboxProviderSortMetric
	// Maximum number of provider-region rows to return, ranked by the `sort` field descending.
	Limit int
	// When true, each row also gets a `trend` array: a short per-bucket series showing that provider region's delivery and engagement rates over the window. This only works when `limit` is 50 or fewer and the window is at most 90 days for `trend_grain=daily` or 720 hours for `trend_grain=hourly`. Ask for more and you get a 422. When you leave `from` out and use `trend_grain=hourly`, the default window tightens to 29 days before `to` (720 hours total), so a request built entirely from defaults always fits inside the cap.
	IncludeTrend bool
	// Bucket grain for the `trend` series. Has no effect unless `include_trend=true`.
	TrendGrain StatsTrendGrain
}

EmailStatsByMailboxProviderRegionParams filters the by_mailbox_provider_region read.

type EmailStatsByMailboxProviderRegionResponse added in v0.10.0

type EmailStatsByMailboxProviderRegionResponse = oapi.EmailStatsByMailboxProviderRegionResponse

Email statistics responses, returned by the Client.Email.Stats methods. Each is the read-side body for one breakdown.

type EmailStatsByMailboxProviderResponse added in v0.10.0

type EmailStatsByMailboxProviderResponse = oapi.EmailStatsByMailboxProviderResponse

Email statistics responses, returned by the Client.Email.Stats methods. Each is the read-side body for one breakdown.

type EmailStatsByRecipientDomainParams added in v0.10.0

type EmailStatsByRecipientDomainParams struct {
	// Start date (inclusive) in YYYY-MM-DD, interpreted as a calendar day in `timezone` (a UTC day when `timezone` is omitted). It defaults to 30 days before `to` when you leave it out. When `include_trend=true` and `trend_grain=hourly`, that default tightens to 29 days before `to` instead, so the defaulted window still fits inside the 720-hour trend cap.
	From time.Time
	// End date (inclusive) in YYYY-MM-DD, interpreted as a calendar day in `timezone` (a UTC day when `timezone` is omitted). Defaults to today in that timezone when omitted. Window may not exceed 365 days.
	To time.Time
	// IANA timezone identifier (for example `Asia/Kathmandu`) to report in; defaults to UTC. Day and hour boundaries and the default window when `from` and `to` are omitted both follow it, so a calendar-day `from` or `to` names a local day. A `from` or `to` carrying its own UTC offset is rejected while this is set: pass a calendar day or a `Z` instant.
	Timezone string
	// Not supported on breakdown endpoints. Supplying it returns 422. To compare categories, use `GET /v1/email/stats/categories`. The summary, daily, and hourly statistics accept `category` as a filter.
	Category string
	// Metric to rank rows by, applied descending. Any count or rate in the response can be used. A row whose rate is undefined because its denominator is zero sorts last. It defaults to `processed`.
	Sort EmailStatsSortMetric
	// Maximum number of recipient-domain rows to return, ranked by the `sort` field descending.
	Limit int
	// When true, each row also gets a `trend` array: a short per-bucket series showing that recipient domain's delivery and engagement rates over the window. This only works when `limit` is 50 or fewer and the window is at most 90 days for `trend_grain=daily` or 720 hours for `trend_grain=hourly`. Ask for more and you get a 422. When you leave `from` out and use `trend_grain=hourly`, the default window tightens to 29 days before `to` (720 hours total), so a request built entirely from defaults always fits inside the cap.
	IncludeTrend bool
	// Bucket grain for the `trend` series. Has no effect unless `include_trend=true`.
	TrendGrain StatsTrendGrain
}

EmailStatsByRecipientDomainParams filters the by_recipient_domain read.

type EmailStatsByRecipientDomainResponse added in v0.10.0

type EmailStatsByRecipientDomainResponse = oapi.EmailStatsByRecipientDomainResponse

Email statistics responses, returned by the Client.Email.Stats methods. Each is the read-side body for one breakdown.

type EmailStatsBySendingDomainParams added in v0.10.0

type EmailStatsBySendingDomainParams struct {
	// Start date (inclusive) in YYYY-MM-DD, interpreted as a calendar day in `timezone` (a UTC day when `timezone` is omitted). It defaults to 30 days before `to` when you leave it out. When `include_trend=true` and `trend_grain=hourly`, that default tightens to 29 days before `to` instead, so the defaulted window still fits inside the 720-hour trend cap.
	From time.Time
	// End date (inclusive) in YYYY-MM-DD, interpreted as a calendar day in `timezone` (a UTC day when `timezone` is omitted). Defaults to today in that timezone when omitted. Window may not exceed 365 days.
	To time.Time
	// IANA timezone identifier (for example `Asia/Kathmandu`) to report in; defaults to UTC. Day and hour boundaries and the default window when `from` and `to` are omitted both follow it, so a calendar-day `from` or `to` names a local day. A `from` or `to` carrying its own UTC offset is rejected while this is set: pass a calendar day or a `Z` instant.
	Timezone string
	// Not supported on breakdown endpoints. Supplying it returns 422. To compare categories, use `GET /v1/email/stats/categories`. The summary, daily, and hourly statistics accept `category` as a filter.
	Category string
	// Metric to rank rows by, applied descending. Any count or rate in the response can be used. A row whose rate is undefined because its denominator is zero sorts last. It defaults to `processed`.
	Sort EmailStatsSortMetric
	// Maximum number of domain rows to return, ranked by the `sort` field descending.
	Limit int
	// When true, each row also gets a `trend` array: a short per-bucket series showing that domain's delivery and engagement rates over the window. This only works when `limit` is 50 or fewer and the window is at most 90 days for `trend_grain=daily` or 720 hours for `trend_grain=hourly`. Ask for more and you get a 422. When you leave `from` out and use `trend_grain=hourly`, the default window tightens to 29 days before `to` (720 hours total), so a request built entirely from defaults always fits inside the cap.
	IncludeTrend bool
	// Bucket grain for the `trend` series. Has no effect unless `include_trend=true`.
	TrendGrain StatsTrendGrain
}

EmailStatsBySendingDomainParams filters the by_sending_domain read.

type EmailStatsBySendingDomainResponse added in v0.10.0

type EmailStatsBySendingDomainResponse = oapi.EmailStatsBySendingDomainResponse

Email statistics responses, returned by the Client.Email.Stats methods. Each is the read-side body for one breakdown.

type EmailStatsBySendingIPParams added in v0.13.0

type EmailStatsBySendingIPParams struct {
	// Start date (inclusive) in YYYY-MM-DD, interpreted as a calendar day in `timezone` (a UTC day when `timezone` is omitted). It defaults to 30 days before `to` when you leave it out. When `include_trend=true` and `trend_grain=hourly`, that default tightens to 29 days before `to` instead, so the defaulted window still fits inside the 720-hour trend cap.
	From time.Time
	// End date (inclusive) in YYYY-MM-DD, interpreted as a calendar day in `timezone` (a UTC day when `timezone` is omitted). Defaults to today in that timezone when omitted. Window may not exceed 365 days.
	To time.Time
	// IANA timezone identifier (for example `Asia/Kathmandu`) to report in; defaults to UTC. Day and hour boundaries and the default window when `from` and `to` are omitted both follow it, so a calendar-day `from` or `to` names a local day. A `from` or `to` carrying its own UTC offset is rejected while this is set: pass a calendar day or a `Z` instant.
	Timezone string
	// Not supported on breakdown endpoints. Supplying it returns 422. To compare categories, use `GET /v1/email/stats/categories`. The summary, daily, and hourly statistics accept `category` as a filter.
	Category string
	// Metric to rank IPs by, applied descending. Sorting by `bounces.block` puts the IPs whose reputation is most likely degraded at the top. A row whose rate is undefined because its denominator is zero sorts last. It defaults to `delivered`. A sending IP has no engagement, so engagement metrics aren't sortable here, and neither are `processed`, `rejected`, or `oob_bounces`.
	Sort string
	// Maximum number of IP rows to return, ranked by the `sort` field descending.
	Limit int
	// When true, each row also gets a `trend` array: a short per-bucket series showing that IP's delivery rates over the window. A trend point's open and click rates read `0` in a bucket that had deliveries and `null` in one that had none, because a sending IP has no engagement data. This only works when `limit` is 50 or fewer and the window is at most 90 days for `trend_grain=daily` or 720 hours for `trend_grain=hourly`. Ask for more and you get a 422. When you leave `from` out and use `trend_grain=hourly`, the default window tightens to 29 days before `to` (720 hours total), so a request built entirely from defaults always fits inside the cap.
	IncludeTrend bool
	// Bucket grain for the `trend` series. Has no effect unless `include_trend=true`.
	TrendGrain StatsTrendGrain
}

EmailStatsBySendingIPParams filters the by_sending_ip read.

type EmailStatsBySendingIPResponse added in v0.13.0

type EmailStatsBySendingIPResponse = oapi.EmailStatsBySendingIpResponse

Email statistics responses, returned by the Client.Email.Stats methods. Each is the read-side body for one breakdown.

type EmailStatsByTagParams added in v0.10.0

type EmailStatsByTagParams struct {
	// Start date (inclusive) in YYYY-MM-DD, interpreted as a calendar day in `timezone` (a UTC day when `timezone` is omitted). It defaults to 30 days before `to` when you leave it out. When `include_trend=true` and `trend_grain=hourly`, that default tightens to 29 days before `to` instead, so the defaulted window still fits inside the 720-hour trend cap.
	From time.Time
	// End date (inclusive) in YYYY-MM-DD, interpreted as a calendar day in `timezone` (a UTC day when `timezone` is omitted). Defaults to today in that timezone when omitted. Window may not exceed 365 days.
	To time.Time
	// IANA timezone identifier (for example `Asia/Kathmandu`) to report in; defaults to UTC. Day and hour boundaries and the default window when `from` and `to` are omitted both follow it, so a calendar-day `from` or `to` names a local day. A `from` or `to` carrying its own UTC offset is rejected while this is set: pass a calendar day or a `Z` instant.
	Timezone string
	// Not supported on breakdown endpoints. Supplying it returns 422. To compare categories, use `GET /v1/email/stats/categories`. The summary, daily, and hourly statistics accept `category` as a filter.
	Category string
	// Metric to rank rows by, applied descending. Any count or rate in the response can be used. A row whose rate is undefined because its denominator is zero sorts last. It defaults to `processed`.
	Sort EmailStatsSortMetric
	// Maximum number of tag rows to return, ranked by the `sort` field descending.
	Limit int
	// When true, each row also gets a `trend` array: a short per-bucket series showing that tag's delivery and engagement rates over the window. This only works when `limit` is 50 or fewer and the window is at most 90 days for `trend_grain=daily` or 720 hours for `trend_grain=hourly`. Ask for more and you get a 422. When you leave `from` out and use `trend_grain=hourly`, the default window tightens to 29 days before `to` (720 hours total), so a request built entirely from defaults always fits inside the cap.
	IncludeTrend bool
	// Bucket grain for the `trend` series. Has no effect unless `include_trend=true`.
	TrendGrain StatsTrendGrain
}

EmailStatsByTagParams filters the by_tag read.

type EmailStatsByTemplateParams added in v0.10.0

type EmailStatsByTemplateParams struct {
	// Start date (inclusive) in YYYY-MM-DD, interpreted as a calendar day in `timezone` (a UTC day when `timezone` is omitted). Defaults to 30 days before `to` when omitted; with `include_trend=true` and `trend_grain=hourly` the default tightens to 29 days before `to`, keeping the defaulted window within the 720-hour trend cap.
	From time.Time
	// End date (inclusive) in YYYY-MM-DD, interpreted as a calendar day in `timezone` (a UTC day when `timezone` is omitted). Defaults to today in that timezone when omitted. Window may not exceed 365 days.
	To time.Time
	// IANA timezone identifier (for example `Asia/Kathmandu`) to report in; defaults to UTC. Day and hour boundaries and the default window when `from` and `to` are omitted both follow it, so a calendar-day `from` or `to` names a local day. A `from` or `to` carrying its own UTC offset is rejected while this is set: pass a calendar day or a `Z` instant.
	Timezone string
	// Not supported on breakdown endpoints; supplying it returns 422. To compare categories use `GET /v1/email/stats/categories`; the summary, daily, and hourly statistics accept `category` as a filter.
	Category string
	// Metric to rank rows by, applied descending. Any count or rate in the response may be used; rows whose rate is undefined (zero denominator) sort last. Defaults to `processed`.
	Sort EmailStatsSortMetric
	// Maximum number of template rows to return, ranked by the `sort` field descending.
	Limit int
	// When true, each row also has a `trend` array: a short per-bucket series of that template's delivery and engagement rates over the window. Returned only when `limit` is 50 or fewer and the window is at most 90 days (trend_grain=daily) or 720 hours (trend_grain=hourly); a larger request returns 422. When `from` is omitted and `trend_grain=hourly`, the default start tightens to 29 days before `to`, keeping the window inside 720 hours, so a request built entirely from defaults always fits the cap.
	IncludeTrend bool
	// Bucket grain for the `trend` series. Has no effect unless `include_trend=true`.
	TrendGrain StatsTrendGrain
}

EmailStatsByTemplateParams filters the by_template read.

type EmailStatsByTemplateResponse added in v0.10.0

type EmailStatsByTemplateResponse = oapi.EmailStatsByTemplateResponse

Email statistics responses, returned by the Client.Email.Stats methods. Each is the read-side body for one breakdown.

type EmailStatsDailyParams added in v0.10.0

type EmailStatsDailyParams struct {
	// Start date (inclusive), YYYY-MM-DD. Interpreted as a calendar day in `timezone` (a UTC day when `timezone` is omitted). Defaults to 30 days before `to` when omitted.
	From time.Time
	// End date (inclusive), YYYY-MM-DD. Interpreted as a calendar day in `timezone` (a UTC day when `timezone` is omitted). Defaults to today in that timezone when omitted. Window may not exceed 365 days.
	To time.Time
	// IANA timezone identifier (for example `Asia/Kathmandu`) to report in; defaults to UTC. Day and hour boundaries and the default window when `from` and `to` are omitted both follow it, so a calendar-day `from` or `to` names a local day. A `from` or `to` carrying its own UTC offset is rejected while this is set: pass a calendar day or a `Z` instant.
	Timezone string
	// Restrict the statistics to a single category: `transactional` or `marketing`. Mutually exclusive with the other dimension filters; only one may be set per request.
	Category string
	// Restrict the statistics to a single sending domain (the part of the From address after @). Mutually exclusive with the other dimension filters; only one may be set per request.
	SendingDomain string
	// Restrict the statistics to a single tag. Use `name` to match any value of a tag, or `name:value` for a specific pair (for example `campaign:spring_launch`). Mutually exclusive with the other dimension filters; only one may be set per request.
	Tag string
	// Restrict the statistics to a single sending IP. Mutually exclusive with the other dimension filters; only one may be set per request. A sending IP is only assigned once a message reaches delivery, so an IP-filtered result reports delivery-side metrics only: accepted, processed, rejected, complaint, and engagement counts are 0 and the processing latency is null; complaint, open, and click rates read 0 when there were deliveries and null when there were none.
	SendingIP string
	// Restrict the statistics to a single recipient mailbox domain (the part of the recipient address after the `@`, for example `gmail.com`). Mutually exclusive with the other dimension filters; only one may be set per request.
	RecipientDomain string
	// Restrict the statistics to a single template, by its ID (`emt_…`) or its name. Mutually exclusive with the other dimension filters; only one may be set per request.
	Template string
}

EmailStatsDailyParams filters the daily read.

type EmailStatsHourlyParams added in v0.10.0

type EmailStatsHourlyParams struct {
	// Start of the window (ISO 8601 instant). Rounded down to the start of its hour (the local hour when `timezone` is set, otherwise the UTC hour), and that hour is included. When `timezone` is set, a numeric UTC offset here (for example `+05:45`) is rejected; use a `Z` (UTC) instant. Defaults to 7 days before `to` when omitted.
	From time.Time
	// End of the window (ISO 8601 instant). Rounded down to the start of its hour (the local hour when `timezone` is set, otherwise the UTC hour), and that hour is included (both bounds inclusive). When `timezone` is set, a numeric UTC offset here is rejected; use a `Z` (UTC) instant. Defaults to the current hour when omitted. Window may not exceed 30 days (720 hours).
	To time.Time
	// IANA timezone identifier (for example `Asia/Kathmandu`) to report in; defaults to UTC. Day and hour boundaries and the default window when `from` and `to` are omitted both follow it, so a calendar-day `from` or `to` names a local day. A `from` or `to` carrying its own UTC offset is rejected while this is set: pass a calendar day or a `Z` instant.
	Timezone string
	// Restrict the statistics to a single category: `transactional` or `marketing`. Mutually exclusive with the other dimension filters; only one may be set per request.
	Category string
	// Restrict the statistics to a single sending domain (the part of the From address after @). Mutually exclusive with the other dimension filters; only one may be set per request.
	SendingDomain string
	// Restrict the statistics to a single tag. Use `name` to match any value of a tag, or `name:value` for a specific pair (for example `campaign:spring_launch`). Mutually exclusive with the other dimension filters; only one may be set per request.
	Tag string
	// Restrict the statistics to a single sending IP. Mutually exclusive with the other dimension filters; only one may be set per request. A sending IP is only assigned once a message reaches delivery, so an IP-filtered result reports delivery-side metrics only: accepted, processed, rejected, complaint, and engagement counts are 0 and the processing latency is null; complaint, open, and click rates read 0 when there were deliveries and null when there were none.
	SendingIP string
	// Restrict the statistics to a single recipient mailbox domain (the part of the recipient address after the `@`, for example `gmail.com`). Mutually exclusive with the other dimension filters; only one may be set per request.
	RecipientDomain string
	// Restrict the statistics to a single template, by its ID (`emt_…`) or its name. Mutually exclusive with the other dimension filters; only one may be set per request.
	Template string
}

EmailStatsHourlyParams filters the hourly read.

type EmailStatsResponse added in v0.10.0

type EmailStatsResponse = oapi.EmailStatsResponse

EmailStatsResponse is a time series of per-bucket points. Returned by Stats.Daily and Stats.Hourly.

type EmailStatsService added in v0.10.0

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

EmailStatsService reads aggregated email statistics. Reach it via Client.Email.Stats. Every method is a read; each takes a params struct whose fields are all optional (zero values are omitted, and the server applies its own defaults for the window, sort, and limit).

func (*EmailStatsService) ByBounceCode added in v0.10.0

ByBounceCode Bounce counts grouped by the SMTP error code the receiving mail server returned. Each row also breaks the bounce down into its hard, soft, admin, block, and undetermined split. There are no delivered, open, or click counts here, because a bounce code only appears on a bounce event. For bounces broken down by destination instead, use `email.stats.by_recipient_domain` or `email.stats.by_mailbox_provider`.

Example

ByBounceCode ranks bounce counts per SMTP error code.

package main

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

	bird "github.com/messagebird/bird-sdk-go"
	"github.com/messagebird/bird-sdk-go/option"
)

func main() {
	client, err := bird.NewClient(option.WithAPIKey(os.Getenv("BIRD_API_KEY")))
	if err != nil {
		log.Fatal(err)
	}
	stats, err := client.Email.Stats.ByBounceCode(context.Background(), bird.EmailStatsByBounceCodeParams{})
	if err != nil {
		log.Fatal(err)
	}
	fmt.Println(stats.Data)
}

func (*EmailStatsService) ByBroadcast added in v0.10.0

ByBroadcast Email delivery and engagement stats grouped by broadcast. Only broadcast sends appear. Reflects roughly the last 30 days of activity.

Example

ByBroadcast ranks statistics per broadcast.

package main

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

	bird "github.com/messagebird/bird-sdk-go"
	"github.com/messagebird/bird-sdk-go/option"
)

func main() {
	client, err := bird.NewClient(option.WithAPIKey(os.Getenv("BIRD_API_KEY")))
	if err != nil {
		log.Fatal(err)
	}
	stats, err := client.Email.Stats.ByBroadcast(context.Background(), bird.EmailStatsByBroadcastParams{
		Limit: 25,
	})
	if err != nil {
		log.Fatal(err)
	}
	fmt.Println(stats.Data)
}

func (*EmailStatsService) ByCategory added in v0.10.0

ByCategory Email delivery and engagement stats grouped by category, meaning `transactional` compared with `marketing`. Rows are ranked by `sort`, `processed` by default. Set `include_trend=true` to add a per-bucket rate series to each row.

Example

ByCategory ranks statistics per category.

package main

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

	bird "github.com/messagebird/bird-sdk-go"
	"github.com/messagebird/bird-sdk-go/option"
)

func main() {
	client, err := bird.NewClient(option.WithAPIKey(os.Getenv("BIRD_API_KEY")))
	if err != nil {
		log.Fatal(err)
	}
	stats, err := client.Email.Stats.ByCategory(context.Background(), bird.EmailStatsByCategoryParams{})
	if err != nil {
		log.Fatal(err)
	}
	fmt.Println(stats.Data)
}

func (*EmailStatsService) ByClient added in v0.10.0

ByClient Opens and clicks grouped by mail client, operating system, or device type, whichever you choose with `group_by`. It only has engagement counts, no delivery counts or rates. For engagement grouped by geography instead, use `email.stats.by_location`.

Example

ByClient ranks engagement statistics per reading environment.

package main

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

	bird "github.com/messagebird/bird-sdk-go"
	"github.com/messagebird/bird-sdk-go/option"
)

func main() {
	client, err := bird.NewClient(option.WithAPIKey(os.Getenv("BIRD_API_KEY")))
	if err != nil {
		log.Fatal(err)
	}
	stats, err := client.Email.Stats.ByClient(context.Background(), bird.EmailStatsByClientParams{
		GroupBy: "email_client",
	})
	if err != nil {
		log.Fatal(err)
	}
	fmt.Println(stats.Data)
}

func (*EmailStatsService) ByComplaintType added in v0.10.0

ByComplaintType Spam-complaint counts grouped by the feedback-loop complaint type, for example `abuse`, `fraud`, or `virus`. Complaint side only, so there are no delivery or engagement counts. For complaints broken down by destination instead, use `email.stats.by_mailbox_provider` or `email.stats.by_recipient_domain`.

Example

ByComplaintType ranks complaint counts per complaint type.

package main

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

	bird "github.com/messagebird/bird-sdk-go"
	"github.com/messagebird/bird-sdk-go/option"
)

func main() {
	client, err := bird.NewClient(option.WithAPIKey(os.Getenv("BIRD_API_KEY")))
	if err != nil {
		log.Fatal(err)
	}
	stats, err := client.Email.Stats.ByComplaintType(context.Background(), bird.EmailStatsByComplaintTypeParams{})
	if err != nil {
		log.Fatal(err)
	}
	fmt.Println(stats.Data)
}

func (*EmailStatsService) ByLocation added in v0.10.0

ByLocation Opens and clicks grouped by country, region, or city, whichever you choose with `group_by`. It only has engagement counts, no delivery counts or rates. For engagement grouped by mail client or device instead, use `email.stats.by_client`.

Example

ByLocation ranks engagement statistics per geographic location.

package main

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

	bird "github.com/messagebird/bird-sdk-go"
	"github.com/messagebird/bird-sdk-go/option"
)

func main() {
	client, err := bird.NewClient(option.WithAPIKey(os.Getenv("BIRD_API_KEY")))
	if err != nil {
		log.Fatal(err)
	}
	stats, err := client.Email.Stats.ByLocation(context.Background(), bird.EmailStatsByLocationParams{
		GroupBy: "country",
	})
	if err != nil {
		log.Fatal(err)
	}
	fmt.Println(stats.Data)
}

func (*EmailStatsService) ByMailboxProvider added in v0.10.0

ByMailboxProvider Email delivery and engagement stats grouped by recipient mailbox provider, for example `gmail`, `microsoft`, or `yahoo`. It covers the delivery stage onward, so there are no accepted or processed counts. For a per-region split within a provider, use `email.stats.by_mailbox_provider_region`; for exact destination domains instead, use `email.stats.by_recipient_domain`.

Example

ByMailboxProvider ranks post-delivery statistics per mailbox provider.

package main

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

	bird "github.com/messagebird/bird-sdk-go"
	"github.com/messagebird/bird-sdk-go/option"
)

func main() {
	client, err := bird.NewClient(option.WithAPIKey(os.Getenv("BIRD_API_KEY")))
	if err != nil {
		log.Fatal(err)
	}
	stats, err := client.Email.Stats.ByMailboxProvider(context.Background(), bird.EmailStatsByMailboxProviderParams{})
	if err != nil {
		log.Fatal(err)
	}
	fmt.Println(stats.Data)
}

func (*EmailStatsService) ByMailboxProviderRegion added in v0.10.0

ByMailboxProviderRegion Email delivery and engagement stats grouped by a mailbox provider and provider region pair, for example `gmail` in `NA`. It covers the delivery stage onward, so there are no accepted or processed counts. For the provider-level view without the region split, use `email.stats.by_mailbox_provider`.

Example

ByMailboxProviderRegion ranks post-delivery statistics per provider region.

package main

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

	bird "github.com/messagebird/bird-sdk-go"
	"github.com/messagebird/bird-sdk-go/option"
)

func main() {
	client, err := bird.NewClient(option.WithAPIKey(os.Getenv("BIRD_API_KEY")))
	if err != nil {
		log.Fatal(err)
	}
	stats, err := client.Email.Stats.ByMailboxProviderRegion(context.Background(), bird.EmailStatsByMailboxProviderRegionParams{})
	if err != nil {
		log.Fatal(err)
	}
	fmt.Println(stats.Data)
}

func (*EmailStatsService) ByRecipientDomain added in v0.10.0

ByRecipientDomain Email delivery and engagement stats grouped by exact recipient mailbox domain, for example `gmail.com`. Finer-grained than `email.stats.by_mailbox_provider`, which buckets domains into providers.

Example

ByRecipientDomain ranks statistics per recipient mailbox domain.

package main

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

	bird "github.com/messagebird/bird-sdk-go"
	"github.com/messagebird/bird-sdk-go/option"
)

func main() {
	client, err := bird.NewClient(option.WithAPIKey(os.Getenv("BIRD_API_KEY")))
	if err != nil {
		log.Fatal(err)
	}
	stats, err := client.Email.Stats.ByRecipientDomain(context.Background(), bird.EmailStatsByRecipientDomainParams{
		Limit: 20,
	})
	if err != nil {
		log.Fatal(err)
	}
	fmt.Println(stats.Data)
}

func (*EmailStatsService) BySendingDomain added in v0.10.0

BySendingDomain Email delivery and engagement stats grouped by sending (`From`) domain, so you can compare deliverability across your workspace's verified domains. For per-IP reputation instead, use `email.stats.by_sending_ip`.

Example

BySendingDomain ranks statistics per sending domain.

package main

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

	bird "github.com/messagebird/bird-sdk-go"
	"github.com/messagebird/bird-sdk-go/option"
)

func main() {
	client, err := bird.NewClient(option.WithAPIKey(os.Getenv("BIRD_API_KEY")))
	if err != nil {
		log.Fatal(err)
	}
	stats, err := client.Email.Stats.BySendingDomain(context.Background(), bird.EmailStatsBySendingDomainParams{})
	if err != nil {
		log.Fatal(err)
	}
	fmt.Println(stats.Data)
}

func (*EmailStatsService) BySendingIP added in v0.13.0

BySendingIP Delivery and bounce stats grouped by sending IP, with deferral counts alongside them. `sort=bounces.block` surfaces reputation-damaged IPs first. Engagement, accepted, and processed counts aren't available per IP, and complaint and out-of-band bounce counts always read 0 here. For workspace-wide figures, use `email.stats.daily`.

Example

BySendingIP ranks delivery statistics per sending IP.

package main

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

	bird "github.com/messagebird/bird-sdk-go"
	"github.com/messagebird/bird-sdk-go/option"
)

func main() {
	client, err := bird.NewClient(option.WithAPIKey(os.Getenv("BIRD_API_KEY")))
	if err != nil {
		log.Fatal(err)
	}
	stats, err := client.Email.Stats.BySendingIP(context.Background(), bird.EmailStatsBySendingIPParams{
		Sort: "bounced",
	})
	if err != nil {
		log.Fatal(err)
	}
	fmt.Println(stats.Data)
}

func (*EmailStatsService) ByTag added in v0.10.0

ByTag Email delivery and engagement stats grouped by tag, one row per `name:value` pair set at send time. Rows are ranked by `sort`, `processed` by default. Set `include_trend=true` to add a per-bucket rate series to each row.

Example

ByTag ranks statistics per tag.

package main

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

	bird "github.com/messagebird/bird-sdk-go"
	"github.com/messagebird/bird-sdk-go/option"
)

func main() {
	client, err := bird.NewClient(option.WithAPIKey(os.Getenv("BIRD_API_KEY")))
	if err != nil {
		log.Fatal(err)
	}
	stats, err := client.Email.Stats.ByTag(context.Background(), bird.EmailStatsByTagParams{
		Sort:  "opens",
		Limit: 10,
	})
	if err != nil {
		log.Fatal(err)
	}
	fmt.Println(stats.Data)
}

func (*EmailStatsService) ByTemplate added in v0.10.0

ByTemplate Email delivery and engagement stats grouped by the template used at send time, keyed by template id (`emt_…`); only templated sends appear. A single template's trend over time comes from `email.stats.daily` with its `template` filter.

Example

ByTemplate ranks statistics per template.

package main

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

	bird "github.com/messagebird/bird-sdk-go"
	"github.com/messagebird/bird-sdk-go/option"
)

func main() {
	client, err := bird.NewClient(option.WithAPIKey(os.Getenv("BIRD_API_KEY")))
	if err != nil {
		log.Fatal(err)
	}
	stats, err := client.Email.Stats.ByTemplate(context.Background(), bird.EmailStatsByTemplateParams{})
	if err != nil {
		log.Fatal(err)
	}
	fmt.Println(stats.Data)
}

func (*EmailStatsService) Daily added in v0.10.0

Daily Per-day email stats series (counts, rates, latency percentiles), gap-filled with zero rows, max 365 days. At most one filter of `category`, `sending_domain`, `tag`, `sending_ip`, `recipient_domain`, `template`. For hour resolution use `email.stats.hourly`; for one aggregate row use `email.stats.summary`.

Example

Daily returns one row per calendar day in the window.

package main

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

	bird "github.com/messagebird/bird-sdk-go"
	"github.com/messagebird/bird-sdk-go/option"
)

func main() {
	client, err := bird.NewClient(option.WithAPIKey(os.Getenv("BIRD_API_KEY")))
	if err != nil {
		log.Fatal(err)
	}
	series, err := client.Email.Stats.Daily(context.Background(), bird.EmailStatsDailyParams{
		From: time.Now().AddDate(0, 0, -7),
		To:   time.Now(),
	})
	if err != nil {
		log.Fatal(err)
	}
	fmt.Println(series.Data)
}

func (*EmailStatsService) Hourly added in v0.10.0

Hourly Per-hour email stats series, gap-filled with zero rows, max 720 hours (30 days). Takes the same single-dimension filters as `email.stats.daily`; for longer ranges use `email.stats.daily`, for one aggregate row use `email.stats.summary`.

Example

Hourly returns one row per hour in the window (max 720 hours).

package main

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

	bird "github.com/messagebird/bird-sdk-go"
	"github.com/messagebird/bird-sdk-go/option"
)

func main() {
	client, err := bird.NewClient(option.WithAPIKey(os.Getenv("BIRD_API_KEY")))
	if err != nil {
		log.Fatal(err)
	}
	series, err := client.Email.Stats.Hourly(context.Background(), bird.EmailStatsHourlyParams{
		From: time.Now().Add(-24 * time.Hour),
		To:   time.Now(),
	})
	if err != nil {
		log.Fatal(err)
	}
	fmt.Println(series.Data)
}

func (*EmailStatsService) Summary added in v0.10.0

Summary Aggregate email KPIs for one period: sends, delivered, bounces, complaints, opens, clicks, their rates, and latency percentiles. `from`/`to` are both YYYY-MM-DD days or both RFC 3339 instants (hour grain); add `compare=previous_period` for deltas versus the prior window. For a per-day or per-hour series use `email.stats.daily` or `email.stats.hourly`.

Example

Summary returns the delivery, engagement, and latency totals for a window.

package main

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

	bird "github.com/messagebird/bird-sdk-go"
	"github.com/messagebird/bird-sdk-go/option"
)

func main() {
	client, err := bird.NewClient(option.WithAPIKey(os.Getenv("BIRD_API_KEY")))
	if err != nil {
		log.Fatal(err)
	}
	summary, err := client.Email.Stats.Summary(context.Background(), bird.EmailStatsSummaryParams{
		From: "2026-05-01", // a calendar day for a day-grain window (up to 365 days), or
		To:   "2026-05-31", // an RFC 3339 instant (e.g. "2026-05-01T00:00:00Z") for hour-grain (up to 720 hours)
	})
	if err != nil {
		log.Fatal(err)
	}
	fmt.Println(summary.SendsAccepted)
}

type EmailStatsSortMetric added in v0.16.0

type EmailStatsSortMetric = oapi.EmailStatsSortMetric

EmailStatsSortMetric is the metric an email-stats breakdown sorts by.

type EmailStatsSummary added in v0.10.0

type EmailStatsSummary = oapi.EmailStatsSummary

EmailStatsSummary is the delivery/engagement/latency totals for a window, optionally with a previous-period comparison. Returned by Stats.Summary.

type EmailStatsSummaryParams added in v0.10.0

type EmailStatsSummaryParams struct {
	// Inclusive start of the window: a calendar day (YYYY-MM-DD) or an RFC 3339 instant (rounded down to the hour). Interpreted in `timezone` (a calendar day names a local day; an instant is rounded down to the local hour), or in UTC when `timezone` is omitted. A numeric UTC offset (for example `+05:45`) is rejected when `timezone` is set; use a calendar day or a `Z` (UTC) instant. Must use the same form as `to`. Defaults to 30 days before `to` for day windows, or 168 hours (7 days) before `to` for hour windows, when omitted.
	From string
	// Inclusive end of the window: a calendar day (YYYY-MM-DD) or an RFC 3339 instant (rounded down to the hour). Interpreted in `timezone` (a calendar day names a local day; an instant is rounded down to the local hour), or in UTC when `timezone` is omitted. A numeric UTC offset is rejected when `timezone` is set; use a calendar day or a `Z` (UTC) instant. Must use the same form as `from`. Defaults to today for day windows, or the current hour for hour windows, in that timezone, when omitted. Day windows may not exceed 365 days; hour windows may not exceed 720 hours (30 days).
	To string
	// IANA timezone identifier (for example `Asia/Kathmandu`) to report in; defaults to UTC. Day and hour boundaries and the default window when `from` and `to` are omitted both follow it, so a calendar-day `from` or `to` names a local day. A `from` or `to` carrying its own UTC offset is rejected while this is set: pass a calendar day or a `Z` instant.
	Timezone string
	// Restrict the statistics to a single category: `transactional` or `marketing`. Mutually exclusive with the other dimension filters; only one may be set per request.
	Category string
	// Restrict the statistics to a single sending domain (the part of the From address after @). Mutually exclusive with the other dimension filters; only one may be set per request.
	SendingDomain string
	// Restrict the statistics to a single tag. Use `name` to match any value of a tag, or `name:value` for a specific pair (for example `campaign:spring_launch`). Mutually exclusive with the other dimension filters; only one may be set per request.
	Tag string
	// Restrict the statistics to a single sending IP. Mutually exclusive with the other dimension filters; only one may be set per request. A sending IP is only assigned once a message reaches delivery, so an IP-filtered result reports delivery-side metrics only: accepted, processed, rejected, complaint, and engagement counts are 0 and the processing latency is null; complaint, open, and click rates read 0 when there were deliveries and null when there were none.
	SendingIP string
	// Restrict the statistics to a single recipient mailbox domain (the part of the recipient address after the `@`, for example `gmail.com`). Mutually exclusive with the other dimension filters; only one may be set per request.
	RecipientDomain string
	// Restrict the statistics to a single template, by its ID (`emt_…`) or its name. Mutually exclusive with the other dimension filters; only one may be set per request.
	Template string
	// Set to `previous_period` to also include the same statistics for the immediately preceding window of equal length, plus the change between the two, so you can show "+X% vs last period" without a second request.
	Compare string
}

EmailStatsSummaryParams filters the summary read.

type EmailStatsTagsResponse added in v0.10.0

type EmailStatsTagsResponse = oapi.EmailStatsTagsResponse

EmailStatsTagsResponse is the ranked tag breakdown. Returned by Stats.ByTag.

type EmailStatus

type EmailStatus = oapi.EmailMessageStatus

EmailStatus is a message's aggregate delivery status.

const (
	EmailStatusScheduled      EmailStatus = "scheduled"
	EmailStatusAccepted       EmailStatus = "accepted"
	EmailStatusProcessed      EmailStatus = "processed"
	EmailStatusDelivered      EmailStatus = "delivered"
	EmailStatusDeferred       EmailStatus = "deferred"
	EmailStatusBounced        EmailStatus = "bounced"
	EmailStatusComplained     EmailStatus = "complained"
	EmailStatusRejected       EmailStatus = "rejected"
	EmailStatusPartialFailure EmailStatus = "partial_failure"
	EmailStatusCanceled       EmailStatus = "canceled"
)

type EmailSuppressionCreatedEvent

type EmailSuppressionCreatedEvent = oapi.EventEmailSuppressionCreated

Webhook event payloads, returned by Event.AsAny. Type-switch on these.

type EmailTag

type EmailTag = oapi.Tag

EmailTag is a structured {Name, Value} label.

type EmailThread added in v0.12.0

type EmailThread = oapi.EmailThread

EmailThread is a conversation: a group of messages on the same topic.

type EmailThreadList added in v0.12.0

type EmailThreadList = oapi.EmailThreadList

EmailThreadList is one page of threads plus its pagination cursors.

type EmailThreadMessage added in v0.12.0

type EmailThreadMessage = oapi.EmailThreadMessage

EmailThreadMessage is a single message in a conversation.

type EmailThreadMessageAttachmentList added in v0.12.0

type EmailThreadMessageAttachmentList = oapi.EmailThreadMessageAttachmentList

EmailThreadMessageAttachmentList is the attachment manifest.

type EmailThreadMessageBody added in v0.12.0

type EmailThreadMessageBody = oapi.EmailThreadMessageBody

EmailThreadMessageBody is the parsed HTML and plain-text body.

type EmailThreadMessageList added in v0.12.0

type EmailThreadMessageList = oapi.EmailThreadMessageList

EmailThreadMessageList is one page of messages.

type EmailThreadsDeleteParams added in v0.17.0

type EmailThreadsDeleteParams struct {
	// Permanently delete the conversation and its messages immediately instead of moving them to the trash.
	Permanent bool
}

EmailThreadsDeleteParams holds the delete's query filters.

type EmailThreadsListParams added in v0.17.0

type EmailThreadsListParams struct {
	// Filter to conversations in a specific mailbox.
	MailboxID string
	// Filter to conversations linked to a specific contact.
	ContactID string
	// Filter to conversations that have this label. Repeat the parameter to ask for more than one: only conversations that have every label you list are returned. A placement label picks a folder: `inbox`, `archive`, `spam`, or `blocked`. A custom label matches a conversation in any folder. Leave this out and you get the inbox.
	Label []string
	// When `true`, only conversations with unread messages are returned. This filters on the conversation's unread state, so you can combine it with `label`, for example to get unread conversations in the archive. The `unread` label itself lives on messages, not conversations.
	HasUnread bool
	// Conversations involving this address, matching the sender or any recipient. The match is case-insensitive and matches on any part of the address, so a fragment works as well as the whole address.
	Participant string
	// Conversations whose subject contains this text (case-insensitive).
	Subject string
	// Filter to conversations whose most recent message is at or after this time. This is a time filter, not a cursor.
	After time.Time
	// Filter to conversations whose most recent message is at or before this time. This is a time filter, not a cursor.
	Before time.Time
	// Maximum number of items to return per page.
	Limit int
}

EmailThreadsListParams filters the list. Zero-value fields are omitted.

type EmailThreadsMessagesListParams added in v0.17.0

type EmailThreadsMessagesListParams struct {
	// Filter to received (`inbound`) or sent (`outbound`) messages.
	Direction MessageDirection
	// Filter to messages that have this label. `trash` lists trashed messages. Any other label, whether that is `archive`, `spam`, `blocked`, `unread` or one of your own, lists the messages that have it and are not in the trash. When omitted, received messages in the inbox and all sent messages are returned.
	Label string
	// Set to `extracted_text` to inline each message's extracted plain text.
	Include string
	// Maximum number of items to return per page.
	Limit int
}

EmailThreadsMessagesListParams filters the list. Zero-value fields are omitted.

type EmailThreadsMessagesReplyParams added in v0.17.0

type EmailThreadsMessagesReplyParams struct {
	// HTML body of the reply. At least one of html or text must be provided.
	HTML string
	// Plain-text body of the reply. At least one of html or text must be provided.
	Text string
	// Also send the reply to the original To and Cc recipients, minus the mailbox's own address.
	ReplyAll *bool
	// Structured `{name, value}` labels for filtering and analytics on the sent-message log. Cap: 20 tags per send.
	Tags []Tag
	// Arbitrary JSON object stored on the send and echoed in webhook payloads. Cap: 2 KB serialized.
	Metadata map[string]any
	// Content classification, which controls suppression policy: - `marketing`: Blocks on all suppression reasons. - `transactional`: Allows delivery through complaint and unsubscribe suppressions, for receipts, password resets, and similar operational mail.
	Category *EmailMessageCategory
	// File attachments to include with the reply. The send is rejected when the estimated generated message size exceeds 20 MB (bodies plus all attachments after base64 encoding). Keep total raw attachment content at or below 15 MB for reliable headroom. Attachment metadata stays on the message's `attachment_manifest`, and the bytes are downloadable for 30 days.
	Attachments []EmailAttachment
}

EmailThreadsMessagesReplyParams is the request body for reply.

type EmailThreadsMessagesService added in v0.17.0

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

EmailThreadsMessagesService reads messages in a conversation thread and sends replies. Reach it via Client.Email.Threads.Messages.

func (*EmailThreadsMessagesService) Attachments added in v0.17.0

Attachments List the attachments on a conversation message. Bytes are downloadable for 30 days, and the metadata stays readable afterward on the message's attachment_manifest.

Example
package main

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

	bird "github.com/messagebird/bird-sdk-go"
	"github.com/messagebird/bird-sdk-go/option"
)

func main() {
	client, err := bird.NewClient(option.WithAPIKey(os.Getenv("BIRD_API_KEY")))
	if err != nil {
		log.Fatal(err)
	}
	result, err := client.Email.Threads.Messages.Attachments(context.Background(), "thr_123", "rem_456")
	if err != nil {
		log.Fatal(err)
	}
	for _, a := range result.Data {
		fmt.Println(a.Filename, a.Size)
	}
}

func (*EmailThreadsMessagesService) Body added in v0.17.0

Body Get the original rendered HTML and plain-text body of a conversation message. Available for 30 days. After that, use the message's extracted_text.

Example
package main

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

	bird "github.com/messagebird/bird-sdk-go"
	"github.com/messagebird/bird-sdk-go/option"
)

func main() {
	client, err := bird.NewClient(option.WithAPIKey(os.Getenv("BIRD_API_KEY")))
	if err != nil {
		log.Fatal(err)
	}
	body, err := client.Email.Threads.Messages.Body(context.Background(), "thr_123", "rem_456")
	if err != nil {
		log.Fatal(err)
	}
	fmt.Println(body.Text)
}

func (*EmailThreadsMessagesService) Get added in v0.17.0

Get Get one conversation message with its extracted plain text, readable for the mailbox's full retention tier without MIME parsing.

Example
package main

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

	bird "github.com/messagebird/bird-sdk-go"
	"github.com/messagebird/bird-sdk-go/option"
)

func main() {
	client, err := bird.NewClient(option.WithAPIKey(os.Getenv("BIRD_API_KEY")))
	if err != nil {
		log.Fatal(err)
	}
	msg, err := client.Email.Threads.Messages.Get(context.Background(), "thr_123", "rem_456")
	if err != nil {
		log.Fatal(err)
	}
	fmt.Println(msg.Id, msg.Direction)
}

func (*EmailThreadsMessagesService) List added in v0.17.0

List List the messages in a conversation newest first, both directions. Page older messages with starting_after, and pass include=extracted_text to inline each message's extracted plain text. Range over it; the second value is non-nil only on the iteration where a fetch failed.

Example
package main

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

	bird "github.com/messagebird/bird-sdk-go"
	"github.com/messagebird/bird-sdk-go/option"
)

func main() {
	client, err := bird.NewClient(option.WithAPIKey(os.Getenv("BIRD_API_KEY")))
	if err != nil {
		log.Fatal(err)
	}
	for msg, err := range client.Email.Threads.Messages.List(context.Background(), "thr_123", bird.EmailThreadsMessagesListParams{}) {
		if err != nil {
			log.Fatal(err)
		}
		fmt.Println(msg.Id, msg.Direction)
	}
}

func (*EmailThreadsMessagesService) ListPage added in v0.17.0

ListPage fetches one page of results. Pass the previous page's NextCursor as startingAfter to advance; "" starts from the first page.

func (*EmailThreadsMessagesService) Reply added in v0.17.0

Reply Reply to a specific conversation message from the mailbox's own address. To reply to a conversation, target its newest received message. Recipients, subject, and threading headers are derived automatically.

Example
package main

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

	bird "github.com/messagebird/bird-sdk-go"
	"github.com/messagebird/bird-sdk-go/option"
)

func main() {
	client, err := bird.NewClient(option.WithAPIKey(os.Getenv("BIRD_API_KEY")))
	if err != nil {
		log.Fatal(err)
	}
	reply, err := client.Email.Threads.Messages.Reply(context.Background(), "thr_123", "rem_456", bird.EmailThreadsMessagesReplyParams{
		Text: "Thanks for reaching out!",
	})
	if err != nil {
		log.Fatal(err)
	}
	fmt.Println(reply.Id)
}

type EmailThreadsService added in v0.17.0

type EmailThreadsService struct {

	// Messages reads and replies to the messages in a conversation.
	Messages *EmailThreadsMessagesService
	// contains filtered or unexported fields
}

EmailThreadsService reads and manages email conversation threads stored in mailboxes. Reach it via Client.Email.Threads.

func (*EmailThreadsService) Delete added in v0.17.0

func (s *EmailThreadsService) Delete(ctx context.Context, threadId string, params EmailThreadsDeleteParams, opts ...option.RequestOption) error

Delete Move a conversation and all its messages to trash (purged after 30 days), or delete permanently with ?permanent=true.

Example
package main

import (
	"context"
	"log"
	"os"

	bird "github.com/messagebird/bird-sdk-go"
	"github.com/messagebird/bird-sdk-go/option"
)

func main() {
	client, err := bird.NewClient(option.WithAPIKey(os.Getenv("BIRD_API_KEY")))
	if err != nil {
		log.Fatal(err)
	}
	if err := client.Email.Threads.Delete(context.Background(), "thr_123", bird.EmailThreadsDeleteParams{Permanent: true}); err != nil {
		log.Fatal(err)
	}
}

func (*EmailThreadsService) Get added in v0.17.0

func (s *EmailThreadsService) Get(ctx context.Context, threadId string, opts ...option.RequestOption) (*EmailThread, error)

Get Get one conversation: participants, counts, labels, read state. Fetch its messages with the thread messages endpoint.

Example
package main

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

	bird "github.com/messagebird/bird-sdk-go"
	"github.com/messagebird/bird-sdk-go/option"
)

func main() {
	client, err := bird.NewClient(option.WithAPIKey(os.Getenv("BIRD_API_KEY")))
	if err != nil {
		log.Fatal(err)
	}
	thread, err := client.Email.Threads.Get(context.Background(), "thr_123")
	if err != nil {
		log.Fatal(err)
	}
	fmt.Println(thread.Id)
}

func (*EmailThreadsService) List added in v0.17.0

List List mailbox conversations as a cursor page, most recently active first. `label` selects the view: inbox (default), archive, spam, blocked, or a custom label. Filter by mailbox, contact, participant address, or subject substring. Range over it; the second value is non-nil only on the iteration where a fetch failed.

Example
package main

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

	bird "github.com/messagebird/bird-sdk-go"
	"github.com/messagebird/bird-sdk-go/option"
)

func main() {
	client, err := bird.NewClient(option.WithAPIKey(os.Getenv("BIRD_API_KEY")))
	if err != nil {
		log.Fatal(err)
	}
	for thread, err := range client.Email.Threads.List(context.Background(), bird.EmailThreadsListParams{}) {
		if err != nil {
			log.Fatal(err)
		}
		fmt.Println(thread.Id)
	}
}

func (*EmailThreadsService) ListPage added in v0.17.0

func (s *EmailThreadsService) ListPage(ctx context.Context, params EmailThreadsListParams, startingAfter string, opts ...option.RequestOption) (*EmailThreadList, error)

ListPage fetches one page of results. Pass the previous page's NextCursor as startingAfter to advance; "" starts from the first page.

func (*EmailThreadsService) Update added in v0.17.0

Update Add or remove labels on a conversation, or link and unlink a contact. Adding `spam` files it as spam, `archive` clears it out of the inbox, and `inbox` brings it back.

Example
package main

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

	bird "github.com/messagebird/bird-sdk-go"
	"github.com/messagebird/bird-sdk-go/option"
)

func main() {
	client, err := bird.NewClient(option.WithAPIKey(os.Getenv("BIRD_API_KEY")))
	if err != nil {
		log.Fatal(err)
	}
	thread, err := client.Email.Threads.Update(context.Background(), "thr_123", bird.EmailThreadsUpdateParams{
		Labels: &bird.EmailLabelsUpdate{Add: &[]string{"urgent"}},
	})
	if err != nil {
		log.Fatal(err)
	}
	fmt.Println(thread.Id)
}

type EmailThreadsUpdateParams added in v0.17.0

type EmailThreadsUpdateParams struct {
	// Label changes to apply. Labels in `add` are applied and labels in `remove` are taken off; other labels are left untouched. Adding a label that is already present, or removing one that is not, has no effect. System labels express state changes: on a conversation, adding `spam` files it as spam, adding `archive` files it away without deleting it, adding `inbox` (or removing `spam`, `blocked`, or `archive`) returns it to the inbox, and removing `unread` marks all retained received messages as read in one call; on a message, adding or removing `unread` flips read state, and adding or removing `trash` moves it to or out of the trash. Changes that contradict this model are rejected: adding more than one placement label in one request, adding `blocked` (blocking a sender is a receive-rule decision), removing `inbox` without adding a destination, adding `trash` or `unread` to a conversation (removing `unread` is the mark-all-read shortcut; `trash` uses the DELETE verb), placement labels on a message (move its conversation instead), and `unread` on a sent message. Custom labels are 1-64 characters with no commas, control characters, or leading or trailing whitespace. System label names and a small reserved set (`all`, `archived`, `deleted`, `draft`, `drafts`, `flagged`, `important`, `junk`, `muted`, `none`, `outbox`, `pinned`, `read`, `scheduled`, `snoozed`, `starred`) cannot be used as custom labels, in any casing. A conversation or message has at most 20 labels, system labels included.
	Labels *EmailLabelsUpdate
	// Contact to link this conversation to, or null to unlink the current contact.
	ContactID Nullable[string]
}

EmailThreadsUpdateParams is the request body for update.

type EmailUnsubscribedEvent

type EmailUnsubscribedEvent = oapi.EventEmailUnsubscribed

Webhook event payloads, returned by Event.AsAny. Type-switch on these.

type ErrorDetail

type ErrorDetail = apierror.ErrorDetail

The SDK error model, re-exported from internal/apierror so these names are the semver-locked public surface. Catch *APIError (via errors.As) to handle any server error; the variants carry extra data. Transport failures with no HTTP response are *ConnectionError / *TimeoutError; a bad webhook signature is *WebhookVerificationError.

type ErrorType

type ErrorType = apierror.ErrorType

The SDK error model, re-exported from internal/apierror so these names are the semver-locked public surface. Catch *APIError (via errors.As) to handle any server error; the variants carry extra data. Transport failures with no HTTP response are *ConnectionError / *TimeoutError; a bad webhook signature is *WebhookVerificationError.

type Event

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

Event is a verified webhook event. Switch on Type, or call AsAny and type-switch on the concrete payload (e.g. EmailDeliveredEvent).

func (Event) AsAny

func (e Event) AsAny() (any, error)

AsAny decodes the event into its concrete payload type. An unknown future event type returns an error rather than a panic, so an older SDK keeps working against a newer server.

func (Event) Type

func (e Event) Type() WebhookEventType

Type returns the event's discriminant, e.g. EventTypeEmailDelivered.

type LookupEmailParams added in v0.31.0

type LookupEmailParams struct {
	// The email address to look up. Send it exactly as you hold it: the part before the `@` is case-sensitive, so nothing is lowercased for you, and a display-name form such as `Aisha <aisha@example.com>` is rejected rather than unwrapped.
	Email string
}

LookupEmailParams is the request body for email.

type LookupFlag added in v0.31.0

type LookupFlag = oapi.LookupFlag

LookupFlag is an open string on the wire: a value added by a newer server deserializes unchanged, so compare against the LookupFlag* constants with a default branch rather than treating the set as closed.

type LookupPhoneNumberParams added in v0.31.0

type LookupPhoneNumberParams struct {
	// The phone number to look up, in international format: the country calling code, then the national number. The leading `+` is optional, and `00` works in its place, so `+31612345678`, `31612345678` and `0031612345678` are all the same number. A number written for dialling inside one country, with no country code, is rejected rather than guessed at.
	PhoneNumber string
	// The paid properties to enrich the answer with. Omit it, or send an empty array, to get the free baseline and make no vendor call. Each delivered property is billed on top of the lookup itself. A property that could not be answered is reported in `properties` and is not billed.
	Type []LookupProperty
}

LookupPhoneNumberParams is the request body for phone_number.

type LookupProperty added in v0.31.0

type LookupProperty = oapi.LookupProperty

type LookupPropertyStatus added in v0.31.0

type LookupPropertyStatus = oapi.LookupPropertyStatus

LookupPropertyStatus is an open string on the wire: a value added by a newer server deserializes unchanged, so compare against the LookupPropertyStatus* constants with a default branch rather than treating the set as closed.

type LookupService added in v0.31.0

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

LookupService looks up what a phone number is and whether an email address is worth sending to. Reach it via Client.Lookup.

func (*LookupService) Email added in v0.31.0

Email Look up whether an email address is worth sending to. Returns `result` (the verdict: `valid`; `neutral`, meaning it could not be confirmed either way; `risky`, meaning it will probably accept mail but is likelier than most to bounce or complain; `undeliverable`; or `typo`), `delivery_confidence` (0-100), `flags` (`role`, `disposable`, `free_provider`), `reason` on an undeliverable address (`invalid_syntax`, `invalid_domain`, `invalid_recipient`), and `did_you_mean` when the address looks like a misspelling of a real one. `result` and `reason` are OPEN vocabularies: the values listed here are today's and more may be added, so treat an unrecognized value as a future one rather than an error, falling back on `delivery_confidence`. One address per call. Every answered lookup is billed the same flat amount whatever the verdict, so treat it as a paid call rather than a free check, and use an `Idempotency-Key` so a retry does not buy a second answer. Nothing is sent to the address.

Example

Email tells you whether an address is worth sending to before you send.

package main

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

	bird "github.com/messagebird/bird-sdk-go"
	"github.com/messagebird/bird-sdk-go/option"
)

func main() {
	client, err := bird.NewClient(option.WithAPIKey(os.Getenv("BIRD_API_KEY")))
	if err != nil {
		log.Fatal(err)
	}
	answer, err := client.Lookup.Email(context.Background(), bird.LookupEmailParams{
		Email: "aisha.khan@example.com",
	})
	if err != nil {
		log.Fatal(err)
	}
	// result is an open vocabulary; delivery_confidence is always comparable.
	fmt.Println(*answer.Result, *answer.DeliveryConfidence)
}

func (*LookupService) PhoneNumber added in v0.31.0

PhoneNumber Look up what a phone number is. Returns the serving network, the issuing network, whether the number was ported, its country, and its line type, free with every call. Pass `type` to buy extra blocks: `classification` (the allocated service of the range, from an intelligence source, reported beside the free `line_type` rather than replacing it), `porting` (whether the number ever moved network, when, and its full history), `presence` (reachable on the network right now), `roaming`, `sim_swap` (when the SIM last changed), and `score` (0-100 credibility). Every requested block reports its own status, and only the ones reading `ok` are billed on top of the lookup. Nothing is sent to the number.

Example

PhoneNumber returns the free baseline plus whichever paid blocks you ask for.

package main

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

	bird "github.com/messagebird/bird-sdk-go"
	"github.com/messagebird/bird-sdk-go/option"
)

func main() {
	client, err := bird.NewClient(option.WithAPIKey(os.Getenv("BIRD_API_KEY")))
	if err != nil {
		log.Fatal(err)
	}
	answer, err := client.Lookup.PhoneNumber(context.Background(), bird.LookupPhoneNumberParams{
		PhoneNumber: "+31612345678",
		Type:        []bird.LookupProperty{"classification", "score"},
	})
	if err != nil {
		log.Fatal(err)
	}
	fmt.Println(*answer.CountryCode, *answer.LineType)
	// Only a block whose status is ok carries a value, and only that one is billed.
	if answer.Score != nil && *answer.Score.Status == "ok" {
		fmt.Println(*answer.Score.Value)
	}
}

type Mailbox added in v0.12.0

type Mailbox = oapi.Mailbox

Mailbox is a durable inbox on inbox.ai or a custom domain.

type MailboxCreateReceivePolicy added in v0.16.0

type MailboxCreateReceivePolicy = oapi.MailboxCreateReceivePolicy

type MailboxCreateRetentionTier added in v0.16.0

type MailboxCreateRetentionTier = oapi.MailboxCreateRetentionTier

type MailboxList added in v0.12.0

type MailboxList = oapi.MailboxList

MailboxList is one page of mailboxes plus its pagination cursors.

type MailboxStatsResponse added in v0.12.0

type MailboxStatsResponse = oapi.MailboxStatsResponse

MailboxStatsResponse is the stats time series for a mailbox.

type MailboxUpdateReceivePolicy added in v0.16.0

type MailboxUpdateReceivePolicy = oapi.MailboxUpdateReceivePolicy

type MailboxUpdateRetentionTier added in v0.16.0

type MailboxUpdateRetentionTier = oapi.MailboxUpdateRetentionTier

type MessageDirection added in v0.16.0

type MessageDirection = oapi.MessageDirection

MessageDirection is whether a message was sent or received.

type NextAction added in v0.32.0

type NextAction = apierror.NextAction

The SDK error model, re-exported from internal/apierror so these names are the semver-locked public surface. Catch *APIError (via errors.As) to handle any server error; the variants carry extra data. Transport failures with no HTTP response are *ConnectionError / *TimeoutError; a bad webhook signature is *WebhookVerificationError.

type Nullable added in v0.14.0

type Nullable[T any] = nullable.Nullable[T]

Nullable is a nullable/clearable request-param field. It carries one of three states: a value, an explicit JSON null (clears the field), or unspecified (the zero value — omitted, leaving the field unchanged). Only request params use it; response fields stay plain pointers. Build it with Value or Null:

bird.AudienceUpdateParams{Description: bird.Null[string]()}   // clear
bird.AudienceUpdateParams{Description: bird.Value("Q4 leads")} // set

func Null added in v0.14.0

func Null[T any]() Nullable[T]

Null sets a Nullable request field to send an explicit JSON null, clearing it.

func Value added in v0.14.0

func Value[T any](v T) Nullable[T]

Value sets a Nullable request field to send v.

type PhoneNumberLookup added in v0.31.0

type PhoneNumberLookup = oapi.PhoneNumberLookup

PhoneNumberLookup is what we know about a phone number; EmailLookup is the verdict on an email address. Every block a phone lookup carries reports its own status, so a partial answer is visible rather than silent.

type RateLimitError

type RateLimitError = apierror.RateLimitError

The SDK error model, re-exported from internal/apierror so these names are the semver-locked public surface. Catch *APIError (via errors.As) to handle any server error; the variants carry extra data. Transport failures with no HTTP response are *ConnectionError / *TimeoutError; a bad webhook signature is *WebhookVerificationError.

type RealtimeBatchEventParams added in v0.15.0

type RealtimeBatchEventParams struct {
	// The event name clients bind to. Application event names are free-form; the `bird:` and `bird_internal:` prefixes are reserved for the protocol and rejected.
	Event string
	// A Realtime channel name. Only letters, digits, and _ - = @ , . ; Prefix with `private-` or `presence-` for authenticated channels.
	Channel string
	// Arbitrary JSON payload delivered as the event data — an object, array, or scalar. Cap: 10 KB serialized.
	Data any
	// Exclude this connection from delivery, to avoid echoing a change back to the client that triggered it. The value is the client's connection id, assigned when its connection is established.
	ExcludeConnectionID string
	// Attributes of this event's channel to return alongside the publish (same semantics and validation errors as on the channel endpoints). Requesting attributes counts as one additional message toward usage.
	Include []RealtimeChannelInclude
}

RealtimeBatchEventParams is one events item.

type RealtimeBatchPublishResult added in v0.15.0

type RealtimeBatchPublishResult = oapi.RealtimeBatchPublishResult

Realtime read and publish results. RealtimePublishResult and RealtimeBatchPublishResult carry per-channel counts only when the call asked for them via Include. RealtimeChannelsList is the app's occupied channels (unpaginated); RealtimeChannelInfo is one channel's state; RealtimeChannelMembers is the members present on a presence channel.

type RealtimeBatchPublishResultItem added in v0.15.0

type RealtimeBatchPublishResultItem = oapi.RealtimeBatchPublishResultItem

Realtime read and publish results. RealtimePublishResult and RealtimeBatchPublishResult carry per-channel counts only when the call asked for them via Include. RealtimeChannelsList is the app's occupied channels (unpaginated); RealtimeChannelInfo is one channel's state; RealtimeChannelMembers is the members present on a presence channel.

type RealtimeChannelGetParams added in v0.15.0

type RealtimeChannelGetParams struct {
	// Attributes to include. Repeatable. Requesting `member_count` for a non-presence channel, or `connection_count` when the app's connection-counting flag is off, returns a validation error (400).
	Include []RealtimeChannelInclude
}

RealtimeChannelGetParams filters the get read.

type RealtimeChannelInclude added in v0.15.0

type RealtimeChannelInclude = oapi.RealtimeChannelInclude

RealtimeChannelInclude names a per-channel attribute to return alongside a publish or channel read.

const (
	// RealtimeIncludeMemberCount is presence-channels only.
	RealtimeIncludeMemberCount RealtimeChannelInclude = "member_count"
	// RealtimeIncludeConnectionCount requires the app's connection-counting flag.
	RealtimeIncludeConnectionCount RealtimeChannelInclude = "connection_count"
)

type RealtimeChannelInfo added in v0.15.0

type RealtimeChannelInfo = oapi.RealtimeChannelInfo

Realtime read and publish results. RealtimePublishResult and RealtimeBatchPublishResult carry per-channel counts only when the call asked for them via Include. RealtimeChannelsList is the app's occupied channels (unpaginated); RealtimeChannelInfo is one channel's state; RealtimeChannelMembers is the members present on a presence channel.

type RealtimeChannelListItem added in v0.15.0

type RealtimeChannelListItem = oapi.RealtimeChannelListItem

Realtime read and publish results. RealtimePublishResult and RealtimeBatchPublishResult carry per-channel counts only when the call asked for them via Include. RealtimeChannelsList is the app's occupied channels (unpaginated); RealtimeChannelInfo is one channel's state; RealtimeChannelMembers is the members present on a presence channel.

type RealtimeChannelListParams added in v0.15.0

type RealtimeChannelListParams struct {
	// Only channels whose name starts with this prefix (e.g. "presence-").
	Prefix string
	// Per-channel attributes to include. Repeatable. Requesting `member_count` without a presence-channel `prefix`, or `connection_count` when the app's connection-counting flag is off, returns a validation error (400).
	Include []RealtimeChannelInclude
}

RealtimeChannelListParams filters the list read.

type RealtimeChannelMember added in v0.15.0

type RealtimeChannelMember = oapi.RealtimeChannelMember

Realtime read and publish results. RealtimePublishResult and RealtimeBatchPublishResult carry per-channel counts only when the call asked for them via Include. RealtimeChannelsList is the app's occupied channels (unpaginated); RealtimeChannelInfo is one channel's state; RealtimeChannelMembers is the members present on a presence channel.

type RealtimeChannelMembers added in v0.15.0

type RealtimeChannelMembers = oapi.RealtimeChannelMembers

Realtime read and publish results. RealtimePublishResult and RealtimeBatchPublishResult carry per-channel counts only when the call asked for them via Include. RealtimeChannelsList is the app's occupied channels (unpaginated); RealtimeChannelInfo is one channel's state; RealtimeChannelMembers is the members present on a presence channel.

type RealtimeChannelsList added in v0.15.0

type RealtimeChannelsList = oapi.RealtimeChannelsList

Realtime read and publish results. RealtimePublishResult and RealtimeBatchPublishResult carry per-channel counts only when the call asked for them via Include. RealtimeChannelsList is the app's occupied channels (unpaginated); RealtimeChannelInfo is one channel's state; RealtimeChannelMembers is the members present on a presence channel.

type RealtimeChannelsService added in v0.15.0

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

RealtimeChannelsService reads channel state. Reach it via Client.Realtime.Channels.

func (*RealtimeChannelsService) Get added in v0.15.0

func (s *RealtimeChannelsService) Get(ctx context.Context, realtimeAppId string, channelName string, params RealtimeChannelGetParams, opts ...option.RequestOption) (*RealtimeChannelInfo, error)
Example

Get reads one channel's occupancy, plus any counts named in Include.

package main

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

	bird "github.com/messagebird/bird-sdk-go"
	"github.com/messagebird/bird-sdk-go/option"
)

func main() {
	client, err := bird.NewClient(
		option.WithAPIKey(os.Getenv("BIRD_API_KEY")),
		option.WithRealtimeCredentials(os.Getenv("BIRD_REALTIME_KEY"), os.Getenv("BIRD_REALTIME_SECRET")),
	)
	if err != nil {
		log.Fatal(err)
	}
	channel, err := client.Realtime.Channels.Get(context.Background(), "rap_123", "presence-lobby", bird.RealtimeChannelGetParams{
		Include: []bird.RealtimeChannelInclude{bird.RealtimeIncludeMemberCount},
	})
	if err != nil {
		log.Fatal(err)
	}
	fmt.Println(channel.Occupied, channel.MemberCount)
}

func (*RealtimeChannelsService) List added in v0.15.0

Example

List returns the app's occupied channels. The Realtime service does not paginate this listing, so one response holds every occupied channel.

package main

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

	bird "github.com/messagebird/bird-sdk-go"
	"github.com/messagebird/bird-sdk-go/option"
)

func main() {
	client, err := bird.NewClient(
		option.WithAPIKey(os.Getenv("BIRD_API_KEY")),
		option.WithRealtimeCredentials(os.Getenv("BIRD_REALTIME_KEY"), os.Getenv("BIRD_REALTIME_SECRET")),
	)
	if err != nil {
		log.Fatal(err)
	}
	channels, err := client.Realtime.Channels.List(context.Background(), "rap_123", bird.RealtimeChannelListParams{
		Prefix:  "presence-",
		Include: []bird.RealtimeChannelInclude{bird.RealtimeIncludeMemberCount},
	})
	if err != nil {
		log.Fatal(err)
	}
	for _, ch := range channels.Data {
		fmt.Println(ch.Name, ch.MemberCount)
	}
}

func (*RealtimeChannelsService) Members added in v0.15.0

func (s *RealtimeChannelsService) Members(ctx context.Context, realtimeAppId string, channelName string, opts ...option.RequestOption) (*RealtimeChannelMembers, error)
Example

Members lists the members present on a presence channel.

package main

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

	bird "github.com/messagebird/bird-sdk-go"
	"github.com/messagebird/bird-sdk-go/option"
)

func main() {
	client, err := bird.NewClient(
		option.WithAPIKey(os.Getenv("BIRD_API_KEY")),
		option.WithRealtimeCredentials(os.Getenv("BIRD_REALTIME_KEY"), os.Getenv("BIRD_REALTIME_SECRET")),
	)
	if err != nil {
		log.Fatal(err)
	}
	members, err := client.Realtime.Channels.Members(context.Background(), "rap_123", "presence-lobby")
	if err != nil {
		log.Fatal(err)
	}
	for _, m := range members.Members {
		fmt.Println(m.MemberId)
	}
}

type RealtimeMemberSendParams added in v0.21.0

type RealtimeMemberSendParams struct {
	// The event name clients bind to. Application event names are free-form; the `bird:` and `bird_internal:` prefixes are reserved for the protocol and rejected.
	Event string
	// Arbitrary JSON payload delivered as the event data — an object, array, or scalar. Cap: 10 KB serialized.
	Data any
}

RealtimeMemberSendParams is the request body for send.

type RealtimeMembersService added in v0.15.0

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

RealtimeMembersService acts on the connections of one member. Reach it via Client.Realtime.Members.

func (*RealtimeMembersService) Disconnect added in v0.15.0

func (s *RealtimeMembersService) Disconnect(ctx context.Context, realtimeAppId string, memberId string, opts ...option.RequestOption) error
Example

Disconnect closes every connection belonging to one member — the sign-out or ban path.

package main

import (
	"context"
	"log"
	"os"

	bird "github.com/messagebird/bird-sdk-go"
	"github.com/messagebird/bird-sdk-go/option"
)

func main() {
	client, err := bird.NewClient(
		option.WithAPIKey(os.Getenv("BIRD_API_KEY")),
		option.WithRealtimeCredentials(os.Getenv("BIRD_REALTIME_KEY"), os.Getenv("BIRD_REALTIME_SECRET")),
	)
	if err != nil {
		log.Fatal(err)
	}
	if err := client.Realtime.Members.Disconnect(context.Background(), "rap_123", "member:42"); err != nil {
		log.Fatal(err)
	}
}

func (*RealtimeMembersService) Send added in v0.21.0

func (s *RealtimeMembersService) Send(ctx context.Context, realtimeAppId string, memberId string, params RealtimeMemberSendParams, opts ...option.RequestOption) error
Example

Send delivers one event to every connection a single member holds, without putting it on a channel anyone else can subscribe to.

package main

import (
	"context"
	"log"
	"os"

	bird "github.com/messagebird/bird-sdk-go"
	"github.com/messagebird/bird-sdk-go/option"
)

func main() {
	client, err := bird.NewClient(
		option.WithAPIKey(os.Getenv("BIRD_API_KEY")),
		option.WithRealtimeCredentials(os.Getenv("BIRD_REALTIME_KEY"), os.Getenv("BIRD_REALTIME_SECRET")),
	)
	if err != nil {
		log.Fatal(err)
	}
	err = client.Realtime.Members.Send(context.Background(), "rap_01krdgeqcxet5s7t44vh8rt9mg", "user_42", bird.RealtimeMemberSendParams{
		Event: "order-shipped",
		Data:  map[string]any{"order_id": "ord_123"},
	})
	if err != nil {
		log.Fatal(err)
	}
}

type RealtimePublishBatchParams added in v0.15.0

type RealtimePublishBatchParams struct {
	// Up to 10 events per batch.
	Events []RealtimeBatchEventParams
}

RealtimePublishBatchParams is the request body for publish_batch.

type RealtimePublishParams added in v0.15.0

type RealtimePublishParams struct {
	// The event name clients bind to. Application event names are free-form; the `bird:` and `bird_internal:` prefixes are reserved for the protocol and rejected.
	Event string
	// The channels to deliver the event to (up to 100 per call). Prefix with `private-` or `presence-` for authenticated channels.
	Channels []string
	// Arbitrary JSON payload delivered as the event data — an object, array, or scalar. Cap: 10 KB serialized.
	Data any
	// Exclude this connection from delivery, to avoid echoing a change back to the client that triggered it. The value is the client's connection id, assigned when its connection is established.
	ExcludeConnectionID string
	// Per-channel attributes to return alongside the publish, reflecting each channel's state at publish time (same semantics and validation errors as on the channel endpoints: `member_count` is presence-channels only, `connection_count` requires the app's connection-counting flag). Requesting attributes counts as one additional message toward usage.
	Include []RealtimeChannelInclude
}

RealtimePublishParams is the request body for publish.

type RealtimePublishResult added in v0.15.0

type RealtimePublishResult = oapi.RealtimePublishResult

Realtime read and publish results. RealtimePublishResult and RealtimeBatchPublishResult carry per-channel counts only when the call asked for them via Include. RealtimeChannelsList is the app's occupied channels (unpaginated); RealtimeChannelInfo is one channel's state; RealtimeChannelMembers is the members present on a presence channel.

type RealtimeService added in v0.15.0

type RealtimeService struct {

	// Channels reads the app's occupied channels and their members.
	Channels *RealtimeChannelsService
	// Members acts on an app-defined member across all of its connections.
	Members *RealtimeMembersService
	// contains filtered or unexported fields
}

RealtimeService publishes events to a Realtime app and inspects its live state. Reach it via Client.Realtime.

Every call needs the app's own credentials on top of the workspace API key: configure them with option.WithRealtimeCredentials, at construction for a single app or per call when one client serves several apps. Without them a method fails before any request is sent.

The app id is a positional argument rather than client config, so one client can address any app the workspace owns.

func (*RealtimeService) Publish added in v0.15.0

func (s *RealtimeService) Publish(ctx context.Context, realtimeAppId string, params RealtimePublishParams, opts ...option.RequestOption) (*RealtimePublishResult, error)
Example

Publish delivers one event to one or more channels. The Realtime app's own key and secret authenticate the call, alongside the workspace API key.

package main

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

	bird "github.com/messagebird/bird-sdk-go"
	"github.com/messagebird/bird-sdk-go/option"
)

func main() {
	client, err := bird.NewClient(
		option.WithAPIKey(os.Getenv("BIRD_API_KEY")),
		option.WithRealtimeCredentials(os.Getenv("BIRD_REALTIME_KEY"), os.Getenv("BIRD_REALTIME_SECRET")),
	)
	if err != nil {
		log.Fatal(err)
	}
	result, err := client.Realtime.Publish(context.Background(), "rap_123", bird.RealtimePublishParams{
		Event:    "order.created",
		Channels: []string{"orders", "presence-lobby"},
		Data:     map[string]any{"order_id": "ord_1", "total": 4200},
	})
	if err != nil {
		log.Fatal(err)
	}
	fmt.Println(result.Data)
}

func (*RealtimeService) PublishBatch added in v0.15.0

func (s *RealtimeService) PublishBatch(ctx context.Context, realtimeAppId string, params RealtimePublishBatchParams, opts ...option.RequestOption) (*RealtimeBatchPublishResult, error)
Example

PublishBatch sends several events, each to a single channel, in one request.

package main

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

	bird "github.com/messagebird/bird-sdk-go"
	"github.com/messagebird/bird-sdk-go/option"
)

func main() {
	client, err := bird.NewClient(
		option.WithAPIKey(os.Getenv("BIRD_API_KEY")),
		option.WithRealtimeCredentials(os.Getenv("BIRD_REALTIME_KEY"), os.Getenv("BIRD_REALTIME_SECRET")),
	)
	if err != nil {
		log.Fatal(err)
	}
	result, err := client.Realtime.PublishBatch(context.Background(), "rap_123", bird.RealtimePublishBatchParams{
		Events: []bird.RealtimeBatchEventParams{
			{Event: "order.created", Channel: "orders", Data: map[string]any{"id": 1}},
			{Event: "order.updated", Channel: "orders", Data: map[string]any{"id": 2}},
		},
	})
	if err != nil {
		log.Fatal(err)
	}
	fmt.Println(result.Data)
}

type ReceiveRule added in v0.12.0

type ReceiveRule = oapi.ReceiveRule

ReceiveRule is a per-sender allow or block rule on a mailbox.

type ReceiveRuleCreateAction added in v0.16.0

type ReceiveRuleCreateAction = oapi.ReceiveRuleCreateAction

type ReceiveRuleList added in v0.12.0

type ReceiveRuleList = oapi.ReceiveRuleList

ReceiveRuleList is one page of receive rules.

type Response

type Response = requestconfig.Response

Response is the transport metadata for one call, captured via option.WithResponseInto.

type SMSBatch added in v0.3.0

type SMSBatch = oapi.SMSMessageBatchResponse

SMSMessage is a sent or received SMS with its status, segment breakdown, and cost; SMSMessageList is a page of messages; SMSBatch is a batch-send result.

type SMSCategory added in v0.3.0

type SMSCategory = oapi.SMSMessageCategory

SMSCategory classifies a send for opt-out (STOP) policy, quiet hours, and per-country compliance.

const (
	SMSCategoryTransactional  SMSCategory = "transactional"
	SMSCategoryMarketing      SMSCategory = "marketing"
	SMSCategoryAuthentication SMSCategory = "authentication"
	SMSCategoryService        SMSCategory = "service"
)

type SMSErrorCode added in v0.28.0

type SMSErrorCode = oapi.SMSErrorCode

SMSErrorCode is an open string on the wire: a value added by a newer server deserializes unchanged, so compare against the SMSErrorCode* constants with a default branch rather than treating the set as closed.

type SMSMessage added in v0.3.0

type SMSMessage = oapi.SMSMessage

SMSMessage is a sent or received SMS with its status, segment breakdown, and cost; SMSMessageList is a page of messages; SMSBatch is a batch-send result.

type SMSMessageCategory added in v0.16.0

type SMSMessageCategory = oapi.SMSMessageCategory

SMSMessageCategory is an SMS's content classification.

type SMSMessageList added in v0.3.0

type SMSMessageList = oapi.SMSMessageList

SMSMessage is a sent or received SMS with its status, segment breakdown, and cost; SMSMessageList is a page of messages; SMSBatch is a batch-send result.

type SMSStatus added in v0.3.0

type SMSStatus = oapi.SMSMessageStatus

SMSStatus is a message's delivery status.

type SMSTag added in v0.3.0

type SMSTag = oapi.Tag

SMSTag is a structured {name, value} label on an SMS send.

type SMSTemplate added in v0.3.0

type SMSTemplate = oapi.SMSTemplate

SMSTemplate is an SMS template with its body, variables, and available languages; SMSTemplateList is the (unpaginated) set of templates available to the workspace.

type SMSTemplateList added in v0.3.0

type SMSTemplateList = oapi.SMSTemplateList

SMSTemplate is an SMS template with its body, variables, and available languages; SMSTemplateList is the (unpaginated) set of templates available to the workspace.

type SMSTemplateListParams added in v0.3.0

type SMSTemplateListParams struct {
	// Keep only templates of this scope: `system` for Bird's built-in templates, `workspace` for templates authored in your workspace. Omit for all.
	Scope TemplateScope
	// Keep only templates whose `category` matches. Omit for all categories.
	Category SMSMessageCategory
	// Keep only templates available in this language, as a BCP-47 tag. Matches the template's `available_languages` entries exactly, with no fallback.
	Language string
}

SMSTemplateListParams filters the list read.

type SmsListParams added in v0.3.0

type SmsListParams struct {
	// Maximum number of items to return per page.
	Limit int
	// Return only resources created at or after this timestamp (inclusive lower bound). Combine with `created_before` to filter to a time window. RFC 3339 / ISO 8601 with timezone.
	CreatedAfter time.Time
	// Return only resources created strictly before this timestamp (exclusive upper bound). Combine with `created_after` to filter to a time window. RFC 3339 / ISO 8601 with timezone.
	CreatedBefore time.Time
	// Filter by direction. Omit for both.
	Direction MessageDirection
	// Keep only messages whose current `status` matches; repeat the parameter to match any of several. One of `scheduled`, `accepted`, `sent`, `delivered`, `undelivered`, `failed`, `rejected`, `canceled`, `expired`, or `received`.
	Status []string
	// Keep only messages whose failure reason (`last_error.code`) matches; repeat the parameter to match any of several. One of `invalid_destination`, `unreachable`, `blocked_by_carrier`, `blocked_by_recipient`, `landline_unreachable`, `content_rejected`, `sender_unregistered`, `recipient_opted_out`, `provider_unavailable`, `insufficient_balance`, or `unknown`.
	ErrorCode []string
	// Filter by category.
	Category SMSMessageCategory
	// Filter by recipient phone number (E.164 exact match).
	To string
	// Filter by sender (E.164, alphanumeric, or short code; exact match).
	From string
	// Filter by tag. Accepts `name` to match any message carrying that tag name, or `name:value` to match a specific tag pair (for example `category:welcome`). Repeat the parameter to add more tags. A message must match every tag listed to be returned.
	Tag []string
}

SmsListParams filters the list. Zero-value fields are omitted.

type SmsSendBatchParams added in v0.3.0

type SmsSendBatchParams struct {
	Messages []SmsSendParams
}

SmsSendBatchParams is a batch of up to 100 independent SMS sends.

type SmsSendParams added in v0.3.0

type SmsSendParams struct {
	To         string         // required; recipient phone number in E.164 format
	From       string         // optional sender; Bird selects one when empty
	Text       string         // free-text body (mutually exclusive with Template)
	Category   SMSCategory    // required with Text; omit on a template send
	Template   string         // stored template id (smt_…) or slug (mutually exclusive with Text)
	Language   string         // template language as a BCP-47 tag; template sends only
	Parameters map[string]any // template variable values; template sends only
	Tags       []SMSTag       // structured {name, value} labels for filtering and analytics
	Metadata   map[string]any // arbitrary JSON stored on the message and echoed in webhooks
	// SmartEncoding replaces characters outside the GSM-7 alphabet with their closest
	// equivalent, which often lowers the segment count and the cost. A pointer because
	// false is a real value the send carries: nil omits the option and takes Bird's
	// default (off), &false records the choice explicitly.
	SmartEncoding *bool
}

SmsSendParams is a single SMS send. Provide either Text (with Category) or a Template (by id or slug, with Parameters) — the two are mutually exclusive. Zero-value fields are omitted from the request.

type SmsService added in v0.16.0

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

SmsService sends SMS messages — free text or by stored template — and reads them back. Reach it via Client.Sms.

func (*SmsService) Get added in v0.16.0

func (s *SmsService) Get(ctx context.Context, messageId string, opts ...option.RequestOption) (*SMSMessage, error)

Get Get one SMS message by id: its current delivery status, segment breakdown, cost, and failure detail if it failed.

func (*SmsService) List added in v0.16.0

List List SMS messages, newest first, as a cursor page ({data, next_cursor, …}). Pass next_cursor back as starting_after to fetch the next page. Filter by direction, status, category, recipient, sender, or tag. Range over it; the second value is non-nil only on the iteration where a fetch failed.

func (*SmsService) ListPage added in v0.16.0

func (s *SmsService) ListPage(ctx context.Context, params SmsListParams, startingAfter string, opts ...option.RequestOption) (*SMSMessageList, error)

ListPage fetches one page of results. Pass the previous page's NextCursor as startingAfter to advance; "" starts from the first page.

func (*SmsService) Send added in v0.16.0

func (s *SmsService) Send(ctx context.Context, params SmsSendParams, opts ...option.RequestOption) (*SMSMessage, error)

Send sends one SMS message. Retried safely: a single idempotency key is reused across attempts. Provide your own key with option.WithIdempotencyKey.

Example

Send a free-text SMS.

package main

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

	bird "github.com/messagebird/bird-sdk-go"
	"github.com/messagebird/bird-sdk-go/option"
)

func main() {
	client, err := bird.NewClient(option.WithAPIKey(os.Getenv("BIRD_API_KEY")))
	if err != nil {
		log.Fatal(err)
	}
	msg, err := client.Sms.Send(context.Background(), bird.SmsSendParams{
		To:       "+15551234567",
		Text:     "Your verification code is 123456.",
		Category: bird.SMSCategoryAuthentication,
	})
	if err != nil {
		log.Fatal(err)
	}
	fmt.Println(msg.Id, *msg.Status)
}
Example (Template)

Send an SMS from a stored template, supplying its variables.

package main

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

	bird "github.com/messagebird/bird-sdk-go"
	"github.com/messagebird/bird-sdk-go/option"
)

func main() {
	client, err := bird.NewClient(option.WithAPIKey(os.Getenv("BIRD_API_KEY")))
	if err != nil {
		log.Fatal(err)
	}
	msg, err := client.Sms.Send(context.Background(), bird.SmsSendParams{
		To:         "+15551234567",
		Template:   "bird_otp_verification",
		Parameters: map[string]any{"code": "123456"},
	})
	if err != nil {
		log.Fatal(err)
	}
	fmt.Println(msg.Id)
}

func (*SmsService) SendBatch added in v0.16.0

func (s *SmsService) SendBatch(ctx context.Context, params SmsSendBatchParams, opts ...option.RequestOption) (*SMSBatch, error)

SendBatch sends up to 100 independent SMS messages in one call. Each item is a full send with its own id, status, and cost; all items are validated before any are queued. Retried safely with a reused idempotency key.

Example

Send up to 100 independent messages in one call. Acceptance is all-or-nothing: every message is validated before any of them queue.

package main

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

	bird "github.com/messagebird/bird-sdk-go"
	"github.com/messagebird/bird-sdk-go/option"
)

func main() {
	client, err := bird.NewClient(option.WithAPIKey(os.Getenv("BIRD_API_KEY")))
	if err != nil {
		log.Fatal(err)
	}
	batch, err := client.Sms.SendBatch(context.Background(), bird.SmsSendBatchParams{
		Messages: []bird.SmsSendParams{
			{To: "+15551111111", Text: "Hi Alice!", Category: bird.SMSCategoryMarketing},
			{To: "+15552222222", Text: "Hi Bob!", Category: bird.SMSCategoryMarketing},
		},
	})
	if err != nil {
		log.Fatal(err)
	}
	for _, msg := range batch.Data {
		fmt.Println(msg.Id, *msg.Status)
	}
}

type SmsTemplatesService added in v0.16.0

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

SmsTemplatesService reads the SMS templates available to a workspace — Bird's built-in templates and any the workspace authored. Reach it via Client.SmsTemplates. The catalogue is read-only through this SDK.

func (*SmsTemplatesService) Get added in v0.16.0

func (s *SmsTemplatesService) Get(ctx context.Context, templateRef string, opts ...option.RequestOption) (*SMSTemplate, error)

Get Get one SMS template by its slug or id, including its body and the variables it expects. Fetch it before sms_send to see which parameter keys a template send requires.

Example

Read one SMS template by its slug (or id).

package main

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

	bird "github.com/messagebird/bird-sdk-go"
	"github.com/messagebird/bird-sdk-go/option"
)

func main() {
	client, err := bird.NewClient(option.WithAPIKey(os.Getenv("BIRD_API_KEY")))
	if err != nil {
		log.Fatal(err)
	}
	tpl, err := client.SmsTemplates.Get(context.Background(), "bird_otp_verification")
	if err != nil {
		log.Fatal(err)
	}
	fmt.Println(tpl.Id, *tpl.Body)
}

func (*SmsTemplatesService) List added in v0.16.0

List List the SMS templates available to your workspace, including Bird's built-in templates. Filter by scope, category, or language. The catalogue is small and returned in full; this list is not paginated. Use sms_templates_get to read one template's variables before sending with it.

Example

List the SMS templates available to the workspace. The catalogue is small and returned in full — this list is not paginated.

package main

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

	bird "github.com/messagebird/bird-sdk-go"
	"github.com/messagebird/bird-sdk-go/option"
)

func main() {
	client, err := bird.NewClient(option.WithAPIKey(os.Getenv("BIRD_API_KEY")))
	if err != nil {
		log.Fatal(err)
	}
	list, err := client.SmsTemplates.List(context.Background(), bird.SMSTemplateListParams{
		Scope: "system",
	})
	if err != nil {
		log.Fatal(err)
	}
	for _, tpl := range list.Data {
		fmt.Println(tpl.Id, *tpl.Slug)
	}
}

type StatsTrendGrain added in v0.16.0

type StatsTrendGrain = oapi.StatsTrendGrain

StatsTrendGrain is the bucket grain of a stats trend series.

type Tag added in v0.16.0

type Tag = oapi.Tag

type TemplateLanguageStatus added in v0.32.0

type TemplateLanguageStatus = oapi.TemplateLanguageStatus

TemplateLanguageStatus is an open string on the wire: a value added by a newer server deserializes unchanged, so compare against the TemplateLanguageStatus* constants with a default branch rather than treating the set as closed.

type TemplateScope added in v0.16.0

type TemplateScope = oapi.TemplateScope

TemplateScope distinguishes Bird's built-in templates from a workspace's own.

type TemplateStatus added in v0.32.0

type TemplateStatus = oapi.TemplateStatus

TemplateStatus is an open string on the wire: a value added by a newer server deserializes unchanged, so compare against the TemplateStatus* constants with a default branch rather than treating the set as closed.

type TimeoutError

type TimeoutError = apierror.TimeoutError

The SDK error model, re-exported from internal/apierror so these names are the semver-locked public surface. Catch *APIError (via errors.As) to handle any server error; the variants carry extra data. Transport failures with no HTTP response are *ConnectionError / *TimeoutError; a bad webhook signature is *WebhookVerificationError.

type UnmetGate added in v0.4.1

type UnmetGate = apierror.UnmetGate

The SDK error model, re-exported from internal/apierror so these names are the semver-locked public surface. Catch *APIError (via errors.As) to handle any server error; the variants carry extra data. Transport failures with no HTTP response are *ConnectionError / *TimeoutError; a bad webhook signature is *WebhookVerificationError.

type ValidationError

type ValidationError = apierror.ValidationError

The SDK error model, re-exported from internal/apierror so these names are the semver-locked public surface. Catch *APIError (via errors.As) to handle any server error; the variants carry extra data. Transport failures with no HTTP response are *ConnectionError / *TimeoutError; a bad webhook signature is *WebhookVerificationError.

type Verification added in v0.7.0

type Verification = oapi.Verification

Verification is a verification's current state (id, status, channel plan); VerificationCheckResult is a check outcome plus the verification's state.

type VerificationAttemptFailureReason added in v0.19.0

type VerificationAttemptFailureReason = oapi.VerificationAttemptFailureReason

VerificationAttemptFailureReason is an open string on the wire: a value added by a newer server deserializes unchanged, so compare against the VerificationAttemptFailureReason* constants with a default branch rather than treating the set as closed.

type VerificationChannel added in v0.19.0

type VerificationChannel = oapi.VerificationChannel

VerificationChannel is an open string on the wire: a value added by a newer server deserializes unchanged, so compare against the VerificationChannel* constants with a default branch rather than treating the set as closed.

type VerificationCheckResult added in v0.7.0

type VerificationCheckResult = oapi.VerificationCheckResult

Verification is a verification's current state (id, status, channel plan); VerificationCheckResult is a check outcome plus the verification's state.

type VerificationOptions added in v0.16.0

type VerificationOptions = oapi.VerificationOptions

type VerificationTerminalReason added in v0.19.0

type VerificationTerminalReason = oapi.VerificationTerminalReason

VerificationTerminalReason is an open string on the wire: a value added by a newer server deserializes unchanged, so compare against the VerificationTerminalReason* constants with a default branch rather than treating the set as closed.

type VerificationTo added in v0.16.0

type VerificationTo = oapi.VerificationTo

type VerifyService added in v0.7.0

type VerifyService struct {
	// Verifications starts verifications and checks the passcodes recipients submit.
	Verifications *VerifyVerificationsService
}

VerifyService is the Verify product namespace. Reach it via Client.Verify.

type VerifyVerificationsCheckParams added in v0.16.0

type VerifyVerificationsCheckParams struct {
	// The recipient to verify. Provide an `email`, a `phone_number`, or both; at least one is required. The addresses also identify the verification: a check must supply exactly the set used on the create call, so a verification created with both addresses is not found by either one alone.
	To VerificationTo
	// The passcode the recipient received. Passcodes are numeric; submit the digits exactly as delivered. An incorrect value is a normal `200` outcome with `success: false`, not an error.
	Code string
}

VerifyVerificationsCheckParams is the request body for check.

type VerifyVerificationsCreateParams added in v0.16.0

type VerifyVerificationsCreateParams struct {
	// The recipient to verify. Provide an `email`, a `phone_number`, or both; at least one is required. The addresses also identify the verification: a check must supply exactly the set used on the create call, so a verification created with both addresses is not found by either one alone.
	To VerificationTo
	// Per-request overrides applied to this verification only.
	Options *VerificationOptions
	// Optional key/value pairs to attach to the verification, for example a correlation id. Returned on the verification.
	Metadata map[string]any
}

VerifyVerificationsCreateParams is the request body for create.

type VerifyVerificationsNextChannelParams added in v0.27.0

type VerifyVerificationsNextChannelParams struct {
	// The recipient to verify. Provide an `email`, a `phone_number`, or both; at least one is required. The addresses also identify the verification: a check must supply exactly the set used on the create call, so a verification created with both addresses is not found by either one alone.
	To VerificationTo
}

VerifyVerificationsNextChannelParams is the request body for next_channel.

type VerifyVerificationsService added in v0.16.0

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

VerifyVerificationsService starts a verification, sending a one-time passcode, and checks the passcode a recipient submits.

func (*VerifyVerificationsService) Check added in v0.16.0

Check Check a passcode a recipient submitted. Identify the verification by the same `to` recipient used to start it; no verification id needed. A wrong or expired code returns HTTP 200 with `success: false` and a `reason` (for example `incorrect_code` or `expired`), not an error. A verification that has already reached a final state is no longer checkable and returns 404, as does a missing verification; malformed input or rate limiting is also an error status.

Example

Check the passcode a recipient submitted, identified by the same recipient.

package main

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

	bird "github.com/messagebird/bird-sdk-go"
	"github.com/messagebird/bird-sdk-go/option"
)

func main() {
	client, err := bird.NewClient(option.WithAPIKey(os.Getenv("BIRD_API_KEY")))
	if err != nil {
		log.Fatal(err)
	}
	result, err := client.Verify.Verifications.Check(context.Background(), bird.VerifyVerificationsCheckParams{
		To:   bird.VerificationTo{PhoneNumber: bird.String("+15551234567")},
		Code: "123456",
	})
	if err != nil {
		log.Fatal(err)
	}
	fmt.Println(*result.Success)
}

func (*VerifyVerificationsService) Create added in v0.16.0

Create Start a verification: generate a one-time passcode and send it to the recipient in `to` (a phone number over the phone channels enabled for its destination country; an email address over email; or both). It is sent over one channel at a time and fails over to the next in the plan, never over two at once. Calling again for the same recipient reuses the in-progress verification and sends a fresh code after the resend cooldown; it does not start a second one, so use this both to send and to resend. The passcode is never returned; submit what the recipient enters with verify_verifications_check. SMS, WhatsApp and Telegram delivery all draw on the workspace's balance.

Example

Start a verification: send a one-time passcode over SMS.

package main

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

	bird "github.com/messagebird/bird-sdk-go"
	"github.com/messagebird/bird-sdk-go/option"
)

func main() {
	client, err := bird.NewClient(option.WithAPIKey(os.Getenv("BIRD_API_KEY")))
	if err != nil {
		log.Fatal(err)
	}
	verification, err := client.Verify.Verifications.Create(context.Background(), bird.VerifyVerificationsCreateParams{
		To: bird.VerificationTo{PhoneNumber: bird.String("+15551234567")},
	})
	if err != nil {
		log.Fatal(err)
	}
	fmt.Println(verification.Id, *verification.Status)
}

func (*VerifyVerificationsService) NextChannel added in v0.27.0

NextChannel Advance an in-progress verification to the next channel in its plan and send a fresh passcode there: the "I didn't receive my code" action. The verification is identified by the same `to` recipient used to start it, with no verification id needed. The send bypasses the resend cooldown, and earlier passcodes stay valid. Returns the verification with `last_channel` set to the channel the new code went to; when concurrent advances race for the same recipient, the response reflects committed state: `last_channel` names the most recent completed send, and the racing call that completed the newer send is authoritative. A plan with no further channel returns a 422 named NoNextChannel, after which only re-creating the verification will resend.

Example

Send a fresh passcode on the next channel when the recipient never got the first.

package main

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

	bird "github.com/messagebird/bird-sdk-go"
	"github.com/messagebird/bird-sdk-go/option"
)

func main() {
	client, err := bird.NewClient(option.WithAPIKey(os.Getenv("BIRD_API_KEY")))
	if err != nil {
		log.Fatal(err)
	}
	verification, err := client.Verify.Verifications.NextChannel(context.Background(), bird.VerifyVerificationsNextChannelParams{
		To: bird.VerificationTo{PhoneNumber: bird.String("+15551234567")},
	})
	if err != nil {
		log.Fatal(err)
	}
	if verification.LastChannel != nil {
		fmt.Println(*verification.LastChannel)
	}
}

type VoiceCall added in v0.27.0

type VoiceCall = oapi.VoiceCall

VoiceCall is one call-detail record, in flight or settled; VoiceCallList is a page of them.

type VoiceCallDirection added in v0.27.0

type VoiceCallDirection = oapi.VoiceCallDirection

VoiceCallStatus is how a call ended, or that it is still ringing or connected. VoiceCallDirection is which way the call was placed.

type VoiceCallList added in v0.27.0

type VoiceCallList = oapi.VoiceCallList

VoiceCall is one call-detail record, in flight or settled; VoiceCallList is a page of them.

type VoiceCallStatus added in v0.27.0

type VoiceCallStatus = oapi.VoiceCallStatus

VoiceCallStatus is how a call ended, or that it is still ringing or connected. VoiceCallDirection is which way the call was placed.

type VoiceListParams added in v0.27.0

type VoiceListParams struct {
	// Return only calls in this direction.
	Direction VoiceCallDirection
	// Return only calls with one of these statuses, comma-separated. In-flight and final statuses may be combined freely.
	Status []VoiceCallStatus
	// Return only calls belonging to this session, which is how the legs of one multi-party or transferred call are correlated.
	SessionID string
	// Return only calls carried by this SIP trunk.
	SipTrunkID string
	// Return only calls placed from this calling party number, matched as a whole number rather than as a fragment. Give it in international form: `+14155551234`, `14155551234`, and `0014155551234` all select the same calls. A number given without a country code is read as an international one, so give the country code to be sure of what you are matching. Use `number` instead to match part of a number, or either side of the call.
	From string
	// Return only calls placed to this called party number, matched as a whole number rather than as a fragment. Give it in international form: `+16505559876`, `16505559876`, and `0016505559876` all select the same calls. A number given without a country code is read as an international one, so give the country code to be sure of what you are matching. Use `number` instead to match part of a number, or either side of the call.
	To string
	// Return only calls where the calling or called number contains this value. Matches a partial number, so a country or area-code prefix returns every call to or from it. Combines with `from`/`to`, which match one side exactly.
	Number string
	// Return only calls that started at or after this instant, inclusive. RFC 3339 timestamp.
	StartedAfter time.Time
	// Return only calls that started at or before this instant, inclusive. RFC 3339 timestamp.
	StartedBefore time.Time
	// Maximum number of items to return per page.
	Limit int
}

VoiceListParams filters the list. Zero-value fields are omitted.

type VoiceService added in v0.27.0

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

VoiceService reads a workspace's call log — the record Bird writes for every call, in flight or settled. Reach it via Client.Voice. Calls are placed by the customer's own SIP equipment rather than through the API, so this is a read surface with no send verb.

func (*VoiceService) Get added in v0.27.0

func (s *VoiceService) Get(ctx context.Context, callId string, opts ...option.RequestOption) (*VoiceCall, error)

Get Fetch one call by id, at any point in its lifecycle. A call still ringing or connected carries no economics yet: `duration_ms`, `billable_ms`, `ended_at`, and `cost` are null until it ends, and this same id then answers with the settled record. Poll here to watch one known call; use voice_list to find calls in the first place. When a call was refused, `rejection_reason` names the gate that turned it away.

Example

Get returns one call at any point in its lifecycle, settled or still up.

package main

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

	bird "github.com/messagebird/bird-sdk-go"
	"github.com/messagebird/bird-sdk-go/option"
)

func main() {
	client, err := bird.NewClient(option.WithAPIKey(os.Getenv("BIRD_API_KEY")))
	if err != nil {
		log.Fatal(err)
	}
	call, err := client.Voice.Get(context.Background(), "vcl_01k0p3v9wera3v6q6xw3e9y2mh")
	if err != nil {
		log.Fatal(err)
	}
	// A call still ringing or connected carries no economics yet.
	fmt.Println(call.Status, call.DurationMs)
}

func (*VoiceService) List added in v0.27.0

List List the workspace's calls, newest first. Filter to `ringing`/`in_progress` for the calls in progress right now, to final statuses for completed records, or to any mix of the two. Use `from`/`to` for one known party number in international form, and `number` to search either side by fragment. These are per-call records: for rates and totals over a period use voice_stats_summary rather than summing them here, and voice_get to follow one call to settlement. Range over it; the second value is non-nil only on the iteration where a fetch failed.

Example

List the workspace's calls. Filtering to the in-flight statuses gives the calls happening right now; omit the filter for completed records.

package main

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

	bird "github.com/messagebird/bird-sdk-go"
	"github.com/messagebird/bird-sdk-go/option"
)

func main() {
	client, err := bird.NewClient(option.WithAPIKey(os.Getenv("BIRD_API_KEY")))
	if err != nil {
		log.Fatal(err)
	}
	for call, err := range client.Voice.List(context.Background(), bird.VoiceListParams{
		Status: []bird.VoiceCallStatus{"ringing", "in_progress"},
	}) {
		if err != nil {
			log.Fatal(err)
		}
		fmt.Println(call.Id, call.Status)
	}
}

func (*VoiceService) ListPage added in v0.27.0

func (s *VoiceService) ListPage(ctx context.Context, params VoiceListParams, startingAfter string, opts ...option.RequestOption) (*VoiceCallList, error)

ListPage fetches one page of results. Pass the previous page's NextCursor as startingAfter to advance; "" starts from the first page.

type WebhookEventType

type WebhookEventType = oapi.WebhookEventType

WebhookEventType is a webhook event's discriminant. It is an open string: the known values are the EventType* constants, and an event type added by a newer server flows through Unwrap as a plain string.

type WebhookService

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

WebhookService verifies inbound webhook deliveries. Reach it via Client.Webhooks. Configure the signing secret with option.WithWebhookSecret on the client (or per call on Unwrap). It is pure crypto — no transport.

func (*WebhookService) Unwrap

func (s *WebhookService) Unwrap(payload []byte, headers http.Header, opts ...option.RequestOption) (Event, error)

Unwrap verifies the Standard Webhooks signature over the raw request body and returns the decoded event. Hand it the exact bytes received — parsing and re-serializing before verifying breaks the signature.

Example

Unwrap verifies the Standard Webhooks signature over the raw request body and returns a typed event to dispatch on.

package main

import (
	"fmt"
	"io"
	"log"
	"net/http"
	"os"

	bird "github.com/messagebird/bird-sdk-go"
	"github.com/messagebird/bird-sdk-go/option"
)

func main() {
	client, err := bird.NewClient(
		option.WithAPIKey(os.Getenv("BIRD_API_KEY")),
		option.WithWebhookSecret(os.Getenv("BIRD_WEBHOOK_SECRET")),
	)
	if err != nil {
		log.Fatal(err)
	}
	http.HandleFunc("/webhooks/bird", func(w http.ResponseWriter, r *http.Request) {
		body, _ := io.ReadAll(r.Body)
		event, err := client.Webhooks.Unwrap(body, r.Header)
		if err != nil {
			http.Error(w, "invalid signature", http.StatusBadRequest)
			return
		}
		w.WriteHeader(http.StatusNoContent) // ack fast, then process

		payload, _ := event.AsAny()
		switch p := payload.(type) {
		case bird.EmailDeliveredEvent:
			fmt.Println("delivered:", p.Data.EmailId, p.Data.Recipient)
		case bird.EmailBouncedEvent:
			fmt.Println("bounced:", p.Type)
		}
	})
}

type WebhookVerificationError

type WebhookVerificationError = apierror.WebhookVerificationError

The SDK error model, re-exported from internal/apierror so these names are the semver-locked public surface. Catch *APIError (via errors.As) to handle any server error; the variants carry extra data. Transport failures with no HTTP response are *ConnectionError / *TimeoutError; a bad webhook signature is *WebhookVerificationError.

type WhatsAppErrorCode added in v0.19.0

type WhatsAppErrorCode = oapi.WhatsAppErrorCode

WhatsAppErrorCode is an open string on the wire: a value added by a newer server deserializes unchanged, so compare against the WhatsAppErrorCode* constants with a default branch rather than treating the set as closed.

type WhatsAppEvent added in v0.6.0

type WhatsAppEvent = oapi.WhatsAppEvent

WhatsAppEvent is a single lifecycle event on a message's timeline; WhatsAppEventList is the (unpaginated) timeline for one message.

type WhatsAppEventList added in v0.6.0

type WhatsAppEventList = oapi.WhatsAppEventList

WhatsAppEvent is a single lifecycle event on a message's timeline; WhatsAppEventList is the (unpaginated) timeline for one message.

type WhatsAppEventType added in v0.32.0

type WhatsAppEventType = oapi.WhatsAppEventType

WhatsAppEventType is an open string on the wire: a value added by a newer server deserializes unchanged, so compare against the WhatsAppEventType* constants with a default branch rather than treating the set as closed.

type WhatsAppMessage added in v0.6.0

type WhatsAppMessage = oapi.WhatsAppMessage

WhatsAppMessage is a sent or received WhatsApp message; WhatsAppMessageList is a page of messages.

type WhatsAppMessageList added in v0.6.0

type WhatsAppMessageList = oapi.WhatsAppMessageList

WhatsAppMessage is a sent or received WhatsApp message; WhatsAppMessageList is a page of messages.

type WhatsAppMessageStatus added in v0.6.0

type WhatsAppMessageStatus = oapi.WhatsAppMessageStatus

WhatsAppMessageStatus is a message's delivery status.

type WhatsAppMessageTemplateComponent added in v0.6.0

type WhatsAppMessageTemplateComponent = oapi.WhatsAppMessageTemplateComponent

WhatsAppMessageTemplateComponent is a filled-in template component — supplied on a template send and echoed back on the sent message. WhatsAppMessageTemplateComponentParameter is one of its placeholder values.

type WhatsAppMessageTemplateComponentParameter added in v0.6.0

type WhatsAppMessageTemplateComponentParameter = oapi.WhatsAppMessageTemplateComponentParameter

WhatsAppMessageTemplateComponent is a filled-in template component — supplied on a template send and echoed back on the sent message. WhatsAppMessageTemplateComponentParameter is one of its placeholder values.

type WhatsAppTemplateCategory added in v0.19.0

type WhatsAppTemplateCategory = oapi.WhatsAppTemplateCategory

WhatsAppTemplateCategory is an open string on the wire: a value added by a newer server deserializes unchanged, so compare against the WhatsAppTemplateCategory* constants with a default branch rather than treating the set as closed.

type WhatsAppTemplateParameterType added in v0.19.0

type WhatsAppTemplateParameterType = oapi.WhatsAppTemplateParameterType

WhatsAppTemplateParameterType is an open string on the wire: a value added by a newer server deserializes unchanged, so compare against the WhatsAppTemplateParameterType* constants with a default branch rather than treating the set as closed.

type WhatsappListEventsParams added in v0.6.0

type WhatsappListEventsParams struct {
	// Keep only events of this exact type (for example `whatsapp.delivered` or `whatsapp.failed`). Omit for the full timeline.
	Type WhatsAppEventType
}

WhatsappListEventsParams filters the list_events read.

type WhatsappListParams added in v0.6.0

type WhatsappListParams struct {
	// Maximum number of items to return per page.
	Limit int
	// Return only resources created at or after this timestamp (inclusive lower bound). Combine with `created_before` to filter to a time window. RFC 3339 / ISO 8601 with timezone.
	CreatedAfter time.Time
	// Return only resources created strictly before this timestamp (exclusive upper bound). Combine with `created_after` to filter to a time window. RFC 3339 / ISO 8601 with timezone.
	CreatedBefore time.Time
	// Filter by status. Repeat the parameter to match any of several statuses.
	Status []WhatsAppMessageStatus
	// Filter by whether the business sent the message (`outbound`) or received it from the contact (`inbound`).
	Direction MessageDirection
	// Filter by contact phone number (E.164 exact match).
	PhoneNumber string
	// Filter by business-scoped user ID (Meta identifier).
	Bsuid string
	// Filter by category.
	Category WhatsAppTemplateCategory
	// Filter by tag. Accepts `name` to match any message carrying that tag name, or `name:value` to match a specific tag pair (for example `category:welcome`). Repeat the parameter to add more tags. A message must match every tag listed to be returned.
	Tag []string
}

WhatsappListParams filters the list. Zero-value fields are omitted.

type WhatsappSendParams added in v0.6.0

type WhatsappSendParams struct {
	To         string                             // required; recipient phone number in E.164 format
	Template   string                             // required; the template's id (wat_…) or its slug (e.g. bird_otp)
	Language   string                             // template language as a BCP-47 tag; omit when the template has a single language
	Components []WhatsAppMessageTemplateComponent // values that fill the template's placeholders
}

WhatsappSendParams is a single WhatsApp message send. Templates are currently the only supported content type, so Template is required; free-form content will be added in a future release. Zero-value fields are omitted from the request.

type WhatsappService added in v0.16.0

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

WhatsappService sends WhatsApp template messages and reads them back. Reach it via Client.Whatsapp.

func (*WhatsappService) Get added in v0.16.0

func (s *WhatsappService) Get(ctx context.Context, messageId string, opts ...option.RequestOption) (*WhatsAppMessage, error)

Get Get one WhatsApp message by id: current delivery status, sent/delivered/read timestamps, the template it was sent from, and failure detail if it failed. For the per-event timeline use whatsapp_list_events.

Example

Read a single WhatsApp message by id.

package main

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

	bird "github.com/messagebird/bird-sdk-go"
	"github.com/messagebird/bird-sdk-go/option"
)

func main() {
	client, err := bird.NewClient(option.WithAPIKey(os.Getenv("BIRD_API_KEY")))
	if err != nil {
		log.Fatal(err)
	}
	msg, err := client.Whatsapp.Get(context.Background(), "wam_01krdgeqcxet5s7t44vh8rt9mg")
	if err != nil {
		log.Fatal(err)
	}
	fmt.Println(msg.Id, *msg.Status)
}

func (*WhatsappService) List added in v0.16.0

List List WhatsApp messages, newest first, as a cursor page ({data, next_cursor, …}). Pass next_cursor back as starting_after to fetch the next page. Filter by direction, status, contact phone number, bsuid, template category, or tag. Use whatsapp_get for one message's current state. Range over it; the second value is non-nil only on the iteration where a fetch failed.

Example

List WhatsApp messages to a given contact, paginating lazily.

package main

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

	bird "github.com/messagebird/bird-sdk-go"
	"github.com/messagebird/bird-sdk-go/option"
)

func main() {
	client, err := bird.NewClient(option.WithAPIKey(os.Getenv("BIRD_API_KEY")))
	if err != nil {
		log.Fatal(err)
	}
	for msg, err := range client.Whatsapp.List(context.Background(), bird.WhatsappListParams{PhoneNumber: "+15551234567"}) {
		if err != nil {
			log.Fatal(err)
		}
		fmt.Println(msg.Id)
	}
}

func (*WhatsappService) ListEvents added in v0.16.0

func (s *WhatsappService) ListEvents(ctx context.Context, messageId string, params WhatsappListEventsParams, opts ...option.RequestOption) (*WhatsAppEventList, error)

ListEvents Get one WhatsApp message's delivery timeline, oldest first: whatsapp.accepted, whatsapp.sent, whatsapp.delivered, whatsapp.read, and whatsapp.failed events, with failure detail on failed events. Not paginated; an unknown message id is a 404. Use whatsapp_get for the condensed current status.

Example

List the lifecycle events for a WhatsApp message, in chronological order.

package main

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

	bird "github.com/messagebird/bird-sdk-go"
	"github.com/messagebird/bird-sdk-go/option"
)

func main() {
	client, err := bird.NewClient(option.WithAPIKey(os.Getenv("BIRD_API_KEY")))
	if err != nil {
		log.Fatal(err)
	}
	events, err := client.Whatsapp.ListEvents(context.Background(), "wam_01krdgeqcxet5s7t44vh8rt9mg", bird.WhatsappListEventsParams{})
	if err != nil {
		log.Fatal(err)
	}
	for _, e := range events.Data {
		fmt.Println(e.Id, e.Type)
	}
}

func (*WhatsappService) ListPage added in v0.16.0

func (s *WhatsappService) ListPage(ctx context.Context, params WhatsappListParams, startingAfter string, opts ...option.RequestOption) (*WhatsAppMessageList, error)

ListPage fetches one page of results. Pass the previous page's NextCursor as startingAfter to advance; "" starts from the first page.

func (*WhatsappService) Send added in v0.16.0

Send sends one WhatsApp template message. Retried safely: a single idempotency key is reused across attempts. Provide your own key with option.WithIdempotencyKey.

Example

Send a WhatsApp template message. Templates are currently the only supported content type.

package main

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

	bird "github.com/messagebird/bird-sdk-go"
	"github.com/messagebird/bird-sdk-go/option"
)

func main() {
	client, err := bird.NewClient(option.WithAPIKey(os.Getenv("BIRD_API_KEY")))
	if err != nil {
		log.Fatal(err)
	}
	msg, err := client.Whatsapp.Send(context.Background(), bird.WhatsappSendParams{
		To:       "+15551234567",
		Template: "bird_otp",
	})
	if err != nil {
		log.Fatal(err)
	}
	fmt.Println(msg.Id, *msg.Status)
}

Directories

Path Synopsis
examples
onboarding-sms command
internal
apierror
Package apierror holds the SDK's error model: the wire-error mapping and the typed error hierarchy returned to callers.
Package apierror holds the SDK's error model: the wire-error mapping and the typed error hierarchy returned to callers.
oapi
Package oapi provides primitives to interact with the openapi HTTP API.
Package oapi provides primitives to interact with the openapi HTTP API.
requestconfig
Package requestconfig holds the resolved per-request configuration.
Package requestconfig holds the resolved per-request configuration.
Package option carries the functional options that configure a bird.Client at construction and override settings for a single call.
Package option carries the functional options that configure a bird.Client at construction and override settings for a single call.

Jump to

Keyboard shortcuts

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