Frequently Asked Questions
Create a RedwoodJS service to handle the messaging logic, integrate the MessageBird Node.js SDK, and expose the service through a GraphQL mutation. This allows your application to send SMS messages programmatically via the MessageBird API.
MessageBird acts as the third-party SMS gateway provider. The RedwoodJS application integrates with MessageBird's API using their Node.js SDK, allowing you to send SMS messages directly from your RedwoodJS application.
RedwoodJS offers a full-stack, serverless-friendly framework with built-in GraphQL and Prisma, simplifying development and deployment. Its structured approach promotes code organization and maintainability for campaign management.
Set a MESSAGEBIRD_DEFAULT_ORIGINATOR environment variable if you want a consistent sender ID for most campaigns. This simplifies the API call but can be overridden per campaign if needed. If not set, a generic default might be used, potentially affecting deliverability.
The basic implementation provides submission status. For detailed delivery reports (e.g., delivered, failed), configure MessageBird webhooks to receive real-time updates and store them in a database.
Install the MessageBird Node.js SDK, obtain your Live API Key from the MessageBird dashboard, and store it securely in a .env file in your project root. Never commit API keys directly into your code.
The core technologies include RedwoodJS, Node.js, MessageBird, Prisma (ORM), GraphQL, and Jest (testing). This combination provides a robust and efficient platform for building and managing SMS campaigns.
Error handling ensures your application gracefully manages issues like invalid recipient numbers, network problems, or MessageBird API errors. Implement try-catch blocks, logging, and retry mechanisms in your RedwoodJS service.
Retry logic is useful for handling transient errors, such as temporary network issues or brief MessageBird service disruptions. Use a library like async-retry to manage retries with exponential backoff.
Be aware of the 160-character limit for standard SMS. Longer messages are split (concatenated), impacting cost. Inform users of potential extra charges. Unicode (emoji) messages have a 70-character limit.
Use the E.164 format (+[country code][number]) for maximum compatibility, especially with international numbers. Consider using a library like libphonenumber-js for validation and normalization.
Storing campaign information in a database using Prisma allows you to track campaign history, monitor status (submitted, failed, etc.), and analyze campaign performance over time.
Use Redwood's authentication (e.g., requireAuth, @requireAuth), validate and sanitize user inputs, protect your MessageBird API key, and implement rate limiting to prevent abuse.
Alphanumeric sender IDs are supported in many countries but not all. Check MessageBird's documentation for country-specific regulations. In some regions (e.g., US/Canada), pre-registered numbers are required.
Adhere to MessageBird's best practices, including using registered sender IDs, handling opt-outs correctly, ensuring valid recipient numbers, and monitoring delivery reports via webhooks.
Build RedwoodJS Marketing Campaigns with MessageBird and Node.js
Build a production-ready SMS marketing campaign system using RedwoodJS, MessageBird SMS API, and Node.js. This comprehensive tutorial covers everything from initial RedwoodJS project setup through GraphQL API implementation, bulk SMS delivery, error handling, and production deployment. Perfect for developers building marketing automation, customer notifications, or promotional messaging systems.
Important Platform Update (2025): MessageBird rebranded as Bird in February 2024. The legacy MessageBird platform (dashboard.messagebird.com) shuts down March 31, 2025. For new implementations after this date, use the Bird next-gen platform (app.bird.com), though the MessageBird API and Node.js SDK remain functional during the transition. See Bird's migration documentation for details.
You'll build a RedwoodJS application with a GraphQL API endpoint that accepts campaign details (message content, recipient list) and uses the MessageBird Node.js SDK to dispatch SMS messages. This solves the common need to programmatically send bulk or targeted SMS campaigns for marketing or notifications.
Project Overview and Goals
<!-- DEPTH: Section needs practical context - missing estimated time-to-completion, skill level requirements, and real-world use case examples (Priority: High) --> <!-- GAP: Missing cost estimation for running campaigns and expected message throughput capabilities (Type: Substantive) -->
Create a robust SMS marketing system within a RedwoodJS application that sends bulk SMS messages through MessageBird's API.
Key Goals:
Technologies Used:
System Architecture:
Prerequisites:
node -v. Install from nodejs.org.yarn -v.<!-- GAP: Missing prerequisite: database setup requirements (PostgreSQL, MySQL, or SQLite) and configuration details (Type: Critical) -->
What You'll Build:
Create a functional RedwoodJS application endpoint that receives recipient numbers and a message, sends SMS messages via MessageBird, and provides feedback on success or failure.
How to Set Up Your RedwoodJS Project for SMS Integration
Initialize your RedwoodJS project, install the MessageBird SDK, and configure environment variables for SMS marketing campaigns.
Create RedwoodJS App: Open your terminal and run the RedwoodJS create command:
Follow the prompts (choosing JavaScript or TypeScript). This guide assumes JavaScript, but the steps work similarly for TypeScript.
<!-- DEPTH: Step lacks troubleshooting guidance for common yarn create errors, version conflicts, or network issues (Priority: Medium) -->
Navigate to Project Directory:
Install MessageBird SDK: Install the MessageBird Node.js SDK in the
apiworkspace:<!-- GAP: Missing MessageBird SDK version compatibility information and potential peer dependency issues (Type: Substantive) -->
Configure Environment Variables: RedwoodJS uses
.envfiles for environment variables. The.env.defaultsfile commits to git and holds default (non-sensitive) values. The.envfile (listed in.gitignore) holds sensitive keys.Create the
.envfile in the project root:Add your MessageBird API Key and optionally a default originator to
.env. Retrieve the API key in Section 4.Add placeholders to
.env.defaultsso team members know what's needed:Verify
.envappears in your root.gitignorefile (Redwood adds this by default).MESSAGEBIRD_API_KEYis your secret credential.MESSAGEBIRD_DEFAULT_ORIGINATORis the default sender ID or number when not provided in requests (see Section 4.3).Understand Project Structure: RedwoodJS organizes code into:
api/: Backend code (GraphQL API, services, database schema)web/: Frontend React codescripts/: Utility scriptsFocus on the
api/directory, specificallyapi/src/graphql,api/src/services, andapi/db. This structure separates concerns and simplifies maintenance.How to Implement the MessageBird Service Layer
Implement the core logic for interacting with MessageBird within a RedwoodJS service. Services contain your business logic on the API side.
Generate Service: Use the RedwoodJS CLI to generate a service file:
This creates
api/src/services/marketingCampaigns/marketingCampaigns.jsand related test files.Implement Sending Logic: Open
api/src/services/marketingCampaigns/marketingCampaigns.jsand add the logic:<!-- GAP: Missing validation for phone number format (E.164) before sending to API (Type: Critical) --> <!-- DEPTH: Code lacks explanation of MessageBird response structure and what fields are available (Priority: Medium) -->
Why This Approach?
try...catchfor robustness with informative error messagesHow to Build the GraphQL API for SMS Campaigns
Expose the service function via a GraphQL mutation to enable SMS campaign sending through your RedwoodJS API.
Define GraphQL Schema (SDL): Generate the GraphQL schema definition file:
Open
api/src/graphql/marketingCampaigns.sdl.jsand define the input type and mutation:Schema Explanation:
SendCampaignInput: Defines the data structure for the mutation. Input types keep mutations clean.CampaignStatus: Defines the response structure returned by the mutation.sendMarketingCampaign: The mutation linking to the service function (Redwood maps this automatically by naming convention). Takes input and returns status.@skipAuth/@requireAuth: Redwood directives for access control. Use@requireAuthwhen authentication is implemented.@skipAuthmakes it publicly accessible (use cautiously in production).<!-- GAP: Missing input validation constraints in GraphQL schema (max recipients, message length limits) (Type: Substantive) -->
Test the Endpoint (GraphQL Playground): RedwoodJS includes a GraphQL Playground.
Start the development server:
Navigate to
http://localhost:8910/graphqlExecute this mutation (replace placeholders):
Expect a success response:
Or an error response:
How to Configure MessageBird API Credentials
Configure the MessageBird SDK correctly for proper SMS functionality. Understanding E.164 phone number formatting is essential for international SMS delivery.
<!-- DEPTH: Missing details about API key permissions, scopes, and restrictions available in MessageBird dashboard (Priority: Medium) -->
Store the API Key Securely:
Paste the Live API Key into your
.envfile in the project root:Never commit your
.envfile or API key to version control (Git). Redwood's default.gitignoreincludes.env.Understand Environment Variables:
MESSAGEBIRD_API_KEYlive_xxxxxxxxxxxxxxxxxxxxMESSAGEBIRD_DEFAULT_ORIGINATOR<!-- GAP: Missing information about sender ID registration requirements for different countries and 10DLC compliance for US campaigns (Type: Critical) -->
How to Handle Errors and Implement Retry Logic
Handle SMS delivery failures gracefully in your RedwoodJS application with proper error handling and retry mechanisms.
Error Handling Strategy:
try...catch. Log detailed errors usinglogger.error(). Return structured error information or throw specific GraphQL errors (UserInputError,AuthenticationError, etc.). The current implementation returns a structured error within theCampaignStatusobject.CampaignStatus), that object appears in thedatafield. If the service throws an error, it appears in theerrorsfield.error.errors(an array) for specific API validation issues (e.g., invalid recipient number, insufficient balance). Log these details. Current error handling extracts the first error description.Configure Logging:
pinofor logging. Uselogger.info(),logger.warn(),logger.error()within your service.api/src/lib/logger.jsas needed.<!-- GAP: Missing structured logging examples with correlation IDs for tracking requests across systems (Type: Substantive) -->
Implement Retry Mechanisms (Basic Example): For transient network issues or temporary MessageBird problems, implement retries using libraries like
async-retry.Install
async-retry:Modify the service function:
<!-- DEPTH: Retry section lacks guidance on configuring retry timeouts based on message volume and rate limits (Priority: Medium) -->
Test Error Handling:
MESSAGEBIRD_API_KEYin.envto test authentication errors and thebailconditionHow to Track Campaign Data with Prisma Database
Store SMS campaign information to track history and delivery status using Prisma ORM in RedwoodJS.
Define Prisma Schema: Open
api/db/schema.prismaand add aCampaignmodel:Database Provider Requirements: Prisma v6.x (included with RedwoodJS v8+) requires PostgreSQL 9.6 minimum. For production, use PostgreSQL 12+ for security patches and performance improvements. SQLite is suitable for development only.
<!-- GAP: Missing index recommendations for performance optimization (messageBirdId, userId, submittedAt) (Type: Substantive) -->
Campaign. When linked toUser, it creates a one-to-many relationship (one User has many Campaigns).Run Database Migration: Apply schema changes to your database:
Enter a migration name when prompted (e.g.,
add campaign model). This creates/updates your database tables.Update Service to Save Campaign: Modify
sendMarketingCampaignto create aCampaignrecord:dbobject is the Prisma client instance for all database operations. This approach logs campaign attempts even when MessageBird calls fail.How to Secure Your SMS Campaign API
Implement security measures for APIs and user data in your RedwoodJS SMS marketing system.
+followed by country code and number). Add regex checks or use libraries likelibphonenumber-jsfor stricter validation<!-- GAP: Missing example code for libphonenumber-js integration and E.164 validation (Type: Substantive) --> <!-- DEPTH: Section lacks specific XSS and SQL injection prevention strategies relevant to SMS campaigns (Priority: Medium) -->
Authentication & Authorization:
requireAuth()in the service (marketingCampaigns.js) when RedwoodJS authentication is configured (e.g.,yarn rw setup auth dbAuth). This ensures only logged-in users trigger campaigns@requireAuthto the GraphQL mutation definition (marketingCampaigns.sdl.js) instead of@skipAuthcontext.currentUser.roles)API Key Security:
.env) and ensure.envappears in.gitignoreRate Limiting:
sendMarketingCampaignmutationyarn rw setup graphql-shield) or middleware (if using custom server file) to implement rate limiting (e.g., usingrate-limiter-flexible). MessageBird also enforces API rate limits<!-- GAP: Missing specific rate limiting configuration examples and recommended thresholds for marketing campaigns (Type: Substantive) -->
userIdagainstcontext.currentUser.idin service logic)How to Handle SMS Special Cases and Compliance
<!-- DEPTH: Section needs more comprehensive compliance guidance covering regional regulations beyond US and EU (Priority: High) -->
Address real-world SMS messaging nuances and compliance requirements for marketing campaigns.
Phone Number Formatting (E.164):
+14155551234). While it may interpret local formats for some regions, E.164 is safer for international deliverylibphonenumber-jsCharacter Limits & Encoding:
Longer messages split automatically (concatenated SMS) by carriers/MessageBird, consuming more credits per effective message sent. Inform users about potential costs. MessageBird's API response (
result.recipients.totalSentCountvsresult.recipients.totalCount) provides clues; webhooks provide more detail.<!-- EXPAND: Could add a character counter utility function or reference implementation (Type: Enhancement) -->
<!-- GAP: Missing implementation example for checking opt-out lists before sending campaigns (Type: Critical) -->
<!-- GAP: Missing reference table or link to country-specific sender ID requirements and registration processes (Type: Substantive) -->
delivered,failed,expiredarrive lateryarn rw g function messageStatus). This function handles POST requests from MessageBird, validates them, and updates your database (e.g., updateCampaignstatus)<!-- DEPTH: Webhook section is too brief - needs complete implementation example with signature verification (Priority: High) -->
Frequently Asked Questions About RedwoodJS SMS Integration
What's the difference between MessageBird and Bird platforms?
MessageBird rebranded to Bird in February 2024. The legacy MessageBird platform (dashboard.messagebird.com) shuts down March 31, 2025. For new implementations after this date, use the Bird next-gen platform (app.bird.com) to access enhanced features and consolidated APIs. The MessageBird Node.js SDK and API endpoints remain compatible during the transition, but migrate your account and obtain new API keys from Bird's platform before the deadline.
What Node.js and RedwoodJS versions do I need?
RedwoodJS v8+ requires Node.js v20.x minimum. Node.js v18 reached end-of-life in April 2025. Use Node.js v20 LTS ("Iron", maintenance until April 2026) or v22 LTS ("Jod", active support until April 2027) for production deployments. Check your version with
node -vand upgrade if necessary. RedwoodJS v8+ includes Prisma v6.x, which requires PostgreSQL 9.6+ (12+ recommended for production).How do I send bulk SMS campaigns with RedwoodJS?
Create a GraphQL mutation (
sendMarketingCampaign) that accepts an array of phone numbers and message content. Use the MessageBird Node.js SDK in your RedwoodJS service layer to send messages viamessagebird.messages.create(). Pass recipients as an array in E.164 format (e.g.,["+14155551234", "+442071234567"]). Store campaign metadata in your Prisma database to track status and delivery. Implement rate limiting to prevent abuse and control costs.<!-- DEPTH: FAQ answer lacks specific batch size recommendations and performance considerations (Priority: Medium) -->
How do I handle failed SMS deliveries in RedwoodJS?
Implement retry logic using the
async-retrylibrary in your RedwoodJS service. Configure exponential backoff (2-3 retries with increasing delays). Check MessageBird error codes to distinguish between retryable errors (network issues) and non-retryable errors (authentication failures, invalid numbers). Store delivery attempts in your database with status tracking ("Submitting", "Submitted", "Failed"). Configure MessageBird webhooks for real-time delivery status updates beyond initial submission confirmation.Can I track SMS campaign analytics in my RedwoodJS app?
Yes. Create a Prisma
Campaignmodel to store campaign metadata (message content, recipient count, submission time, MessageBird ID, status). Update the status field based on MessageBird webhook callbacks for detailed delivery tracking. Query your database using RedwoodJS services to generate analytics reports. Track metrics like total sent, delivery rate, failure reasons, and campaign performance over time. Use GraphQL queries to expose analytics data to your React frontend.<!-- EXPAND: Could add example GraphQL queries for common analytics use cases (Type: Enhancement) -->
How much does MessageBird SMS cost for marketing campaigns?
MessageBird (now Bird) SMS pricing varies by destination country. US SMS typically costs $0.0075 – $0.0125 per message. International rates range from $0.02 – $0.15+ per message depending on destination. Longer messages exceeding 160 characters (GSM-7) or 70 characters (Unicode) split into multiple segments, consuming more credits. Check Bird's pricing page for current rates and consider enterprise pricing for high-volume campaigns (10,000+ messages/month).
<!-- GAP: Missing information about volume discounts and pricing tiers for different campaign sizes (Type: Substantive) -->
How do I secure MessageBird API keys in RedwoodJS?
Store API keys in the
.envfile at your project root and add.envto your.gitignore. RedwoodJS uses@fastify/envfor environment validation – define required keys in yourenvSchema.js. Never commit API keys to version control. Use distinct keys per environment (development, staging, production). For production, use secret management services like AWS Secrets Manager or HashiCorp Vault. Rotate API keys periodically (every 90 days) through Bird's dashboard.<!-- EXPAND: Could add code examples for AWS Secrets Manager and Vault integration (Type: Enhancement) -->
Can I schedule SMS campaigns for future delivery with MessageBird?
Yes. MessageBird supports scheduling messages up to 30 days in advance using the
scheduledDatetimeparameter in themessages.create()call. Pass an ISO 8601 timestamp (e.g.,"2025-12-25T10:00:00Z"). For campaigns beyond 24 hours, implement a two-stage system: store the scheduled time in your Prisma database immediately, then use a cron job or background worker to send the actual SMS when the time approaches. This reduces API load and allows cancellations or updates before sending.<!-- DEPTH: Scheduling answer lacks implementation details for cron jobs or background workers in RedwoodJS (Priority: Medium) -->
How do I comply with SMS marketing regulations (TCPA, GDPR)?
Provide recipients an easy opt-out mechanism (e.g., reply STOP). MessageBird manages opt-out lists automatically – check their compliance documentation. Before sending campaigns, query your internal suppression list or MessageBird's opt-out list. Store user consent records in your database with timestamps and consent method. For US campaigns, register sender IDs through 10DLC or Toll-Free numbers. For EU campaigns under GDPR, obtain explicit consent and honor data deletion requests. Failure to comply results in legal penalties and carrier filtering.
<!-- GAP: Missing information about CASL (Canada), PECR (UK), and other regional compliance requirements (Type: Substantive) -->
How do I test MessageBird integration locally in RedwoodJS?
Use MessageBird's Test API key for local development (obtain from dashboard.messagebird.com > Developers > API access). The Test key enables API testing without sending actual SMS or incurring charges. Start your RedwoodJS dev server with
yarn rw devand access the GraphQL Playground athttp://localhost:8910/graphql. Execute test mutations with sample phone numbers. MessageBird returns simulated responses for testing. For production testing, use your own verified phone numbers with the Live API key to confirm actual SMS delivery before launching campaigns.<!-- EXPAND: Could add integration testing examples with Jest mocks for the MessageBird SDK (Type: Enhancement) -->