fastify-x-twilio
fastify-x-twilio
Fastify plugin combining Twilio and SendGrid communications. Registers a single fastify.xTwilio decorator namespace holding up to four services: sms (SMS/MMS), conversations (Twilio Conversations), rcs (RCS rich messaging, optional), and email (SendGrid transactional email).
Installation
npm install @xenterprises/fastify-xtwilio fastify@5
Quick Start
Register with only the services you need. A service whose option object is omitted is skipped silently — no active: false boilerplate required.
import Fastify from "fastify";
import xTwilio from "@xenterprises/fastify-xtwilio";
const fastify = Fastify();
await fastify.register(xTwilio, {
twilio: {
accountSid: process.env.TWILIO_ACCOUNT_SID, // consumer owns env access
authToken: process.env.TWILIO_AUTH_TOKEN,
phoneNumber: process.env.TWILIO_PHONE_NUMBER,
},
});
// Send an SMS
await fastify.xTwilio.sms.send("+15551234567", "Hello from Fastify!");
The plugin never reads process.env itself — all configuration arrives via register options. To add SendGrid email, include the sendgrid object:
await fastify.register(xTwilio, {
twilio: {
accountSid: process.env.TWILIO_ACCOUNT_SID,
authToken: process.env.TWILIO_AUTH_TOKEN,
phoneNumber: process.env.TWILIO_PHONE_NUMBER,
},
sendgrid: {
apiKey: process.env.SENDGRID_API_KEY,
fromEmail: process.env.SENDGRID_FROM_EMAIL,
},
});
await fastify.xTwilio.email.send("user@example.com", "Welcome!", "<h1>Welcome!</h1>");
A service object that is present but missing its credentials is a hard registration error (active defaults to true — explicit active: true without credentials still throws). You can also disable a service explicitly with active: false; omitting the object entirely has the same effect.
Options
All options are optional at the top level: omit twilio or sendgrid entirely to skip that service group. Once a service object is present, its credential options are required unless active: false.
twilio options
| 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 | Twilio phone number (E.164). Required if messagingServiceSid is not provided. |
messagingServiceSid | string | — | One of phone/msgSvc | Messaging Service SID. Required for scheduling and RCS. |
active | boolean | true | No | Set false to disable all Twilio services (omitting twilio entirely does the same). |
*Either phoneNumber or messagingServiceSid is required for SMS.
sendgrid options
| 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 | From display name (sends { email, name } as the from field). |
active | boolean | true | No | Set false to disable the email service (omitting sendgrid entirely does the same). |
Decorators
Single namespace fastify.xTwilio holding the four services. A service is absent (undefined) when its option object is omitted or disabled via active: false; rcs is additionally absent unless twilio.messagingServiceSid is provided.
| Decorator | Description |
|---|---|
fastify.xTwilio.sms | SMS/MMS messaging via Twilio Messages API. |
fastify.xTwilio.conversations | Multi-channel messaging threads via Twilio Conversations API. |
fastify.xTwilio.rcs | Rich Communication Services messaging. Only registered when messagingServiceSid is provided. |
fastify.xTwilio.email | Transactional email and contact management via SendGrid. |
Methods
SMS
- sms.send / sms.sendMMS / sms.sendBulk / sms.schedule / sms.cancelScheduled / sms.get / sms.getStatus / sms.list / sms.delete / sms.getMedia / sms.validatePhoneNumber — all SMS/MMS operations
Conversations
RCS
- rcs.send / rcs.sendMedia / rcs.sendTemplate / rcs.sendRichCard / rcs.sendCarousel / rcs.sendQuickReplies / rcs.getStatus / rcs.listTemplates / rcs.getTemplate / rcs.deleteTemplate — rich RCS messaging
- email.send / email.sendTemplate / email.sendWithAttachments / email.sendBulk / email.sendPersonalizedBulk — send transactional emails
- email.validate / email.addContact / email.searchContact / email.deleteContact / email.createList / email.getLists / email.deleteList — SendGrid contact and list management
Error Reference
Registration fails fast on missing or invalid options. Registration errors use the xtwilio: prefix and each message ends with a full usage example (e.g. \app.register(xTwilio, { ... })``, elided below).
| Error | Cause |
|---|---|
xtwilio: option `twilio` must be an object, e.g. ... | twilio option is present but not an object. |
xtwilio: option `sendgrid` must be an object, e.g. ... | sendgrid option is present but not an object. |
xtwilio: option `twilio.active` must be a boolean, e.g. ... | twilio.active is not a boolean. |
xtwilio: option `sendgrid.active` must be a boolean, e.g. ... | sendgrid.active is not a boolean. |
xtwilio: missing required option `twilio.accountSid` (string), e.g. ... | Twilio service active but accountSid missing/invalid. |
xtwilio: missing required option `twilio.authToken` (string), e.g. ... | Twilio service active but authToken missing/invalid. |
xtwilio: either `twilio.phoneNumber` or `twilio.messagingServiceSid` is required for SMS, e.g. ... | Neither phone number nor Messaging Service SID provided. |
xtwilio: option `twilio.phoneNumber` must be a string, e.g. ... | phoneNumber present but not a string. |
xtwilio: option `twilio.messagingServiceSid` must be a string, e.g. ... | messagingServiceSid present but not a string. |
xtwilio: missing required option `sendgrid.apiKey` (string), e.g. ... | Email service active but apiKey missing/invalid. |
xtwilio: missing required option `sendgrid.fromEmail` (string), e.g. ... | Email service active but fromEmail missing/invalid. |
xtwilio: option `sendgrid.fromName` must be a string, e.g. ... | fromName present but not a string. |
At runtime, every public method validates its arguments before calling external APIs; argument errors are prefixed with the service and method (e.g. [xTwilio] sms.send: to (string) is required.). External API failures are logged via fastify.log.error and re-thrown as [xTwilio] Failed to <operation>: <original message>. Two methods intentionally do not throw on API failure and instead return a result object: sms.validatePhoneNumber returns { valid: false, ... } and email.validate returns { valid: false, verdict: "Unknown", error }.
Environment Variables
The plugin never reads process.env itself. The consumer sets these variables (by convention) and passes the values into app.register(xTwilio, { ... }). They are inputs to the consumer's configuration, not to the plugin — a variable is only needed when you register the service it feeds.
| Variable | Feeds option | Description |
|---|---|---|
TWILIO_ACCOUNT_SID | twilio.accountSid | Twilio Account SID. |
TWILIO_AUTH_TOKEN | twilio.authToken | Twilio Auth Token. |
TWILIO_PHONE_NUMBER | twilio.phoneNumber | Twilio phone number (E.164). |
TWILIO_MESSAGING_SERVICE_SID | twilio.messagingServiceSid | Messaging Service SID (required for scheduling, RCS). |
SENDGRID_API_KEY | sendgrid.apiKey | SendGrid API key. |
SENDGRID_FROM_EMAIL | sendgrid.fromEmail | Verified sender email address. |
How It Works
On registration the plugin validates the top-level option types, decorates the instance with an empty xTwilio namespace, and calls four setup* functions. A setup* function returns immediately when its option object is omitted or active: false; otherwise it validates credentials, initializes its own Twilio or SendGrid client, and attaches its API to fastify.xTwilio. The rcs service additionally skips registration when messagingServiceSid is not provided. All Twilio/SendGrid API errors are caught, logged via fastify.log.error (message only — no request config or credentials), and re-thrown with the [xTwilio] prefix and the original error message attached.
AI Context
package: "@xenterprises/fastify-xtwilio"
type: fastify-plugin
use-when: SMS/MMS, Twilio Conversations, RCS rich messaging, and SendGrid transactional email in one plugin
decorators: fastify.xTwilio (namespace holding sms, conversations, rcs — only if messagingServiceSid provided — and email; omitted services are absent)
env: TWILIO_ACCOUNT_SID, TWILIO_AUTH_TOKEN, TWILIO_PHONE_NUMBER, TWILIO_MESSAGING_SERVICE_SID, SENDGRID_API_KEY, SENDGRID_FROM_EMAIL (consumer sets and passes into register options; plugin never reads process.env)
services: sms (11 methods), conversations (15 methods), rcs (10 methods), email (12 methods)
