Frequently Asked Questions
You can send bulk SMS messages by creating a RedwoodJS application that integrates with the Infobip API. This involves setting up a RedwoodJS project, configuring your Infobip credentials, defining a database schema for storing broadcast information, and implementing the API service to interact with Infobip's SMS API.
RedwoodJS is a full-stack JavaScript framework chosen for its rapid development capabilities and clear architecture. It provides the structure for building both the frontend UI and the backend API for the bulk SMS application, handling user interactions, data management, and communication with the Infobip API.
Infobip is a global communication platform chosen for its reliable SMS delivery, comprehensive API features, and ability to handle bulk messaging efficiently. The Infobip API allows sending messages to multiple recipients simultaneously and tracking their status.
Bulk SMS systems are ideal when you need to efficiently send targeted communications to multiple recipients at once. Use cases include sending notifications, alerts, marketing messages, or other time-sensitive information to a large group.
RedwoodJS typically uses PostgreSQL by default, but Prisma, its ORM, supports other databases like MySQL and SQLite. PostgreSQL is a robust and scalable option for storing broadcast details and recipient information. You can easily configure your preferred database in your RedwoodJS project settings using Prisma.
Your Infobip API key should be stored as an environment variable called INFOBIP_API_KEY in your .env file. This keeps your credentials secure and separate from your codebase. The API side of your RedwoodJS application will then access this key when interacting with the Infobip API.
Infobip requires recipient phone numbers to be in E.164 format. This international standard format includes a '+' sign followed by the country code and the phone number, with no spaces or special characters. For example, a US number would be formatted as +14155552671.
While Infobip's API can handle bulk messages, very large lists might require splitting into smaller batches. RedwoodJS can implement chunking to send multiple requests to Infobip, managing status across the batches. Always consult Infobip’s documentation for their recommended best practices when dealing with large lists or high-throughput messaging.
Yes, you can track delivery status by implementing a webhook endpoint in your RedwoodJS application. Configure this webhook URL in your Infobip settings to receive delivery reports. Then create a serverless function to process these reports and update the status of each message accordingly.
Standard SMS messages have character limits (160 for GSM-7, 70 for UCS-2). Infobip automatically splits longer messages, but it impacts cost. Design your UI to be mindful of length. Special characters might require UCS-2, reducing the limit.
Prisma acts as the Object-Relational Mapper (ORM) for your RedwoodJS application. It simplifies database interactions by providing a type-safe way to query and manipulate data in your chosen database (like PostgreSQL). Prisma handles database connections and schema migrations efficiently.
Your Infobip Base URL is specific to your account region and is crucial for correct API communication. You can find this URL in the Infobip API documentation or your account settings, often labeled as Base URL, Endpoint URL or similar. It is essential to use the correct regional URL.
Building a Bulk SMS Broadcast System with RedwoodJS and Infobip
Build a robust bulk SMS broadcasting application using RedwoodJS and the Infobip API. Create a system that enables users to input phone numbers and messages, send broadcasts via Infobip, and track status.
Send targeted SMS communications – such as notifications, alerts, or marketing messages – to multiple recipients simultaneously.
Technologies Used:
System Architecture:
(Note: The following diagram uses Mermaid syntax. Rendering may vary depending on the platform.)
Final Outcome:
Build a functional RedwoodJS application with:
Prerequisites:
1. Setting up the Project
Initialize your RedwoodJS project and configure the essentials.
Create RedwoodJS App: Open your terminal and run:
Choose TypeScript if prompted (recommended, but JavaScript works too).
Database Configuration: Configure your database connection string in the
.envfile at the project root. Replace the placeholder with your PostgreSQL connection URL:Ensure your PostgreSQL server is running and the specified database (
infobip_broadcastin this example) exists.Initial Migration: Apply the initial database schema:
Enter a migration name when prompted (e.g.,
initial_setup).Infobip Environment Variables: Add your Infobip credentials to the
.envfile:INFOBIP_API_KEY: Find this in your Infobip account under API Key management.INFOBIP_BASE_URL: Specific to your account's region (e.g.,https://<your-subdomain>.api.infobip.com). Find this in the Infobip API documentation or account settings.INFOBIP_SENDER_ID: The alphanumeric sender ID or phone number registered and approved in your Infobip account. Optional depending on your Infobip setup and destination country regulations, but recommended.Obtaining Infobip Credentials:
2. Implementing Core Functionality
Define the database model, create the API service and GraphQL schema, and build the UI component.
Define Database Schema: Update the Prisma schema file (
api/db/schema.prisma) to include aBroadcastmodel.String[]to store multiple recipient phone numbers.statustracks the broadcast progress.infobipBulkIdhelps correlate with Infobip's system.Apply Schema Changes: Generate and apply the migration:
Enter a migration name like
add_broadcast_model.Generate Redwood Files: Use Redwood's generators to scaffold the necessary GraphQL SDL, service, and UI components:
Implement the Broadcast Service: Modify the generated service file (
api/src/services/broadcasts/broadcasts.ts) to include logic for creating broadcasts and interacting with the Infobip API.fetchfromcross-undici-fetchfor reliable fetching in Node.js.PENDINGstatus.POST /sms/2/text/advancedendpoint. Note theAuthorization: App <YOUR_API_KEY>header format.SENTand store thebulkId.FAILEDand store the error message.try...catchblocks and logging are used throughout.Define GraphQL Schema (SDL): Update the generated SDL file (
api/src/graphql/broadcasts.sdl.ts) to match our service logic and model.Broadcasttype mirroring the Prisma model.CreateBroadcastInputexpectsmessageand an array ofrecipients.@requireAuthto protect the endpoints. Remove@requireAuthif you are testing without authentication configured.3. Building the API Layer (RedwoodJS GraphQL)
RedwoodJS automatically builds the GraphQL API based on your SDL files and service implementations.
/.redwood/functions/graphql(or/api/graphqlin production builds).@requireAuthto the SDL. To make this work, you need to set up authentication (e.g., usingyarn rw setup auth dbAuthor another provider). If you keep@requireAuth, the guide implicitly assumes a standard RedwoodJS authentication setup (likedbAuth) is configured. See RedwoodJS Authentication documentation for setup instructions. For initial testing without auth setup, you can temporarily remove@requireAuthfrom the SDL.createBroadcastservice. For more complex validation, consider libraries likeyuporzodwithin the service layer.Testing the API Endpoint:
Start the Dev Server:
Access GraphQL Playground: Open your browser to
http://localhost:8911/graphql(or the GraphQL endpoint URL shown in the terminal).Run the
createBroadcastMutation: Use the Playground interface to send a mutation. Replace placeholders with real (test) E.164 numbers and your message.Check the Response: Observe the response in the Playground. If successful, you should see the created broadcast details with
status: ""SENT""and aninfobipBulkId. If there's an error (e.g., bad API key, invalid number), theerrorsarray will contain details, and the DB record should showstatus: ""FAILED"". Check the terminal runningyarn rw devfor detailed logs from the API service.Check Infobip Portal: Log in to Infobip and check the SMS logs or analytics section to confirm the messages were processed (or see specific errors there).
4. Integrating with Infobip (Covered in Service Implementation)
The core integration happens within the
createBroadcastservice function (api/src/services/broadcasts/broadcasts.ts), detailed in Section 2, Step 4.Key Integration Points:
POST {INFOBIP_BASE_URL}/sms/2/text/advancedAuthorization: App {INFOBIP_API_KEY}header.messagesarray, each withdestinations(array of{ to: number }) andtext. Optionally includesfrom(sender ID)..envusingprocess.env.Security:
.envlocally, platform's secrets management in production). The.gitignorefile included with RedwoodJS correctly ignores.env.Fallback Mechanisms: (Advanced)
For critical broadcasts, consider:
async-retry). Be cautious not to retry on definitive failures (like invalid credentials).5. Implementing Error Handling, Logging, and Retries
Error Handling Strategy:
try...catchblocks for database operations and API calls.Broadcastrecord status (FAILED) and storeerrorMessagein the database upon failure.Logging:
api/src/lib/logger.js).logger.info(),logger.warn(),logger.error()within the service to log key events, input data (carefully, avoid logging sensitive info like full recipient lists if privacy is paramount), API responses, and errors.yarn rw dev. In production, configure log destinations (e.g., stdout for platform logging services, or specific transports like Datadog/Sentry).Infobip API request failederrors, the status code, and the response body provided by Infobip. Also check for database errors (Failed to create broadcast record,Failed to update broadcast status).Retry Mechanisms: (Basic Example - see Service code for placement) A simple retry loop could be added, but for robust retries, a library is better.
This is a simplified example. Libraries like
async-retryhandle this more elegantly.6. Creating the Database Schema and Data Layer (Covered in Section 2)
Broadcastmodel was defined inapi/db/schema.prisma.yarn rw prisma migrate dev. Prisma tracks applied migrations.dbimported fromsrc/lib/db) for type-safe database operations (db.broadcast.create,db.broadcast.findMany,db.broadcast.update, etc.).statusorcreatedAtmight be useful if querying large numbers of broadcasts frequently. Prisma automatically handles connection pooling.7. Adding Security Features
createBroadcast) to check for empty messages/recipients and valid E.164 phone number formats. Sanitize inputs further if necessary (e.g., stripping unexpected characters, although Prisma helps prevent SQL injection).@requireAuthin SDL) to ensure only logged-in users can trigger broadcasts. Implement role-based access control if different user types have different permissions.graphql-shieldor custom logic in your service/GraphQL setup) to limit requests per user/IP. Infobip also enforces its own API rate limits.8. Handling Special Cases
+followed by country code and number, no spaces or dashes) as required by Infobip. The validation function provides a basic check./sms/2/text/advanced) is designed for multiple destinations in a single API call. However, extremely large lists (e.g., >10,000) might hit request size limits or timeouts. Consider:infobipBulkIds.INFOBIP_SENDER_IDis valid and approved for your target countries via the Infobip portal. Sending might fail otherwise.api/src/functions/infobipWebhook.ts) to handle incoming POST requests from Infobip.RecipientStatustoBroadcast).9. Building the User Interface
Now, let's wire up the frontend components generated earlier.
Broadcast Form Component: Implement the form to capture recipients and the message.