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
This guide provides a step-by-step walkthrough for building a robust bulk SMS broadcasting application using the RedwoodJS framework and the Infobip API. We will create a system that enables users to input a list of phone numbers and a message, send the broadcast via Infobip, and track its status.
This solution addresses the need for businesses to efficiently 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:
By the end of this guide, you will have a functional RedwoodJS application with:
Prerequisites:
1. Setting up the Project
Let's initialize our 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: Redwood uses Prisma. Configure your database connection string in the
.env
file at the project root. Replace the placeholder with your actual PostgreSQL connection URL:Ensure your PostgreSQL server is running and the specified database (
infobip_broadcast
in this example) exists.Initial Migration: Apply the initial database schema (which is empty by default but sets up Prisma's migration tracking):
Enter a name for the migration when prompted (e.g.,
initial_setup
).Infobip Environment Variables: Add your Infobip credentials to the
.env
file. You'll also need to specify which environment variables theweb
side needs access to (prefixed withREDWOOD_ENV_
).INFOBIP_API_KEY
: Found in your Infobip account under API Key management.INFOBIP_BASE_URL
: Specific to your account's region. Find this in the Infobip API documentation or your account settings (e.g.,https://<your-subdomain>.api.infobip.com
).INFOBIP_SENDER_ID
: The alphanumeric sender ID or phone number registered and approved in your Infobip account for sending messages. This might be optional depending on your Infobip setup and destination country regulations, but it's best practice to include it.Obtaining Infobip Credentials:
2. Implementing Core Functionality
We'll now 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 aBroadcast
model.String[]
to store multiple recipient phone numbers.status
tracks the broadcast progress.infobipBulkId
helps correlate with Infobip's system.Apply Schema Changes: Generate and apply the migration:
Enter a name like
add_broadcast_model
.Generate Redwood Files: Use Redwood's generators to scaffold the necessary GraphQL SDL, service, and UI components for managing broadcasts.
Implement the Broadcast Service: Modify the generated service file (
api/src/services/broadcasts/broadcasts.ts
) to include the logic for creating a broadcast and interacting with the Infobip API.fetch
fromcross-undici-fetch
for reliable fetching in Node.js.PENDING
status.POST /sms/2/text/advanced
endpoint. Note theAuthorization: App <YOUR_API_KEY>
header format.SENT
and store thebulkId
.FAILED
and store the error message.try...catch
blocks 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.Broadcast
type mirroring the Prisma model.CreateBroadcastInput
expectsmessage
and an array ofrecipients
.@requireAuth
to protect the endpoints. Remove@requireAuth
if 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/graphql
in production builds).@requireAuth
to the SDL. To make this work, you need to set up authentication (e.g., usingyarn rw setup auth dbAuth
or 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@requireAuth
from the SDL.createBroadcast
service. For more complex validation, consider libraries likeyup
orzod
within 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
createBroadcast
Mutation: 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), theerrors
array will contain details, and the DB record should showstatus: ""FAILED""
. Check the terminal runningyarn rw dev
for 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
createBroadcast
service function (api/src/services/broadcasts/broadcasts.ts
), detailed in Section 2, Step 4.Key Integration Points:
POST {INFOBIP_BASE_URL}/sms/2/text/advanced
Authorization: App {INFOBIP_API_KEY}
header.messages
array, each withdestinations
(array of{ to: number }
) andtext
. Optionally includesfrom
(sender ID)..env
usingprocess.env
.Security:
.env
locally, platform's secrets management in production). The.gitignore
file 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...catch
blocks for database operations and API calls.Broadcast
record status (FAILED
) and storeerrorMessage
in 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 failed
errors, 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-retry
handle this more elegantly.6. Creating the Database Schema and Data Layer (Covered in Section 2)
Broadcast
model was defined inapi/db/schema.prisma
.yarn rw prisma migrate dev
. Prisma tracks applied migrations.db
imported fromsrc/lib/db
) for type-safe database operations (db.broadcast.create
,db.broadcast.findMany
,db.broadcast.update
, etc.).status
orcreatedAt
might 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).@requireAuth
in SDL) to ensure only logged-in users can trigger broadcasts. Implement role-based access control if different user types have different permissions.graphql-shield
or 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:infobipBulkId
s.INFOBIP_SENDER_ID
is 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.RecipientStatus
toBroadcast
).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.