Sign inGet started

Go SDK

github.com/messagebird/bird-sdk-go (paquete bird) es el SDK oficial de Go para la API de Bird. Esta página cubre instalación, configuración, errores, reintentos, paginación y webhooks. Para enviar correo electrónico con el SDK, empieza con el inicio rápido de email en Go.

Instalación

Ejemplo de código
go get github.com/messagebird/bird-sdk-go
Requiere Go 1.24+. Los ejemplos ejecutables por método aparecen bajo cada símbolo en pkg.go.dev.

Crear un cliente

bird.NewClient acepta opciones funcionales del paquete option. Solo la clave API es obligatoria. El prefijo bk_{region}_… de la clave selecciona la URL base:
Ejemplo 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)
}
Cada método de API recibe el contexto como primer argumento y devuelve (T, error). Pasa el contexto de tu solicitud para propagar la cancelación como context.Canceled o context.DeadlineExceeded sin envolverla en un error SDK.

Opciones

Las opciones se aplican en orden (la última gana). Cuatro son solo de construcción y devuelven un error si se pasan a una llamada individual: WithAPIKey, WithBaseURL, WithRegion y WithHTTPClient. Todo lo demás funciona tanto en la construcción (valor predeterminado del cliente) como por llamada (una anulación para esa solicitud):
Ejemplo 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))
OpciónÁmbitoQué hace
WithAPIKey, WithBaseURL, WithRegion, WithHTTPClientSolo construcciónCredenciales, resolución del endpoint y el *http.Client subyacente.
WithTimeout, WithMaxRetriesConstrucción o por llamadaTiempo de espera por intento y presupuesto de reintentos para fallos transitorios.
WithIdempotencyKeyPor llamadaFija la clave de idempotencia para una llamada mutante (se genera una automáticamente si no la proporcionas).
WithHeaderConstrucción o por llamadaEncabezados de solicitud adicionales. Los encabezados propios de SDK (Authorization, Idempotency-Key, …) tienen prioridad.
WithEmailDefaults, WithWebhookSecret, WithResponseIntoConstrucción o por llamadaValores de envío predeterminados del canal, el secreto de firma de webhooks y captura de metadatos de transporte sin procesar.

Cómo está construido

Los tipos de red y el cliente de bajo nivel se generan a partir de la especificación OpenAPI de Bird. El paquete bird, escrito a mano, proporciona la superficie de recursos curada (client.Email, client.Webhooks) y structs de parámetros con tipos de Go como []string y time.Time. Sus tipos de respuesta son alias de los modelos generados para mantenerse alineados con el formato de red. El núcleo gestiona reintentos, tiempos de espera e idempotencia para cada recurso. Consulta conceptos de SDK para el modelo completo.

Errores

Cada fallo del servidor es un *bird.APIError que contiene StatusCode, Type (la categoría de error general), Code (el código estable de E#####), Message y RequestID para correlación con soporte. Dos variantes incluyen datos adicionales: *bird.RateLimitError (un 429, con RetryAfter) y *bird.ValidationError (un 422, con Details por campo). Ambas se desenvuelven a *APIError, así que un solo errors.As(err, &apiErr) captura cualquier respuesta del servidor. Diferencia con errors.As:
Ejemplo 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
		}
	}
}
Los fallos sin respuesta HTTP son tipos separados: *bird.ConnectionError (DNS, conexión rechazada) y *bird.TimeoutError (un intento individual excedió su tiempo de espera). Una firma de webhook inválida es *bird.WebhookVerificationError.

Reintentos seguros

Los fallos transitorios, incluyendo tiempos de espera, respuestas 429 y respuestas 5xx, se reintentan automáticamente. El presupuesto predeterminado es de dos reintentos; ajústalo con WithMaxRetries, o usa cero para desactivar los reintentos. Para llamadas mutantes, el SDK genera una clave de idempotencia por llamada lógica y la reutiliza en cada intento. Pasa option.WithIdempotencyKey para establecer tu propia clave y hacer seguros los reintentos a nivel de aplicación.

Paginación

Los métodos de listado devuelven un iter.Seq2[*T, error], un iterador perezoso range-over-func que obtiene páginas a medida que lo consumes:
Ejemplo 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
}
Salir del bucle detiene la obtención de páginas; un error de obtención se emite una vez y termina la secuencia. Para control manual del cursor, ListPage devuelve una página más el siguiente cursor.

Webhooks

client.Webhooks.Unwrap verifica una firma de Standard Webhooks sobre el cuerpo sin procesar de la solicitud y devuelve un evento tipado. Configura el secreto de firma con option.WithWebhookSecret en el cliente o por llamada. Pasa a Unwrap los bytes exactos que recibiste, porque analizarlos y volver a serializarlos rompe la firma:
Ejemplo 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)
		}
	})
}
Usa switch sobre event.Type() para el discriminante, o AsAny() para el payload concreto. Un tipo de evento futuro desconocido devuelve un error en lugar de provocar un panic, así que un SDK anterior sigue funcionando contra un servidor más nuevo.

Alternativa directa

Los endpoints que aún no están en la superficie tipada son accesibles mediante client.Get / Post / Put / Patch / Delete, con la misma autenticación, reintentos y gestión de idempotencia:
Ejemplo 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))
}
Encuentra las rutas en la referencia de API.

Próximos pasos