eSMS AfricaeSMS Africa
SDKs

Go

Official Go SDK for the eSMS Africa SMS API.

The esms-go module uses the standard library only — no third-party dependencies. Requests take a context.Context, so timeouts and cancellation work as usual.

Install

go get github.com/eSMS-Africa/esms-go

Quickstart

main.go
package main

import (
	"context"
	"fmt"
	"log"
	"os"

	esms "github.com/eSMS-Africa/esms-go"
)

func main() {
	client := esms.New(os.Getenv("ESMS_API_KEY"))

	res, err := client.Messages.Send(context.Background(), esms.SendParams{
		To:       "+256700000000",
		Text:     "Your verification code is 123456",
		SenderID: "eSMSAfrica", // optional — falls back to the route default
	})
	if err != nil {
		log.Fatal(err)
	}
	fmt.Println(res.ID, res.Status) // "…", "submitted"
}

Get an API key in the dashboard under Developers → API Keys.

Sending

ctx := context.Background()

// Auto-detects the route (country) from the number.
client.Messages.Send(ctx, esms.SendParams{To: "+254711000000", Text: "Hi from Kenya"})

// Or pin a route explicitly.
client.Messages.Send(ctx, esms.SendParams{To: "+256700000000", Text: "Hi", Route: "ESMS_UG"})

// Schedule for later (5 minutes to 7 days out).
client.Messages.Schedule(ctx, esms.SendParams{
	To:          "+256700000000",
	Text:        "Reminder",
	ScheduledAt: "2026-08-01T09:00:00Z",
})

Delivery status

msg, _ := client.Messages.Get(ctx, res.ID)
fmt.Println(msg.Status) // queued | submitted | delivered | failed | …
for _, e := range msg.Timeline {
	fmt.Println(e.At, e.Event)
}

// List recent messages
page, _ := client.Messages.List(ctx, esms.ListParams{Limit: 20, Status: "delivered"})
fmt.Println(page.Total)

// Retry a failed one
client.Messages.Retry(ctx, res.ID)

Balance & routes

bal, _ := client.Balance.Get(ctx)
fmt.Printf("%s %.2f\n", bal.Currency, bal.Balance)

routes, _ := client.Routes.List(ctx)
for _, r := range routes {
	fmt.Println(r.Code, r.CountryName, r.Currency, r.PricePerSegment)
}

Error handling

Every API failure is an *esms.Error. Use errors.As and the helper methods:

import "errors"

res, err := client.Messages.Send(ctx, params)
if err != nil {
	var e *esms.Error
	if errors.As(err, &e) {
		switch {
		case e.IsInsufficientBalance():
			bal, _ := e.Balance()
			cost, _ := e.Cost()
			cur, _ := e.Currency()
			log.Printf("top up: have %.2f, need %.2f %s", bal, cost, cur)
		case e.IsAuthentication():
			log.Print("check your API key")
		default:
			log.Printf("%d %s: %s", e.Status, e.Code, e.Message)
		}
	}
}
HelperWhen
IsAuthentication()401 — key missing or invalid
IsPermission()403 — not allowed
IsNotFound()404 — no such message
IsInsufficientBalance()422 — not enough credit (Balance(), Cost(), Currency())
IsRateLimit()429 — slow down
IsConnection()network failure or timeout

Configuration

client := esms.New("esms_live_...",
	esms.WithBaseURL("https://sms.esmsafrica.io/api"), // default
	esms.WithMaxRetries(2),                            // transient failures with backoff
	esms.WithHTTPClient(&http.Client{Timeout: 30 * time.Second}),
)

On this page