Frequently Asked Questions
Send SMS messages using Node.js, Express, and the Vonage Messages API by creating a POST request to the /send-sms endpoint with the recipient's number and the message text in the request body. The server-side code then uses the Vonage SDK to handle sending the SMS through the Vonage API.
The Vonage Messages API is a multi-channel communication platform for sending and receiving messages across various channels, including SMS. This tutorial focuses on using the API for sending and receiving text messages (SMS) within a Node.js application.
Setting up Vonage involves purchasing a virtual number, creating a Vonage application, and linking the number to your application. You will need to generate public and private keys, save the private key securely and enable the messages capability and configure webhook URLs for inbound messages and delivery statuses.
ngrok creates a secure tunnel to your local server, providing a temporary public HTTPS URL. This allows Vonage to deliver webhooks to your local development environment during testing, simulating how real-world webhooks function when deployed.
Vonage uses webhooks to send real-time updates to your server. Inbound SMS messages to your Vonage number trigger a webhook to the '/webhooks/inbound' endpoint. Delivery status updates for your sent SMS messages trigger a webhook to the '/webhooks/status' endpoint.
Receive incoming SMS messages sent to your Vonage virtual number by configuring a webhook URL in your Vonage application settings that points to the '/webhooks/inbound' endpoint of your Node.js application.
Delivery status updates are received via webhooks sent to the '/webhooks/status' endpoint of your server. The webhook request will include the message UUID, the status of the delivery (e.g., 'submitted', 'delivered', 'rejected'), and a timestamp.
The project utilizes several Node.js libraries: 'express' for the web framework, '@vonage/server-sdk' for interacting with the Vonage API, 'dotenv' for managing environment variables, and optionally 'jsonwebtoken' for webhook signature verification in a production environment.
You can install the necessary dependencies (Express, the Vonage Server SDK, and dotenv) by using either 'npm install express @vonage/server-sdk dotenv' or 'yarn add express @vonage/server-sdk dotenv' in your terminal within the project directory.
Safeguard the private key by never committing it to version control and securing file permissions. In production environments, utilize environment variables provided by your hosting platform to handle sensitive information like API keys.
Webhook signature verification, especially with JWT (JSON Web Tokens), is crucial in production for confirming the authenticity of incoming webhooks. This process ensures that the incoming requests originate from Vonage and haven't been tampered with.
Common errors include ngrok timing out, credentials not being set correctly in .env, webhook URLs being wrong, private keys being handled incorrectly, and servers not running.
Vonage expects a 2xx response from your webhook endpoint to acknowledge that your server received it. Without a 2xx response, the system may assume the webhook failed and retry the request, potentially causing duplicate messages or other issues.
Vonage SMS with Node.js: Delivery Status Webhooks & Callbacks Tutorial
Build a Node.js Express server that sends SMS messages, receives inbound SMS, and handles delivery status updates via webhooks using the Vonage Messages API. This guide covers project setup, implementation, security, and deployment.
What you'll build:
Technologies you'll use:
.env
file.System Architecture:
Prerequisites:
ngrok authtoken your-token
for stable URLs and longer sessions.1. Set Up the Project
Initialize your Node.js project and install dependencies.
Create project directory: Open your terminal and create a new directory for the project.
Initialize Node.js project: Create a
package.json
file.Install dependencies: Install Express, the Vonage SDK, and dotenv.
Create project structure: Create the main application file and environment variables file.
Configure
.gitignore
: Prevent committing sensitive information and dependencies.Note: Add
private.key
preemptively to ensure this sensitive file is never accidentally committed to version control.Set up environment variables (
.env
): Create a.env
file in the project root. You'll populate this with credentials from Vonage later.VONAGE_APPLICATION_ID
: Identifies your specific Vonage application.VONAGE_PRIVATE_KEY_PATH
: Local path to the private key file for authenticating API requests.VONAGE_NUMBER
: Your Vonage virtual phone number for sending SMS.MY_NUMBER
: Your personal mobile number for testing (use E.164 format).PORT
: Port your local Express server listens on.2. Integrate with Vonage
Configure Vonage by creating an Application and linking a number to get credentials and webhook URLs.
Log in to Vonage Dashboard: Access your Vonage API Dashboard.
Purchase a virtual number: Navigate to
Numbers
→Buy numbers
. Find a number with SMS capabilities in your desired country and purchase it.Create a Vonage Application:
Applications
→Create a new application
.Generate public and private key
. Save theprivate.key
file immediately and place it in your project's root directory.Messages
capability.Inbound URL
andStatus URL
(e.g.,http://example.com/webhooks/inbound
andhttp://example.com/webhooks/status
). Set HTTP Method toPOST
for both. You'll update these later with your ngrok URL.Get Application ID: Copy the
Application ID
displayed after creation.Link your virtual number:
Linked numbers
.Update
.env
file: Populate your.env
file with the Application ID and Vonage virtual number.Start ngrok: Open a new terminal window and run ngrok, pointing it to port 3000.
Copy the
Forwarding
HTTPS URL (e.g.,https://randomstring.ngrok.io
).Configure webhook URLs in Vonage Application:
Applications
→ Your App Name →Edit
).Messages
capability URLs:https://randomstring.ngrok.io/webhooks/inbound
https://randomstring.ngrok.io/webhooks/status
POST
for both.Webhook URL purposes:
Inbound URL
: Vonage sends data about incoming SMS messages (sent to your Vonage number) here.Status URL
: Vonage sends delivery status updates (e.g.,submitted
,delivered
,rejected
) for messages you send here.3. Implement Core Functionality (Express Server)
Write the Node.js code in
server.js
to handle sending, receiving, and status updates.Code explanation:
dotenv
, importsexpress
andVonage
, initializes Express, and sets up middleware for parsing request bodies.Vonage
instance using theapplicationId
andprivateKey
path from.env
. Includes error handling if the key file is missing or credentials are not set./send-sms
(POST):to
(recipient number) andtext
(message content) in the JSON request body.!to || !text
). Note: Production applications need more robust validation (see Section 6).vonage.messages.send()
with appropriate parameters (message_type
,to
,from
,channel
,text
).message_uuid
upon successful submission to Vonage.try...catch
for robust error handling, logging errors, and returning appropriate HTTP status codes (400 for bad input, 500 or specific Vonage status for API errors)./webhooks/inbound
(POST):Inbound URL
configured in Vonage.VONAGE_NUMBER
, Vonage makes a POST request here.from
), recipient (to
), message content (text
), and the full request body. Note: Production applications should verify the webhook signature (see Section 6).200 OK
status usingres.status(200).end()
. If Vonage doesn't receive a 2xx response, it assumes the webhook failed and retries, potentially leading to duplicate processing./webhooks/status
(POST):Status URL
configured in Vonage.submitted
,delivered
,failed
,rejected
), Vonage makes a POST request here.message_uuid
(linking it back to the sent message), thestatus
, timestamp, any potential error details, and the full request body. Note: Production applications should verify the webhook signature (see Section 6).200 OK
status to acknowledge receipt.4. Running and Testing the Application
Ensure ngrok is running: Keep the terminal window where you started
ngrok http 3000
open. Confirm the HTTPS URL is correctly configured in your Vonage Application settings.Start the Node.js server: In the terminal window for your project directory (where
server.js
is), run:You should see output indicating the server is listening and the Vonage SDK initialized.
Test sending SMS: Open a new terminal window or use a tool like Postman or Insomnia to send a POST request to your
/send-sms
endpoint. ReplaceYOUR_PERSONAL_MOBILE_NUMBER
with the actual value from your.env
file (MY_NUMBER
).Using
curl
:curl
: You should get a JSON response like{"message":"SMS sent successfully","message_uuid":"some-uuid-string"}
.server.js
: You'll see logs for the/send-sms
request and "Message sent successfully…".server.js
: Soon after, you should see logs from/webhooks/status
showing the status changing (e.g.,submitted
, then potentiallydelivered
). Check themessage_uuid
to match the sent message.Test receiving inbound SMS:
VONAGE_NUMBER
(the one configured in.env
).server.js
: You should see logs from/webhooks/inbound
showing the message details (From:
,To:
,Text:
)./webhooks/inbound
.Test delivery failure (optional): Try sending an SMS to an invalid or non-existent number via the
/send-sms
endpoint. Observe the/webhooks/status
logs in yourserver.js
terminal – you should receive statuses likefailed
orrejected
with corresponding error codes/reasons.5. Error Handling and Logging
/send-sms
route includestry...catch
to handle errors during the Vonage API call. It attempts to parse and return specific error details from the Vonage response./inbound
,/status
) encounter an error processing the request before sending the200 OK
, Vonage will retry. Implement robust internal error handling within these routes if you perform complex logic (e.g., database lookups).console.log
andconsole.error
. For production, this is insufficient. Implement a structured logging library likewinston
orpino
. This allows for better log formatting (e.g., JSON), writing logs to files or external services, setting different log levels (debug, info, warn, error), and easier log analysis. This guide does not include the implementation of structured logging.2xx
status code response from your webhook endpoints within a reasonable time (usually a few seconds) to consider the delivery successful. Design your webhook handlers to be fast and acknowledge receipt quickly, performing heavier processing asynchronously if needed (e.g., using a message queue).6. Security Considerations
.env
file or yourprivate.key
file to source control. Use a.gitignore
file as shown. In production, use your hosting provider's mechanism for managing environment variables securely.private.key
file like a password. Ensure its file permissions restrict access (e.g.,chmod 400 private.key
on Linux/macOS).jsonwebtoken
in your Node.js app (npm install jsonwebtoken
)./webhooks/inbound
and/webhooks/status
routes to verify theAuthorization: Bearer <token>
header of incoming requests against your configured secret before processing the payload. This guide does not include the JWT verification implementation. Refer to the official Vonage documentation on "Signed Webhooks" for implementation details./send-sms
endpoint currently only checks ifto
andtext
exist. This is insufficient for production. Add more robust validation:to
number against the E.164 standard using a library likelibphonenumber-js
(npm install libphonenumber-js
).text
content could potentially come from user input elsewhere in your system, sanitize it to prevent cross-site scripting (XSS) or other injection attacks, depending on how you use the text later. This guide does not include robust input validation implementation./send-sms
endpoint (either accidental or malicious), implement rate limiting. Use middleware likeexpress-rate-limit
(npm install express-rate-limit
) to restrict the number of requests a user can make in a given time window. Check Vonage's own API rate limits as well. This guide does not include rate limiting implementation.7. Troubleshooting and Caveats
Inbound URL
andStatus URL
.Error initializing Vonage SDK: Private key file not found…
: VerifyVONAGE_PRIVATE_KEY_PATH
in.env
is correct relative to where you runnode server.js
, and the file exists.VONAGE_APPLICATION_ID
is correct. Ensure theprivate.key
file content hasn't been corrupted.Logs
→API Logs
(or similar section) for errors related to webhook delivery failures from Vonage's side.node server.js
) and didn't crash. Check server logs for errors./webhooks/inbound
,/webhooks/status
) return a200 OK
or204 No Content
status quickly. Check server logs for errors within these handlers. Failure to respond quickly or with a 2xx status will cause Vonage to retry.delivered
) Not Received:delivered
status updates back to Vonage. You will usually receivesubmitted
, butdelivered
is not guaranteed.Status URL
is correctly configured and your/webhooks/status
endpoint is working and returning200 OK
.15551234567
– the SDK often handles adding the+
if needed, but being explicit is safer) forto
andfrom
numbers.8. Deployment Considerations
VONAGE_APPLICATION_ID
,VONAGE_PRIVATE_KEY_PATH
,VONAGE_NUMBER
,PORT
, etc.) securely using your hosting provider's tools (e.g., Heroku Config Vars, AWS Secrets Manager, .env files managed securely on the server). Do not include the.env
file in your deployment package/repository. Securely transfer or provide theprivate.key
file to your production server and ensure theVONAGE_PRIVATE_KEY_PATH
environment variable points to its location on the server.pm2
to keep your Node.js application running reliably in production.pm2
handles automatic restarts on crashes, manages logs, enables clustering for better performance, and more.9. Verification Checklist
Before considering this production-ready:
/send-sms
endpoint?/send-sms
request in the server console?/webhooks/status
update (at leastsubmitted
) in the server console?/webhooks/inbound
message in the server console?200 OK
or204 No Content
quickly?.env
,private.key
) excluded from Git?This guide provides a solid foundation for sending, receiving, and tracking SMS messages using Node.js and Vonage. Enhance logging, error handling, and especially security (webhook verification, input validation, rate limiting) based on your specific production requirements. Refer to the official Vonage Messages API documentation for further details and advanced features.