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-goRequiere 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 | Ámbito | Qué hace |
|---|---|---|
| WithAPIKey, WithBaseURL, WithRegion, WithHTTPClient | Solo construcción | Credenciales, resolución del endpoint y el *http.Client subyacente. |
| WithTimeout, WithMaxRetries | Construcción o por llamada | Tiempo de espera por intento y presupuesto de reintentos para fallos transitorios. |
| WithIdempotencyKey | Por llamada | Fija la clave de idempotencia para una llamada mutante (se genera una automáticamente si no la proporcionas). |
| WithHeader | Construcción o por llamada | Encabezados de solicitud adicionales. Los encabezados propios de SDK (Authorization, Idempotency-Key, …) tienen prioridad. |
| WithEmailDefaults, WithWebhookSecret, WithResponseInto | Construcción o por llamada | Valores 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
- Inicio rápido de email en Go: Envía tu primer mensaje y usa Send, Get y List.
- Conceptos de SDK: Aprende el modelo multi-SDK para errores, idempotencia, paginación y webhooks.
- Referencia de API: Revisa el contrato HTTP subyacente.
Recursos relacionados
Continúa con la documentación, guías y ejemplos sobre este tema. Los recursos están en inglés.
Comprender el conceptoShould I use a Bird SDK or call the API directly?Seguir la ruta de aprendizajeBuild your first integrationGuía de implementaciónSend your first email
Obtener un resumen de implementación