WhatsApp API Node.js Tutorial Developer Guide

How to Send WhatsApp Messages with Node.js (Step-by-Step)

By SendAPI Engineering · Last updated April 4, 2026 · 8 min read

A complete Node.js tutorial for sending WhatsApp messages via API. Covers setup, sending text and media messages, receiving webhooks, and handling errors — with real code examples.

What You Will Build

By the end of this tutorial you will have a Node.js script that can send WhatsApp text messages, send image and document messages, and receive incoming messages via webhook — all through the SendAPI REST API.

Prerequisites:

  • Node.js 18 or later
  • A SendAPI account (sign up free)
  • A WhatsApp account to connect as your sending session

---

Step 1: Create a WhatsApp Session

Before sending any messages, you need a connected WhatsApp session. SendAPI uses WhatsApp Web protocol — you connect your WhatsApp account by scanning a QR code.

  1. Log in to your SendAPI dashboard
  2. Go to WhatsApp → Sessions
  3. Click New Session, give it a name
  4. Scan the QR code with your WhatsApp mobile app
  5. Copy the Session ID — you will need it in your code

> Note: The Starter plan includes 1 WhatsApp session. Growth includes 3, Business includes 10.

---

Step 2: Get Your API Key

  1. In the dashboard, go to API Keys
  2. Click Create Key, give it a name, and copy the key
  3. Store it in a .env file — never hardcode it in source
SENDAPI_KEY=your_api_key_here
WHATSAPP_SESSION_ID=your_session_id_here

---

Step 3: Install the SDK

npm install @sendapi/node dotenv

---

Step 4: Send a Text Message

import 'dotenv/config'
import SendAPI from '@sendapi/node'

const client = new SendAPI(process.env.SENDAPI_KEY)

async function sendTextMessage() {
  const result = await client.whatsapp.send({
    session_id: process.env.WHATSAPP_SESSION_ID,
    to: '14155552671',      // recipient in E.164 format (no + prefix)
    type: 'text',
    text: 'Hello from SendAPI! 👋',
  })

  console.log('Message sent:', result.message_id)
}

sendTextMessage()

Phone numbers must be in E.164 format without the + — for example, US number +1 415 555 2671 becomes 14155552671.

---

Step 5: Send an Image

const result = await client.whatsapp.send({
  session_id: process.env.WHATSAPP_SESSION_ID,
  to: '14155552671',
  type: 'image',
  url: 'https://example.com/receipt.png',
  caption: 'Your order receipt',
})

console.log('Image sent:', result.message_id)

Supported media types: image, document, audio, video. The url must be a publicly accessible HTTPS URL.

---

Step 6: Send a Document

const result = await client.whatsapp.send({
  session_id: process.env.WHATSAPP_SESSION_ID,
  to: '14155552671',
  type: 'document',
  url: 'https://example.com/invoice.pdf',
  filename: 'Invoice-2026-001.pdf',
  caption: 'Your invoice for April',
})

---

Step 7: Send Bulk Messages

For sending to multiple recipients at once, use sendBulk. SendAPI processes the queue asynchronously.

const result = await client.whatsapp.sendBulk({
  session_id: process.env.WHATSAPP_SESSION_ID,
  messages: [
    { to: '14155552671', type: 'text', text: 'Your order has shipped!' },
    { to: '447911123456', type: 'text', text: 'Your order has shipped!' },
    { to: '971501234567', type: 'text', text: 'Your order has shipped!' },
  ],
})

console.log('Bulk job ID:', result.job_id)

---

Step 8: Receive Incoming Messages (Webhooks)

To receive replies and delivery status events, register a webhook URL in your dashboard under Webhooks.

Here is a minimal Express.js webhook handler:

import express from 'express'

const app = express()
app.use(express.json())

app.post('/webhooks/whatsapp', (req, res) => {
  const { event, data } = req.body

  if (event === 'whatsapp.message.received') {
    const { from, type, text } = data
    console.log(`Message from ${from}: ${text?.body}`)

    // Handle the message — trigger a reply, update a record, etc.
  }

  if (event === 'whatsapp.message.delivered') {
    console.log(`Message ${data.message_id} delivered`)
  }

  res.sendStatus(200)
})

app.listen(3000)

For local development, use a tunnel like ngrok to expose your localhost:

ngrok http 3000

Then paste the HTTPS URL into your SendAPI dashboard webhook settings.

---

Step 9: Error Handling

Always wrap API calls in try/catch. SendAPI returns structured errors with a code and message.

import 'dotenv/config'
import SendAPI from '@sendapi/node'

const client = new SendAPI(process.env.SENDAPI_KEY)

async function sendMessage(to, text) {
  try {
    const result = await client.whatsapp.send({
      session_id: process.env.WHATSAPP_SESSION_ID,
      to,
      type: 'text',
      text,
    })
    return result
  } catch (err) {
    if (err.status === 401) {
      console.error('Invalid API key')
    } else if (err.status === 402) {
      console.error('No active subscription or session limit reached')
    } else if (err.status === 429) {
      console.error('Rate limit exceeded — back off and retry')
    } else {
      console.error('Send failed:', err.message)
    }
    throw err
  }
}

---

Without the SDK: Raw fetch

If you prefer not to use the SDK, every endpoint is a standard REST call:

const response = await fetch('https://api.sendapi.co/api/v1/whatsapp/send', {
  method: 'POST',
  headers: {
    'Authorization': `Bearer ${process.env.SENDAPI_KEY}`,
    'Content-Type': 'application/json',
  },
  body: JSON.stringify({
    session_id: process.env.WHATSAPP_SESSION_ID,
    to: '14155552671',
    type: 'text',
    text: 'Hello from raw fetch!',
  }),
})

const data = await response.json()
console.log(data)

---

One API Key, Three Channels

The same API key and SDK that just sent your WhatsApp message can also send an SMS or a transactional email — no extra accounts, no extra setup:

// WhatsApp
await client.whatsapp.send({ session_id, to, type: 'text', text: 'Order shipped!' })

// SMS (uses top-up credits)
await client.sms.send({ to: '+14155552671', message: 'Order shipped!', sender_id: 'MyApp' })

// Email
await client.email.send({
  to: 'user@example.com',
  from: 'hello@yourapp.com',
  subject: 'Your order has shipped',
  html: '<p>Your order is on the way.</p>',
})

Three channels. One integration. Starting at $9.99/month.

---

Next Steps

Get your free API key →