How to Send WhatsApp Messages via API: cURL, Python and Node.js Examples

Send WhatsApp messages via API with cURL, Python and Node.js

Order confirmations, appointment reminders, payment alerts, login codes: if your app sends it by email or SMS today, your customers would probably rather get it on WhatsApp. The catch is the setup. The official route means a Meta developer app, business verification and pre-approved templates before you send a single message.

This guide skips that. You'll send WhatsApp messages via API from your own number, with copy-ready examples in cURL, Python and Node.js. You'll send plain text, attach images and PDFs, and send to a list. Every example uses SyncMate by Assistro, so there's no BSP verification and no template approval.

Two Ways to Send WhatsApp Messages via API

There are two main routes, and the right one depends on what you're sending and who you're sending it to.

The official WhatsApp Cloud API

Meta's Cloud API is the official route. To use it you need a Meta developer app, a business portfolio, a phone number ID and a long-lived system-user access token. Then two rules shape everything you send:

  • The 24-hour window. You can send free-form messages only within 24 hours of the customer's last message to you. Outside that window, you can only send pre-approved message templates.
  • Per-message pricing. Since 1 July 2025, Meta charges for each delivered message. Each number gets 1,000 free service messages a month, and from 1 October 2026 utility messages sent inside the window are billable too. See the official WhatsApp API pricing breakdown for current rates.

The official API is the right choice when you need the verified business badge, very high volumes, or interactive buttons and lists.

SyncMate: an API for your own number

SyncMate connects your existing WhatsApp or WhatsApp Business number when you scan a QR code. Your app then sends through SyncMate's API, and messages go out from your number like any other chat. This is WhatsApp API without BSP verification.

 

Official Cloud API

SyncMate

Setup

Meta developer app, business portfolio, verification

Scan a QR code

Sender

A number registered to the Cloud API

Your existing WhatsApp or WhatsApp Business number

First message to a customer

Approved template only

Any text you like

Message cost

Meta per-message rates

Included in your SyncMate plan

Groups

Groups API: up to 8 people per group

Any group your number can post in

Verified business badge

Yes

No

SyncMate can also connect a Meta Cloud API number, so you can start with your own number and move to the official API later without rewriting your app.

Before You Start

You need four things:

  1. A SyncMate account. You can start free with 450 messages a month. See SyncMate pricing for paid plans.
  2. Your WhatsApp number connected. Follow the guide to connect your WhatsApp number. For API use, choose the cloud-based Assistro Standard connection so sending doesn't depend on a browser staying open.
  3. An API token. Here's how to get your API key or access token. Save it as an environment variable named SYNCMATE_API_TOKEN. Never paste it into code you commit.
  4. Recipient numbers in international format. Country code first, digits only, no +, spaces or leading zero. An Indian number is 919876543210; a UK number is 447700900123.

Prefer clicking through the dashboard first? Follow the guide to connect a custom app to the WhatsApp API, or watch the custom application video tutorial.

The Request Format

SyncMate's API is small. There are two endpoints, and both take the same JSON body.

Endpoint

Use it for

POST https://app.assistro.co/api/v1/whatsapp/messages/text

A text message to a person or a group

POST https://app.assistro.co/api/v1/whatsapp/messages/media

An image, video, audio file or document from a public link

Every request carries three headers: Authorization: Bearer YOUR_API_TOKEN, Integration: custom and Content-Type: application/json. A text message looks like this:

{ "to": "919876543210", "text": "Hi Priya, your order #1042 has shipped." }

Field

What it is

to

A group ID (ends in @g.us), or a person's number with country code, digits only (919876543210).

text

The text to send. Write line breaks as \n.

mentions

Optional. Numbers to tag in a group; also write @ and the number in text.

quoted

Optional. A message to reply to, as {key, text}.

kind (media)

image, video, audio or document

media (media)

{url, mime_type, file_name}: a public link to the file

caption (media)

Optional text shown under the file

Send a WhatsApp Message with cURL

cURL is the fastest way to check that your token and number work. Run this in your terminal:

curl -X POST "https://app.assistro.co/api/v1/whatsapp/messages/text" \ -H "Authorization: Bearer $SYNCMATE_API_TOKEN" \ -H "Integration: custom" \ -H "Content-Type: application/json" \ -d '{"to":"919876543210","text":"Hello from cURL"}'

If the message arrives on the phone, your setup is done. A successful call returns the sent message's key, which you can store to reply to, edit or delete that message later:

{ "success": true, "status": 1, "data": { "success": true, "data": { "key": { "remoteJid": "[email protected]", "fromMe": true, "id": "3EB0C4F1A2B3C4D5E6F7" }, "messageTimestamp": 1761800000 } } }

Everything below is the same request written in other languages. The WhatsApp API for developers page has every endpoint with samples in eight languages, and lets you try them with your own token.

Send a PDF or image with cURL

Files are sent by link: host the file somewhere public (your server, S3 or a CDN) and pass its URL:

curl -X POST "https://app.assistro.co/api/v1/whatsapp/messages/media" \ -H "Authorization: Bearer $SYNCMATE_API_TOKEN" \ -H "Integration: custom" \ -H "Content-Type: application/json" \ -d '{"to":"919876543210","kind":"document","media":{"url":"https://example.com/invoices/1042.pdf","mime_type":"application/pdf","file_name":"invoice.pdf"},"caption":"Your invoice is attached."}'

Keep the extension in file_name so WhatsApp shows the right preview. Media sends can take up to a minute. File size limits depend on your plan; current plans allow 2 MB to 8 MB per file.

Send a WhatsApp Message with Python

Install requests with pip install requests, then use this module. It handles text, files and sending to a list:

import os import requests BASE_URL = "https://app.assistro.co/api/v1/whatsapp/messages" HEADERS = { "Authorization": f"Bearer {os.environ['SYNCMATE_API_TOKEN']}", "Integration": "custom", } def post(endpoint, payload, timeout=30): response = requests.post(f"{BASE_URL}/{endpoint}", json=payload, headers=HEADERS, timeout=timeout) response.raise_for_status() return response.json() def send_message(to, text): return post("text", {"to": to, "text": text}) def send_file(to, url, file_name, mime_type, kind="document", caption=""): media = {"url": url, "file_name": file_name, "mime_type": mime_type} return post("media", {"to": to, "kind": kind, "media": media, "caption": caption}, timeout=90) if __name__ == "__main__": send_message("919876543210", "Hi Priya, your order #1042 has shipped.") send_file("919876543210", "https://example.com/invoices/1042.pdf", "invoice.pdf", "application/pdf", caption="Your invoice is attached.")

json= sets the Content-Type header for you, and raise_for_status() turns a failed request (a bad token, say) into an exception you can catch and log.

Send to a list with Python

For reminders or notices to a list, loop through it and pause between sends. The API accepts up to 60 requests a minute, and steady pacing also keeps your number safe:

import time def send_to_list(messages, pause_seconds=3): results = [] for number, text in messages: results.append(send_message(number, text)) time.sleep(pause_seconds) # stay well under 60 requests a minute return results send_to_list([ ("919876543210", "Hi Priya, your appointment is tomorrow at 10 AM."), ("447700900123", "Hi Tom, your appointment is tomorrow at 2 PM."), ])

Build the list from your database or a CSV, and keep each batch small. The best practices section explains why.

Send a WhatsApp Message with Node.js

Node.js 18 and later have fetch built in, so there's nothing to install. Save this as whatsapp.mjs:

const BASE_URL = "https://app.assistro.co/api/v1/whatsapp/messages"; const HEADERS = { Authorization: `Bearer ${process.env.SYNCMATE_API_TOKEN}`, Integration: "custom", "Content-Type": "application/json", }; async function post(endpoint, payload) { const res = await fetch(`${BASE_URL}/${endpoint}`, { method: "POST", headers: HEADERS, body: JSON.stringify(payload), }); if (!res.ok) { throw new Error(`SyncMate API error ${res.status}: ${await res.text()}`); } return res.json(); } export const sendMessage = (to, text) => post("text", { to, text }); export const sendFile = (to, url, fileName, mimeType, kind = "document", caption = "") => post("media", { to, kind, media: { url, file_name: fileName, mime_type: mimeType }, caption }); export async function sendToList(messages, pauseMs = 3000) { for (const [number, text] of messages) { await sendMessage(number, text); await new Promise((resolve) => setTimeout(resolve, pauseMs)); // stay under 60 requests a minute } } await sendMessage("919876543210", "Hi Priya, your order #1042 has shipped.");

Run it with node whatsapp.mjs. sendFile() takes a public file link, and sendToList() takes a list of [number, text] pairs, exactly like the Python version.

Sending to WhatsApp Groups

The same endpoint posts to groups. Only the to field changes:

Send to

to

A person

919876543210

You can get a group's ID with the free WhatsApp Group ID finder. For full group examples, see how to send messages to a WhatsApp group via API. WhatsApp Channels aren't supported by the API yet.

Where to Trigger Messages in a Real App

The code above becomes useful when an event in your system calls it. Common places:

To receive WhatsApp events back in your app, set up webhooks for WhatsApp events.

Troubleshooting Common Errors

Problem

Likely cause

Fix

401 or 403 error

Token is missing, wrong or was regenerated

Check the Authorization: Bearer header, or regenerate your token

Request succeeds, message never arrives

Number format is wrong, or the number isn't on WhatsApp

Use country code + digits only; see message not received or not sent

Messages queue up or arrive late

Your WhatsApp connection dropped

Check if WhatsApp is connected, then see messages stuck in queue

Sends fail after working all day

Plan's message limit reached

See messages failed due to daily limit or add more message credits

Attachment missing or broken

File too large, or file_name has no extension

Check your plan's size limit; use names like invoice.pdf

Messages end with Assistro branding

Free plan

Upgrade, then remove branding from messages

For anything else, start with resolving message sending failures.

Best Practices for Sending at Scale

Because SyncMate sends from your real number, WhatsApp judges your API messages the way it judges anything else you send. These habits keep your number in good standing:

  • Message people who expect it. Customers who ordered, booked or opted in. Never buy or scrape lists.
  • Personalise every message. Use the customer's name and order details. Identical text sent to hundreds of people looks like spam.
  • Pace your sends. Split large lists into small batches with pauses between them, and grow volume gradually.
  • Retry with backoff. If a request fails, wait a few seconds before retrying, and double the wait each time. Don't retry in a tight loop.
  • Log every send. Store the number, the message and the API response, so you can trace any complaint.
  • Keep your token secret. Use environment variables or a secrets manager, and regenerate the token if it ever leaks.

Read the full guide on how to keep your WhatsApp account safe and avoid bans.

Start Sending WhatsApp Messages via API

You now have working cURL, Python and Node.js code to send text, files and messages to a list from your own WhatsApp number. Run the cURL test, paste a function into your app, and connect it to the event that matters most to your customers.

Get your free API token

Connect the WhatsApp number you already use, link your store or CRM, and send your first automated message today.
Browse the developer guide

Start your 7-day free trial

Frequently Asked Questions

Can I send WhatsApp messages via API without the WhatsApp Business API?

Yes. SyncMate connects your existing WhatsApp or WhatsApp Business number and gives you an API to send from it. You don't need Meta verification, a BSP or approved templates.

Do I need message templates to send a WhatsApp message via API?

On the official Cloud API, yes, whenever the customer hasn't messaged you in the last 24 hours. With SyncMate you send any text, because messages go out from your own number like a normal chat.

Can I send images and PDFs through the API?

Yes. Host the file at a public link and send it to the media endpoint with kind set to image, video, audio or document. The maximum file size depends on your plan.

Which programming languages can I use?

Any language that can send an HTTPS POST request with JSON. This guide covers cURL, Python and Node.js; PHP, Java, Go and C# work the same way.

How many WhatsApp messages can I send through the API?

Your SyncMate plan sets the monthly limit: 450 messages on the Free and Personal plans, up to 10,000 on Business. See SyncMate pricing for current plans.

Is it free to send WhatsApp messages via API?

You can start free with 450 messages a month, with Assistro branding added to each message. Paid plans remove the branding and raise the limit.

Leave a Reply

Your email address will not be published. Required fields are marked *