Official SDKs
SMSGist SDKs handle authentication, token encryption, and retries automatically. Full documentation for every SDK is below — no README required.
| Language | Status | Package |
|---|---|---|
| Go | Available | devops.zedeks.com/go-packages/zNotification |
| PHP / Laravel | Available | smsgist/smsgist-php |
| Node.js | Available | @smsgist/node |
| Python | Coming soon | — |
Install
go get devops.zedeks.com/go-packages/zNotification@v2.0.0Environment Variables
Get your credentials from the dashboard under Apps.
ZN_CLIENT_ID=your-client-id
ZN_CLIENT_SECRET=your-client-secret
ZN_APP_KEY=your-32-byte-encryption-key
ZN_URI=https://api.smsgist.comSend SMS
Send to one or many recipients. Use MessageOtp() for OTP messages with priority routing.
package main
import (
"fmt"
"log"
zNotification "devops.zedeks.com/go-packages/zNotification"
)
func main() {
client, err := zNotification.New("smsgist")
if err != nil {
log.Fatal(err)
}
// Basic SMS
resp, err := client.Send("sms").
To("0240000001", "0240000002").
From("MyApp").
Message("Hello World").
Exec()
if err != nil {
log.Fatal(err)
}
fmt.Println(resp.MessageID) // "9b1deb4d-..."
fmt.Println(resp.Status) // "queued"
fmt.Println(resp.RecipientsCount) // 2
// OTP with priority routing
resp, err = client.Send("sms").
To("0240000001").
MessageOtp("Your verification code is 123456").
Exec()
// With idempotency key (prevents duplicate sends on retry)
resp, err = client.Send("sms").
To("0240000001").
Message("Order #1234 confirmed").
IdempotencyKey("order-confirm-1234").
Exec()
}Send Email
Send HTML email with optional reply-to and tracking controls.
// Basic email
resp, err := client.Send("email").
To("user@example.com").
From("My App").
Subject("Welcome!").
Message("<h1>Hello</h1><p>Welcome to our platform.</p>").
Exec()
if err != nil {
log.Fatal(err)
}
// With reply-to and no tracking
resp, err = client.Send("email").
To("user@example.com").
From("Billing").
Subject("Your Invoice").
Message("<p>Invoice attached.</p>").
ReplyTo("billing@myapp.com").
NoTracking().
Exec()Delivery Status
Poll delivery status for a sent message using its message ID.
status, err := client.GetDeliveryStatus("message-id")
if err != nil {
log.Fatal(err)
}
fmt.Println(status.Delivered) // int — delivered recipients
fmt.Println(status.Pending) // int — pending recipients
fmt.Println(status.Failed) // int — failed recipientsRetry Failed
Retry a previously failed message. Returns a new response with a new message ID.
resp, err := client.Retry("message-id")
if err != nil {
log.Fatal(err)
}
fmt.Println(resp.MessageID) // new message ID
fmt.Println(resp.Status) // "queued"Credit Balance
Check available credit balance for your organisation.
balance, err := client.GetCreditBalance()
if err != nil {
log.Fatal(err)
}
fmt.Println(balance.Available) // 150.50
fmt.Println(balance.Reserved) // 10.00
fmt.Println(balance.Currency) // "GHS"Modes
Control send behaviour during development. The backend credential mode is the source of truth; client-level overrides are for local use only.
// Live — sends to real recipients (default)
client, _ := zNotification.New("smsgist",
zNotification.WithModeOverride(zNotification.ModeLive),
)
// DryRun — logs only, no real sends, no credits consumed
client, _ = zNotification.New("smsgist",
zNotification.WithModeOverride(zNotification.ModeDryRun),
)
// Test — sends to test phone/email instead of real recipients
client, _ = zNotification.New("smsgist",
zNotification.WithModeOverride(zNotification.ModeTest),
zNotification.WithTestPhone("0249999999"),
zNotification.WithTestEmail("test@example.com"),
)Idempotency
Prevent duplicate sends when retrying requests. The API deduplicates based on the key within a 24-hour window.
// Pass any stable, unique string as the idempotency key.
// If the same key is sent twice, the second request returns
// the original response without sending a new message.
resp, err := client.Send("sms").
To("0240000001").
Message("Your order #5678 has shipped").
IdempotencyKey("order-shipped-5678").
Exec()Webhook Verification
Verify incoming webhook signatures to ensure requests come from SMSGist. Uses HMAC-SHA256 with 5-minute replay protection.
import (
"io"
"net/http"
zNotification "devops.zedeks.com/go-packages/zNotification"
)
func webhookHandler(w http.ResponseWriter, r *http.Request) {
body, _ := io.ReadAll(r.Body)
if !zNotification.VerifyWebhookSignature(
body,
r.Header.Get("X-SMSGist-Signature"),
r.Header.Get("X-SMSGist-Timestamp"),
webhookSecret,
) {
http.Error(w, "Invalid signature", 401)
return
}
// Signature verified — process the event
w.WriteHeader(200)
}Error Handling
Errors are typed so you can handle API errors, validation errors, and sentinel errors separately.
import (
"errors"
"fmt"
zNotification "devops.zedeks.com/go-packages/zNotification"
"devops.zedeks.com/go-packages/zNotification/gateway"
)
resp, err := client.Send("sms").
To("0240000001").
Message("Hello").
Exec()
if err != nil {
var apiErr *gateway.APIError
if errors.As(err, &apiErr) {
// HTTP-level error from the SMSGist API
fmt.Println("API error:", apiErr.StatusCode, apiErr.Body)
} else if errors.Is(err, zNotification.ErrMissingRecipients) {
fmt.Println("No recipients provided")
} else {
fmt.Println("Unexpected error:", err)
}
}All Options
Full list of functional options available when constructing a client.
import (
"log/slog"
"time"
zNotification "devops.zedeks.com/go-packages/zNotification"
)
client, err := zNotification.New("smsgist",
zNotification.WithModeOverride(zNotification.ModeLive),
zNotification.WithTestPhone("0249999999"), // redirect SMS in Test mode
zNotification.WithTestEmail("test@example.com"), // redirect email in Test mode
zNotification.WithTimeout(60 * time.Second), // default: 30s
zNotification.WithLogger(slog.Default()), // structured logger
)Notes
- Zero external dependencies — uses the standard library only
- Automatic token encryption using your App Key
- Thread-safe token caching with sync.RWMutex
- Supports DryRun, Test, and Live modes
- Built-in idempotency key support
- Go 1.21+
