Frequently Asked Questions
You can send SMS messages by creating a Next.js server action that uses the Vonage Node.js SDK. This action handles sending messages securely on the server-side and interacts with a form component on the front-end. The form collects the recipient's phone number and the message text, which are then sent to the Vonage API via the SDK.
A Vonage Delivery Receipt (DLR) is a status update sent via webhook to your application, confirming the delivery status of an SMS message. It provides information on whether the message was successfully delivered, failed, or expired. The DLR is crucial for tracking message delivery beyond the initial 'accepted' status.
Inbound SMS messages are handled using a webhook route handler in your Next.js application. When someone sends a message to your Vonage number, Vonage forwards it to this endpoint as a POST request. The handler processes the message content and sender number, allowing your application to respond or trigger actions.
Vonage uses webhooks for delivery receipts because message delivery is an asynchronous process. The initial API response only confirms message acceptance, not final delivery. Webhooks provide real-time status updates as they become available without requiring your application to constantly poll the API.
Zod is beneficial for validating user input in your Next.js SMS application. By defining schemas, you ensure data integrity and prevent invalid phone numbers or message text from being processed. This helps avoid unexpected errors and improves the reliability of your application.
Prerequisites include a Vonage API account, a rented Vonage virtual number with SMS capabilities, Node.js and npm or yarn, Git, and a deployment platform account (like Vercel). Basic understanding of JavaScript, React, Next.js, and terminal commands is also recommended.
Create a `.env.local` file in the root of your Next.js project and add your `VONAGE_API_KEY`, `VONAGE_API_SECRET`, and `VONAGE_VIRTUAL_NUMBER`. This file should be added to your `.gitignore` to prevent sensitive information from being committed to version control. On platforms like Vercel, set environment variables within the project's settings.
The guide uses the latest version of Next.js with the App Router, which provides improved routing and server-side capabilities. This simplifies the process of setting up API routes and handling webhook requests.
Testing webhooks locally requires tools like ngrok to create a public tunnel to your local server, as Vonage needs a publicly accessible URL. The guide emphasizes deployment for proper webhook functionality due to this requirement.
Configure webhook URLs in your Vonage API Dashboard settings. Provide the full public URLs of your deployed Next.js route handlers for delivery receipts (DLRs) and inbound messages, ensuring the HTTP method is set to POST. These URLs are where Vonage will send webhook data.
To troubleshoot webhook issues, double-check URL accuracy in the Vonage dashboard, verify successful deployment, ensure your handler returns a 200 OK response, and check firewalls if self-hosting. Inspect your Vercel function logs for errors, and ensure correct Vonage number format and SMS capabilities.
Key security measures include using environment variables for API credentials, implementing thorough input validation with tools like Zod, and potentially incorporating secret tokens or rate limiting for webhooks to prevent misuse or unauthorized access.
A complete, working code repository can be found on GitHub at: https://github.com/vonage-community/vonage-nextjs-sms-guide. This allows you to explore a fully functional implementation of the concepts discussed in the guide.
This guide provides a step-by-step walkthrough for building a Next.js application capable of sending SMS messages via the Vonage API, receiving delivery receipts (DLRs), and handling inbound SMS messages using webhooks.
We will build a simple web form to send SMS messages and set up API routes (route handlers in Next.js App Router) to act as webhook endpoints for receiving status updates and incoming messages from Vonage. This enables real-time tracking of message delivery and allows your application to react to messages sent to your Vonage number.
Technologies Used:
Outcome:
By the end of this guide, you will have a functional Next.js application that can:
Prerequisites:
1. Setting Up the Project
Let's initialize our Next.js project and configure the necessary environment variables and dependencies.
Create a New Next.js Project: Open your terminal and run the following command to create a new Next.js project using the App Router:
When prompted, select the following options (or adjust as needed, but this guide assumes these settings):
This creates a new directory named
vonage-sms-nextjs
with the basic project structure.Navigate into Project Directory:
Declare Environment Variables: Create a file named
.env.local
in the root of your project. This file will store your sensitive credentials and configuration. Never commit this file to Git.Add the following lines to
.env.local
, replacing the placeholder values with your actual credentials:VONAGE_API_KEY
: Your Vonage API key.VONAGE_API_SECRET
: Your Vonage API secret.VONAGE_VIRTUAL_NUMBER
: The Vonage phone number you rented, used as the sender ID (ensure it's in the format required by Vonage, usually E.164 format without the leading+
).Install Dependencies: We need the Vonage Node.js SDK to interact with the API and optionally Zod for input validation.
@vonage/server-sdk
: The official Vonage library for Node.js.zod
: Used for validating the phone number and message text before sending.Configure
.gitignore
: Ensure.env.local
is included in your.gitignore
file (create-next-app usually adds it by default) to prevent accidentally committing your secrets.2. Implementing SMS Sending Functionality
We'll create a server action to handle sending the SMS securely on the server and a form component for the user interface.
Create the Server Action (
send-sms.js
): Server Actions allow us to run server-side code directly in response to UI interactions, without needing to manually create API routes for simple form submissions.Create a directory
app/lib
and inside it, create a file namedsend-sms.js
:Explanation:
'use server'
: Marks this module for Server Actions..env.local
.number
) and message content (text
). The regex comment highlights its basic nature.sendSMS
Function: This is the core server action.prevState
(previous state from the form hook) andformData
.schema.parse
: Validates the incoming form data. Throws an error if validation fails.vonage.sms.send
: Calls the Vonage API to send the SMS.to
,from
, andtext
are required parameters.status
field in thevonageResponse
. A status of'0'
usually means the message was accepted for delivery. Other statuses indicate errors. Note that for long (concatenated) SMS messages, this only reflects the status of the first part of the message. Handling DLRs (Delivery Receipts) via webhooks is necessary for final delivery confirmation.revalidatePath('/')
: Clears the cache for the homepage, useful if you were displaying data that needs updating after the action.try...catch
block to handle validation errors (from Zod) and other potential errors during the API call.Create the Form Component (
send-form.jsx
): This client component provides the UI for entering the phone number and message. It uses React hooks (useFormState
,useFormStatus
) to manage form submission state and display responses from the server action.Create a file named
app/send-form.jsx
:Explanation:
'use client'
: Marks this as a Client Component.useFormStatus
: Provides thepending
state, used inSubmitButton
to show loading feedback.useFormState
: Connects thesendSMS
server action to the component's state (state
). When the form is submitted,sendSMS
runs, and its return value updatesstate
, causing the UI to re-render and display theresponse
.type=""tel""
) and message (textarea
).required
attribute ensures fields are not empty.aria-live=""polite""
: Improves accessibility by announcing the response message when it appears.Integrate Form into the Page (
page.js
): Import and use theSendForm
component in your main page file.Update
app/page.js
:Run the Development Server: Start your Next.js development server to test the sending functionality locally.
Open your browser to
http://localhost:3000
. You should see the form. Try sending an SMS to your own phone number. Check the form's response message and confirm if you receive the SMS. Note that webhooks (delivery receipts, inbound messages) won't work locally without extra tooling like ngrok, which is why deployment is necessary for the next steps.3. Receiving Delivery Receipts & Inbound SMS (Webhooks)
Vonage uses webhooks to push data to your application asynchronously. We need publicly accessible endpoints (URLs) in our deployed application for Vonage to send delivery receipt status updates and inbound SMS messages.
Explain Webhooks: When you send an SMS, the initial API response (
status: 0
) only confirms Vonage accepted the message. The actual delivery status (delivered, failed, etc.) comes later via a webhook. Similarly, when someone sends an SMS to your Vonage number, Vonage forwards it to your application via an inbound SMS webhook. These require your application to expose specific HTTP POST endpoints.Create Route Handlers for Webhooks: Next.js Route Handlers allow us to create API endpoints within the
app
directory.Delivery Receipt Handler: Create the directory structure
app/webhook/status
and add a file namedroute.js
:Inbound SMS Handler: Create the directory structure
app/webhook/inbound
and add a file namedroute.js
:Explanation:
POST
Function: This handles the incoming HTTP POST requests from Vonage.request.json()
: Parses the JSON payload sent by Vonage.console.log
: Logs the received data. In a production app, you'd replace this with proper logging and database operations.return new Response('OK', { status: 200 })
: This is critical. You must return a200 OK
(or204 No Content
) response quickly to acknowledge receipt of the webhook. If Vonage doesn't receive a 2xx response, it will assume the delivery failed and retry sending the webhook, potentially leading to duplicate processing.GET
Function (Optional): Provides a simple way to check if the endpoint is deployed and reachable via a browser or health check tool.Deploy the Application: Webhooks require a publicly accessible URL. Deploy your application to a platform like Vercel.
Push to GitHub/GitLab/Bitbucket:
git init
git add .
git commit -m ""Initial commit with SMS sending and webhook handlers""
git remote add origin <your-repo-url>
git push -u origin main
(or your default branch name)Deploy on Vercel:
VONAGE_API_KEY
,VONAGE_API_SECRET
, andVONAGE_VIRTUAL_NUMBER
with their respective values. Ensure they are available for all environments (Production, Preview, Development).https://your-project-name.vercel.app
).Configure Vonage Webhook URLs: Now, tell Vonage where to send the delivery receipts and inbound messages.
https://your-project-name.vercel.app/webhook/status
https://your-project-name.vercel.app/webhook/inbound
POST
.4. Verification and Testing
With the application deployed and Vonage configured, let's verify everything works.
Test Sending:
https://your-project-name.vercel.app
).Test Delivery Receipt Webhook:
/webhook/status
. You should see the logged JSON payload containing the delivery status (delivered
,failed
,expired
, etc.) for the message you sent.Example DLR Payload (Failed):
Test Inbound SMS Webhook:
/webhook/inbound
. You should see the logged JSON payload containing the message text, sender number (msisdn
), and other details.Example Inbound SMS Payload:
5. Error Handling and Logging
sendSMS
function includestry...catch
blocks to handle Zod validation errors and general API/network errors, returning informative messages to the UI.try...catch
blocks. In production, implement more robust error handling:console.log
.status
anderr-code
fields in delivery receipts to understand why messages might fail. Consult the Vonage SMS API error codes documentation.6. Security Considerations
.env.local
locally, platform settings in deployment) and ensure.env.local
is in.gitignore
.send-sms.js
provides basic validation. Sanitize or validate all user input thoroughly to prevent injection attacks or unexpected behavior./webhook/status?token=YOUR_SECRET
), and verify this token in your handler. This adds a layer of assurance that the request originated from Vonage (or at least someone who knows the token).7. Troubleshooting and Caveats
.env.local
is correctly formatted and placed in the project root. On deployment platforms like Vercel, ensure environment variables are configured in the project settings. Restart your local dev server after changing.env.local
.https://
and the correct path/webhook/status
or/webhook/inbound
).200 OK
response quickly. Check Vercel function logs for errors within your handlers. If your logic takes too long, Vonage might time out and retry. Consider processing webhook data asynchronously (e.g., push to a queue).to
number insendSMS
and yourVONAGE_VIRTUAL_NUMBER
are in the correct format (usually E.164 without leading+
).8. Deployment and CI/CD (Vercel Example)
Vercel provides seamless CI/CD via Git integration.
main
) to your production URL.9. Complete Code Repository
A complete, working example of this project can be found on GitHub:
https://github.com/vonage-community/vonage-nextjs-sms-guide
Conclusion
You have successfully built a Next.js application that leverages the Vonage SMS API to send messages and uses webhooks to receive delivery receipts and handle inbound SMS. You learned how to set up the project, implement server actions for sending, create route handlers for webhooks, deploy the application, and configure Vonage settings.
This forms a solid foundation for building more complex SMS-based features, such as two-factor authentication, appointment reminders, customer support chat via SMS, or automated responses to inbound messages. Remember to implement robust error handling, logging, and security measures for production applications.