Frequently Asked Questions
Use the messagebird.messages.create
method with the scheduledDatetime
parameter set to your desired reminder time in ISO 8601 format. This, combined with NestJS's scheduling capabilities, allows for automated SMS reminders through the MessageBird API. Ensure your API key has the necessary permissions in the MessageBird dashboard.
MessageBird is the communication platform used to send SMS messages and validate phone numbers. You'll need a MessageBird account and API key to integrate their services. The provided code examples demonstrate how to interact with the MessageBird Lookup and Messages APIs using their Node.js SDK.
NestJS provides a robust and structured framework for building scalable server-side applications in Node.js. Its modular architecture, dependency injection, and TypeScript support contribute to a more maintainable and efficient application for handling SMS scheduling and other backend logic.
Validate phone numbers before scheduling SMS reminders using the MessageBird Lookup API. This ensures the number is valid and correctly formatted, improving the reliability of your reminder system. The example code demonstrates how to perform this validation within the scheduling process.
Yes, while the article recommends PostgreSQL and provides setup instructions for it, NestJS supports various databases through TypeORM. You can adapt the TypeOrmModule
configuration in the app.module.ts
file to connect to your preferred database.
Create a .env
file in your project's root directory and store your MessageBird API key as MESSAGEBIRD_API_KEY
. Then, use NestJS's ConfigModule
to load this environment variable securely into your application's configuration.
The MESSAGEBIRD_ORIGINATOR
environment variable sets the sender ID that recipients will see on their phones. This can be an alphanumeric string or a MessageBird Virtual Mobile Number. Be mindful of country-specific restrictions on sender IDs.
Implement error handling using try-catch blocks around MessageBird API calls and use NestJS's built-in exception handling mechanisms like BadRequestException
and InternalServerErrorException
. Log errors for debugging and monitoring. Consider retry mechanisms with exponential backoff for transient network errors.
The article recommends using a Long-Term Support (LTS) version of Node.js, such as v18 or v20, to ensure stability and compatibility with the other project dependencies like NestJS and the MessageBird SDK.
Install the necessary packages (@nestjs/typeorm
, typeorm
, pg
), configure the TypeOrmModule
in your app.module.ts
file with your database credentials, define your entities (like the Appointment
entity), and inject the repository into your service to interact with the database.
Use the ISO 8601 format (e.g., '2025-12-31T14:30:00.000Z') in UTC for the appointmentTime
to avoid timezone issues. The @IsISO8601
decorator enforces this format and the code uses the date-fns
library for parsing and manipulation.
Organize your project using modules. The article demonstrates creating an AppointmentModule
to encapsulate the appointment scheduling logic, including the controller, service, and DTOs. This promotes code organization and maintainability.
Validating phone numbers ensures accurate delivery of SMS reminders. The MessageBird Lookup API helps verify the format and type of phone number, preventing wasted messages and improving system reliability. Robust validation using libraries like 'google-libphonenumber' is highly recommended for production.
The REMINDER_HOURS_BEFORE
variable defines how many hours before the appointment the SMS reminder should be sent. It is read from the .env
file and used to calculate the scheduledDatetime
for the MessageBird API call.
This guide walks you through creating a production-ready SMS appointment scheduling and reminder system using NestJS, Node.js, and the MessageBird API. You'll learn everything from initial project setup to deployment and monitoring.
Important Note (2024): MessageBird rebranded as "Bird" in February 2024. The existing MessageBird APIs and SDKs remain fully functional and compatible with the new branding (Bird Legal Change Notice, February 2024). This guide uses the
messagebird
npm package (v4.0.1, published January 25, 2023), which continues to work with Bird's infrastructure. Find new API documentation at bird.com/api-reference, while legacy documentation remains at developers.messagebird.com.Project Overview and Goals
Build a backend system that enables users (or other systems) to schedule appointments and automatically trigger SMS reminders via MessageBird at a set time before each appointment.
Problem Solved: Reduce no-shows for appointments by sending timely SMS reminders, improving operational efficiency and customer experience. Automate the reminder process, eliminating manual effort.
Technologies:
System Flow:
AppointmentService
to handle the business logic.AppointmentService
validates the phone number using MessageBird Lookup.AppointmentService
(optionally) persists appointment details to the database (e.g., PostgreSQL via TypeORM).AppointmentService
uses the MessageBird SDK to schedule the SMS reminder via the MessageBird API.Prerequisites:
Final Outcome: A robust NestJS application with an API endpoint to schedule appointments, validate phone numbers, store appointment data, and reliably schedule SMS reminders via MessageBird.
1. Setting up the Project
Initialize your NestJS project and install the necessary dependencies.
Install NestJS CLI: If you don't have the NestJS CLI installed globally, run:
Create New NestJS Project:
Choose your preferred package manager (npm or yarn) when prompted.
Install Dependencies: Install modules for configuration, validation, MessageBird integration, and database operations (if using one).
@nestjs/config
: Manages environment variables.class-validator
,class-transformer
: Validate request DTOs.dotenv
: Loads environment variables from a.env
file.messagebird
: Official Node.js SDK for the MessageBird API (v4.0.1, January 25, 2023). Despite being published in 2023, it remains fully functional with Bird's current infrastructure.date-fns
: Modern library for date manipulation.@nestjs/typeorm
,typeorm
,pg
: PostgreSQL integration via TypeORM.@nestjs/schedule
: Useful for internal application scheduling, distinct from MessageBird's SMS scheduling.Environment Configuration (
.env
): Create a.env
file in your project root:MESSAGEBIRD_API_KEY
: Obtain this from your Bird Dashboard (formerly MessageBird Dashboard: Developers → API access → Show key). Use a live key for real messages or a test key for development without sending actual SMS. API keys created before the February 2024 rebrand remain valid.MESSAGEBIRD_ORIGINATOR
: The sender ID displayed on the recipient's phone. Use an alphanumeric string (max 11 chars, country restrictions apply) or a purchased MessageBird/Bird virtual mobile number (required for some countries like the US). Check Bird documentation for country-specific restrictions.MESSAGEBIRD_LOOKUP_COUNTRY_CODE
: Helps the Lookup API parse numbers entered without a country code (use ISO 3166-1 alpha-2 format).REMINDER_HOURS_BEFORE
: Configures the reminder timing.NODE_ENV
: Important for TypeORM configuration (see Section 6).Load Configuration (
app.module.ts
): Configure theConfigModule
to load the.env
file.Enable Validation Pipe (
main.ts
): Enable the global validation pipe to automatically validate incoming request bodies based on DTOs.Project Structure: NestJS encourages a modular structure. We'll create an
AppointmentModule
to encapsulate all appointment-related logic.This creates:
src/appointment/appointment.module.ts
src/appointment/appointment.controller.ts
src/appointment/appointment.service.ts
Create a DTO directory:
mkdir src/appointment/dto
2. Implementing Core Functionality (Scheduling Logic)
Implement the service responsible for validating data, interacting with MessageBird, and (optionally) saving to the database.
Define Appointment DTO (
create-appointment.dto.ts
): Create a Data Transfer Object to define the expected shape and validation rules for incoming request bodies.class-validator
decorators to enforce rules.@IsPhoneNumber
: Provides basic validation. See warning in the code comment about production readiness.@IsISO8601
: Ensures the date uses the correct format. Using UTC is crucial for avoiding timezone issues.Implement
AppointmentService
: This service will contain the core logic. Note: This version does not include database persistence (see Section 6 for the optional DB integration).REMINDER_HOURS_BEFORE
) and initializes MessageBird.date-fns
for parsing, calculation (subHours
), and validation (isBefore
).messagebird.lookup.read
wrapped in aPromise
, handles errors, checks formobile
type.messagebird.messages.create
withscheduledDatetime
, wrapped in aPromise
.Promise<{ id: string; message: string }>
as database persistence is not included here.Logger
.3. Building the API Layer
Create the controller to expose an endpoint for scheduling appointments.
/appointments/schedule
.CreateAppointmentDto
using@Body()
.AppointmentService
.Testing the Endpoint (Example using curl):
Assuming your app runs on port 3000:
Note: Use a real mobile number for testing with live keys. The
appointmentTime
must be later than the configured reminder hours plus a small buffer (e.g., 5 minutes) from the current time, specified in UTC.Expected Success Response (201 Created – without DB):
Expected Error Response (400 Bad Request – e.g., invalid date):
4. Integrating with MessageBird (Deep Dive)
You've already initialized the client and used the Lookup and Messages APIs. Review key integration points:
AppointmentService
constructor usingMessageBird(this.apiKey)
..env
file andConfigModule
. Never commit your API key to version control. Use environment variables in deployment environments.MESSAGEBIRD_ORIGINATOR
.MESSAGEBIRD_LOOKUP_COUNTRY_CODE
in.env
aids parsing numbers without a country code.MESSAGEBIRD_API_KEY
: Your secret key.MESSAGEBIRD_ORIGINATOR
: Sender ID.MESSAGEBIRD_LOOKUP_COUNTRY_CODE
: Default country for Lookup.REMINDER_HOURS_BEFORE
: Reminder timing configuration.5. Error Handling, Logging, and Retry Mechanisms
BadRequestException
,InternalServerErrorException
, etc.) thrown from the service layer.ValidationPipe
.Logger
service (@nestjs/common
).messagebird.lookup.read
andmessagebird.messages.create
promise calls with a retry mechanism. Use libraries likeasync-retry
or implement a simple loop with exponential backoff and jitter. Limit retry attempts.6. Database Schema and Data Layer (Optional: PostgreSQL + TypeORM)
This section details how to add database persistence using TypeORM and PostgreSQL. If you implement this, you need to modify the
AppointmentService
andAppModule
shown in previous sections.Install Dependencies: (Should be done in Section 1)
Configure
TypeOrmModule
(app.module.ts
): Modify yoursrc/app.module.ts
to includeTypeOrmModule
.synchronize: true
is for development only. In production, always usesynchronize: false
and manage schema changes via TypeORM migrations. Settingsynchronize: true
in production can cause data loss as TypeORM automatically syncs schema changes without validation.Define
Appointment
Entity: Create the entity file:mkdir src/appointment/entities
Inject Repository and Update Service:
Import
TypeOrmModule
inAppointmentModule
:Inject Repository and Modify
AppointmentService
: Updatesrc/appointment/appointment.service.ts
to inject the repository and save the appointment. ThescheduleAppointmentReminder
method needs modifications to include database persistence.This completes the database integration section. The service now persists appointments to PostgreSQL and returns both the database appointment ID and MessageBird message ID.