npm package discovery and stats viewer.

Discover Tips

  • General search

    [free text search, go nuts!]

  • Package details

    pkg:[package-name]

  • User packages

    @[username]

Sponsor

Optimize Toolset

I’ve always been into building performant and accessible sites, but lately I’ve been taking it extremely seriously. So much so that I’ve been building a tool to help me optimize and monitor the sites that I build to make sure that I’m making an attempt to offer the best experience to those who visit them. If you’re into performant, accessible and SEO friendly sites, you might like it too! You can check it out at Optimize Toolset.

About

Hi, 👋, I’m Ryan Hefner  and I built this site for me, and you! The goal of this site was to provide an easy way for me to check the stats on my npm packages, both for prioritizing issues and updates, and to give me a little kick in the pants to keep up on stuff.

As I was building it, I realized that I was actually using the tool to build the tool, and figured I might as well put this out there and hopefully others will find it to be a fast and useful way to search and browse npm packages as I have.

If you’re interested in other things I’m working on, follow me on Twitter or check out the open source projects I’ve been publishing on GitHub.

I am also working on a Twitter bot for this site to tweet the most popular, newest, random packages from npm. Please follow that account now and it will start sending out packages soon–ish.

Open Software & Tools

This site wouldn’t be possible without the immense generosity and tireless efforts from the people who make contributions to the world and share their work via open source initiatives. Thank you 🙏

© 2026 – Pkg Stats / Ryan Hefner

@xenterprises/fastify-xtwilio

v1.3.0

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. One registration decorates the Fastify instance with a single xTwilio namespace exposing sms, conversations, rcs, and email services — for SaaS apps that need transactional messaging with the least possible setup code.

Installation

npm install @xenterprises/fastify-xtwilio fastify@5

Minimal example

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 SMS
await fastify.xTwilio.sms.send("+1234567890", "Hello!");

The plugin never reads process.env itself — all configuration arrives via register options. Register with only the services you need: a service whose option object (twilio or sendgrid) is omitted is skipped silently, and you can still disable one explicitly with active: false. A service object that is present but missing credentials is a hard registration error.

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 (object)

| 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 and scheduled SMS) | | active | boolean | true | No | Set false to disable all Twilio services (omitting twilio entirely does the same) |

sendgrid (object)

| 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 (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

fastify.xTwilio

Single namespace 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.

fastify.xTwilio.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.xTwilio.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.xTwilio.rcs

Only registered when twilio.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.xTwilio.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 |

Routes

None. The plugin adds no routes and no request hooks; it only decorates the instance.

Error behavior

Registration fails fast on missing or invalid options. Option errors name the plugin, the option, and show an example registration:

xtwilio: missing required option `twilio.accountSid` (string), e.g. `app.register(xTwilio, { twilio: { accountSid: 'AC...', authToken: 'your_auth_token', phoneNumber: '+15551234567' } })`
xtwilio: option `sendgrid.apiKey` must be a string, e.g. ...

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 (message only — no request config or credentials) 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 }.

Requirements

  • Node.js >= 20
  • Fastify ^5.0.0 (peer dependency)

License

Proprietary — All Rights Reserved X Enterprises. See LICENSE.