Building a Bulk SMS Broadcast System with RedwoodJS and Sinch - code-examples -

Frequently Asked Questions

Navigate to your RedwoodJS api directory using your terminal, then run 'yarn workspace api add @sinch/sdk-core'. This command adds the Sinch Node.js SDK to your project's API side, allowing you to interact with the Sinch SMS API.
Integrate the Sinch SMS API into your RedwoodJS application. This involves setting up your project, configuring your database with Prisma, creating necessary services and GraphQL endpoints, and then leveraging the Sinch Node.js SDK to send messages via the API. This setup allows you to manage contacts and broadcast messages efficiently.
RedwoodJS is the core framework for building the bulk SMS application. It provides structure for the backend API using GraphQL and services, connects to a database via Prisma, and offers a frontend framework with React. This allows for a streamlined development process.
Sinch provides a reliable and powerful SMS API along with an official Node.js SDK. The API allows for efficient bulk messaging by enabling sending to multiple recipients in a single API call, simplifying the integration and improving performance.
Prisma acts as the Object-Relational Mapper (ORM) connecting your RedwoodJS application to your chosen database (PostgreSQL or SQLite). It simplifies database interactions by defining models (like Contact and Broadcast) in a schema file, allowing you to query and manage data using JavaScript.
RedwoodJS uses a .env file in the project root. Create or open this file and add your Sinch credentials like Project ID, Key ID, Key Secret, and your Sinch virtual number. Make sure to add .env to your .gitignore file to protect your secrets.
Implement a try-catch block around the sinchClient.sms.batches.send API call. Inside the catch block, update the broadcast status to 'FAILED', log detailed error messages including the Sinch API response if available, and throw an error to notify the user.
Fetching all contacts at once using db.contact.findMany() is not scalable. Implement background jobs with Redwood's exec command or a task queue like BullMQ. The job should process contacts in batches, ensuring the application doesn't timeout when sending to thousands of recipients.
Create GraphQL SDL and corresponding service functions to handle contact creation. Implement input validation, specifically for phone numbers using E.164 formatting, and use Prisma to save the contact data to the database.
Login to the Sinch Customer Dashboard. Note your Project ID, navigate to Access Keys, and generate a new key pair (Key ID and Key Secret). Save the Key Secret securely as it's only displayed once. Find your provisioned Sinch phone number under Numbers > Your Virtual Numbers.
Use the BroadcastRecipient model when you need detailed tracking of individual message statuses within a broadcast. This join table helps manage retries, provide detailed reporting, and understand specific delivery failures, especially for large-scale SMS campaigns.
In this implementation, 'SENT' signifies that the Sinch API has *accepted* the batch send request. It doesn't guarantee delivery to the recipient. To track actual delivery, you must configure Sinch Delivery Report Webhooks.
Yes, the current design allows retrying a 'FAILED' broadcast by calling the sendBroadcast mutation again. For robust automated retries against transient issues, consider setting up a background job queue system with exponential backoff.
Use background jobs, database batching, and select specific data fields in queries. Instead of pulling all contacts at once, which can lead to timeouts, process them in smaller groups in the background and use Prisma's 'select' feature to only retrieve necessary data.
The guide emphasizes storing API keys securely as environment variables, validating phone number format using E.164, using Redwood's @requireAuth directive for access control, and handling errors robustly to prevent information leakage. It also recommends using additional measures like rate limiting for production deployments.