code examples

Sent logo
Sent TeamMay 3, 2025 / code examples / Article

Production Guide: Sending SMS and Handling Status Callbacks with Node.js, Express, and Vonage

A comprehensive guide to building a Node.js/Express application for sending SMS via Vonage Messages API and handling delivery status webhooks.

This guide provides a comprehensive walkthrough for building a production-ready Node.js application using the Express framework to send SMS messages via the Vonage Messages API and reliably handle delivery status updates through webhooks. We will cover project setup, core functionality, Vonage configuration, webhook handling, basic error management, security considerations, and deployment pointers.

By the end of this tutorial, you will have a functional application capable of:

  1. Sending SMS messages programmatically using the Vonage Messages API.
  2. Receiving and processing delivery status updates (e.g., delivered, failed) via webhooks.
  3. Securely managing API credentials and configurations.
  4. Running locally using ngrok for development and testing.

Why this approach?

  • Node.js and Express: A popular, efficient, and widely adopted combination for building web applications and APIs, especially well-suited for I/O-bound tasks like handling API calls and webhooks.
  • Vonage Messages API: A unified API for sending messages across multiple channels (SMS, MMS, WhatsApp, etc.). Using the Messages API provides a consistent interface and allows for future expansion to other channels. It utilizes Application authentication (App ID + Private Key) for enhanced security compared to just API Key/Secret.
  • Webhooks for Status: Relying on status webhooks provides near real-time updates on message delivery, enabling robust tracking and response mechanisms without constant polling.

System Architecture

text
+-----------------+      +----------------------+      +-----------------+
| Your Application|----->| Vonage Messages API  |----->| Carrier Network |-----> User's Phone
| (Node.js/Express)|      | (Send SMS Request)   |      | (SMS Delivery)  |
+-----------------+      +----------------------+      +-----------------+
       ^                                                     |
       | (Webhook: /webhooks/status)                         | (Delivery Status)
       |                                                     |
       +-----------------------------------------------------+
                         (Status Update)

Prerequisites

  • Vonage API Account: Sign up for free at Vonage.com. Note your API Key and API Secret found on the API Dashboard.
  • Vonage Application and Number: You'll need to create a Vonage Application and link a virtual phone number to it (covered in steps below).
  • Node.js: Installed on your development machine (LTS version recommended). Download from nodejs.org.
  • npm (or yarn): Node.js package manager, typically included with Node.js installation.
  • ngrok: A tool to expose your local development server to the internet. Sign up for a free account and install it from ngrok.com. Authenticate your ngrok client (ngrok config add-authtoken YOUR_TOKEN). Note: ngrok is essential for easily testing webhooks during local development, but a permanently hosted public URL is required for production deployments.
  • (Optional) Vonage CLI: Useful for managing Vonage resources. Install via npm: npm install -g @vonage/cli. Configure it with vonage config setup --apiKey YOUR_API_KEY --apiSecret YOUR_API_SECRET.

1. Project Setup

Let's structure our project and install the necessary dependencies.

  1. Create Project Directory: Open your terminal and create a new directory for your project, then navigate into it.

    bash
    mkdir vonage-sms-express-guide
    cd vonage-sms-express-guide
  2. Initialize Node.js Project: Initialize the project using npm, accepting the defaults. This creates a package.json file.

    bash
    npm init -y
  3. Install Dependencies: We need express for the web server, @vonage/server-sdk for interacting with the Vonage API, and dotenv to manage environment variables securely.

    bash
    npm install express @vonage/server-sdk dotenv --save
    • express: Web framework for handling HTTP requests and defining routes (our webhooks).
    • @vonage/server-sdk: The official Vonage Node.js library for interacting with Vonage APIs. We'll use this for the Messages API.
    • dotenv: Loads environment variables from a .env file into process.env, keeping sensitive information out of your codebase.
  4. Create Project Files: Create the main files for our application.

    bash
    touch index.js server.js .env .gitignore
    • index.js: Script to send an SMS message.
    • server.js: Express server to handle incoming webhooks (inbound messages and status updates).
    • .env: File to store environment variables (API keys, secrets, configuration). Never commit this file to version control.
    • .gitignore: Specifies intentionally untracked files that Git should ignore.
  5. Configure .gitignore: Add node_modules and .env to your .gitignore file to prevent committing dependencies and sensitive credentials. Also, include the private key file we will generate later.

    Code
    node_modules/
    .env
    private.key
    *.key
  6. Project Structure: Your project directory should now look like this:

    text
    vonage-sms-express-guide/
    ├── node_modules/
    ├── .env
    ├── .gitignore
    ├── index.js
    ├── package-lock.json
    ├── package.json
    └── server.js

2. Vonage Configuration

To use the Messages API, we need to create a Vonage Application, generate security credentials, and link a phone number.

  1. Create a Vonage Application:

    • Navigate to Your applications in the Vonage API Dashboard.
    • Click + Create a new application.
    • Give your application a meaningful name (e.g., Node Express SMS Guide App).
    • Click Generate public and private key. This will automatically download a private.key file. Save this file securely in the root of your project directory (vonage-sms-express-guide/private.key). Vonage does not store this key, so keep it safe and ensure it's listed in your .gitignore.
    • Enable the Messages capability.
    • You'll see fields for Inbound URL and Status URL. These are the endpoints Vonage will send webhook data to. For now, enter placeholder URLs. We will update these later with our live ngrok URL.
      • Inbound URL: http://example.com/webhooks/inbound
      • Status URL: http://example.com/webhooks/status
    • Click Generate application.
    • You will be shown your Application ID. Copy this ID – we'll need it for our environment variables.
  2. Link a Vonage Number:

    • While still on the Application configuration page, go to the Linked numbers section.
    • Click Link next to one of your available Vonage virtual numbers. If you don't have one, click Buy numbers to acquire one. SMS messages will be sent from this number, and messages to this number will trigger the Inbound webhook.
  3. Configure Environment Variables (.env): Open the .env file and add the following variables, replacing the placeholder values with your actual credentials and configuration:

    dotenv
    # Vonage API Credentials (Found on Dashboard - potentially needed for CLI or other APIs)
    VONAGE_API_KEY=YOUR_API_KEY
    VONAGE_API_SECRET=YOUR_API_SECRET
    
    # Vonage Application Credentials (Generated during Application creation - used by Messages API SDK)
    VONAGE_APPLICATION_ID=YOUR_APPLICATION_ID
    VONAGE_APPLICATION_PRIVATE_KEY_PATH=./private.key
    
    # Vonage Number (Linked to the Application)
    VONAGE_NUMBER=YOUR_VONAGE_NUMBER
    
    # Recipient Phone Number for testing
    RECIPIENT_NUMBER=E.164_FORMAT_PHONE_NUMBER # e.g., 14155550100
    
    # Server Port
    PORT=3000
    • VONAGE_API_KEY, VONAGE_API_SECRET: Found at the top of your Vonage Dashboard. While the Messages API primarily uses Application ID/Private Key for authentication via the SDK in this guide, having these can be useful for other potential API interactions or if using the Vonage CLI.
    • VONAGE_APPLICATION_ID: The ID generated when you created the Vonage Application.
    • VONAGE_APPLICATION_PRIVATE_KEY_PATH: The relative path to the private.key file you downloaded (e.g., ./private.key if it's in the root).
    • VONAGE_NUMBER: The Vonage virtual number you linked to the application, in E.164 format (e.g., 12015550101).
    • RECIPIENT_NUMBER: The phone number you want to send the test SMS to, also in E.164 format.
    • PORT: The port your local Express server will listen on.

    Security: Ensure the .env file is included in your .gitignore and never committed to your repository. The private.key file should also be in .gitignore. For production deployments, use your hosting provider's mechanism for managing environment variables securely.


3. Implementing Core Functionality: Sending SMS

Let's write the code to send an SMS message using the Vonage Messages API and the credentials stored in our .env file.

Open index.js and add the following code:

javascript
// index.js
// Load environment variables from .env file
require('dotenv').config();

// Import the Vonage Server SDK
const { Vonage } = require('@vonage/server-sdk');

// Initialize Vonage client with Application ID and Private Key
const vonage = new Vonage({
  applicationId: process.env.VONAGE_APPLICATION_ID,
  privateKey: process.env.VONAGE_APPLICATION_PRIVATE_KEY_PATH
});

// Define message parameters
const fromNumber = process.env.VONAGE_NUMBER;
const toNumber = process.env.RECIPIENT_NUMBER;
const messageText = `Hello from Vonage and Node.js! [${new Date().toLocaleTimeString()}]`;

// Function to send the SMS
async function sendSms() {
  console.log(`Attempting to send SMS from ${fromNumber} to ${toNumber}`);
  try {
    // Ensure required variables are loaded
    if (!fromNumber || !toNumber || !process.env.VONAGE_APPLICATION_ID || !process.env.VONAGE_APPLICATION_PRIVATE_KEY_PATH) {
        console.error('Error: Missing required environment variables for sending SMS.');
        return;
    }

    const resp = await vonage.messages.send({
      channel: 'sms',
      message_type: 'text',
      to: toNumber,
      from: fromNumber,
      text: messageText
    });
    console.log(`Message sent successfully with UUID: ${resp.message_uuid}`);
  } catch (err) {
    console.error('Error sending SMS:');
    // Log detailed error information if available
    if (err.response && err.response.data) {
      console.error('Status:', err.response.status);
      console.error('Data:', JSON.stringify(err.response.data, null, 2));
    } else {
      console.error(err);
    }
  }
}

// Execute the function
sendSms();

Explanation:

  1. require('dotenv').config();: Loads the variables defined in your .env file into process.env. This must be done early, before accessing process.env.
  2. const { Vonage } = require('@vonage/server-sdk');: Imports the main Vonage class from the SDK.
  3. const vonage = new Vonage(...): Initializes the Vonage client. Crucially, for the Messages API, we authenticate using the applicationId and the path to the privateKey obtained during Application setup.
  4. Environment Variables: We retrieve the sender number (VONAGE_NUMBER) and recipient number (RECIPIENT_NUMBER) from process.env.
  5. sendSms Function: An async function encapsulates the sending logic. Includes a basic check for required environment variables.
  6. vonage.messages.send({...}): This is the core method call.
    • channel: 'sms': Specifies the communication channel.
    • message_type: 'text': Defines the type of message content.
    • to: The recipient's phone number (E.164 format).
    • from: Your Vonage virtual number (E.164 format) linked to the Application ID.
    • text: The content of the SMS message.
  7. Response Handling:
    • On success (try block), the API returns a response object containing the message_uuid, a unique identifier for the message attempt. We log this UUID.
    • On failure (catch block), we log the error. The SDK often provides detailed error information within err.response.data, which can be helpful for debugging.
  8. Execution: sendSms() is called to run the function when the script executes.

4. Implementing Webhook Handlers

Now, let's set up the Express server to listen for incoming webhooks from Vonage. We need endpoints for both delivery status updates (/webhooks/status) and inbound messages (/webhooks/inbound), as configured in our Vonage Application.

Open server.js and add the following code:

javascript
// server.js
// Load environment variables from .env file
require('dotenv').config();

// Import Express
const express = require('express');

// Initialize Express app
const app = express();

// Middleware to parse JSON request bodies
app.use(express.json());
// Middleware to parse URL-encoded request bodies
app.use(express.urlencoded({ extended: true }));

const port = process.env.PORT || 3000; // Use port from .env or default to 3000

// --- Webhook Endpoints ---

// Endpoint for Delivery Status updates
app.post('/webhooks/status', (req, res) => {
  const statusData = req.body;
  console.log('--- Delivery Status Received ---');
  console.log('Timestamp:', statusData.timestamp);
  console.log('Status:', statusData.status);
  console.log('Message UUID:', statusData.message_uuid);
  console.log('To:', statusData.to);
  if (statusData.error) {
    console.error('Error Code:', statusData.error.code);
    console.error('Error Reason:', statusData.error.reason);
  }
  console.log('---------------------------------');

  // Vonage requires a 200 OK response to acknowledge receipt of the webhook
  res.status(200).send('OK');
});

// Endpoint for Inbound SMS messages
app.post('/webhooks/inbound', (req, res) => {
  const inboundData = req.body;
  console.log('--- Inbound Message Received ---');
  // Basic check for expected structure
  if (inboundData && inboundData.from && inboundData.to && inboundData.message && inboundData.message.content) {
      console.log('Timestamp:', inboundData.timestamp);
      console.log('From:', inboundData.from.number);
      console.log('To:', inboundData.to.number);
      console.log('Message UUID:', inboundData.message_uuid);
      console.log('Text:', inboundData.message.content.text);
  } else {
      console.log('Received incomplete inbound data:', inboundData);
  }
  console.log('------------------------------');

  // Respond with 200 OK
  res.status(200).send('OK');
});

// --- Server Startup ---
app.listen(port, () => {
  console.log(`Server listening for webhooks at http://localhost:${port}`);
});

Explanation:

  1. require('dotenv').config();: Loads environment variables.
  2. const express = require('express');: Imports the Express framework.
  3. const app = express();: Creates an Express application instance.
  4. Middleware:
    • express.json(): Parses incoming requests with JSON payloads (Vonage webhooks use JSON).
    • express.urlencoded({ extended: true }): Parses incoming requests with URL-encoded payloads (less common for Vonage webhooks, but good practice to include).
  5. Port: Retrieves the port number from process.env.PORT or defaults to 3000.
  6. /webhooks/status Endpoint:
    • Defines a POST route matching the Status URL configured in the Vonage Application.
    • req.body contains the JSON payload sent by Vonage.
    • We log key information like timestamp, status (submitted, delivered, rejected, undeliverable), message_uuid (correlates with the sent message), to number, and any error details if the status indicates a failure.
    • res.status(200).send('OK');: Crucially, Vonage expects a 200 OK response within a reasonable timeframe (e.g., a few seconds) to acknowledge successful receipt of the webhook. Failure to respond correctly may cause Vonage to retry sending the webhook, leading to duplicate processing.
  7. /webhooks/inbound Endpoint:
    • Defines a POST route matching the Inbound URL. This is triggered when someone sends an SMS to your Vonage number.
    • Logs details from the inbound message payload, such as timestamp, from number, to number (your Vonage number), message_uuid, and the text content. Includes a basic check for expected payload structure.
    • Responds with 200 OK.
  8. app.listen(...): Starts the Express server, making it listen for incoming requests on the specified port.

5. Running and Testing Locally with ngrok

To test the webhooks, Vonage needs to be able to reach your local development server. ngrok creates a secure tunnel from the public internet to your machine. Remember, this setup is for development; production requires deploying to a server with a stable public address.

  1. Start ngrok: Open a new terminal window (keep the first one for running your scripts). Run ngrok, telling it to expose the port your Express server will run on (defined in .env, default 3000).

    bash
    ngrok http 3000

    ngrok will display output similar to this:

    text
    Session Status                online
    Account                       Your Name (Plan: Free)
    Version                       x.x.x
    Region                        United States (us-cal-1)
    Web Interface                 http://127.0.0.1:4040
    Forwarding                    https://<RANDOM_SUBDOMAIN>.ngrok-free.app -> http://localhost:3000
    
    Connections                   ttl     opn     rt1     rt5     p50     p90
                                  0       0       0.00    0.00    0.00    0.00

    Copy the https://<RANDOM_SUBDOMAIN>.ngrok-free.app URL. This is your public URL for this ngrok session.

  2. Update Vonage Webhook URLs:

    • Go back to your Application settings in the Vonage API Dashboard.
    • Edit the application you created earlier.
    • Update the Inbound URL and Status URL fields:
      • Inbound URL: <YOUR_NGROK_URL>/webhooks/inbound (e.g., https://<RANDOM_SUBDOMAIN>.ngrok-free.app/webhooks/inbound)
      • Status URL: <YOUR_NGROK_URL>/webhooks/status (e.g., https://<RANDOM_SUBDOMAIN>.ngrok-free.app/webhooks/status)
    • Save the changes.
  3. Start the Express Server: In your first terminal window (in the project directory), run the server script:

    bash
    node server.js

    You should see: Server listening for webhooks at http://localhost:3000

  4. Send a Test SMS: Open another terminal window (now you have one for ngrok, one for the server, one for sending). Run the sending script:

    bash
    node index.js
    • You should see Attempting to send SMS... and then Message sent successfully with UUID: ... in this terminal.
    • Shortly after, check the phone number you set as RECIPIENT_NUMBER. You should receive the SMS.
  5. Observe Webhooks:

    • Watch the terminal where server.js is running.
    • You should see logs for the Delivery Status:
      • First, likely a submitted status.
      • Then, a delivered status (if successful) or potentially a failed/undeliverable status. Each log will include the message_uuid matching the one from index.js.
    • To test the Inbound Message webhook, send an SMS message from your personal phone to your Vonage number (VONAGE_NUMBER). You should see the --- Inbound Message Received --- logs in the server terminal.
  6. Use the ngrok Web Interface: Open http://127.0.0.1:4040 in your browser (the Web Interface URL provided by ngrok). This interface lets you inspect the actual HTTP requests Vonage sent to your webhook endpoints, which is invaluable for debugging.


6. Error Handling and Logging

The current implementation includes basic console.log and console.error. For production:

  • Use a Structured Logger: Implement a proper logging library (like winston or pino) for structured, leveled logging (INFO, WARN, ERROR, DEBUG). This makes logs easier to parse, filter, and analyze.
  • Centralized Logging: Send logs to a centralized logging service (e.g., Datadog, Splunk, ELK stack) for better monitoring and alerting.
  • Webhook Error Handling: Wrap the logic inside your webhook handlers in try...catch blocks to prevent the server from crashing due to unexpected errors in processing the payload. Always ensure a 200 OK response is sent back to Vonage, even if internal processing fails (log the error for later investigation).
  • Retry Mechanisms (for Sending): If sending an SMS fails due to transient network issues or temporary Vonage API problems, consider implementing a retry strategy with exponential backoff using libraries like async-retry.
  • Webhook Idempotency: Vonage might occasionally send the same webhook more than once (e.g., if it didn't receive a timely 200 OK). Design your webhook handlers to be idempotent – processing the same webhook multiple times should not cause unintended side effects. You can achieve this by checking if you've already processed a specific message_uuid (for status) or inbound message_uuid, perhaps by storing processed IDs temporarily or in a database.

7. Security Considerations

  • Environment Variables: Never hardcode credentials. Use environment variables managed securely by your deployment environment. Ensure .env and private.key are in .gitignore.
  • Webhook Signature Verification (Critical for Production Security): Vonage can sign webhook requests using JWT (JSON Web Tokens) or a shared secret signature. Verifying this signature in your webhook handler ensures that the request genuinely came from Vonage and wasn't tampered with. This guide does not implement signature verification, but it is essential for production. Refer to the Vonage documentation on Signed Webhooks for implementation details using the SDK or manually.
  • Input Validation: Although less critical for webhooks (as the source is trusted after signature verification), always validate any user-provided input if your application incorporates it elsewhere.
  • Rate Limiting: Implement rate limiting on your API endpoints if you expose any publicly, and potentially even on webhooks if you anticipate very high volume, to prevent abuse.
  • HTTPS: Always use https for your webhook URLs (ngrok provides this by default). Ensure your production deployment uses HTTPS.

8. Troubleshooting and Caveats

  • Incorrect Credentials: Double-check VONAGE_APPLICATION_ID, VONAGE_APPLICATION_PRIVATE_KEY_PATH (ensure the file exists at the specified path relative to where you run the script), VONAGE_NUMBER, and RECIPIENT_NUMBER format (E.164). Check the .env file loaded correctly.
  • ngrok URL Not Updated: If you restart ngrok, you get a new URL. Remember to update the Inbound and Status URLs in your Vonage Application settings each time.
  • Firewall Issues: Ensure your local firewall isn't blocking incoming connections to the port ngrok is forwarding (default 3000).
  • Number Not Linked: Verify the VONAGE_NUMBER is correctly linked to the VONAGE_APPLICATION_ID in the dashboard.
  • Webhook Not Responding 200 OK: If your server crashes or takes too long to process, Vonage won't get the 200 OK and may retry the webhook, leading to duplicate logs/processing. Check the ngrok web interface (http://127.0.0.1:4040) for response codes.
  • Delivery Receipt (delivered status) Delays: DLRs depend on downstream carriers acknowledging delivery. There can sometimes be delays, or in some regions/networks, DLRs might not be fully supported, potentially resulting in only a submitted status.
  • Messages API vs. SMS API: This guide uses the Messages API. Configuration and webhook payloads differ significantly from the older Vonage SMS API. Ensure you are consistently using the Messages API approach (Application ID/Private Key, specific webhook URLs in the Application settings).

9. Deployment

Deploying this application involves moving beyond ngrok to a persistent hosting environment.

  1. Choose a Hosting Provider: Options include Heroku, AWS (EC2, Lambda, Elastic Beanstalk), Google Cloud (Cloud Run, App Engine), DigitalOcean, Vercel, Render, etc.
  2. Permanent Public URL: Your hosting provider will give you a stable public URL for your application.
  3. Update Vonage Webhooks: Update the Inbound and Status URLs in your Vonage Application settings to use your permanent production URL (e.g., https://your-app-domain.com/webhooks/status). Ensure it uses HTTPS.
  4. Environment Variables and Private Key: Configure your production environment variables (VONAGE_APPLICATION_ID, VONAGE_NUMBER, etc.) using your hosting provider's secure mechanism (e.g., Heroku Config Vars, AWS Parameter Store, GCP Secret Manager). Do not deploy your .env file. You must securely provide the private.key to your production environment. Strategies include:
    • Securely copying the file during deployment (ensure correct permissions).
    • Storing the content of the key file in a secure environment variable or secrets manager and configuring the SDK to read it from there instead of a file path.
    • Using platform-specific secrets management services.
  5. Process Management: Use a process manager like pm2 to keep your Node.js application running reliably in the background, handle restarts, and manage logs.
    • Install: npm install pm2 -g (or as a project dependency)
    • Start (example): pm2 start server.js --name vonage-webhook-server
    • Configure pm2 to restart on server reboot.
  6. CI/CD: Set up a Continuous Integration/Continuous Deployment pipeline (using GitHub Actions, GitLab CI, Jenkins, etc.) to automate testing and deployment whenever you push changes to your repository.

10. Verification and Testing

  1. Unit Tests: Write unit tests (e.g., using jest or mocha) for individual functions, mocking the Vonage SDK and webhook request/response objects.

  2. Integration Tests:

    • Test sending SMS: Verify the vonage.messages.send function is called with correct parameters and handles success/error responses appropriately (mocking the actual API call).
    • Test webhook handling: Simulate POST requests to your /webhooks/status and /webhooks/inbound endpoints with sample Vonage payloads and verify your handlers process them correctly and return a 200 OK.
  3. End-to-End Testing (Manual):

    • Deploy the application (or run locally with ngrok).
    • Ensure ngrok/production URLs are correctly configured in the Vonage Application.
    • Run the index.js script (or trigger sending via an API endpoint if you build one).
    • Verify: SMS is received on the target phone.
    • Verify: submitted status logged by server.js.
    • Verify: delivered status logged by server.js.
    • Send an SMS to the Vonage number from a personal phone.
    • Verify: Inbound message details logged by server.js.
  4. Test Coverage: Use tools like jest --coverage to measure how much of your code is covered by automated tests.

    bash
    jest --coverage

You now have a robust foundation for sending SMS messages and handling delivery statuses using Node.js, Express, and the Vonage Messages API. Remember to implement enhanced logging, error handling, and especially webhook signature verification for a truly production-ready system. You can extend this further by storing message statuses in a database, building automated replies to inbound messages, or integrating other Vonage APIs.

Frequently Asked Questions

How to send SMS with Node.js and Vonage?

Use the Vonage Messages API with the Node.js Server SDK. Initialize the Vonage client with your Application ID and private key path, then use `vonage.messages.send()` with the recipient's number, your Vonage number, and the message text. Ensure your Vonage number is linked to your application in the Vonage Dashboard.

What is the Vonage Messages API?

The Vonage Messages API is a unified platform for sending messages across various channels, including SMS, MMS, and WhatsApp. It uses Application authentication (App ID and Private Key) for improved security, offering a consistent interface for multi-channel messaging.

Why use webhooks for SMS delivery status?

Webhooks provide near real-time updates on message delivery status (e.g., delivered, failed) without constant polling. This allows for efficient tracking and automated responses, enhancing the reliability of your messaging application.

When should I use ngrok for Vonage webhooks?

Use ngrok during local development to expose your Express server's webhook endpoints to the internet, enabling Vonage to send delivery status updates to your server. For production, deploy to a server with a stable public URL.

Can I send messages to multiple channels with Vonage?

Yes, the Vonage Messages API supports various channels like SMS, MMS, and WhatsApp. This allows you to use a consistent API for sending messages across different platforms, streamlining your communication strategy.

How to set up Vonage application for SMS?

Create a Vonage Application in the Vonage API Dashboard, generate public and private keys, and link a Vonage virtual number to the application. Enable the Messages capability and configure the Inbound and Status URLs for webhooks.

What are the prerequisites for Vonage SMS Node.js guide?

You need a Vonage API account, a Vonage Application with a linked number, Node.js and npm, ngrok for local testing, and optionally the Vonage CLI. Ensure you have saved your API credentials, Application ID, private key, and Vonage number.

How to handle Vonage webhook delivery receipts?

Create an Express server with a POST route at `/webhooks/status`. The request body will contain delivery status data like timestamp, status, and message UUID. Always respond with a 200 OK status to acknowledge receipt.

What is the purpose of private.key file in Vonage setup?

The `private.key` file contains your application's private key, crucial for authenticating with the Vonage Messages API. It should be kept secure, never committed to version control, and added to your `.gitignore` file.

How to configure environment variables for Vonage app?

Create a `.env` file and store your Vonage API Key, API Secret, Application ID, private key path, Vonage number, and recipient number. Load these variables into your application using `require('dotenv').config()`.

Why does Vonage require a 200 OK response for webhooks?

Vonage requires a 200 OK response to confirm successful receipt of the webhook. If your server doesn't respond with 200 OK, Vonage may retry sending the webhook, which could lead to duplicate processing of delivery updates.

How to test Vonage SMS webhooks locally?

Use ngrok to create a public URL for your local server, update the webhook URLs in your Vonage application settings to point to your ngrok URL, and then run your Express server. Send a test SMS and observe the webhook logs.

What is the structure of Vonage inbound SMS webhook?

The inbound SMS webhook contains data such as timestamp, sender number, recipient number, message UUID, and the text content of the message. This information allows your application to respond to incoming SMS messages programmatically.

When should I implement webhook signature verification?

Webhook signature verification is essential for production applications. It confirms the webhook request originated from Vonage and prevents tampering. Refer to Vonage's documentation on Signed Webhooks to implement this security measure.