Frequently Asked Questions
You can send SMS messages in a RedwoodJS application by creating a GraphQL mutation that interacts with the MessageBird API. This involves setting up a service to handle the API call logic and defining the mutation in your GraphQL schema. The provided code example uses the MessageBird Node.js SDK to simplify the integration.
MessageBird is a communication platform that provides the SMS API and virtual phone numbers for sending and receiving text messages within your RedwoodJS application. This allows you to add features like notifications, alerts, and customer support interactions via SMS.
ngrok creates a temporary public URL that tunnels HTTP traffic to your local RedwoodJS development server. This is necessary during development so MessageBird's webhook can reach your locally running messagebirdWebhook function to test incoming SMS messages before deploying to production.
Verifying the MessageBird webhook signature is crucial for security and should always be done, especially in production. This step confirms that incoming webhook requests genuinely originate from MessageBird and haven't been tampered with.
Yes, but be aware of character limits. Standard SMS (GSM-7) allows 160 characters. Using emojis or non-standard characters switches to UCS-2 encoding, reducing the limit to 70 characters. MessageBird handles concatenation for longer messages, but they're billed as multiple parts.
Incoming SMS messages are handled by creating a RedwoodJS function, which acts as a webhook endpoint. This function receives POST requests from MessageBird, verifies the signature, parses the message data, and then processes it (e.g., logging, triggering actions).
A RedwoodJS function serves as the webhook endpoint for receiving incoming SMS messages from MessageBird. It handles the incoming HTTP requests, signature verification, and processing of the received SMS data.
MessageBird requires a 200 OK response from your webhook to acknowledge successful receipt of the message. Failure to respond quickly or returning an error can cause MessageBird to retry sending the webhook, potentially leading to duplicate processing.
If processing inbound SMS messages involves time-consuming operations (database writes, external API calls), perform them asynchronously after returning a 200 OK to MessageBird. This keeps your webhook responsive and prevents MessageBird from retrying.
The MessageBird Node.js SDK provides a webhooks.verify function for signature verification. Your webhook function must check if the signature is missing from the request, compare it against the signing key (stored securely in environment variables) and return a 401 error if there is an issue with the signature.
The MessageBird originator number is your provisioned virtual phone number, used as the sender ID for outbound messages and the number users reply to for inbound messages. It must be in E.164 format (e.g., +14155552671).
You can store SMS message logs using Prisma, RedwoodJS's ORM. Define a model in your schema.prisma file to represent the message data (direction, originator, recipient, body, status, etc.) and then use db.messageLog.create in your service and function to save the message details.
E.164 (+14155552671) ensures consistent, internationally recognized phone number formatting, crucial for reliable SMS delivery and routing. MessageBird strongly recommends using E.164.
Carriers often mandate handling keywords like STOP, HELP, INFO. Check MessageBird's documentation, sometimes they handle opt-out logic with a STOP keyword. Implement logic in your webhook to process HELP messages (e.g., by sending an automated reply) and to update your database with user preferences if a user texts STOP, preventing future communication.
Build Two-Way SMS Messaging in RedwoodJS with MessageBird
Build production-ready two-way SMS messaging in your RedwoodJS application using MessageBird's SMS API and webhook system. This tutorial shows you how to send outbound SMS messages via GraphQL and receive inbound SMS through secure webhooks—perfect for customer support chat, appointment confirmations, OTP verification, automated responses, and real-time notifications.
You'll implement complete bidirectional SMS communication with webhook signature verification, message logging, replay attack prevention, and production deployment strategies for RedwoodJS applications.
What You'll Build: Two-Way SMS Communication System
Core Features:
Real-World Use Cases:
This two-way SMS system enables interactive communication for appointment reminders with confirmations, customer support conversations, two-factor authentication codes, order status updates with customer replies, survey responses, and automated chatbot interactions.
Technology Stack:
System Architecture:
Prerequisites:
node --versionnpm install -g yarn. Verify:yarn --versionyarn global add @redwoodjs/cliExpected Outcome:
A fully functional RedwoodJS application that sends SMS via GraphQL and receives/processes/logs incoming SMS messages via secure webhooks for true two-way communication.
1. Setting up the Project
Initialize a new RedwoodJS project, set up the database, and install dependencies.
Step 1.1: Install Prerequisites
Node.js and Yarn:
Database Setup (PostgreSQL recommended):
For local development, install PostgreSQL:
brew install postgresql@14 && brew services start postgresql@14sudo apt-get install postgresql postgresql-contribOr use a hosted database service like Railway, Render, or Supabase.
Step 1.2: Create RedwoodJS Project
Open your terminal and run:
Using TypeScript provides better type safety and developer experience, especially for larger applications.
Step 1.3: Configure Database Connection
Update your
.envfile with your database connection string:Run initial database migration:
Step 1.4: Install MessageBird SDK
Navigate to the
apidirectory and add the MessageBird Node.js SDK:SDK version: The messagebird package (v3.8.0+) is compatible with Node.js >=0.10, including Node.js v20.x.
Step 1.5: Set Up MessageBird Account
Obtain API Keys:
live_) for production usetest_) for developmentTest keys simulate API requests without sending actual SMS or consuming credits. Live keys send real messages and deduct from your balance (official documentation).
Obtain Signing Key:
Purchase Virtual Number:
+14155552671)Step 1.6: Configure Environment Variables
Never commit API keys to version control. Use environment variables.
Create a
.envfile in the project root (redwood-messagebird-app/.env):E.164 Format: Phone numbers must be in international format without spaces or special characters:
+12145551234(country code +1, area code 214, number 5551234)+442012345678(country code +44, area code 20, number 12345678)+[country code][area code][local number](max 15 digits) (official documentation)Add
.envto.gitignore:Ensure
.gitignorecontains.envto prevent committing keys. RedwoodJS includes this by default.Step 1.7: Accessing Environment Variables
RedwoodJS automatically loads variables from
.envintoprocess.env. Access them in your API-side code (services, functions) likeprocess.env.MESSAGEBIRD_ACCESS_KEY.2. Implementing Core Functionality (Outbound SMS)
Create the service for sending SMS messages.
Step 2.1: Create the Outbound SMS Service
Generate a new service to encapsulate the outbound SMS logic:
This creates
api/src/services/sms/sms.tsandapi/src/services/sms/sms.test.ts.RedwoodJS services contain business logic and data access. GraphQL resolvers call them, and you can reuse them throughout your application (RedwoodJS documentation).
Configure the
sms.tsservice:SMS Character Limits:
Common API Errors:
3. Building the API Layer (GraphQL Mutation)
Create a GraphQL mutation to send SMS messages from your web application.
Step 3.1: Define GraphQL Schema
Create or update
api/src/graphql/sms.sdl.ts:@requireAuthensures only authenticated users can send SMS. Remove it if you don't need authentication.Step 3.2: Implement GraphQL Resolver
Update
api/src/services/sms/sms.tsto add the resolver:4. Building the Webhook Handler (Inbound SMS)
Receive and process incoming SMS messages through a webhook endpoint—the key component for two-way SMS functionality.
Step 4.1: Create the Webhook Handler Function
Generate a serverless function to handle incoming webhooks:
This creates
api/src/functions/webhook/webhook.ts.RedwoodJS serverless functions are independent API endpoints ideal for webhooks, background jobs, and external integrations (RedwoodJS documentation).
Implement the webhook handler:
MessageBird Webhook Payload Structure:
Inbound SMS webhooks contain the following fields (official documentation):
id: Unique message identifieroriginator: Sender's phone number (E.164 format)recipient: Your MessageBird virtual numberbody: Message contentcreatedDatetime: Timestamp in RFC3339 formattype: Message type (usually "sms")direction: "mo" (mobile originated = inbound)Webhook Retry Behavior:
MessageBird retries failed webhooks up to 10 times with exponential backoff. Return HTTP 200 within 30 seconds to acknowledge receipt (webhook documentation).
5. Securing Your Implementation
Protect your webhook endpoint from unauthorized access with signature verification.
Webhook Signature Verification
Verify every webhook request using MessageBird's signing key to prevent unauthorized requests and confirm message authenticity.
How signature verification works:
messagebird-signatureheadermessagebird-request-timestampheader (Unix timestamp)HMAC-SHA256(signing_key, timestamp + "\n" + body)Timestamp Validation (Prevents Replay Attacks):
Validate the timestamp to prevent replay attacks. Accept requests within a 5-minute tolerance window (security best practices):
Best practices:
crypto.timingSafeEqual)Environment Variable Security
Protect sensitive credentials by storing them as environment variables:
Security checklist:
.envto.gitignore6. Database Schema and Message Logging
Store incoming and outgoing SMS for tracking, analytics, and conversation history.
Step 6.1: Create the Prisma Schema
Define a
Messagemodel in your Prisma schema to store SMS data:Schema improvements:
@@uniqueconstraint onmessageBirdIdprevents duplicate webhook processingsender,recipient,direction, andreceivedAtoptimize common queriesstatusfield stores delivery status for outbound messages (sent, delivered, failed)Step 6.2: Apply Database Migrations
Run Prisma migrations to create the database table:
This:
api/db/migrations/Migration conflicts: Use
yarn rw prisma migrate resetto reset the database. This deletes all data in development.Step 6.3: Query Messages
Use Prisma Client to query message history:
7. Testing Your Implementation
Test your SMS integration before deploying to production.
Testing Outbound SMS
Test SMS sending through your GraphQL API:
Verification steps:
yarn rw prisma studioyarn rw devTesting with Test Keys:
Use MessageBird test keys (
test_xxxxxxx) for development. Test keys simulate API calls without sending SMS or consuming credits. The API returns success responses, but delivers no messages (official documentation).Testing Inbound Webhooks Locally
Use ngrok to expose your local development server for webhook testing:
Step 1: Install and start ngrok:
Step 2: Configure MessageBird webhook:
https://abc123.ngrok.io)https://abc123.ngrok.io/.redwood/functions/webhookStep 3: Send test SMS:
Send an SMS from your phone to your MessageBird number. Monitor:
yarn rw dev) for webhook processingyarn rw prisma studio) for stored message recordsSimulating Webhook Requests
Test webhook handling without sending actual SMS using curl with a valid signature:
Calculate valid test signature:
Common Testing Issues
Problem: Webhook receives requests but returns 401
.envProblem: Messages don't appear in database
.envyarn rw prisma migrate devmessageBirdIdconstraint violationsProblem: Outbound SMS fails with 401
Problem: ngrok tunnel disconnects
ngrok config add-authtoken YOUR_TOKENProblem: SMS character limit exceeded
8. Deployment Considerations
Deploy your RedwoodJS SMS application to production.
Environment Variables
Configure production environment variables in your hosting platform:
Platform-specific configuration:
Webhook URL Configuration
Update your MessageBird webhook URL to point to your production domain:
https://your-app.vercel.app)https://your-app.vercel.app/.redwood/functions/webhookZero-downtime updates: When deploying updates:
HTTPS Requirements
MessageBird requires HTTPS for all webhook endpoints.
Automatic HTTPS support:
Verify HTTPS is working:
curl -I https://your-domain.com/.redwood/functions/webhookDatabase Migrations
Apply database migrations before deploying new code:
CI/CD pipeline configuration (GitHub Actions example):
Monitoring and Logging
Implement monitoring to track SMS delivery and webhook processing.
Log critical events:
Key metrics to track:
Recommended monitoring tools:
RedwoodJS logging configuration:
Use in your code:
Rate Limiting
Implement rate limiting to prevent API abuse and protect your budget:
Rate limit recommendations:
9. Compliance and Legal Considerations
CRITICAL: SMS marketing is heavily regulated. Non-compliance can result in fines of $500+ per message.
TCPA Compliance (United States)
The Telephone Consumer Protection Act (TCPA) requires:
Obtain Express Written Consent: Get explicit written permission before sending marketing SMS. Customers must opt-in via web form, keyword, or checkbox (TCPA guide)
Provide Clear Disclosure: After opt-in, send a disclosure message:
Honor Opt-Out Requests: Process STOP, UNSUBSCRIBE, CANCEL, END, and QUIT keywords within 10 business days (as of April 2025) (TCPA 2025 updates)
Respect Quiet Hours: Don't send messages before 8:00 AM or after 9:00 PM recipient's local time
Include Business Name: Every message must identify your business
Maintain Do-Not-Contact List: Keep records of opt-outs for at least 4 years
Example opt-out implementation:
International Regulations
Cost Considerations
MessageBird uses pay-as-you-go pricing:
10. Conclusion
You have successfully integrated two-way SMS messaging into your RedwoodJS application using MessageBird. You can send messages via GraphQL and receive incoming messages through a secure webhook function, with all communication logged to your database.
What you built:
Next steps:
Related topics:
Prioritize security (especially webhook verification), handle errors gracefully, comply with TCPA and international regulations, and monitor SMS costs and delivery rates.
Resources: