Frequently Asked Questions
Configure a webhook in the MessageBird dashboard to forward incoming SMS messages to your application's endpoint (e.g., your-ngrok-url/messagebird). Use Flow Builder for attaching it to a number or the number's settings directly. Ensure you set the method to POST and enable request signing to get a signing key for verification on your side.
Fastify is a high-performance Node.js web framework known for its speed and extensibility. It is an ideal choice for building efficient, scalable SMS applications. Its plugin architecture and developer-friendly features make development smoother.
The guide details setting up a campaign sending endpoint (not fully implemented in the provided snippet). This would use MessageBird's messages.create API endpoint to dispatch messages to multiple recipients retrieved from the database. Be sure to protect this endpoint with authentication (an API Key is used as an example).
MessageBird uses request signing as a security measure to allow you to verify that incoming webhooks actually originate from MessageBird and haven't been tampered with in transit. This is important to prevent fraudulent requests.
Phone number normalization should be done as early as possible in the process—ideally immediately after receiving a number. Consistent formatting, such as E.164, is crucial for accurate storage, lookup, and sending of messages. This guide uses a basic normalization function, but a robust library is recommended for production.
The tutorial uses better-sqlite3, a lightweight SQLite library for Node.js, for simplicity. For production systems with higher load and scalability requirements, PostgreSQL or MySQL would be more suitable.
The webhook handler checks for keywords in uppercase (e.g., 'JOIN', 'STOP') in the message payload. If 'JOIN', it adds the subscriber to the database. If 'STOP', it unsubscribes them. The database functions are accessed through fastify.db provided by the database plugin.
Yes, the provided webhook handler logic can be easily extended. Add additional checks for other keywords and define corresponding actions. For more complex menu systems or automated responses, a more sophisticated message processing logic might be needed.
ngrok is a tunneling service that creates a publicly accessible URL to your local development server. This is needed so MessageBird can send webhook notifications to your application during development. For production, your server would have a dedicated public URL.
Setting "type": "module" in package.json tells Node.js to treat all files as ES modules, allowing you to use the import/export syntax. This is the modern standard for modules in JavaScript and offers several advantages.
Navigate to your project folder in your terminal, then use npm install fastify messagebird dotenv better-sqlite3 @fastify/rate-limit @fastify/auth command to install the necessary packages. This command downloads the necessary libraries for your application.
The dotenv package is used to load environment variables from a .env file. This is essential for securely managing sensitive information such as API keys and other secrets without committing them directly to your code.
E.164 format (e.g., +14155552671) ensures consistent and internationally recognized storage of phone numbers. It simplifies processing, validation, and avoids ambiguity when handling numbers from different regions. The database schema recommends this format.
You can obtain a MessageBird API key by signing up for or logging in to your MessageBird account. Go to the Developers > API access section of your dashboard, and retrieve the key from there.
Build SMS Marketing Campaigns with MessageBird, Node.js, and Fastify
Meta Description: Learn to build production-ready SMS marketing campaigns using MessageBird API, Node.js, and Fastify. Complete tutorial with webhook handling, subscriber management, security, and bulk messaging.
This comprehensive guide provides a step-by-step walkthrough for building a production-ready SMS marketing campaign management system using Node.js, the Fastify framework, and the MessageBird API. You'll implement project setup, core logic, security, deployment, and testing for a fully functional SMS subscription service.
By the end of this tutorial, you'll have a functional application that can:
JOIN) and opt-outs (STOP).Target Audience: Developers familiar with Node.js and basic web framework concepts. Prior experience with Fastify or MessageBird is helpful but not required.
Technologies Used:
messagebirdnpm package v4.0.1) was last updated in 2021–2022 and may not receive frequent updates. Verify current support status at MessageBird Developers. MessageBird API enforces rate limits: 500 req/s for POST (SMS sending), 50 req/s for GET/PATCH/DELETE operations (MessageBird SMS API documentation).better-sqlite3: A simple, file-based SQL database, suitable for this example. For production, consider PostgreSQL or MySQL.dotenv: For managing environment variables.@fastify/rate-limit: Plugin for basic API rate limiting. Documentation@fastify/auth: Plugin for authentication strategy integration.System Architecture:
Prerequisites:
curlor Postman).ngrokor a similar tunneling service: Essential for exposing your local development server to MessageBird's webhooks. For production, you'll need a stable public URL for your deployed application (see Section 10). Install ngrokFinal Outcome:
A robust Node.js application capable of managing SMS subscriptions and sending broadcasts, ready for further extension and deployment.
How to Set Up Your Node.js Project with Fastify
Initialize your Node.js project and install the necessary dependencies.
1.1 Create Project Directory & Initialize:
Open your terminal and run these commands:
This creates a new directory, navigates into it, and initializes a
package.jsonfile with default settings.1.2 Enable ES Modules:
Use ES Modules (import/export syntax). Open
package.jsonand add this top-level key:Why ES Modules? It's the standard module system for JavaScript and offers benefits like static analysis and better tooling support compared to CommonJS (
require).1.3 Install Dependencies:
Install Fastify_ the MessageBird SDK_
dotenvfor environment variables_better-sqlite3for the database_@fastify/rate-limitfor protection_ and@fastify/authfor authentication handling.fastify: The core web framework.messagebird: The official Node.js SDK for interacting with the MessageBird API.dotenv: Loads environment variables from a.envfile intoprocess.env. Essential for managing sensitive credentials.better-sqlite3: A high-performance SQLite driver for Node.js. Chosen for simplicity in this guide.@fastify/rate-limit: A plugin to protect API endpoints from abuse.@fastify/auth: A plugin to handle various authentication strategies.1.4 Create Project Structure:
Organize the project for clarity and maintainability:
app.js: The main application entry point..env: Stores environment variables (API keys_ secrets). Never commit this file..gitignore: Specifies intentionally untracked files that Git should ignore.db/: Contains database-related files (schema_ connection logic).routes/: Defines the application's API endpoints.plugins/: Holds reusable Fastify plugins (like DB connection_ MessageBird client setup_ authentication).utils/: Contains utility functions (like phone number normalization).1.5 Configure
.gitignore:Add this content to your
.gitignorefile to prevent sensitive information and generated files from being committed:1.6 Set Up Environment Variables (
.env):Create a
.envfile in the root of your project. Populate it with actual values in the next steps.MESSAGEBIRD_API_KEY: Your live API key from the MessageBird dashboard.MESSAGEBIRD_WEBHOOK_SIGNING_KEY: The key used to verify incoming webhooks. Found in MessageBird webhook settings.MESSAGEBIRD_ORIGINATOR: The MessageBird virtual number (e.g._+12025550142) or approved Alphanumeric Sender ID (e.g._MyCompany) used to send messages.API_SECRET_KEY: A secret key you generate to protect the campaign sending endpoint. Use a strong_ random string.DATABASE_PATH: The file path for the SQLite database.How to Integrate MessageBird SMS API with Node.js
Configure the connection to MessageBird and set up the necessary components on their platform.
2.1 Get MessageBird Credentials:
.envfile asMESSAGEBIRD_API_KEY.+and country code)..envfile asMESSAGEBIRD_ORIGINATOR. (Alternatively, use an approved Alphanumeric Sender ID if applicable).MESSAGEBIRD_WEBHOOK_SIGNING_KEYblank for now or use a placeholder.2.2 Initialize MessageBird Client Plugin:
Create a Fastify plugin to initialize and share the MessageBird client instance.
fastify-plugin: Used to prevent Fastify from creating separate encapsulation contexts for the plugin, allowingfastify.decorateto addmessagebirdto the global Fastify instance.fastify.decorate: Makes the initializedmbClientavailable throughout your application viafastify.messagebird.Creating a Database Schema for SMS Subscriber Management
Use
better-sqlite3for storing subscriber phone numbers and their status.3.1 Define Database Schema:
Create the SQL schema definition:
phone_number: Stores the subscriber's number, acting as the unique identifier. Storing in E.164 format (e.g.,+14155552671) is highly recommended for consistency. ITU-T Recommendation E.164 defines the international public telecommunication numbering plan with a maximum of 15 digits after the '+' sign.subscribed: A simple flag (integer 0 or 1) to indicate active subscription status.3.2 Implement Database Connection Plugin:
Create a plugin to manage the SQLite database connection and provide helper functions:
initDb: Connects to the SQLite file and executes the schema definition.addSubscriber: Inserts a new number or updates an existing one to be subscribed. UsesON CONFLICT…DO UPDATE(UPSERT) for efficiency.removeSubscriber: Sets thesubscribedflag to 0 for a given number.isSubscribed: Checks the subscription status.getAllSubscribers: Retrieves a list of all active subscribers' phone numbers.closeDb: Closes the database connection.3.3 Create the Fastify DB Plugin:
Wrap the database initialization in a Fastify plugin:
dbPathfrom options, callsinitDb, decoratesfastifywith the data access functions underfastify.db, and ensurescloseDbis called when the server shuts down using theonClosehook.How to Handle SMS Webhooks from MessageBird
This route receives incoming SMS messages from MessageBird, parses them for keywords (
JOIN,STOP), updates the database, and sends a confirmation reply.4.1 Create the Webhook Route:
Key Points:
originatorandpayloadexist. Use@fastify/sensibleorfastify-type-provider-zodfor more complex validation in production.JOINorSTOP.fastify.dbfunctions to update subscription status.normalizePhoneNumber,isValidE164) created next. The implementation is basic; stronger validation is recommended for production.fastify.messagebird.messages.createto send an SMS back to the user. Theoriginatorhere is your MessageBird number/sender ID.200 OKto MessageBird. This acknowledges receipt and prevents MessageBird from retrying potentially failing requests indefinitely. Monitor logs for actual errors.preHandler: Specifies that this route needs authentication/verification usingfastify.authand a verification function (verifyMessageBird) created as a plugin. Note the route path is/messagebird.4.2 Implementing Phone Number Validation with E.164 Format:
Create a utility file for handling phone numbers:
Important Note: The
normalizePhoneNumberfunction provided here is intentionally basic and carries significant limitations. For any production system, using a dedicated library likelibphonenumber-jsis strongly recommended for accurate parsing, validation, and formatting of international phone numbers according to the E.164 standard.4.3 How to Configure MessageBird Webhook Settings:
Tell MessageBird where to send incoming SMS messages.
Start
ngrok: Expose your local development server to the internet. If your app runs on port 3000:ngrokwill give you a public HTTPS URL (e.g.,https://<unique-id>.ngrok-free.app). Copy this URL.Configure Flow Builder or Number Settings:
ngrokURL followed by the webhook path:https://<unique-id>.ngrok-free.app/messagebird.POST..envfile asMESSAGEBIRD_WEBHOOK_SIGNING_KEY.ngrokURL + path:https://<unique-id>.ngrok-free.app/messagebird..env.Important: Every time you restart
ngrok, you get a new public URL. You must update the webhook URL in your MessageBird Flow/Number settings accordingly. For production, use your server's permanent public URL.Securing Your SMS Application with Webhook Verification
Security is paramount when dealing with external webhooks and sending bulk messages.
5.1 How to Verify MessageBird Webhook Signatures:
MessageBird signs its webhook requests using HMAC-SHA256 so you can verify they genuinely came from MessageBird. The signature is generated from the request URL and request body and is signed using your signing key (MessageBird webhook signature documentation). Ensure you installed
@fastify/auth(npm install @fastify/auth).Create a plugin for this verification logic:
@fastify/authbeing registered first (handled inapp.js).request.rawBody: Crucially relies on the custom content type parser defined inapp.jsto access the raw, unparsed request body. This is essential because the signature is calculated over the raw bytes, not the parsed JSON.crypto.timingSafeEqual: Used for secure comparison of signatures to prevent timing attacks. Requires buffers of equal length.fastify.verifyMessageBirdavailable. It's intended to be used withinfastify.authin route options.5.2 Implementing API Key Authentication for Campaign Endpoints:
Create a simple API key authentication plugin:
crypto.timingSafeEqualto prevent timing attacks that could leak information about the secret key.fastify.verifyApiKeyavailable for use withfastify.authin route protection.Building the Campaign Send Endpoint with Bulk SMS
Create an API endpoint for administrators to send marketing campaigns to all subscribed users.
6.1 Create Campaign Route:
Key Points:
fastify.verifyApiKeyto protect the endpoint.Main Application Setup
Create the main application file that ties everything together.
7.1 Create Main App File:
Key Features:
.envfile usingdotenv/config.Testing Your SMS Marketing Application
Test your application thoroughly before deploying to production.
8.1 Manual Testing with ngrok:
Update MessageBird webhook URL with the ngrok URL.
Send an SMS with "JOIN" to your MessageBird number.
Check logs for successful subscription.
Test campaign sending:
8.2 Testing Unsubscribe Flow:
Send "STOP" to your MessageBird number and verify:
Deployment Considerations for Production
9.1 Environment Configuration:
Set production environment variables:
NODE_ENV=production9.2 Database Migration:
For production, migrate from SQLite to PostgreSQL or MySQL:
9.3 Monitoring and Observability:
Implement monitoring for:
9.4 Security Hardening:
9.5 Scaling Strategies:
SMS Marketing Compliance and Best Practices
10.1 Legal Compliance:
TCPA Compliance (United States):
GDPR Compliance (European Union):
10.2 Best Practices:
Troubleshooting Common Issues
11.1 Webhook Not Receiving Messages:
11.2 Database Connection Errors:
11.3 MessageBird API Errors:
11.4 Authentication Failures:
Next Steps and Advanced Features
12.1 Feature Enhancements:
12.2 Technical Improvements:
This comprehensive guide provides everything you need to build, deploy, and maintain a production-ready SMS marketing campaign system using MessageBird, Node.js, and Fastify. Follow security best practices, comply with regulations, and continuously monitor and improve your system for optimal performance.