X Enterprises

fastify-x-twilio

Fastify plugin for Twilio communications (SMS, MMS, Conversations, RCS) and SendGrid email — 48 methods across 4 services under one decorator.

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

NameTypeDefaultRequiredDescription
accountSidstringYes (if active)Twilio Account SID.
authTokenstringYes (if active)Twilio Auth Token.
phoneNumberstringOne of phone/msgSvcTwilio phone number (E.164). Required if messagingServiceSid is not provided.
messagingServiceSidstringOne of phone/msgSvcMessaging Service SID. Required for scheduling and RCS.
activebooleantrueNoSet false to disable all Twilio services (omitting twilio entirely does the same).

*Either phoneNumber or messagingServiceSid is required for SMS.

sendgrid options

NameTypeDefaultRequiredDescription
apiKeystringYes (if active)SendGrid API key.
fromEmailstringYes (if active)Verified sender email address.
fromNamestringNoFrom display name (sends { email, name } as the from field).
activebooleantrueNoSet 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.

DecoratorDescription
fastify.xTwilio.smsSMS/MMS messaging via Twilio Messages API.
fastify.xTwilio.conversationsMulti-channel messaging threads via Twilio Conversations API.
fastify.xTwilio.rcsRich Communication Services messaging. Only registered when messagingServiceSid is provided.
fastify.xTwilio.emailTransactional email and contact management via SendGrid.

Methods

SMS

Conversations

RCS

Email

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).

ErrorCause
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.

VariableFeeds optionDescription
TWILIO_ACCOUNT_SIDtwilio.accountSidTwilio Account SID.
TWILIO_AUTH_TOKENtwilio.authTokenTwilio Auth Token.
TWILIO_PHONE_NUMBERtwilio.phoneNumberTwilio phone number (E.164).
TWILIO_MESSAGING_SERVICE_SIDtwilio.messagingServiceSidMessaging Service SID (required for scheduling, RCS).
SENDGRID_API_KEYsendgrid.apiKeySendGrid API key.
SENDGRID_FROM_EMAILsendgrid.fromEmailVerified 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)
Copyright © 2026