Skip to main content
Version: Next (unreleased)

Core

Everything on this page lives in the root module (github.com/KARTIKrocks/gosms) and has no third-party dependencies.

Provider interface

Every backend — Twilio, SNS, Vonage, MSG91, and the mock provider — implements the same interface. Anything that satisfies it is a drop-in provider:

type Provider interface {
Send(ctx context.Context, msg *Message) (*Result, error)
SendBulk(ctx context.Context, msgs []*Message) ([]*Result, error)
GetStatus(ctx context.Context, messageID string) (*Status, error)
Name() string
}

Beyond this base interface, a provider may also implement one of two optional capabilities, detected with a type assertion:

  • OTPProviderSendOTP / VerifyOTP / ResendOTP. Currently implemented by MSG91.
  • WebhookParser — not an interface on Provider, but a documented func signature (func(*http.Request) (*Status, error)) that Twilio, Vonage, and MSG91 each expose as a package-level ParseWebhook. See Webhooks.

Client

Client wraps any Provider and adds convenience methods. It is safe for concurrent use after construction.

MethodDescription
Send(ctx, to, body)Send plain text — shortcut over SendMessage
SendMessage(ctx, msg)Send a fully-built Message (overrides, schedule, metadata)
SendBulk(ctx, msgs)Send a slice of Messages — see Bulk Messaging
GetStatus(ctx, id)Look up delivery status by provider message ID
Provider()Access the underlying Provider (for type assertions like OTPProvider)
ProviderName()The underlying provider's Name()
WithDefaultFrom(from)Set a default sender applied when a Message doesn't set one
client := gosms.NewClient(provider).WithDefaultFrom("+15551234567")

result, err := client.Send(ctx, "+15559876543", "Hello!")

Client.Send and SendMessage validate the message (Message.Validate) before delegating to the provider; an invalid message never reaches the network. SendBulk validates per-message and records validation failures as failed Results rather than aborting the whole batch — see Bulk Messaging.

Message builder

Build a message with the fluent API. Every With* method returns *Message for chaining.

msg := gosms.NewMessage("+15559876543", "Hello!").
WithFrom("+15551234567").
WithReference("order-123").
WithValidity(1 * time.Hour).
WithMetadata("user_id", "12345")

result, err := client.SendMessage(ctx, msg)
Field / methodPurpose
To, BodySet via NewMessage(to, body)
WithFrom(from)Sender ID or phone number
WithReference(ref)Client-supplied reference, echoed back where the provider supports it
WithSchedule(t)Schedule for future delivery (Twilio)
WithValidity(d)How long the message stays valid for delivery
WithMetadata(key, val)Arbitrary provider-specific data

Result and Status

Every send returns a *Result:

type Result struct {
MessageID string // Provider-assigned ID
To string // Recipient
Status DeliveryStatus
Provider string
Cost string
Currency string
Segments int
SentAt time.Time
Error string // Set on per-message failure (bulk)
Raw map[string]any // Raw provider response
}

if result.Success() {
log.Printf("Sent to %s: %s", result.To, result.MessageID)
}

Result.Success() means the provider accepted the message (accepted, sent, or delivered) — not that it was confirmed delivered. For confirmed delivery, check DeliveryStatus.IsSuccess() on a Status fetched via GetStatus or a webhook. See Errors for the full DeliveryStatus lifecycle.