Frequently Asked Questions
Use NestJS's @nestjs/schedule module along with the Vonage Messages API. Create a scheduled task (cron job) that queries your database for upcoming appointments and sends SMS reminders via the Vonage API at the designated time before the appointment. This guide provides a complete walkthrough using PostgreSQL, Prisma, and other key technologies.
NestJS provides a structured, scalable backend framework. It facilitates API endpoint creation for scheduling, database integration with PostgreSQL via Prisma, and scheduled task management for sending SMS reminders through the Vonage Messages API. Its modular architecture and dependency injection simplify development and maintenance.
The Vonage Messages API allows you to programmatically send SMS messages. This is ideal for appointment reminders as it enables automation and ensures timely notifications to reduce no-shows and improve communication with users.
This guide uses PostgreSQL, a robust and open-source relational database, combined with Prisma, a modern database toolkit and ORM. Prisma simplifies database interactions and data modeling within the NestJS application.
These packages are crucial for request data validation. class-validator provides decorators for defining validation rules (e.g., required fields, data types, string length). class-transformer facilitates transforming request payloads into data transfer objects (DTOs), enforcing data integrity and security.
Obtain your API Key and API Secret from your Vonage API Dashboard. Store these securely in a .env file (never commit this to version control) and access them within your NestJS application using @nestjs/config for secure configuration management.
Use the Vonage CLI to create a new application with the Messages capability. The command vonage apps:create "My SMS Scheduler App" --capabilities=messages --messages_version=v1 --keyfile=private.key sets up an application and generates a private key file (ensure this key is stored securely).
A Vonage virtual number is required to send SMS messages via the Vonage API. After purchasing and linking a Vonage number to your application, add it to your .env file (VONAGE_SMS_FROM_NUMBER) as the sender ID for your reminders. Ensure the number is in E.164 format (+12015550123).
Never commit the private.key file to version control. Instead, manage it through a secure method such as environment variables, a dedicated secrets manager, or mounting it as a volume in containerized environments (e.g. Kubernetes secrets).
Prisma is a modern database toolkit that includes an ORM (Object-Relational Mapper). It simplifies database interactions, schema management, and data modeling in your Node.js and TypeScript applications, making it easier to work with PostgreSQL or other supported databases.
The @nestjs/schedule module allows you to define cron jobs (scheduled tasks). A cron job runs every minute (using CronExpression.EVERY_MINUTE) to check the database for appointments whose reminder time has passed but haven't had a reminder sent. If found, the app sends an SMS using the Vonage Messages API.
The @nestjs/config module provides a way to manage environment variables and application configuration securely. It helps access sensitive data like database credentials and API keys from a .env file without exposing them directly in the codebase. Create a .env.example file to track these environment variables.
This guide provides a complete walkthrough for building a robust SMS appointment scheduling and reminder system using NestJS, Node.js, PostgreSQL, Prisma, and the Vonage Messages API. You will learn how to create an API endpoint to schedule appointments, store them in a database, and automatically send SMS reminders at a specified time before the appointment.
We aim to build a reliable backend service capable of handling appointment creation and triggering timely SMS notifications. This solves the common business need for reducing no-shows and keeping users informed about their upcoming appointments.
Key Technologies:
@nestjs/schedule: For running scheduled tasks (cron jobs) within NestJS to trigger reminders.@nestjs/config: For managing environment variables securely.class-validator&class-transformer: For robust request data validation.System Architecture:
Final Outcome & Prerequisites:
By the end of this guide, you will have a functional NestJS application with:
POST /appointments) to schedule new appointments.Prerequisites:
npm install -g @vonage/cli).ngrokinstalled (optional, for testing inbound webhooks if needed later).1. Setting up the Project
Let's initialize our NestJS project and install the necessary dependencies.
1.1 Install NestJS CLI:
If you don't have it installed globally, run:
1.2 Create New NestJS Project:
Choose your preferred package manager (npm or yarn) when prompted.
1.3 Install Dependencies:
We need several packages for configuration, scheduling, database interaction, validation, and the Vonage SDK.
@nestjs/config: For environment variable management.@nestjs/schedule: For scheduling reminder jobs (usesnode-croninternally).@vonage/server-sdk: The official Vonage Node.js library.class-validator,class-transformer: For input validation using DTOs.@prisma/client,prisma: Prisma client and CLI for database interactions.@nestjs/terminus,@nestjs/axios: For implementing health check endpoints.1.4 Set up Prisma:
Initialize Prisma in your project:
This creates:
prismadirectory with aschema.prismafile..envfile at the project root (if it doesn't exist).1.5 Configure Environment Variables (
.env):Open the
.envfile created by Prisma and add your database connection string and Vonage API credentials. Never commit this file to version control. Create a.env.examplefile to track necessary variables..env:.env.example(Commit this file):Note: Ensure your
VONAGE_SMS_FROM_NUMBERis a number purchased from Vonage and linked to your application (see Section 4). It should be in E.164 format (e.g.,14155552671).1.6 Project Structure (Conceptual):
NestJS encourages a modular structure. We'll create modules for different concerns:
We will create these modules and files in the subsequent steps.
2. Implementing Core Functionality (Appointments & Scheduling)
Now, let's build the core logic for creating appointments and scheduling reminders.
2.1 Create Prisma Module:
This module provides the Prisma service for database interactions throughout the application.
src/database/prisma.service.ts:src/database/prisma.module.ts:Register
PrismaModuleinAppModule:src/app.module.ts:2.2 Create Vonage Module:
Encapsulate Vonage SDK interaction within its own module and service.
src/vonage/vonage.service.ts:src/vonage/vonage.module.ts:Register
VonageModuleinAppModule:src/app.module.ts:2.3 Create Appointments Module:
This module handles the creation and management of appointments.
Define Data Transfer Object (DTO) for Validation:
src/appointments/dto/create-appointment.dto.ts:Implement Appointments Service:
src/appointments/appointments.service.ts:Implement Appointments Controller:
src/appointments/appointments.controller.ts:Configure Appointments Module:
src/appointments/appointments.module.ts:Register
AppointmentsModuleinAppModule:src/app.module.ts:2.4 Create Scheduler Module for Reminders:
This module will contain the scheduled task (cron job) that checks for due reminders and triggers SMS sending.
src/scheduler/reminder.task.service.ts:src/scheduler/scheduler.module.ts:Register
AppSchedulerModuleinAppModule:src/app.module.ts:2.5 Enable Validation Pipe Globally:
To ensure all incoming requests are validated against DTOs, enable the
ValidationPipeglobally.src/main.ts:3. Building the API Layer
The primary API endpoint is
POST /appointments, which we created in the previous section.Endpoint Definition:
POST/appointmentsCreateAppointmentDto(JSON)201 Createdwith the createdAppointmentobject (JSON).400 Bad Request: If validation fails (e.g., invalid phone number, missing fields).500 Internal Server Error: If database operation or other internal process fails.Request Example (JSON):
Response Example (JSON - Success 201 Created):
Testing with
curl:Replace placeholders with your actual data and running application URL (e.g.,
http://localhost:3000).4. Integrating with Vonage
This involves setting up your Vonage account, application, and number correctly.
4.1 Vonage Account & Credentials:
.envfile (VONAGE_API_KEY,VONAGE_API_SECRET).4.2 Create a Vonage Application:
An application acts as a container for your configurations and links your virtual number. You can create this via the Dashboard or the CLI. Using the CLI is often faster for developers.
Authenticate CLI (if first time):
Create Application: We only need the Messages capability for sending SMS. Webhooks aren't strictly required for this guide's core functionality (sending reminders), but you might enable them if you plan to handle inbound messages later.
4.3 Purchase and Link a Vonage Number:
You need a Vonage virtual number to send SMS messages from.
.env: Add the purchased number (in E.164 format, e.g.,12015550123) toVONAGE_SMS_FROM_NUMBERin your.envfile.4.4 Configure Private Key:
vonage apps:createcommand generated aprivate.keyfile.VONAGE_PRIVATE_KEY_PATHin your.envfile correctly points to the location of this file relative to your project root (e.g.,./private.key).private.keyto your.gitignorefile. In production, manage this key securely (e.g., environment variable content, secrets manager, mounted volume) rather than committing it or copying it directly into container images.Your Vonage integration setup is now complete. The
VonageServiceuses these credentials and the private key to authenticate with the Vonage API for sending SMS messages.