Frequently Asked Questions
You can schedule SMS messages by sending a POST request to the /schedule endpoint with the recipient's phone number, message content, and desired send time (scheduledAt) in ISO 8601 format. The application uses NestJS to handle the request, validate the data, and interact with the Infobip API to schedule the message. The scheduled message details are stored in a PostgreSQL database using Prisma.
The Infobip SMS API is used to send and schedule SMS messages. The NestJS application integrates with this API to handle the actual sending and scheduling of messages after they are stored in the database. The Infobip Node.js SDK simplifies the integration process.
NestJS provides a robust and structured framework for building server-side applications. Its modular architecture, dependency injection, and built-in features like validation and configuration make it ideal for building reliable and scalable SMS scheduling systems. NestJS also works well with TypeScript, enhancing type safety and code maintainability.
An SMS scheduler is beneficial for automated reminders, notifications, and time-sensitive alerts. Use cases include appointment reminders, marketing campaigns, two-factor authentication, and any scenario requiring automated SMS messages at specific times.
Yes, you can cancel a scheduled SMS message by sending a DELETE request to the /schedule/{id} endpoint, where {id} is the unique identifier of the scheduled message. The application will attempt to cancel the message with Infobip and update the status in the database.
The application uses PostgreSQL as the database to store scheduled SMS message information. Prisma, a next-generation ORM, simplifies database interactions and provides type safety.
Obtain your Infobip API Key and Base URL from your Infobip account dashboard. These credentials should be stored securely in a .env file as INFOBIP_API_KEY and INFOBIP_BASE_URL. The NestJS ConfigModule loads these environment variables.
Prisma is an Object-Relational Mapper (ORM) that simplifies database operations. It allows you to define your data models in a schema file (schema.prisma), generate migrations, and interact with the database using type-safe methods.
Create a new NestJS project using the NestJS CLI, install the required dependencies (@nestjs/config, @infobip-api/sdk, prisma, @prisma/client, etc.), configure the environment variables (database URL, Infobip credentials), and set up the Prisma schema.
You need Node.js, npm or yarn, an Infobip account, access to a PostgreSQL database, basic familiarity with TypeScript, REST APIs, and asynchronous programming. Docker and Docker Compose are optional but recommended.
The provided code uses date-fns-tz
library to handle timezone conversions. Although the application stores all dates internally in UTC, it accepts input dates with timezone offsets and parses them correctly. For the Infobip API call, always send the scheduledAt
parameter as a UTC Date object, which ensures timezone-independent scheduling.
If cancellation with Infobip fails, the application will log the error and still mark the message as CANCELED in the database. This simplifies error handling but might mask potential issues with the Infobip API. For production, consider more advanced error handling strategies.
Use the GET /schedule endpoint to retrieve all scheduled messages or /schedule/{id} to get a specific message by ID. You can optionally filter by status using the status
query parameter (e.g., /schedule?status=PENDING).
The bulkId is a unique identifier generated for each batch of scheduled SMS messages. It's used to reference the scheduled messages within Infobip, particularly for cancellation or status updates. This ensures that operations target the correct message batch.
Scheduled messages can have the following statuses: PENDING (scheduled in our DB but not yet sent to Infobip), SCHEDULED_INFOBIP (successfully scheduled with Infobip), SENT (confirmed sent by Infobip - requires webhooks), FAILED (failed to schedule or send), and CANCELED (canceled by user request).
This guide provides a step-by-step walkthrough for building a robust SMS scheduling and reminder application using the NestJS framework and the Infobip SMS API. We will cover everything from initial project setup to deployment considerations, enabling you to create a reliable system for sending timed SMS messages.
By the end of this tutorial, you will have a functional NestJS application capable of accepting API requests to schedule SMS messages, storing these schedules, interacting with the Infobip API to schedule and cancel messages, and providing endpoints to manage these scheduled messages. This solves the common business need for automated reminders, notifications, and time-sensitive alerts via SMS.
Project Overview and Goals
What We'll Build:
Technologies Used:
@infobip-api/sdk
): Simplifies interaction with the Infobip API.System Architecture:
Prerequisites:
1. Setting up the Project
Let's initialize our NestJS project and configure the necessary dependencies and environment variables.
Create a new NestJS Project: Open your terminal and run the NestJS CLI command:
When prompted, choose your preferred package manager (npm or yarn). We'll use
npm
in this guide.Install Dependencies: We need several packages for configuration, scheduling (within NestJS, though Infobip handles final scheduling), Infobip SDK, Prisma, validation, and date handling.
@nestjs/config
: Manages environment variables.@infobip-api/sdk
: The official Infobip SDK for Node.js.class-validator
,class-transformer
: For request data validation using DTOs.date-fns
,date-fns-tz
: Robust libraries for date and timezone manipulation.prisma
,@prisma/client
: Prisma CLI and Client for database interaction.Configure Environment Variables: Prisma initialization created a
prisma/
directory and a.env
file. Update the.env
file with your database connection string and placeholders for Infobip credentials.DATABASE_URL
: The connection string for your PostgreSQL database. Ensure the database (schedulerdb
in the example) exists. If using Docker, adjust the host (e.g.,postgres
).INFOBIP_BASE_URL
: Your unique API base URL provided by Infobip. Find this in your Infobip account under API Keys or on the main dashboard after logging in.INFOBIP_API_KEY
: Your secret API key generated within the Infobip portal (API > API Keys). Keep this secure.Set up Configuration Module: Integrate the
@nestjs/config
module to load environment variables.Set up Database (Optional - Docker): If you don't have PostgreSQL running, you can use Docker Compose. Create a
docker-compose.yml
file:Run
docker-compose up -d
in your terminal to start the database container. YourDATABASE_URL
in.env
should match the credentials (user
,password
,schedulerdb
) and point tolocalhost:5432
.2. Creating a Database Schema and Data Layer (Prisma)
We'll define the schema for storing scheduled SMS information using Prisma.
Define the Prisma Schema: Open
prisma/schema.prisma
and define theScheduledSms
model.scheduledAt
time (always store in UTC).status
tracks the lifecycle of the scheduled message.infobipBulkId
is crucial for referencing the scheduled message batch within Infobip for status updates or cancellation.Apply Schema Changes and Generate Prisma Client: Run the following commands in your terminal:
db push
is suitable for development; for production, useprisma migrate dev
andprisma migrate deploy
.generate
updates the@prisma/client
library with type-safe methods for your schema.Create Prisma Service: Create a reusable service to interact with the Prisma Client.
Implement the service to connect and disconnect Prisma cleanly:
Make the
PrismaService
available globally by exporting it fromPrismaModule
and importingPrismaModule
intoAppModule
.Update
src/main.ts
to enable shutdown hooks for Prisma:3. Integrating with Infobip
Now, let's create a dedicated module and service to handle interactions with the Infobip API.
Generate Infobip Module and Service:
Implement Infobip Service: This service will initialize the Infobip client using credentials from the
ConfigService
and provide methods to interact with the SMS API.Define Interface: Create an interface for the
scheduleSms
options.Update Infobip Module: Make the
InfobipService
available.Import into AppModule: Ensure the
InfobipModule
is imported inAppModule
.4. Implementing Core Functionality (Scheduling Service)
This service orchestrates the process: saving schedule details to the database and triggering the Infobip API call.
Generate Scheduling Module, Service, Controller:
Create Data Transfer Objects (DTOs): Define DTOs for validating incoming API request data.
Implement Scheduling Service: Inject
PrismaService
andInfobipService
.Update Scheduling Module: Import dependencies.
Import into AppModule:
5. Building the API Layer (Controller)
Implement the controller to expose endpoints for interacting with the
SchedulingService
.Implement Scheduling Controller:
Enable Global Validation Pipe: It's often better to enable validation globally. Ensure this line is present and uncommented in
src/main.ts
:6. API Endpoint Testing
You can now test the API endpoints using
curl
or a tool like Postman. Ensure your NestJS application is running (npm run start:dev
).Schedule an SMS: Replace
YOUR_PHONE_NUMBER
(e.g.,447123456789
) and adjust thescheduledAt
time (must be in the future, ISO 8601 format).Expected Response (Example - IDs will vary):