How to Integrate SendPulse with Your WhatsApp Bot in 2026
SendPulse has been a solid automation option for a while, but by 2026 its WhatsApp chatbot module has matured enough to be worth integrating into real production projects. The platform gives you access to the WhatsApp Business API (via Meta Cloud API), a visual flow builder, outbound webhooks, and a REST API you can hit from any backend. This tutorial covers the full integration: from initial setup to webhook handling and programmatic message sending.

Prerequisites
Before opening your code editor, make sure you have the following ready:
- Active SendPulse account with a plan that includes WhatsApp chatbots (the free plan has hard limits on contacts and monthly messages).
- Verified WhatsApp Business number linked to a Meta Business Manager account. If you're still using a personal number, stop. That path leads to bans.
- SendPulse API Key: found under
Settings > APIin your dashboard. - Client ID and Client Secret from the same location, required for OAuth2.
- HTTPS-enabled server to receive webhooks. Without valid SSL, Meta rejects your endpoint. Locally you can use ngrok for development, but never ship it to production that way.
- Node.js 20+ or Python 3.11+ for the examples in this tutorial.
Step 1: Authenticate Against the SendPulse API
SendPulse uses OAuth2 with short-lived access tokens. Each token lasts 3600 seconds, so you need a refresh mechanism.
// auth.js — Node.js
const axios = require('axios');
const SP_CLIENT_ID = process.env.SP_CLIENT_ID;
const SP_CLIENT_SECRET = process.env.SP_CLIENT_SECRET;
let accessToken = null;
let tokenExpiry = 0;
async function getAccessToken() {
if (accessToken && Date.now() < tokenExpiry) return accessToken;
const res = await axios.post('https://api.sendpulse.com/oauth/access_token', {
grant_type: 'client_credentials',
client_id: SP_CLIENT_ID,
client_secret: SP_CLIENT_SECRET,
});
accessToken = res.data.access_token;
tokenExpiry = Date.now() + (res.data.expires_in - 60) * 1000; // 60s buffer
return accessToken;
}
module.exports = { getAccessToken };
Production warning: never hardcode credentials. Use environment variables or a secrets manager like AWS Secrets Manager or HashiCorp Vault. If you push them to git, they'll be rotated before you finish reading this paragraph.
Step 2: Configure the Chatbot Flow in SendPulse
In the SendPulse dashboard:
- Go to
Chatbots > Manage Botsand select or create your WhatsApp bot. - In the visual builder, create a welcome flow triggered by the keyword
/startor by any incoming message for first-time contacts. - Add a "Send message" node with your initial greeting.
- Add an "Action" node to save contact variables (name, preferences, whatever you need).
- At the end of the main flow, add a "Webhook" node pointing to your endpoint. This way SendPulse notifies you every time a user reaches that point in the flow.
The Webhook node in SendPulse sends a POST with a JSON payload that includes the contact ID, bot ID, and any variables you captured in the flow.
Step 3: Receive and Process the SendPulse Webhook
// webhook.js — Express
const express = require('express');
const router = express.Router();
router.post('/sendpulse/webhook', express.json(), async (req, res) => {
const { contact_id, bot_id, variables } = req.body;
if (!contact_id || !bot_id) {
return res.status(400).json({ error: 'Incomplete payload' });
}
console.log(`Contact received: ${contact_id} from bot ${bot_id}`);
console.log('Variables:', variables);
// Your business logic goes here:
// - Save to DB
// - Trigger an external action
// - Reply with a programmatic message
res.status(200).json({ status: 'ok' });
});
module.exports = router;
Production warning: SendPulse expects a fast 200 OK. If your logic takes more than 5 seconds, the webhook is marked as failed and SendPulse may retry. Respond immediately and process in the background using a queue (Bull, BullMQ, or whatever you use).
Step 4: Send Messages Programmatically from Your Backend
When you need to initiate a conversation or send a message outside a flow (for example, an order notification), you use SendPulse's messages endpoint.
// sendMessage.js
const axios = require('axios');
const { getAccessToken } = require('./auth');
async function sendWhatsAppMessage(contactId, message) {
const token = await getAccessToken();
const payload = {
contact_id: contactId,
messages: [
{
type: 'text',
message: {
text: message,
},
},
],
};
const res = await axios.post(
'https://api.sendpulse.com/whatsapp/contacts/sendByContact',
payload,
{
headers: {
Authorization: `Bearer ${token}`,
'Content-Type': 'application/json',
},
}
);
return res.data;
}
module.exports = { sendWhatsAppMessage };
For template messages (Meta-approved templates), the type changes to template and you must include the template name and parameters. Templates are mandatory for initiating conversations outside WhatsApp Business's 24-hour window.
Step 5: Handle the 24-Hour Window Correctly
This is where most projects stumble in production. The WhatsApp Business API has a session window of 24 hours counted from the user's last message. Within that window you can send free-form text. Outside of it, only approved templates.
Recommended strategy:
// sessionManager.js
const sessions = new Map(); // In production: use Redis
function updateSession(contactId) {
sessions.set(contactId, Date.now());
}
function isInSession(contactId) {
const lastMessage = sessions.get(contactId);
if (!lastMessage) return false;
return (Date.now() - lastMessage) < 23 * 60 * 60 * 1000; // 23h buffer
}
module.exports = { updateSession, isInSession };
When you receive an incoming message webhook, call updateSession(contactId). Before sending a free-form message, check isInSession(contactId). If there's no active session, use a template.
Final Production Warnings
- Rate limits: SendPulse and Meta both have per-second and per-day message limits depending on your WhatsApp Business account tier. Implement a rate limiter in your sending queue.
- Structured logs: log every received webhook and every sent message with timestamps and contact IDs. When something breaks in production (and it will), logs are the only thing that saves you.
- Webhook error handling: if your endpoint returns anything other than 2xx, SendPulse retries. Make sure your logic is idempotent so you don't process the same event twice.
- Testing environment: SendPulse has a limited sandbox. For more complete testing, create a separate bot connected to a Meta test number.
- Monitoring: set up alerts in Grafana, Datadog, or whatever you use. A bot that goes down at 2am and nobody notices until 9am is a support disaster.
With this you have a functional integration ready to scale. The WhatsApp automation ecosystem in 2026 is mature, the tools are there, and SendPulse is a viable option if you don't want to deal with Meta's Cloud API directly from scratch.