🎁 Offer: Sign up and get 500 WhatsApp messages free.Claim now
AiSender

Home / Blog / Developers

WhatsApp API Integration Guide for Developers (India)

Developers8 min readUpdated 2 November 2026By the AiSender team

WhatsApp API integration with AiSender takes a single authenticated HTTP call: you send a Meta-approved template name, a phone number and the variable values, and the message is queued and charged from your prepaid wallet. This guide covers authentication, single and bulk sends, status checks, webhooks, idempotency with client_ref, error handling and best practices, with curl and Node.js examples.

AiSender is built on the official WhatsApp Business Platform (Cloud API). If you're new to the platform, start with what is WhatsApp Business API.

Before you start

You need three things:

  1. A connected WhatsApp number. Connect it from the AiSender panel with Continue with Facebook; it takes about 10 minutes.
  2. At least one approved template. Business-initiated messages must use a template Meta has approved. See WhatsApp template message approval.
  3. An API key. Create one in the panel's API section. It is shown only once, so store it in a secret manager or environment variable, never in front-end code.

All requests go to the base URL https://whatsapp.aisender.io and send the key as a Bearer token:

Authorization: Bearer YOUR_API_KEY
Content-Type: application/json

WhatsApp API integration endpoints at a glance

MethodPathWhat it does
POST/api/v1/messagesSend one template message, or up to 1,000 in one request
GET/api/v1/messages/{id}Get the status of a message
GET/api/v1/templatesList your approved templates and their variables
GET/api/v1/balanceCheck your wallet balance
GET/api/v1/inbox?after_id=123&limit=100Poll incoming replies

See the API docs in your panel for full details of every field.

Step 1: List your approved templates

Check the exact template name, language and number of variables before sending:

curl https://whatsapp.aisender.io/api/v1/templates \
  -H "Authorization: Bearer $AISENDER_KEY"

Variables are positional: the first value in params fills {{1}}, the second fills {{2}}, and so on.

Step 2: Send a single message

Phone numbers use the full international format without a plus sign, for example 919876543210 for an Indian number.

curl -X POST https://whatsapp.aisender.io/api/v1/messages \
  -H "Authorization: Bearer $AISENDER_KEY" \
  -H "Content-Type: application/json" \
  -d '{
    "to": "919876543210",
    "template": { "name": "order_update", "language": "en", "params": ["Ravi", "#4521"] },
    "client_ref": "order-4521-shipped"
  }'

The same call in Node.js (18+ has fetch built in):

const BASE = 'https://whatsapp.aisender.io';

async function sendOrderUpdate(phone, name, orderNo) {
  const res = await fetch(`${BASE}/api/v1/messages`, {
    method: 'POST',
    headers: {
      Authorization: `Bearer ${process.env.AISENDER_KEY}`,
      'Content-Type': 'application/json',
    },
    body: JSON.stringify({
      to: phone,
      template: { name: 'order_update', language: 'en', params: [name, orderNo] },
      client_ref: `order-${orderNo}-shipped`,
    }),
  });
  const data = await res.json();
  if (!res.ok) throw new Error(`AiSender ${res.status}: ${JSON.stringify(data)}`);
  return data; // { queued, ids, charged, balance }
}

A successful response tells you how many messages were queued, their ids, how much was charged and your remaining balance:

{ "queued": 1, "ids": [811], "charged": 0.89, "balance": 1243.11 }

The values above are illustrative; the actual charge depends on the template category and current rates.

Step 3: Send in bulk (up to 1,000 per request)

For campaigns, send a recipients array with per-recipient params and a campaign name, so the send shows up in your panel reports:

const body = {
  campaign: 'Diwali offer',
  template: { name: 'diwali_offer', language: 'en' },
  recipients: [
    { to: '919876543210', params: ['Ravi'] },
    { to: '919812345678', params: ['Priya'] },
  ],
};

For lists larger than 1,000, split them into chunks and send the chunks one after another. Check your balance with GET /api/v1/balance before a large send so you don't stop halfway.

Step 4: Track delivery with webhooks

Polling every message is wasteful. Instead, add an HTTPS webhook URL in the panel. AiSender will POST delivery updates (sent, delivered, read, failed) and incoming customer replies to it. A status event looks like this:

{ "event": "message.status", "data": { "id": 811, "client_ref": "order-4521-shipped", "to": "919876543210", "status": "delivered" }, "sent_at": "..." }

Each webhook request is signed with your webhook secret. Verify the signature before trusting the data. A minimal Express handler:

import express from 'express';
import crypto from 'node:crypto';

const app = express();
app.post('/whatsapp/webhook', express.raw({ type: '*/*' }), (req, res) => {
  const expected = 'sha256=' + crypto
    .createHmac('sha256', process.env.AISENDER_WEBHOOK_SECRET)
    .update(req.body).digest('hex');
  const got = req.get('X-Signature') || '';
  if (got.length !== expected.length ||
      !crypto.timingSafeEqual(Buffer.from(got), Buffer.from(expected))) {
    return res.sendStatus(401);
  }
  res.sendStatus(200); // acknowledge fast, process after
  const evt = JSON.parse(req.body);
  queueForProcessing(evt); // your own job queue
});

Respond quickly with a 200 and do slow work (database writes, CRM updates) in the background. Handle events idempotently, because the same event can arrive more than once.

If you can't expose a public URL, poll replies instead with GET /api/v1/inbox?after_id=123&limit=100, storing the last id you processed and passing it as after_id next time. For one-off checks, GET /api/v1/messages/{id} returns a single message's status.

Idempotency with client_ref

Network timeouts happen. If your request times out, you don't know whether the message was queued, and a blind retry could send it twice. Pass a client_ref on single sends: a unique string from your own system, such as order-4521-shipped. Sending the same client_ref again will not send a second message; the API returns the original result instead. The client_ref also comes back in status webhooks, so you can match updates to your own records without storing AiSender ids.

Good client_ref values are deterministic: build them from your order id plus the event, not from a random value generated at retry time.

Error handling

Check the HTTP status on every call. The common ones:

StatusMeaningWhat to do
202QueuedStore the ids; wait for webhooks
400Bad request (missing field, wrong template or params)Fix the payload; don't retry as-is
401Invalid or revoked API keyCheck the key; alert your team
402Not enough wallet balanceTop up, then retry
403Blocked, or request from an IP not allowed for this keyCheck key IP settings
429Too many requestsBack off and retry with a delay
5xxTemporary server problemRetry with exponential backoff and the same client_ref

The exact list and rate limits are in the API docs in your panel. Failed messages are refunded to your wallet automatically, so a "failed" webhook doesn't mean you lost the money.

WhatsApp API integration best practices

  1. Keep API keys on the server and restrict each key to your server's IP addresses where the panel allows it.
  2. Use one key per system (website, CRM, billing) so you can revoke one without breaking the others.
  3. Validate and normalise phone numbers to country code + number before sending.
  4. Send only to customers who opted in; see WhatsApp opt-in best practices.
  5. Use client_ref for every transactional send and retry only with the same value.
  6. Verify webhook signatures and process events idempotently.
  7. Check /api/v1/templates at startup so a renamed or paused template fails loudly in testing, not silently in production.
  8. Watch balance in responses and alert before it runs low.
  9. Log request ids and responses for support and debugging.

FAQ

Can I send free-form text messages through the API?

Business-initiated messages must use an approved template. Free-form replies are only allowed inside the 24-hour customer service window, which your team can handle from the shared Live Chat inbox. See the API docs in your panel for what the API supports.

How many messages can I send per request?

One message with to, or up to 1,000 recipients with the recipients array. Your overall daily reach also depends on your number's Meta messaging limit tier.

Do I need webhooks?

No, but they're recommended. Without them, you can poll GET /api/v1/messages/{id} for status and GET /api/v1/inbox for replies.

What happens if a message fails?

You'll get a failed status via webhook or the status endpoint, and the charge is refunded to your wallet automatically.

Ready to build? Sign up at AiSender (prepaid wallet, no monthly fee), connect your number, generate an API key and send your first template in minutes.

Try AiSender for your business

WhatsApp Business API, team inbox and AI chatbot. No monthly fee.

Chat with us