Go SDK

github.com/usezend/zend-go is the official Go client for Zend. It wraps the messaging API in one typed client, so you can send SMS, WhatsApp, email, and voice — and read templates — without hand-rolling HTTP requests.

Note

The SDK is open source on GitHub and documented on pkg.go.dev.

Installation

go get github.com/usezend/zend-go

Requires Go 1.21 or later. It uses only the standard library — no third-party dependencies.

Authenticate

Create a client with your API key (find it in your Zend dashboard):

import zend "github.com/usezend/zend-go"

client, err := zend.New("sent_live_...")
if err != nil {
	log.Fatal(err)
}

You can also set the ZEND_API_KEY environment variable and construct the client with an empty key:

client, err := zend.New("")

Note

Keep your API key secret — never expose it in client-side code. Store it in an environment variable rather than committing it to source control.

Every method returns (*T, error). On failure the error is a *zend.Error — check err before using the result (see Errors).

Send an SMS

res, err := client.Messages.Send(zend.SendMessageParams{
	To:                "+233201234567",
	Body:              "Hello from Zend!",
	PreferredChannels: []zend.Channel{zend.ChannelSMS},
	SenderID:          "MyBrand",
})
if err != nil {
	log.Fatal(err)
}
fmt.Printf("Message %s (%s)\n", res.ID, res.Status)
Tostringrequired
Recipient phone number in E.164 format.
Bodystring
Message text. Omit when sending a template.
PreferredChannels[]zend.Channel
Channels to attempt, in order — one or more of zend.ChannelSMS, zend.ChannelWhatsApp.
SenderIDstring
Your approved SMS sender ID. Omit to use your account default.
FallbackEnabled*bool
Try the next channel if one fails. Use the zend.Bool(true) helper so an explicit false is sent.
Prioritystring
low · normal · high · urgent.
DeliveryPrioritystring
cost · speed · reliability.
WebhookURLstring
URL to receive delivery-status callbacks.
ScheduledForstring
ISO 8601 timestamp to send later.

Send a WhatsApp message

WhatsApp business messages use approved templates, and can fall back to SMS:

_, err := client.Messages.Send(zend.SendMessageParams{
	To:                "+233201234567",
	TemplateID:        "welcome",
	TemplateParams:    map[string]any{"first_name": "John"},
	PreferredChannels: []zend.Channel{zend.ChannelWhatsApp, zend.ChannelSMS},
	FallbackEnabled:   zend.Bool(true),
})

See WhatsApp for templates, media, and delivery.

Send in bulk

_, err := client.Messages.SendBulk(zend.BulkMessageParams{
	Messages: []zend.BulkMessageItem{
		{To: "+233201234567", Body: "Hi Ama!"},
		{To: "+233207654321", Body: "Your code is 123456"},
	},
	PreferredChannels: []zend.Channel{zend.ChannelSMS},
	SenderID:          "MyBrand",
})

See Bulk messaging for larger sends and personalization.

Send an email

email, err := client.Emails.Send(zend.SendEmailParams{
	From:    "you@example.com",
	To:      "user@gmail.com",
	Subject: "Hello world",
	HTML:    "<p>It works!</p>",
	Text:    "It works!",
})
Fromstringrequired
A verified sender address on one of your domains.
Tostringrequired
Recipient email address.
Subjectstringrequired
Subject line.
HTMLstring
HTML body.
Textstring
Plain-text fallback.
Attachments[]zend.EmailAttachment
Files to attach — see Attachments below.

Attachments

Attach files by passing an Attachments slice. Each file's Content is raw bytes, base64-encoded for you:

pdf, err := os.ReadFile("invoice.pdf")
if err != nil {
	log.Fatal(err)
}

_, err = client.Emails.Send(zend.SendEmailParams{
	From:    "you@example.com",
	To:      "user@gmail.com",
	Subject: "Your invoice",
	HTML:    "<p>Invoice attached.</p>",
	Attachments: []zend.EmailAttachment{
		{
			Filename:    "invoice.pdf",
			Content:     pdf,
			ContentType: "application/pdf",
		},
	},
})
Filenamestringrequired
File name shown to the recipient, including its extension.
Content[]byterequired
File data — raw bytes, base64-encoded for you.
ContentTypestring
MIME type, e.g. application/pdf. Set it so mail clients render the file correctly.

Note

Up to 10 attachments per email, and 7 MB total across all files (measured on the decoded bytes).

See Email for sending domains and deliverability.

Send a voice call

Read a message aloud with text-to-speech, falling back to SMS if the call isn't answered:

_, err := client.Voice.Send(zend.SendVoiceParams{
	Recipients: []string{"+233201234567"},
	Text:       "Your order has shipped.",
	Voice:      "female",
	Fallback:   &zend.VoiceFallback{SMS: true, SMSText: "Your order has shipped."},
})

Or play a pre-recorded audio file (a hosted MP3/WAV):

_, err := client.Voice.Send(zend.SendVoiceParams{
	Recipients: []string{"+233201234567"},
	VoiceURL:   "https://cdn.example.com/message.mp3",
})

To send a local audio file, upload it first with client.Voice.Upload(file, filename) (it takes an io.Reader) and pass the returned URL as VoiceURL. See Voice for audio, TTS, and billing.

Read templates

Templates are read-only from the SDK — list them and fetch one to reuse when sending:

list, err := client.Templates.List(zend.ListTemplatesParams{Category: "transactional"})

template, err := client.Templates.Get("welcome")

Track and manage messages

message, err := client.Messages.Get("6884da240f0e633b7b979bff")
_, err = client.Messages.Cancel("6884da240f0e633b7b979bff")

Voice batches expose per-recipient results:

batch, err := client.Voice.Get("voice_13d858b9-...")

Errors

Every method returns (*T, error). On failure the error is a *zend.Error, which you can inspect with errors.As:

res, err := client.Messages.Send(zend.SendMessageParams{To: "+233201234567", Body: "Hi"})
if err != nil {
	var zerr *zend.Error
	if errors.As(err, &zerr) {
		fmt.Println(zerr.Name, zerr.StatusCode, zerr.Message)
	}
	return
}
fmt.Println(res.ID)

*zend.Error carries:

Messagestring
Human-readable error description.
Namestring
Error category, e.g. api_error, timeout, application_error.
StatusCodeint
HTTP status code, when available.
Codestring
Provider error code, when available.

Next steps