Developers

Send a WhatsApp message with the API

One request sends a WhatsApp message from your own software. Ready examples in curl, PHP, Python and Node.js.

Updated

On this page

Your software sends a WhatsApp message with one request to POST https://wasms.net/api/public/v1/whatsapp/send. The message leaves from the WhatsApp number connected to your organization.

Before you start you need two things: an API key with the messages:send permission (Developers, API keys) and a connected WhatsApp number (your dashboard shows whether one is connected).

The request

Put your key in the Authorization header and send the number and the text as JSON. Replace YOUR_WASMS_API_KEY with your key.

curl

Copy and paste
curl -X POST https://wasms.net/api/public/v1/whatsapp/send \
  -H "Authorization: Bearer YOUR_WASMS_API_KEY" \
  -H "Content-Type: application/json" \
  -d '{"to": "923001234567", "message": "Hello from my software"}'

PHP

Copy and paste
<?php
$ch = curl_init("https://wasms.net/api/public/v1/whatsapp/send");
curl_setopt_array($ch, [
    CURLOPT_POST => true,
    CURLOPT_RETURNTRANSFER => true,
    CURLOPT_HTTPHEADER => [
        "Authorization: Bearer YOUR_WASMS_API_KEY",
        "Content-Type: application/json",
    ],
    CURLOPT_POSTFIELDS => json_encode([
        "to" => "923001234567",
        "message" => "Hello from my software",
    ]),
]);
$result = json_decode(curl_exec($ch), true);
curl_close($ch);

if (!empty($result["success"])) {
    echo "Sent to " . $result["data"]["to"];
} else {
    echo "Not sent: " . ($result["message"] ?? "unknown error");
}

Python

Copy and paste
import requests

response = requests.post(
    "https://wasms.net/api/public/v1/whatsapp/send",
    headers={"Authorization": "Bearer YOUR_WASMS_API_KEY"},
    json={"to": "923001234567", "message": "Hello from my software"},
    timeout=30,
)
result = response.json()

if result.get("success"):
    print("Sent to", result["data"]["to"])
else:
    print("Not sent:", result.get("message"))

Node.js

Copy and paste
// Node.js 18 or newer (fetch is built in)
const response = await fetch("https://wasms.net/api/public/v1/whatsapp/send", {
  method: "POST",
  headers: {
    Authorization: "Bearer YOUR_WASMS_API_KEY",
    "Content-Type": "application/json",
  },
  body: JSON.stringify({ to: "923001234567", message: "Hello from my software" }),
});
const result = await response.json();

if (result.success) {
  console.log("Sent to", result.data.to);
} else {
  console.log("Not sent:", result.message);
}

Fields

  • to (required) — the recipient's number with its country code, digits only, for example 923001234567. A leading + is accepted.
  • message (required unless you send a file) — the text. With a file it becomes the caption.
  • media_url (optional) — the public https address of a file to send: an image, a video, audio or a document.
  • media_type (optional) — image, video, audio or document. Worked out from the address when left out.
  • filename (optional) — the name shown for a document.
  • whatsapp_id (optional) — which connected number to send from, when you have more than one. Get the ids from GET https://wasms.net/api/public/v1/whatsapp/accounts.

The reply when it worked

Copy and paste
{
  "success": true,
  "data": {
    "sent": true,
    "id": "<id of this message, for asking about it later>",
    "to": "923001234567",
    "type": "text",
    "whatsapp_id": "<id of the sending number>",
    "account_phone": "<the sending number>",
    "message_id": "<WhatsApp's own id for the message>"
  }
}

Was it delivered? Was it read?

Keep the id from the reply. The best way to follow a message is the message.status webhook, which tells you when it is delivered and when it is read. To ask about one message instead, call GET https://wasms.net/api/public/v1/messages/{id} (permission messages:read); it answers status, delivered_at and read_at.

Delivered is dependable. Read is only reported when the recipient has read receipts switched on in WhatsApp, and your own number has them on too, so a message that stays at delivered is not proof that it was not read. Messages to groups are not tracked.

The reply when it did not

Every failure has the same shape. Show message to a person; let your code decide on code.

Copy and paste
{ "success": false, "error": "NO_CONNECTED_ACCOUNT", "code": "NO_CONNECTED_ACCOUNT",
  "message": "No connected WhatsApp account for this organization" }
  • 400 INVALID_BODY — to is missing, or there is neither message nor media_url.
  • 401 UNAUTHORIZED — the key is missing, mistyped or revoked.
  • 403 INSUFFICIENT_SCOPE — the key does not have the messages:send permission.
  • 403 PLAN_LIMIT — your plan's sending limit is used up.
  • 409 WHATSAPP_DISCONNECTED — the number was signed out of WhatsApp. Connect it again.
  • 429 RATE_LIMITED — the key made more requests this minute than it is allowed (60 unless you changed it on the API keys page). Wait the number of seconds in the Retry-After header.
  • 502 GATEWAY_CLOSED — the WaSMS app that sends for this number is not running. Open it and try again.
  • 503 NO_CONNECTED_ACCOUNT — no WhatsApp number is connected to your organization.

Other things you can send

  • POST https://wasms.net/api/public/v1/sms/send — an SMS.
  • POST https://wasms.net/api/public/v1/email/send — an email.
  • POST https://wasms.net/api/public/v1/whatsapp/bulk — up to 1000 WhatsApp messages in one request.

The fields for these are in the full reference.

Reading what customers send you

The best way to learn about a new message is a webhook: WaSMS calls your server the moment it arrives. If you would rather ask, use GET https://wasms.net/api/public/v1/messages with since; it covers every channel. GET https://wasms.net/api/public/v1/conversations lists web chat conversations only, not WhatsApp.

Let an AI assistant write it

On the API keys page, Build it with AI copies a complete instruction you can paste into an AI coding assistant. The same guide is public as plain text at wasms.net/llms.txt.

Did this guide solve it?