Sign inGet Started

Go SDK

github.com/messagebird/bird-sdk-go (pacote bird) é o SDK Go oficial para a Bird API. Esta página cobre instalação, configuração, erros, retentativas, paginação e webhooks. Para enviar e-mail com o SDK, comece pelo Quickstart de e-mail em Go.

Instalação

Exemplo de código
go get github.com/messagebird/bird-sdk-go
Requer Go 1.24+. Exemplos executáveis por método aparecem sob cada símbolo no pkg.go.dev.

Criar um client

bird.NewClient aceita opções funcionais do pacote option. Apenas a chave API é obrigatória. O prefixo bk_{region}_… da chave seleciona a URL base:
Exemplo de código
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)
}
Todo método de API recebe o contexto primeiro e retorna (T, error). Passe o contexto da sua solicitação para propagar o cancelamento como context.Canceled ou context.DeadlineExceeded sem encapsulá-lo em um erro SDK.

Opções

As opções são aplicadas em ordem (a última vence). Quatro são somente de construção e retornam erro se passadas em uma chamada individual: WithAPIKey, WithBaseURL, WithRegion e WithHTTPClient. Todas as demais funcionam tanto na construção (padrão para todo o client) quanto por chamada (substituição para aquela solicitação específica):
Exemplo de código
client, err := bird.NewClient(
  option.WithAPIKey(os.Getenv("BIRD_API_KEY")),
  option.WithTimeout(10*time.Second), // per-attempt; each retry gets a fresh budget
)

// This send does not retry transient failures.
msg, err := client.Email.Send(ctx, params, option.WithMaxRetries(0))
OpçãoEscopoO que faz
WithAPIKey, WithBaseURL, WithRegion, WithHTTPClientSomente construçãoCredenciais, resolução de endpoint e o *http.Client subjacente.
WithTimeout, WithMaxRetriesConstrução ou por chamadaTimeout por tentativa e o limite de retentativas para falhas transitórias.
WithIdempotencyKeyPor chamadaFixa a chave de idempotência para uma chamada mutável (uma é gerada automaticamente caso contrário).
WithHeaderConstrução ou por chamadaHeaders extras de solicitação. Headers controlados por SDK (Authorization, Idempotency-Key, …) têm prioridade.
WithEmailDefaults, WithWebhookSecret, WithResponseIntoConstrução ou por chamadaPadrões de envio para todo o canal, o segredo de assinatura de webhook e captura bruta de metadados de transporte.

Como é construído

Os tipos de protocolo e o client de baixo nível são gerados a partir da especificação OpenAPI do Bird. O pacote bird, escrito manualmente, fornece a superfície curada de recursos (client.Email, client.Webhooks) e structs de parâmetros com tipos Go como []string e time.Time. Seus tipos de resposta são aliases dos modelos gerados para manter alinhamento com o formato de protocolo. O núcleo gerencia retentativas, timeouts e idempotência para cada recurso. Consulte Conceitos do SDK para o modelo completo.

Erros

Toda falha de servidor é um *bird.APIError contendo StatusCode, Type (a categoria de erro geral), Code (o código E##### estável), Message e RequestID para correlação com o suporte. Duas variantes carregam dados extras: *bird.RateLimitError (um 429, com RetryAfter) e *bird.ValidationError (um 422, com Details por campo). Ambas fazem unwrap para *APIError, então um único errors.As(err, &apiErr) captura toda resposta do servidor. Diferencie com errors.As:
Exemplo de código
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
		}
	}
}
Falhas sem resposta HTTP são tipos separados: *bird.ConnectionError (DNS, conexão recusada) e *bird.TimeoutError (uma tentativa individual excedeu seu timeout). Uma assinatura de webhook inválida é *bird.WebhookVerificationError.

Retentativas seguras

Falhas transitórias, incluindo timeouts, respostas 429 e respostas 5xx, são retentadas automaticamente. O limite padrão é duas retentativas; ajuste-o com WithMaxRetries ou use zero para desativar retentativas. Para chamadas mutáveis, o SDK gera uma chave de idempotência por chamada lógica e a reutiliza em todas as tentativas. Passe option.WithIdempotencyKey para definir sua própria chave e tornar retentativas no nível da aplicação seguras.

Paginação

Métodos de listagem retornam um iter.Seq2[*T, error], um iterador lazy range-over-func que busca páginas conforme você o consome:
Exemplo de código
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
}
Sair do loop interrompe a busca; um erro de fetch é emitido uma vez e encerra a sequência. Para controle manual de cursor, ListPage retorna uma página mais o próximo cursor.

Webhooks

client.Webhooks.Unwrap verifica uma assinatura Standard Webhooks sobre o corpo bruto da solicitação e retorna um evento tipado. Configure o segredo de assinatura com option.WithWebhookSecret no client ou por chamada. Passe para Unwrap os bytes exatos que você recebeu, porque analisar e re-serializar os dados invalida a assinatura:
Exemplo de código
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)
		}
	})
}
Use switch em event.Type() para o discriminante, ou AsAny() para o payload concreto. Um tipo de evento futuro desconhecido retorna um erro em vez de causar panic, então um SDK mais antigo continua funcionando com um servidor mais recente.

Alternativa direta

Endpoints ainda não disponíveis na superfície tipada podem ser acessados via client.Get / Post / Put / Patch / Delete, com a mesma autenticação, retentativas e tratamento de idempotência:
Exemplo de código
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))
}
Encontre os paths na Referência do API.

Próximos passos