Skip to main content

Twilio WhatsApp Connector

WhatsApp Business messaging through Twilio's API for WhatsApp.

Package

dotnet add package Ratatosk.Twilio

Required settings

ParameterTypeDescription
AccountSidstringTwilio account SID (starts with AC)
AuthTokenstringTwilio auth token (sensitive)

Optional settings

ParameterTypeDescription
WebhookUrlstringURL for inbound WhatsApp messages
StatusCallbackstringURL for delivery status callbacks

Number format

Phone numbers must use the whatsapp: prefix with E.164 format:

new MessageBuilder()
// Sender — must be a Twilio WhatsApp-enabled number
.FromPhone("whatsapp:+14155238886") // Twilio's default WhatsApp number
// Recipient — must have opted in to receive messages from your business
.ToPhone("whatsapp:+15550002222")
.WithText("Hello")
.Build();

Schema

PropertyValue
ProviderTwilio
TypeWhatsApp
Version1.0.0
CapabilitiesSendMessages, MessageStatusQuery, Templates
Content typesPlainText, Media, Template
EndpointsPhoneNumber (send + receive)
AuthenticationBasic (AccountSid + AuthToken)

Send examples

Text message

var settings = new ConnectionSettings()
.SetParameter("AccountSid", "AC...")
.SetParameter("AuthToken", "...");

var connector = new TwilioWhatsAppConnector(TwilioChannelSchemas.TwilioWhatsApp, settings);
await connector.InitializeAsync(ct);

var message = new MessageBuilder()
.WithId("wa-1")
.FromPhone("whatsapp:+14155238886")
.ToPhone("whatsapp:+15550002222")
.WithText("Hello from WhatsApp!")
.Build();

var result = await connector.SendMessageAsync(message, ct);

Template message (for business-initiated conversations)

WhatsApp requires approved templates for the first message to a user:

var message = new MessageBuilder()
.WithId("wa-template-1")
.ToPhone("whatsapp:+15550002222")
.WithContent(new TemplateContent("order_confirmed", new Dictionary<string, object?>
{
["order_id"] = "ORD-123",
["delivery_date"] = "2026-05-15"
}))
.Build();

Media message with caption

new MessageBuilder()
.FromPhone("whatsapp:+14155238886")
.ToPhone("whatsapp:+15550002222")
.WithContent(new MediaContent(MediaType.Image, "product.jpg",
"https://example.com/product.jpg"))
.WithProperty("caption", "Check out our new product!")
.Build();

Message properties

PropertyTypeDescription
captionstringCaption for media messages
ValidityPeriodintMessage validity in seconds

Webhook handling

Similar to Twilio SMS — inbound messages arrive as form POST with MessageSource.UrlPost():

[HttpPost("/webhooks/twilio/whatsapp")]
public async Task<IActionResult> WhatsAppWebhook(CancellationToken ct)
{
using var reader = new StreamReader(Request.Body);
var body = await reader.ReadAsStringAsync(ct);
var source = MessageSource.UrlPost(body);

var result = await _connector.ReceiveMessagesAsync(source, ct);
return TwiML.Empty;
}

Validate X-Twilio-Signature header before processing.

Error codes

Twilio-specific error codes are defined in TwilioErrorCodes with domain "Twilio".

CodeDescription
INVALID_CONNECTION_SETTINGSConnection settings validation failed
MISSING_FROM_NUMBERSender WhatsApp number is required
INVALID_SENDERSender number is not in valid whatsapp:+E164 format
INVALID_MESSAGEMessage properties failed schema validation
MISSING_CONTENT_SIDWhatsApp template Content SID is missing
INVALID_WHATSAPP_NUMBERWhatsApp number does not follow required format
SEND_WHATSAPP_MESSAGE_FAILEDWhatsApp message send failed via Twilio API
WHATSAPP_STATUS_QUERY_FAILEDWhatsApp message status query failed
STATUS_QUERY_FAILEDMessage status query failed
STATUS_ERRORConnector status retrieval failed
RECEIVE_MESSAGE_FAILEDIncoming message webhook processing failed
RECEIVE_STATUS_FAILEDStatus callback webhook processing failed

Standard MessagingErrorCodes are also used — see the error codes reference.

Original provider codes

Twilio API errors (ApiException) are mapped to framework error codes in TwilioService.MapTwilioErrorCode():

Twilio codeMapped framework code
21211INVALID_RECIPIENT
21610INVALID_RECIPIENT
21614INVALID_SENDER
21408INVALID_SENDER
20001INVALID_MESSAGE
OtherSEND_MESSAGE_FAILED

Troubleshooting

SymptomLikely causeFix
INVALID_RECIPIENTNumber without whatsapp: prefixUse whatsapp:+E164 format
Template rejectedTemplate not approvedVerify template status in Twilio Console
RATE_LIMITEDToo many messagesWhatsApp has per-conversation limits
No deliveryUser hasn't opted inUser must send first message or accept invite
Media not sentUnsupported formatCheck WhatsApp media requirements (max 64MB, specific formats)

TwilioChannelSchemas

// WhatsApp messaging schema
TwilioChannelSchemas.TwilioWhatsApp