Frequently Asked Questions
Integrate the Vonage Messages API into your RedwoodJS application. This involves setting up a RedwoodJS project, installing the Vonage SDK, configuring environment variables, creating a secure API endpoint, and implementing a service to interact with the Vonage API. The provided guide offers a detailed walkthrough of the process, covering key aspects like error handling, security, and deployment considerations, to achieve a robust SMS broadcasting solution within your RedwoodJS app.
The Vonage Messages API enables sending and receiving messages across various channels, including SMS, directly from your RedwoodJS application's backend. This guide focuses on using it for bulk SMS broadcasting, allowing you to efficiently notify multiple recipients simultaneously for alerts, marketing campaigns (with required consent), or group notifications.
RedwoodJS offers a structured, full-stack JavaScript framework with built-in conventions for API services (GraphQL), database interaction (Prisma), and more. This accelerates development and provides a robust foundation for integrating features like bulk SMS sending via the Vonage API, as outlined in the guide.
For production-level bulk SMS applications, especially with large recipient lists, a queue system (like BullMQ or AWS SQS) is strongly recommended. This handles individual message processing in the background, respecting Vonage's rate limits and ensuring reliable delivery without overwhelming the API or your application server. Simple throttling with delays is less robust for scaling and error handling.
Yes, but be aware of character limits. Emojis and special characters use UCS-2 encoding, limiting messages to 70 characters per segment. Standard GSM-7 encoding allows 160 characters. Longer messages, including those with emojis, are concatenated into multiple segments, each incurring a separate charge.
The Vonage Application ID, along with the associated private key, is essential for authenticating your application with the Vonage Messages API. You generate these when you create a new Vonage Application in your Vonage Dashboard. In addition to generating keys, enable 'Messages' as a capability in your Vonage application, and download the private key which needs to be added as an additional environment variable. Remember to store these credentials securely.
Vonage imposes rate limits on SMS sending. The guide strongly recommends implementing a queue system (like BullMQ or AWS SQS) for production applications. This offloads message processing to background workers, enabling controlled, rate-limit-respecting sending. While simple throttling with delays is possible, it's less robust for scaling and error handling.
Prisma, RedwoodJS's default ORM, is used for defining the database schema (including the SmsLog model to track message attempts), managing database migrations, and providing convenient data access within your services. It simplifies database interactions and ensures data integrity.
Store your Vonage API key, secret, application ID, and the path to your downloaded private key as environment variables in a `.env` file. Crucially, add both `.env` and `private.key` to your `.gitignore` file to prevent committing these secrets to version control. For deployment, utilize your hosting provider's secure environment variable management features.
The guide provides a `logSmsAttempt` helper function that uses Prisma to create records in a dedicated `SmsLog` table in your database. This function is called within the `sendSingleSms` function, logging each attempt with details like recipient, message, status, Vonage message ID (if successful), and error messages (if failed).
The `sendSingleSms` function uses `try...catch` blocks to handle errors from the Vonage SDK. `sendBulkSms` uses `Promise.allSettled` to manage individual message failures within a batch. Logging via Redwood's logger and database logging via Prisma provide detailed records for troubleshooting. Implement retry mechanisms for temporary errors.
A2P 10DLC (Application-to-Person 10-Digit Long Code) is a mandatory registration framework in the US for sending application-to-person SMS messages using standard long codes. It requires registering your brand and campaign with Vonage (or The Campaign Registry) to ensure compliance and avoid message filtering or blocking. This is crucial for reliable SMS delivery in the US.
Several factors can cause non-delivery even if the Vonage API reports success. Check for carrier filtering (spam), verify your sender ID, review country-specific regulations, ensure message content compliance, and crucially, confirm A2P 10DLC registration for US traffic. Consult Vonage delivery receipts and logs for specific error codes.
The guide recommends a multi-layered approach: unit tests (mocking the Vonage SDK and database interactions), integration tests for the GraphQL mutation, and end-to-end tests with tools like Cypress for UI interaction (if applicable). Manual testing with real test phone numbers is also essential for validating real-world delivery and edge cases.
Follow Redwood's deployment guides for your chosen hosting provider (Vercel, Render, Netlify, AWS, etc.). Configure all environment variables securely, provision a production database (PostgreSQL recommended), and set up a CI/CD pipeline for automated build, testing, database migrations, and deployment. Handle private key uploads securely.
This guide provides a step-by-step walkthrough for building a feature within a RedwoodJS application to send bulk SMS messages using the Vonage Messages API. We'll cover everything from project setup and core implementation to error handling, security, and deployment considerations, enabling you to build a robust and scalable SMS broadcasting solution.
Project Overview and Goals
What We're Building:
We will add functionality to a RedwoodJS application that enables authorized users to send the same SMS message to a list of phone numbers concurrently via an API endpoint. This involves:
Problem Solved:
This guide addresses the need to efficiently notify multiple recipients via SMS simultaneously for purposes like alerts, marketing campaigns (with consent), or group notifications, directly from a web application backend.
Technologies Used:
@vonage/server-sdk
: The official Vonage Node.js SDK for interacting with the API.System Architecture:
Prerequisites:
Final Outcome:
By the end of this guide, you will have a RedwoodJS API endpoint capable of accepting a list of phone numbers and a message body, sending an SMS to each number via Vonage, logging the attempt, and handling basic rate limiting considerations.
1. Setting up the Project
Let's start by creating a new RedwoodJS project and installing the necessary dependencies.
1.1 Create RedwoodJS Project:
Open your terminal and run:
This command scaffolds a new RedwoodJS project with TypeScript enabled.
1.2 Install Vonage SDK:
Navigate to the API workspace and install the Vonage Node.js SDK:
1.3 Configure Environment Variables:
Vonage requires several credentials. We'll store these securely in environment variables.
Create a
.env
file in the root of your project (if it doesn't exist) and add the following variables. You'll obtain these values from your Vonage Dashboard.VONAGE_API_KEY
/VONAGE_API_SECRET
: Found directly on the main page of your Vonage Dashboard.VONAGE_APPLICATION_ID
: Go toApplications
>+ Create a new application
. Give it a name (e.g., ""Redwood Bulk Sender""). Enable theMessages
capability. ClickGenerate public and private key
and download theprivate.key
file. Save it (e.g., in the project root). The Application ID will be displayed on this page. You don't need to fill in webhook URLs if you are only sending messages initially.VONAGE_PRIVATE_KEY_PATH
: The relative or absolute path to theprivate.key
file you just downloaded. Crucially, addprivate.key
to your.gitignore
file to prevent committing secrets.VONAGE_FROM_NUMBER
: Go toNumbers
>Your numbers
. Copy one of your Vonage virtual numbers capable of sending SMS (usually listed as SMS/Voice). Use the E.164 format (e.g.,14155550100
).1.4 Setup Prisma Database:
RedwoodJS uses Prisma. Let's configure a basic SQLite setup for simplicity (you can switch to PostgreSQL or others later).
Ensure your
api/db/schema.prisma
file has a provider set up:Update your
.env
file with theDATABASE_URL
:2. Implementing Core Functionality (Redwood Service)
We'll create a RedwoodJS service to encapsulate the logic for interacting with Vonage.
2.1 Generate SMS Service:
Use the Redwood CLI to generate the service files:
This creates
api/src/services/sms/sms.ts
and related test/scenario files.2.2 Implement Sending Logic:
Open
api/src/services/sms/sms.ts
and add the following code:Explanation:
process.env
.Messages
instance is created.sendSingleSms
Helper: Encapsulates sending one message, now includes a comment placeholder for crucial E.164 validation, callsvonageMessages.send
, logs the outcome using Redwood's logger, callslogSmsAttempt
, and returns a structured result. Includes improved error message extraction.logSmsAttempt
Helper: Handles writing log entries to the database via Prisma, with error handling and a comment about potential critical failure handling. Includes improved error message extraction.sendBulkSms
:recipients
andmessage
.map
andPromise.allSettled
for concurrent execution.allSettled
ensures all attempts complete. Logging is now primarily handled withinsendSingleSms
. Includes improved error message extraction for rejected promises.3. Building the API Layer (GraphQL)
Now, let's expose the
sendBulkSms
service function through Redwood's GraphQL API.3.1 Generate SDL:
Use the Redwood CLI to generate the GraphQL Schema Definition Language file:
3.2 Define GraphQL Schema:
Open
api/src/graphql/sms.sdl.ts
and define the input type and mutation:Explanation:
SendBulkSmsInput
: Defines the input: recipient array and message string.SmsSendResult
: Defines the output structure for a single recipient's attempt.BulkSmsSummary
: Defines the overall response structure.Mutation.sendBulkSms
: Declares the mutation, taking input and returning the summary.@requireAuth
: Redwood directive for authentication. Requires Redwood Auth setup (see Redwood Auth Docs). Remove temporarily for testing if auth isn't configured, but reinstate for production.3.3 Test with GraphQL Playground:
yarn rw dev
http://localhost:8911/graphql
.Authorization: Bearer <token>
).Check terminal logs and test phones. View the response in Playground.
4. Integrating with Vonage (Recap & Details)
Recap of the core integration setup:
VONAGE_API_KEY
,VONAGE_API_SECRET
,VONAGE_APPLICATION_ID
,VONAGE_PRIVATE_KEY_PATH
,VONAGE_FROM_NUMBER
configured via.env
.Applications
>Create a new application
. Name it, enableMessages
, generate keys, downloadprivate.key
. Note theApplication ID
. Webhook URLs can be dummy HTTPS URLs (e.g.,https://example.com/status
) if only sending.Numbers
>Your numbers
. Ensure the number forVONAGE_FROM_NUMBER
is SMS capable in the target country..env
andprivate.key
out of Git (.gitignore
). Use hosting provider's environment variable management for deployment.5. Error Handling, Logging, and Retry Mechanisms
Robustness requires solid error handling and logging.
5.1 Consistent Error Handling:
sendSingleSms
usestry...catch
for Vonage SDK errors, logging and returning{ success: false, error: message }
.sendBulkSms
usesPromise.allSettled
to handle individual failures within the batch.5.2 Logging:
Redwood's Pino logger (
api/src/lib/logger.ts
) is used:logger.debug
).logger.info
).logger.error
).Production Logging:
info
).5.3 Retry Mechanisms:
Handle temporary Vonage errors (network issues, rate limits).
Simple Retry (Illustrative Example): Could be added within
sendSingleSms
for specific errors.Note: This simple retry adds complexity directly within the request path. The
isRetryable(error)
logic is essential to avoid retrying permanent errors like invalid credentials.Queue-Based Retries (Recommended): Use a job queue (BullMQ, etc.). Leverage its built-in retry strategies (exponential backoff, max attempts). This is the standard, robust approach for background tasks like bulk sending.
Testing Errors:
vonageMessages.send
in unit tests to throw errors.6. Database Schema and Data Layer (Logging)
Log attempts for tracking.
6.1 Define Prisma Model:
Add to
api/db/schema.prisma
:(Added indexes for common query patterns and unique constraint on message ID)
6.2 Apply Migrations:
6.3 Implement Database Logging:
The logging logic is already integrated into
sendSingleSms
and thelogSmsAttempt
helper function shown in Section 2.2. Every attempt initiated bysendSingleSms
will now be recorded in theSmsLog
table.7. Adding Security Features
Protect your API and data.
@requireAuth
used on the mutation. Ensure Redwood Auth is properly configured.requireAuth({ roles: ['admin'] })
within the service or secure the service method.sendSingleSms
). Uselibphonenumber-js
.recipients.length
per request.graphql-rate-limit-directive
) to prevent abuse..env
,private.key
. Use secure environment variables in deployment.8. Handling Special Cases
SMS nuances:
+14155550100
). Validate rigorously.9. Implementing Performance Optimizations
For high volume:
sendSingleSms
calls to a background queue (BullMQ, SQS, etc.).db.smsLog.createMany
if processing batches from a queue for better DB performance.10. Monitoring, Observability, and Analytics
Understand system health:
/health
endpoint (check DB, maybe Vonage connectivity).11. Troubleshooting and Caveats
Common problems:
429 Too Many Requests
, timeouts.401 Unauthorized
.VONAGE_*
vars andprivate.key
path/readability.@vonage/server-sdk
.12. Deployment and CI/CD
Deploying your application:
VONAGE_*
,DATABASE_URL
) securely in the hosting environment. Do not commit sensitive files/vars. Handleprivate.key
upload/storage securely per provider features.DATABASE_URL
.yarn install --frozen-lockfile
.yarn rw lint && yarn rw type-check
.yarn rw test api
(mock external services like Vonage).yarn rw build
.yarn rw prisma migrate deploy
(requires secure DB access).13. Verification and Testing
Validate your implementation:
Unit Tests (
api/src/services/sms/sms.test.ts
):@vonage/server-sdk
(usingjest.mock
orvi.mock
).sendSingleSms
: Verify calls tovonageMessages.send
anddb.smsLog.create
with correct args. Mock success/error from Vonage. Test validation logic.sendBulkSms
: Verify callssendSingleSms
per recipient. Test mixed results. Test empty list. Check summary object.Integration Tests: Test the GraphQL mutation endpoint directly (using Redwood's test setup or tools like
supertest
). Requires careful handling of external API calls (mocking or using test credentials).End-to-End (E2E) Tests: Use tools like Cypress or Playwright to simulate user interaction if there's a UI. Requires Vonage test numbers and potentially a dedicated test environment.
Manual Testing: Send messages to real test phones (including your own) using valid credentials in a development or staging environment. Verify delivery and check logs. Test edge cases like invalid numbers.