Twilio¶
The Twilio provider uses omni-twilio for SMS, MMS, and RCS messaging via Twilio's REST API.
Installation¶
Configuration¶
import "github.com/plexusone/omnichat/providers/twilio"
p, err := twilio.New(twilio.Config{
AccountSID: "ACxxxxxxxx",
AuthToken: "your-auth-token",
PhoneNumber: "+15551234567", // Your Twilio phone number
Logger: slog.Default(),
})
Config Options¶
| Field | Type | Required | Description |
|---|---|---|---|
AccountSID |
string |
Yes | Twilio Account SID |
AuthToken |
string |
Yes | Twilio Auth Token |
PhoneNumber |
string |
No | Default outbound phone number (E.164 format) |
MessagingServiceSid |
string |
No | Messaging Service SID for RCS (enables RCS with SMS/MMS fallback) |
Logger |
*slog.Logger |
No | Logger instance |
Twilio Setup¶
- Sign up at Twilio
- Get your Account SID and Auth Token from the Console
- Buy or configure a phone number with SMS capability
Finding Your Credentials¶
- Go to Twilio Console
- Your Account SID and Auth Token are on the dashboard
- Click Phone Numbers > Manage > Active numbers for your phone numbers
Usage¶
Basic Setup¶
package main
import (
"context"
"log/slog"
"net/http"
"os"
"github.com/plexusone/omnichat/provider"
"github.com/plexusone/omnichat/providers/twilio"
)
func main() {
logger := slog.Default()
p, err := twilio.New(twilio.Config{
AccountSID: os.Getenv("TWILIO_ACCOUNT_SID"),
AuthToken: os.Getenv("TWILIO_AUTH_TOKEN"),
PhoneNumber: os.Getenv("TWILIO_PHONE_NUMBER"),
Logger: logger,
})
if err != nil {
panic(err)
}
router := provider.NewRouter(logger)
router.Register(p)
router.OnMessage(provider.All(), func(ctx context.Context, msg provider.IncomingMessage) error {
return router.Send(ctx, "twilio", msg.SenderID, provider.OutgoingMessage{
Content: "Thanks for your message!",
})
})
ctx := context.Background()
router.ConnectAll(ctx)
defer router.DisconnectAll(ctx)
// Set up webhook for incoming SMS
http.Handle("/sms", p.WebhookHandler())
http.ListenAndServe(":8080", nil)
}
Sending SMS¶
// Send SMS to a phone number
router.Send(ctx, "twilio", "+15559876543", provider.OutgoingMessage{
Content: "Hello from OmniChat!",
})
Sending MMS¶
Send media attachments (images, video, audio) via MMS:
// Send MMS with an image
router.Send(ctx, "twilio", "+15559876543", provider.OutgoingMessage{
Content: "Check out this photo!",
Media: []provider.Media{
{
Type: provider.MediaTypeImage,
URL: "https://example.com/photo.jpg",
},
},
})
// Send multiple media attachments
router.Send(ctx, "twilio", "+15559876543", provider.OutgoingMessage{
Content: "Here are the documents",
Media: []provider.Media{
{Type: provider.MediaTypeImage, URL: "https://example.com/image.jpg"},
{Type: provider.MediaTypeDocument, URL: "https://example.com/doc.pdf"},
},
})
Note: MMS requires a URL-accessible media file. The URL must be publicly accessible by Twilio's servers.
Sending RCS¶
RCS (Rich Communication Services) provides rich messaging with automatic fallback to SMS/MMS:
import "github.com/plexusone/omnichat/providers/twilio"
// Enable RCS by setting MessagingServiceSid
p, err := twilio.New(twilio.Config{
AccountSID: os.Getenv("TWILIO_ACCOUNT_SID"),
AuthToken: os.Getenv("TWILIO_AUTH_TOKEN"),
MessagingServiceSid: os.Getenv("TWILIO_MESSAGING_SERVICE_SID"), // RCS-enabled
Logger: logger,
})
// Send message - RCS attempted, falls back to SMS/MMS if unavailable
router.Send(ctx, "twilio", "+15559876543", provider.OutgoingMessage{
Content: "Hello via RCS!",
})
// Send RCS with content template (rich cards, carousels)
router.Send(ctx, "twilio", "+15559876543", provider.OutgoingMessage{
Content: "Order update",
Metadata: map[string]any{
"content_sid": "HXxxxxxxxx", // Pre-created content template
"content_variables": `{"1": "John", "2": "#12345"}`,
},
})
RCS Setup:
- Create a Messaging Service in the Twilio Console
- Add an RCS sender to your Messaging Service (requires carrier approval)
- Set
MessagingServiceSidin your configuration
RCS Features:
- Branded sender identity
- Rich cards and carousels (via Content API templates)
- Suggested replies and actions
- Read receipts and typing indicators
- Automatic fallback to SMS/MMS when RCS unavailable
Receiving SMS/MMS¶
Incoming SMS and MMS messages are received via Twilio webhooks. Configure your Twilio phone number to POST to your webhook endpoint:
- Go to Phone Numbers > Manage > Active numbers
- Click your phone number
- Under Messaging, set the webhook URL to your endpoint (e.g.,
https://yourapp.com/sms)
Handling Incoming Media (MMS)¶
When receiving MMS messages, media attachments are automatically extracted:
router.OnMessage(provider.All(), func(ctx context.Context, msg provider.IncomingMessage) error {
// Check for media attachments
for _, media := range msg.Media {
fmt.Printf("Received %s: %s\n", media.Type, media.URL)
fmt.Printf("MIME type: %s\n", media.MimeType)
}
// Text content is still available
fmt.Println("Message:", msg.Content)
return nil
})
Media types supported:
| Type | Description |
|---|---|
MediaTypeImage |
Images (JPEG, PNG, GIF, etc.) |
MediaTypeVideo |
Videos (MP4, etc.) |
MediaTypeAudio |
Audio files (MP3, WAV, etc.) |
MediaTypeDocument |
Other files (PDF, etc.) |
Message Mapping¶
| Twilio | OmniChat |
|---|---|
| MessageSid | ID |
| From | SenderID |
| To | ChatID |
| Body | Content |
| MediaUrl0, MediaUrl1, ... | Media (slice of attachments) |
| MediaContentType0, ... | Media[].MimeType |
| NumMedia | Number of items in Media |
Environment Variables¶
TWILIO_ACCOUNT_SID=ACxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx
TWILIO_AUTH_TOKEN=your_auth_token_here
TWILIO_PHONE_NUMBER=+15551234567
TWILIO_MESSAGING_SERVICE_SID=MGxxxxxxxx # Optional: for RCS
Webhook Security¶
For production, validate incoming webhooks using Twilio's request signature:
Troubleshooting¶
SMS not sending¶
- Verify Account SID and Auth Token are correct
- Check phone number is SMS-capable
- Verify recipient number format (E.164:
+15551234567) - Check Twilio Console for error logs
Webhooks not receiving¶
- Verify webhook URL is publicly accessible
- Check Twilio Console for webhook errors
- Ensure endpoint returns 200 status code
- Verify TLS certificate is valid (Twilio requires HTTPS)
Phone number format¶
Always use E.164 format:
- Correct:
+15551234567 - Incorrect:
555-123-4567,(555) 123-4567
Limitations¶
- SMS character limits apply (160 for GSM-7, 70 for Unicode per segment)
- MMS media must be URL-accessible (no direct byte uploads)
- MMS availability depends on carrier and region support
- Maximum 10 media attachments per MMS