Sign inGet Started

Go SDK

github.com/messagebird/bird-sdk-go (package bird) è l'SDK Go SDK ufficiale per Bird API. Questa pagina copre installazione, configurazione, errori, ripetizioni, paginazione e webhook. Per inviare email con SDK, inizia dal quickstart email in Go.

Installazione

Esempio di codice
go get github.com/messagebird/bird-sdk-go
Richiede Go 1.24+. Esempi eseguibili per ogni metodo sono visibili sotto ciascun simbolo su pkg.go.dev.

Creare un client

bird.NewClient accetta opzioni funzionali dal package option. Solo la chiave API è obbligatoria. Il prefisso bk_{region}_… della chiave seleziona il base URL:
Esempio di codice
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)
}
Ogni metodo di API riceve il context come primo argomento e restituisce (T, error). Passa il context della tua richiesta per propagare la cancellazione come context.Canceled o context.DeadlineExceeded senza incapsularla in un errore SDK.

Opzioni

Le opzioni si applicano in ordine (un'opzione successiva prevale). Quattro sono solo per la costruzione e restituiscono un errore se passate a una singola chiamata: WithAPIKey, WithBaseURL, WithRegion e WithHTTPClient. Tutte le altre funzionano sia alla costruzione (default a livello di client) sia per chiamata (override per quella singola richiesta):
Esempio di codice
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))
OpzioneAmbitoFunzione
WithAPIKey, WithBaseURL, WithRegion, WithHTTPClientSolo costruzioneCredenziali, risoluzione dell'endpoint e *http.Client sottostante.
WithTimeout, WithMaxRetriesCostruzione o per chiamataTimeout per tentativo e budget di ripetizioni per errori transitori.
WithIdempotencyKeyPer chiamataFissa la chiave di idempotenza per una singola chiamata mutante (altrimenti ne viene generata una).
WithHeaderCostruzione o per chiamataHeader aggiuntivi per la richiesta. Gli header gestiti da SDK (Authorization, Idempotency-Key, …) prevalgono.
WithEmailDefaults, WithWebhookSecret, WithResponseIntoCostruzione o per chiamataValori predefiniti di invio a livello di canale, secret di firma del webhook e cattura raw dei metadati di trasporto.

Come è costruito

I tipi wire e il client di basso livello sono generati dalla specifica OpenAPI di Bird. Il package bird, scritto a mano, fornisce la superficie curata delle risorse (client.Email, client.Webhooks) e le struct dei parametri con tipi Go come []string e time.Time. I tipi di risposta sono alias dei modelli generati per restare allineati al formato wire. Il core gestisce ripetizioni, timeout e idempotenza per ogni risorsa. Consulta i concetti SDK per il modello completo.

Errori

Ogni errore del server è un *bird.APIError che contiene StatusCode, Type (la categoria di errore generale), Code (il codice E##### stabile), Message e RequestID per la correlazione con il supporto. Due varianti portano dati aggiuntivi: *bird.RateLimitError (un 429, con RetryAfter) e *bird.ValidationError (un 422, con Details per campo). Entrambe eseguono l'unwrap a *APIError, quindi un singolo errors.As(err, &apiErr) intercetta ogni risposta del server. Usa errors.As per distinguere:
Esempio di codice
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
		}
	}
}
Gli errori senza risposta HTTP sono tipi separati: *bird.ConnectionError (DNS, connessione rifiutata) e *bird.TimeoutError (un singolo tentativo ha superato il timeout). Una firma webhook non valida è *bird.WebhookVerificationError.

Ripetizioni sicure

Gli errori transitori, inclusi timeout, risposte 429 e risposte 5xx, vengono ripetuti automaticamente. Il budget predefinito è di due ripetizioni; regolalo con WithMaxRetries, oppure usa zero per disabilitare le ripetizioni. Per le chiamate mutanti, SDK genera una chiave di idempotenza per ogni chiamata logica e la riutilizza in tutti i tentativi. Passa option.WithIdempotencyKey per impostare la tua chiave e rendere sicure le ripetizioni a livello applicativo.

Paginazione

I metodi di lista restituiscono un iter.Seq2[*T, error], un iteratore lazy range-over-func che recupera le pagine man mano che le consumi:
Esempio di codice
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
}
Uscire dal ciclo interrompe il recupero; un errore di fetch viene restituito una sola volta e termina la sequenza. Per il controllo manuale del cursore, ListPage restituisce una pagina più il cursore successivo.

Webhook

client.Webhooks.Unwrap verifica una firma Standard Webhooks sul corpo raw della richiesta e restituisce un evento tipizzato. Configura il secret di firma con option.WithWebhookSecret sul client o per chiamata. Passa a Unwrap esattamente i byte ricevuti, perché il parsing e la ri-serializzazione invalidano la firma:
Esempio di codice
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)
		}
	})
}
Usa uno switch su event.Type() per il discriminante, oppure su AsAny() per il payload concreto. Un tipo di evento futuro sconosciuto restituisce un errore invece di andare in panic, così un SDK più vecchio continua a funzionare con un server più recente.

Scorciatoia di emergenza

Gli endpoint non ancora presenti nella superficie tipizzata sono raggiungibili tramite client.Get / Post / Put / Patch / Delete, con la stessa autenticazione, ripetizioni e gestione dell'idempotenza:
Esempio di codice
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))
}
Trova i path nel reference API.

Prossimi passi