@xenterprises/fastify-xtwilio
v1.2.1
Published
Fastify plugin for Twilio communications (SMS, Conversations, RCS) and SendGrid email.
Readme
@xenterprises/fastify-xtwilio
Fastify v5 plugin for Twilio communications (SMS, Conversations, RCS) and SendGrid email. Decorates the Fastify instance with sms, conversations, rcs, and email services.
Installation
npm install @xenterprises/fastify-xtwilioUsage
import Fastify from "fastify";
import xTwilio from "@xenterprises/fastify-xtwilio";
const fastify = Fastify();
await fastify.register(xTwilio, {
twilio: {
accountSid: process.env.TWILIO_ACCOUNT_SID,
authToken: process.env.TWILIO_AUTH_TOKEN,
phoneNumber: process.env.TWILIO_PHONE_NUMBER,
messagingServiceSid: process.env.TWILIO_MESSAGING_SERVICE_SID,
},
sendgrid: {
apiKey: process.env.SENDGRID_API_KEY,
fromEmail: process.env.SENDGRID_FROM_EMAIL,
fromName: process.env.SENDGRID_FROM_NAME,
},
});
// Send SMS
await fastify.sms.send("+1234567890", "Hello!");
// Send email
await fastify.email.send("[email protected]", "Welcome", "<h1>Hi</h1>");Options
twilio
| Name | Type | Default | Required | Description |
|------|------|---------|----------|-------------|
| accountSid | string | — | Yes (if active) | Twilio Account SID |
| authToken | string | — | Yes (if active) | Twilio Auth Token |
| phoneNumber | string | — | One of phone/msgSvc | Phone number for SMS (E.164 format) |
| messagingServiceSid | string | — | One of phone/msgSvc | Messaging Service SID (required for RCS, scheduled SMS) |
| active | boolean | true | No | Set false to disable all Twilio services |
sendgrid
| Name | Type | Default | Required | Description |
|------|------|---------|----------|-------------|
| apiKey | string | — | Yes (if active) | SendGrid API key |
| fromEmail | string | — | Yes (if active) | Verified sender email address |
| fromName | string | — | No | Display name for the sender |
| active | boolean | true | No | Set false to disable email service |
Decorated Properties
fastify.sms
| Method | Signature | Description |
|--------|-----------|-------------|
| send | (to, body, extraOptions?) => Promise | Send an SMS message |
| sendMMS | (to, body, mediaUrl, extraOptions?) => Promise | Send an MMS with media attachment(s) |
| schedule | (to, body, sendAt) => Promise | Schedule an SMS (requires messagingServiceSid) |
| cancelScheduled | (messageSid) => Promise | Cancel a scheduled message |
| get | (messageSid) => Promise | Fetch a message by SID |
| getStatus | (messageSid) => Promise | Get delivery status of a message |
| list | (filters?) => Promise | List messages with optional filters |
| delete | (messageSid) => Promise<boolean> | Delete a message |
| getMedia | (messageSid) => Promise | Get media items from an MMS |
| validatePhoneNumber | (phoneNumber, options?) => Promise | Validate a phone number via Twilio Lookup v2 |
| sendBulk | (messages) => Promise | Send multiple SMS concurrently |
fastify.conversations
| Method | Signature | Description |
|--------|-----------|-------------|
| create | (friendlyName, attributes?) => Promise | Create a new conversation |
| get | (conversationSid) => Promise | Get conversation by SID |
| update | (conversationSid, updates) => Promise | Update conversation properties |
| list | (filters?) => Promise | List all conversations |
| delete | (conversationSid) => Promise<boolean> | Delete a conversation |
| addParticipant | (conversationSid, identity?, address?) => Promise | Add a chat or SMS participant |
| listParticipants | (conversationSid) => Promise | List conversation participants |
| removeParticipant | (conversationSid, participantSid) => Promise<boolean> | Remove a participant |
| sendMessage | (conversationSid, body, author?, attributes?) => Promise | Send a text message |
| sendMediaMessage | (conversationSid, mediaUrl, body?, author?) => Promise | Send a media message |
| getMessages | (conversationSid, options?) => Promise | List conversation messages |
| getMessage | (conversationSid, messageSid) => Promise | Get a specific message |
| deleteMessage | (conversationSid, messageSid) => Promise<boolean> | Delete a message |
| getWebhooks | (conversationSid) => Promise | List conversation webhooks |
| createWebhook | (conversationSid, webhookConfig) => Promise | Create a conversation webhook |
fastify.rcs
Only registered when messagingServiceSid is provided.
| Method | Signature | Description |
|--------|-----------|-------------|
| send | (to, body, extraOptions?) => Promise | Send a basic RCS text message |
| sendMedia | (to, body, mediaUrl) => Promise | Send an RCS message with media |
| sendTemplate | (to, contentSid, contentVariables?) => Promise | Send using a Content Template |
| sendRichCard | (to, card) => Promise | Send a rich card (title, description, media, actions) |
| sendCarousel | (to, cards) => Promise | Send a carousel of cards |
| sendQuickReplies | (to, body, replies) => Promise | Send with suggested quick replies |
| getStatus | (messageSid) => Promise | Get RCS message delivery status |
| listTemplates | (options?) => Promise | List Content API templates |
| getTemplate | (contentSid) => Promise | Get a template by SID |
| deleteTemplate | (contentSid) => Promise<boolean> | Delete a template |
fastify.email
| Method | Signature | Description |
|--------|-----------|-------------|
| send | (to, subject, html, text?, extraOptions?) => Promise | Send an email |
| sendTemplate | (to, subject, templateId, dynamicData?, extraOptions?) => Promise | Send using a SendGrid template |
| sendWithAttachments | (to, subject, html, attachments) => Promise | Send with file attachments |
| sendBulk | (to[], subject, html) => Promise | Send same content to multiple recipients |
| sendPersonalizedBulk | (messages[]) => Promise | Send different content per recipient |
| validate | (email) => Promise | Validate an email address |
| addContact | (email, data?, listIds?) => Promise | Add/update a marketing contact |
| searchContact | (email) => Promise | Search for a contact by email |
| deleteContact | (contactId) => Promise<boolean> | Delete a marketing contact |
| createList | (name) => Promise | Create a contact list |
| getLists | () => Promise | Get all contact lists |
| deleteList | (listId) => Promise<boolean> | Delete a contact list |
Environment Variables
| Name | Required | Description |
|------|----------|-------------|
| TWILIO_ACCOUNT_SID | Yes* | Twilio Account SID |
| TWILIO_AUTH_TOKEN | Yes* | Twilio Auth Token |
| TWILIO_PHONE_NUMBER | One of** | SMS sender phone number |
| TWILIO_MESSAGING_SERVICE_SID | One of** | Messaging Service SID |
| SENDGRID_API_KEY | Yes*** | SendGrid API key |
| SENDGRID_FROM_EMAIL | Yes*** | Verified sender email |
| SENDGRID_FROM_NAME | No | Sender display name |
* Required when twilio.active !== false
** At least one of phoneNumber or messagingServiceSid is required for Twilio services
*** Required when sendgrid.active !== false
Error Reference
All errors thrown by the plugin are prefixed with [xTwilio] for easy identification in logs.
| Error Pattern | When |
|---------------|------|
| [xTwilio] twilio option must be an object. | twilio is not an object |
| [xTwilio] sendgrid option must be an object. | sendgrid is not an object |
| [xTwilio] twilio.accountSid (string) is required for SMS. | Missing or invalid accountSid |
| [xTwilio] twilio.authToken (string) is required for SMS. | Missing or invalid authToken |
| [xTwilio] sendgrid.apiKey (string) is required for Email service. | Missing or invalid apiKey |
| [xTwilio] sendgrid.fromEmail (string) is required for Email service. | Missing or invalid fromEmail |
| [xTwilio] sms.send: to (string) is required. | Method called without required argument |
| [xTwilio] Failed to send SMS: <message> | Twilio API error during send |
Every public method validates its inputs before making API calls. If validation fails, the error message identifies the service, method, and missing parameter (e.g., [xTwilio] sms.send: to (string) is required.).
How It Works
Registration — The plugin validates top-level option shapes, then calls four setup functions in sequence:
setupSMS,setupConversations,setupRCS, andsetupEmail. Each setup function can be skipped by settingactive: falseon its parent options object (or, for RCS, by omittingmessagingServiceSid).Twilio client — Each Twilio-based service (SMS, Conversations, RCS) creates its own
Twilio(accountSid, authToken)client. This keeps services isolated and avoids cross-contamination if they are registered in different Fastify scopes.Fastify decorators — Each service decorates the Fastify instance:
fastify.sms,fastify.conversations,fastify.rcs,fastify.email. Because the plugin is wrapped withfastify-plugin, decorators are visible to the enclosing scope.Input validation — Every public method checks required arguments before calling external APIs. This catches developer errors early with clear messages rather than letting them surface as cryptic Twilio/SendGrid errors.
Error handling — API call failures are caught, logged via
fastify.log.error, and re-thrown with a[xTwilio]prefix and the original error message. No credentials are ever included in error output.SendGrid from field — If
fromNameis provided, the from field is sent as{ email, name }to display a friendly sender name. Otherwise, just the email string is used.
License
UNLICENSED
