WapiFlux API
Send WhatsApp text, media and template messages, manage contacts, read your plan usage and receive incoming messages on your own server. Simple JSON over HTTPS - works with any language.
Introduction
The API lets your website, app, CRM or shop send WhatsApp messages through your connected WhatsApp Business number (official Meta Cloud API).
https://wapiflux.com/api/YOUR_VENDOR_UIDWhat you can do
- Send text, image, video, document and audio messages.
- Send approved template messages (OTP, order updates, invoices, reminders, offers) - also outside the 24-hour window.
- Create and update contacts and put them in groups.
- Read your plan, expiry date and remaining monthly messages.
- Receive incoming customer messages and delivery statuses on your own server (webhook).
Quick start
From zero to your first message in 5 steps.
- Create an account and choose a plan with API accessAPI and webhooks are included in plans that show "API and Webhook Access". Register
- Connect your WhatsApp Business numberSetup → WhatsApp Setup. The number must show as connected before messages can be sent.
- Generate your API tokenIntegrations → API Integration → Generate New Token. Copy the token and your Vendor UID. Generating a new token disables the old one immediately.
- Approve a template (for first contact)Templates → create and submit. You need an approved template to message a customer who has not written to you in the last 24 hours.
- Send your first messageCopy the request below, put your token in it and run it.
curl -X POST "https://wapiflux.com/api/YOUR_VENDOR_UID/contact/send-template-message" \
-H "Authorization: Bearer YOUR_API_TOKEN" \
-H "Accept: application/json" \
-H "Content-Type: application/json" \
-d '{
"phone_number": "923001234567",
"template_name": "order_shipped",
"template_language": "en",
"header_image": "https://example.com/images/order.jpg",
"field_1": "{first_name}",
"field_2": "#1042",
"button_0": "1042"
}'
<?php
$ch = curl_init('https://wapiflux.com/api/YOUR_VENDOR_UID/contact/send-template-message');
curl_setopt_array($ch, [
CURLOPT_POST => true,
CURLOPT_RETURNTRANSFER => true,
CURLOPT_TIMEOUT => 30,
CURLOPT_HTTPHEADER => [
'Authorization: Bearer YOUR_API_TOKEN',
'Accept: application/json',
'Content-Type: application/json',
],
CURLOPT_POSTFIELDS => json_encode([
'phone_number' => '923001234567',
'template_name' => 'order_shipped',
'template_language' => 'en',
'header_image' => 'https://example.com/images/order.jpg',
'field_1' => '{first_name}',
'field_2' => '#1042',
'button_0' => '1042',
]),
]);
$response = json_decode(curl_exec($ch), true);
curl_close($ch);
if (($response['result'] ?? '') === 'success') {
print_r($response['data']);
} else {
echo 'Error: ' . ($response['message'] ?? 'no response');
}
use Illuminate\Support\Facades\Http;
$response = Http::withToken('YOUR_API_TOKEN')
->acceptJson()
->timeout(30)
->post('https://wapiflux.com/api/YOUR_VENDOR_UID/contact/send-template-message', [
'phone_number' => '923001234567',
'template_name' => 'order_shipped',
'template_language' => 'en',
'header_image' => 'https://example.com/images/order.jpg',
'field_1' => '{first_name}',
'field_2' => '#1042',
'button_0' => '1042',
]);
$data = $response->json();
if (($data['result'] ?? '') === 'success') {
// $data['data']
} else {
logger()->warning($data['message'] ?? 'API error');
}
import requests
response = requests.post(
"https://wapiflux.com/api/YOUR_VENDOR_UID/contact/send-template-message",
headers={"Authorization": "Bearer YOUR_API_TOKEN", "Accept": "application/json"},
json={
"phone_number": "923001234567",
"template_name": "order_shipped",
"template_language": "en",
"header_image": "https://example.com/images/order.jpg",
"field_1": "{first_name}",
"field_2": "#1042",
"button_0": "1042",
},
timeout=30,
)
data = response.json()
if data.get("result") == "success":
print(data["data"])
else:
print("Error:", data.get("message"))
// Node.js 18+ (built-in fetch). Never put your token in browser code.
const response = await fetch("https://wapiflux.com/api/YOUR_VENDOR_UID/contact/send-template-message", {
method: "POST",
headers: {
Authorization: "Bearer YOUR_API_TOKEN",
Accept: "application/json",
"Content-Type": "application/json",
},
body: JSON.stringify({
phone_number: "923001234567",
template_name: "order_shipped",
template_language: "en",
header_image: "https://example.com/images/order.jpg",
field_1: "{first_name}",
field_2: "#1042",
button_0: "1042",
}),
});
const data = await response.json();
if (data.result === "success") {
console.log(data.data);
} else {
console.error("Error:", data.message);
}
// Java 15+
import java.net.URI;
import java.net.http.HttpClient;
import java.net.http.HttpRequest;
import java.net.http.HttpResponse;
public class ApiExample {
public static void main(String[] args) throws Exception {
String body = """
{
"phone_number": "923001234567",
"template_name": "order_shipped",
"template_language": "en",
"header_image": "https://example.com/images/order.jpg",
"field_1": "{first_name}",
"field_2": "#1042",
"button_0": "1042"
}
""";
HttpRequest request = HttpRequest.newBuilder()
.uri(URI.create("https://wapiflux.com/api/YOUR_VENDOR_UID/contact/send-template-message"))
.header("Authorization", "Bearer YOUR_API_TOKEN")
.header("Accept", "application/json")
.header("Content-Type", "application/json")
.POST(HttpRequest.BodyPublishers.ofString(body))
.build();
HttpResponse<String> response = HttpClient.newHttpClient()
.send(request, HttpResponse.BodyHandlers.ofString());
System.out.println(response.body());
}
}
// .NET 7+ (C# 11)
using System.Net.Http.Headers;
using System.Text;
using var client = new HttpClient();
client.DefaultRequestHeaders.Authorization = new AuthenticationHeaderValue("Bearer", "YOUR_API_TOKEN");
client.DefaultRequestHeaders.Accept.Add(new MediaTypeWithQualityHeaderValue("application/json"));
var json = """
{
"phone_number": "923001234567",
"template_name": "order_shipped",
"template_language": "en",
"header_image": "https://example.com/images/order.jpg",
"field_1": "{first_name}",
"field_2": "#1042",
"button_0": "1042"
}
""";
var response = await client.PostAsync(
"https://wapiflux.com/api/YOUR_VENDOR_UID/contact/send-template-message",
new StringContent(json, Encoding.UTF8, "application/json"));
Console.WriteLine(await response.Content.ReadAsStringAsync());
package main
import (
"fmt"
"io"
"net/http"
"strings"
)
func main() {
body := strings.NewReader(`{
"phone_number": "923001234567",
"template_name": "order_shipped",
"template_language": "en",
"header_image": "https://example.com/images/order.jpg",
"field_1": "{first_name}",
"field_2": "#1042",
"button_0": "1042"
}`)
req, _ := http.NewRequest("POST", "https://wapiflux.com/api/YOUR_VENDOR_UID/contact/send-template-message", body)
req.Header.Set("Content-Type", "application/json")
req.Header.Set("Authorization", "Bearer YOUR_API_TOKEN")
req.Header.Set("Accept", "application/json")
res, err := http.DefaultClient.Do(req)
if err != nil {
panic(err)
}
defer res.Body.Close()
out, _ := io.ReadAll(res.Body)
fmt.Println(string(out))
}
Authentication
Every request needs your Vendor UID in the URL and your API token.
Recommended: Authorization header
Authorization: Bearer YOUR_API_TOKEN
Accept: application/json
Content-Type: application/json
Alternative: token in the URL
Only when your tool cannot send headers (some no-code tools):
https://wapiflux.com/api/YOUR_VENDOR_UID/contact/send-message?token=YOUR_API_TOKEN
Phone number format
Always send the full international number: country code + number, digits only, without +, 00 or a leading 0.
| Written as | Send as |
|---|---|
| 0300 1234567 | 923001234567 |
| +92 300 1234567 | 923001234567 |
| +1 (415) 555-0100 | 14155550100 |
| +44 7700 900123 | 447700900123 |
If the number is not in your contacts yet, it is added automatically when you send a message. Use the optional contact object to save the name, email, country and groups at the same time.
Contact variables
In template values (field_1, header_field_1, button_0 ...) you can use these placeholders. They are replaced with the contact's data before sending:
{first_name} {last_name} {full_name} {phone_number} {email} {country} {language_code}
Your own contact custom fields work the same way, e.g. {city}. They are not replaced inside phone_number, template_name or template_language.
Plan limits
Your plan decides how many WhatsApp numbers you can use and how many messages you can send per month. Every outgoing message counts: API, chat, bots, campaigns and automations. Failed messages do not count.
- The monthly counter restarts on the same day of the month your plan started.
- When the limit is reached, send requests are refused with HTTP 429 until you upgrade or renew.
- An expired plan stops all sending - renew from My Plan (renewal is added after the current expiry date).
- Check your remaining messages any time with GET /account.
Responses and errors
Every response is JSON. Check the result field - not only the HTTP status:
{
"result": "success", // or "failed"
"message": "Message processed", // human readable
"data": { } // endpoint data
}
Validation errors return HTTP 422 with an errors object:
{
"message": "The phone number field is required.",
"errors": { "phone_number": ["The phone number field is required."] }
}
Common errors
| HTTP / message | Meaning and fix |
|---|---|
| Invalid Token | Wrong, missing or regenerated token, or wrong Vendor UID. Copy both again from API Integration. |
| 401 API access is not available… | Your plan does not include API access. Upgrade the plan. |
| Please complete your WhatsApp Cloud API Setup first | Connect your WhatsApp number in Setup → WhatsApp Setup. |
| 422 | A field is missing or invalid - see the errors object. |
| 429 Your plan allows … messages | Monthly message limit reached. Upgrade or renew. |
| Template for the selected language not found… | Wrong template_name / template_language, or the template is new - sync templates in the Templates page. |
| Your subscription plan has been expired… | Renew your plan from My Plan. |
| (#131047) Re-engagement message | More than 24 hours since the customer last wrote. Send a template message instead. |
Send a text message
Sends a normal WhatsApp text message. WhatsApp only allows free text inside the 24-hour customer service window (the customer messaged you in the last 24 hours). Outside it, use a template message.
Parameters
| Name | Type | Description | |
|---|---|---|---|
| phone_number | string | required | Receiver number with country code, digits only, no + or 0. Example: 923001234567 |
| message_body | string | required | Text to send. WhatsApp formatting like *bold* and _italic_ works. |
| from_phone_number_id | string | optional | Send from a specific connected number (phone number ID). Default: your current number. |
| contact | object | optional | Only used when the phone number is not in your contacts yet - the contact is created automatically with these details. |
| contact.first_name | string | optional | First name (max 150). |
| contact.last_name | string | optional | Last name (max 150). |
| contact.email | optional | Email address. | |
| contact.country | string | optional | Country name, e.g. pakistan. |
| contact.language_code | string | optional | Language code, e.g. en. |
| contact.groups | string | optional | Comma separated group names. Missing groups are created. |
Request
curl -X POST "https://wapiflux.com/api/YOUR_VENDOR_UID/contact/send-message" \
-H "Authorization: Bearer YOUR_API_TOKEN" \
-H "Accept: application/json" \
-H "Content-Type: application/json" \
-d '{
"phone_number": "923001234567",
"message_body": "Hello Ali, your order #1042 has been shipped!",
"contact": {
"first_name": "Ali",
"last_name": "Khan",
"email": "ali@example.com",
"country": "pakistan",
"language_code": "en",
"groups": "Customers,Lahore"
}
}'
<?php
$ch = curl_init('https://wapiflux.com/api/YOUR_VENDOR_UID/contact/send-message');
curl_setopt_array($ch, [
CURLOPT_POST => true,
CURLOPT_RETURNTRANSFER => true,
CURLOPT_TIMEOUT => 30,
CURLOPT_HTTPHEADER => [
'Authorization: Bearer YOUR_API_TOKEN',
'Accept: application/json',
'Content-Type: application/json',
],
CURLOPT_POSTFIELDS => json_encode([
'phone_number' => '923001234567',
'message_body' => 'Hello Ali, your order #1042 has been shipped!',
'contact' => [
'first_name' => 'Ali',
'last_name' => 'Khan',
'email' => 'ali@example.com',
'country' => 'pakistan',
'language_code' => 'en',
'groups' => 'Customers,Lahore',
],
]),
]);
$response = json_decode(curl_exec($ch), true);
curl_close($ch);
if (($response['result'] ?? '') === 'success') {
print_r($response['data']);
} else {
echo 'Error: ' . ($response['message'] ?? 'no response');
}
use Illuminate\Support\Facades\Http;
$response = Http::withToken('YOUR_API_TOKEN')
->acceptJson()
->timeout(30)
->post('https://wapiflux.com/api/YOUR_VENDOR_UID/contact/send-message', [
'phone_number' => '923001234567',
'message_body' => 'Hello Ali, your order #1042 has been shipped!',
'contact' => [
'first_name' => 'Ali',
'last_name' => 'Khan',
'email' => 'ali@example.com',
'country' => 'pakistan',
'language_code' => 'en',
'groups' => 'Customers,Lahore',
],
]);
$data = $response->json();
if (($data['result'] ?? '') === 'success') {
// $data['data']
} else {
logger()->warning($data['message'] ?? 'API error');
}
import requests
response = requests.post(
"https://wapiflux.com/api/YOUR_VENDOR_UID/contact/send-message",
headers={"Authorization": "Bearer YOUR_API_TOKEN", "Accept": "application/json"},
json={
"phone_number": "923001234567",
"message_body": "Hello Ali, your order #1042 has been shipped!",
"contact": {
"first_name": "Ali",
"last_name": "Khan",
"email": "ali@example.com",
"country": "pakistan",
"language_code": "en",
"groups": "Customers,Lahore",
},
},
timeout=30,
)
data = response.json()
if data.get("result") == "success":
print(data["data"])
else:
print("Error:", data.get("message"))
// Node.js 18+ (built-in fetch). Never put your token in browser code.
const response = await fetch("https://wapiflux.com/api/YOUR_VENDOR_UID/contact/send-message", {
method: "POST",
headers: {
Authorization: "Bearer YOUR_API_TOKEN",
Accept: "application/json",
"Content-Type": "application/json",
},
body: JSON.stringify({
phone_number: "923001234567",
message_body: "Hello Ali, your order #1042 has been shipped!",
contact: {
first_name: "Ali",
last_name: "Khan",
email: "ali@example.com",
country: "pakistan",
language_code: "en",
groups: "Customers,Lahore",
},
}),
});
const data = await response.json();
if (data.result === "success") {
console.log(data.data);
} else {
console.error("Error:", data.message);
}
// Java 15+
import java.net.URI;
import java.net.http.HttpClient;
import java.net.http.HttpRequest;
import java.net.http.HttpResponse;
public class ApiExample {
public static void main(String[] args) throws Exception {
String body = """
{
"phone_number": "923001234567",
"message_body": "Hello Ali, your order #1042 has been shipped!",
"contact": {
"first_name": "Ali",
"last_name": "Khan",
"email": "ali@example.com",
"country": "pakistan",
"language_code": "en",
"groups": "Customers,Lahore"
}
}
""";
HttpRequest request = HttpRequest.newBuilder()
.uri(URI.create("https://wapiflux.com/api/YOUR_VENDOR_UID/contact/send-message"))
.header("Authorization", "Bearer YOUR_API_TOKEN")
.header("Accept", "application/json")
.header("Content-Type", "application/json")
.POST(HttpRequest.BodyPublishers.ofString(body))
.build();
HttpResponse<String> response = HttpClient.newHttpClient()
.send(request, HttpResponse.BodyHandlers.ofString());
System.out.println(response.body());
}
}
// .NET 7+ (C# 11)
using System.Net.Http.Headers;
using System.Text;
using var client = new HttpClient();
client.DefaultRequestHeaders.Authorization = new AuthenticationHeaderValue("Bearer", "YOUR_API_TOKEN");
client.DefaultRequestHeaders.Accept.Add(new MediaTypeWithQualityHeaderValue("application/json"));
var json = """
{
"phone_number": "923001234567",
"message_body": "Hello Ali, your order #1042 has been shipped!",
"contact": {
"first_name": "Ali",
"last_name": "Khan",
"email": "ali@example.com",
"country": "pakistan",
"language_code": "en",
"groups": "Customers,Lahore"
}
}
""";
var response = await client.PostAsync(
"https://wapiflux.com/api/YOUR_VENDOR_UID/contact/send-message",
new StringContent(json, Encoding.UTF8, "application/json"));
Console.WriteLine(await response.Content.ReadAsStringAsync());
package main
import (
"fmt"
"io"
"net/http"
"strings"
)
func main() {
body := strings.NewReader(`{
"phone_number": "923001234567",
"message_body": "Hello Ali, your order #1042 has been shipped!",
"contact": {
"first_name": "Ali",
"last_name": "Khan",
"email": "ali@example.com",
"country": "pakistan",
"language_code": "en",
"groups": "Customers,Lahore"
}
}`)
req, _ := http.NewRequest("POST", "https://wapiflux.com/api/YOUR_VENDOR_UID/contact/send-message", body)
req.Header.Set("Content-Type", "application/json")
req.Header.Set("Authorization", "Bearer YOUR_API_TOKEN")
req.Header.Set("Accept", "application/json")
res, err := http.DefaultClient.Do(req)
if err != nil {
panic(err)
}
defer res.Body.Close()
out, _ := io.ReadAll(res.Body)
fmt.Println(string(out))
}
Response
{
"result": "success",
"message": "Message processed",
"data": {
"log_uid": "9f2c1a7e-3b1d-4c55-9a8e-6f0d2b7c4e11",
"contact_uid": "d4d2da1e-4292-4ac1-925a-39bbd298c6b6",
"phone_number": "923001234567",
"wamid": "wamid.HBgMOTIzMDAxMjM0NTY3FQIAERgSQjE2RkQ5QTk5NEQ3QzM0QkY3AA==",
"status": "accepted"
}
}
{
"result": "failed",
"message": "Please complete your WhatsApp Cloud API Setup first",
"data": []
}
{
"result": "failed",
"message": "Your plan allows 1000 messages per month and 0 are left. Please upgrade or renew your plan to send more messages."
}
{
"result": "failed",
"message": "Invalid Token",
"data": []
}
{
"result": "failed",
"message": "API access is not available in your plan, please upgrade your subscription plan.",
"data": []
}
Send an image, video, document or audio
Sends a file from a public URL. The 24-hour window rule applies here too. Voice notes must be OGG files with the OPUS codec.
Parameters
| Name | Type | Description | |
|---|---|---|---|
| phone_number | string | required | Receiver number with country code, digits only. |
| media_type | string | required | One of: image, video, document, audio. |
| media_url | url | required | Public https link to the file. WhatsApp downloads it from this URL. |
| caption | string | optional | Caption for image, video or document. |
| file_name | string | optional | File name shown for documents, e.g. invoice-1042.pdf |
| is_voice | boolean | optional | true to send an audio file as a voice note (OGG/OPUS only). |
| from_phone_number_id | string | optional | Send from a specific connected number. |
| contact | object | optional | Only used when the phone number is not in your contacts yet - the contact is created automatically with these details. |
| contact.first_name | string | optional | First name (max 150). |
| contact.last_name | string | optional | Last name (max 150). |
| contact.email | optional | Email address. | |
| contact.country | string | optional | Country name, e.g. pakistan. |
| contact.language_code | string | optional | Language code, e.g. en. |
| contact.groups | string | optional | Comma separated group names. Missing groups are created. |
Request
curl -X POST "https://wapiflux.com/api/YOUR_VENDOR_UID/contact/send-media-message" \
-H "Authorization: Bearer YOUR_API_TOKEN" \
-H "Accept: application/json" \
-H "Content-Type: application/json" \
-d '{
"phone_number": "923001234567",
"media_type": "document",
"media_url": "https://example.com/invoices/invoice-1042.pdf",
"caption": "Your invoice #1042",
"file_name": "invoice-1042.pdf"
}'
<?php
$ch = curl_init('https://wapiflux.com/api/YOUR_VENDOR_UID/contact/send-media-message');
curl_setopt_array($ch, [
CURLOPT_POST => true,
CURLOPT_RETURNTRANSFER => true,
CURLOPT_TIMEOUT => 30,
CURLOPT_HTTPHEADER => [
'Authorization: Bearer YOUR_API_TOKEN',
'Accept: application/json',
'Content-Type: application/json',
],
CURLOPT_POSTFIELDS => json_encode([
'phone_number' => '923001234567',
'media_type' => 'document',
'media_url' => 'https://example.com/invoices/invoice-1042.pdf',
'caption' => 'Your invoice #1042',
'file_name' => 'invoice-1042.pdf',
]),
]);
$response = json_decode(curl_exec($ch), true);
curl_close($ch);
if (($response['result'] ?? '') === 'success') {
print_r($response['data']);
} else {
echo 'Error: ' . ($response['message'] ?? 'no response');
}
use Illuminate\Support\Facades\Http;
$response = Http::withToken('YOUR_API_TOKEN')
->acceptJson()
->timeout(30)
->post('https://wapiflux.com/api/YOUR_VENDOR_UID/contact/send-media-message', [
'phone_number' => '923001234567',
'media_type' => 'document',
'media_url' => 'https://example.com/invoices/invoice-1042.pdf',
'caption' => 'Your invoice #1042',
'file_name' => 'invoice-1042.pdf',
]);
$data = $response->json();
if (($data['result'] ?? '') === 'success') {
// $data['data']
} else {
logger()->warning($data['message'] ?? 'API error');
}
import requests
response = requests.post(
"https://wapiflux.com/api/YOUR_VENDOR_UID/contact/send-media-message",
headers={"Authorization": "Bearer YOUR_API_TOKEN", "Accept": "application/json"},
json={
"phone_number": "923001234567",
"media_type": "document",
"media_url": "https://example.com/invoices/invoice-1042.pdf",
"caption": "Your invoice #1042",
"file_name": "invoice-1042.pdf",
},
timeout=30,
)
data = response.json()
if data.get("result") == "success":
print(data["data"])
else:
print("Error:", data.get("message"))
// Node.js 18+ (built-in fetch). Never put your token in browser code.
const response = await fetch("https://wapiflux.com/api/YOUR_VENDOR_UID/contact/send-media-message", {
method: "POST",
headers: {
Authorization: "Bearer YOUR_API_TOKEN",
Accept: "application/json",
"Content-Type": "application/json",
},
body: JSON.stringify({
phone_number: "923001234567",
media_type: "document",
media_url: "https://example.com/invoices/invoice-1042.pdf",
caption: "Your invoice #1042",
file_name: "invoice-1042.pdf",
}),
});
const data = await response.json();
if (data.result === "success") {
console.log(data.data);
} else {
console.error("Error:", data.message);
}
// Java 15+
import java.net.URI;
import java.net.http.HttpClient;
import java.net.http.HttpRequest;
import java.net.http.HttpResponse;
public class ApiExample {
public static void main(String[] args) throws Exception {
String body = """
{
"phone_number": "923001234567",
"media_type": "document",
"media_url": "https://example.com/invoices/invoice-1042.pdf",
"caption": "Your invoice #1042",
"file_name": "invoice-1042.pdf"
}
""";
HttpRequest request = HttpRequest.newBuilder()
.uri(URI.create("https://wapiflux.com/api/YOUR_VENDOR_UID/contact/send-media-message"))
.header("Authorization", "Bearer YOUR_API_TOKEN")
.header("Accept", "application/json")
.header("Content-Type", "application/json")
.POST(HttpRequest.BodyPublishers.ofString(body))
.build();
HttpResponse<String> response = HttpClient.newHttpClient()
.send(request, HttpResponse.BodyHandlers.ofString());
System.out.println(response.body());
}
}
// .NET 7+ (C# 11)
using System.Net.Http.Headers;
using System.Text;
using var client = new HttpClient();
client.DefaultRequestHeaders.Authorization = new AuthenticationHeaderValue("Bearer", "YOUR_API_TOKEN");
client.DefaultRequestHeaders.Accept.Add(new MediaTypeWithQualityHeaderValue("application/json"));
var json = """
{
"phone_number": "923001234567",
"media_type": "document",
"media_url": "https://example.com/invoices/invoice-1042.pdf",
"caption": "Your invoice #1042",
"file_name": "invoice-1042.pdf"
}
""";
var response = await client.PostAsync(
"https://wapiflux.com/api/YOUR_VENDOR_UID/contact/send-media-message",
new StringContent(json, Encoding.UTF8, "application/json"));
Console.WriteLine(await response.Content.ReadAsStringAsync());
package main
import (
"fmt"
"io"
"net/http"
"strings"
)
func main() {
body := strings.NewReader(`{
"phone_number": "923001234567",
"media_type": "document",
"media_url": "https://example.com/invoices/invoice-1042.pdf",
"caption": "Your invoice #1042",
"file_name": "invoice-1042.pdf"
}`)
req, _ := http.NewRequest("POST", "https://wapiflux.com/api/YOUR_VENDOR_UID/contact/send-media-message", body)
req.Header.Set("Content-Type", "application/json")
req.Header.Set("Authorization", "Bearer YOUR_API_TOKEN")
req.Header.Set("Accept", "application/json")
res, err := http.DefaultClient.Do(req)
if err != nil {
panic(err)
}
defer res.Body.Close()
out, _ := io.ReadAll(res.Body)
fmt.Println(string(out))
}
Response
{
"result": "success",
"message": "Message processed",
"data": {
"log_uid": "9f2c1a7e-3b1d-4c55-9a8e-6f0d2b7c4e11",
"contact_uid": "d4d2da1e-4292-4ac1-925a-39bbd298c6b6",
"phone_number": "923001234567",
"wamid": "wamid.HBgMOTIzMDAxMjM0NTY3FQIAERgSQjE2RkQ5QTk5NEQ3QzM0QkY3AA==",
"status": "accepted"
}
}
{
"result": "failed",
"message": "Please complete your WhatsApp Cloud API Setup first",
"data": []
}
{
"result": "failed",
"message": "Your plan allows 1000 messages per month and 0 are left. Please upgrade or renew your plan to send more messages."
}
{
"result": "failed",
"message": "Invalid Token",
"data": []
}
{
"result": "failed",
"message": "API access is not available in your plan, please upgrade your subscription plan.",
"data": []
}
Send a template message
Sends an approved WhatsApp template. This is the only way to start a conversation or message a customer outside the 24-hour window. Only send the fields your template uses: body variables are field_1, field_2 ... in order, header variables are header_field_1, button variables are button_0, button_1 ...
Parameters
| Name | Type | Description | |
|---|---|---|---|
| phone_number | string | required | Receiver number with country code, digits only. |
| template_name | string | required | Exact template name as approved by Meta. |
| template_language | string | required | Template language code, e.g. en or en_US. |
| field_1 ... field_N | string | optional | Values for body variables {{1}}, {{2}} ... Required when the template has them. You can use contact variables like {first_name}. |
| header_field_1 | string | optional | Value for a text header variable. |
| header_image / header_video / header_document | url | optional | Public link for a media header (required when the template has one). |
| header_document_name | string | optional | File name for a document header. |
| location_latitude / location_longitude / location_name / location_address | string | optional | Required for a location header. |
| button_0 ... button_N | string | optional | Values for dynamic URL / quick reply buttons, by button position. |
| copy_code | string | optional | Coupon code for a copy-code button. |
| from_phone_number_id | string | optional | Send from a specific connected number. |
| contact | object | optional | Only used when the phone number is not in your contacts yet - the contact is created automatically with these details. |
| contact.first_name | string | optional | First name (max 150). |
| contact.last_name | string | optional | Last name (max 150). |
| contact.email | optional | Email address. | |
| contact.country | string | optional | Country name, e.g. pakistan. |
| contact.language_code | string | optional | Language code, e.g. en. |
| contact.groups | string | optional | Comma separated group names. Missing groups are created. |
Request
curl -X POST "https://wapiflux.com/api/YOUR_VENDOR_UID/contact/send-template-message" \
-H "Authorization: Bearer YOUR_API_TOKEN" \
-H "Accept: application/json" \
-H "Content-Type: application/json" \
-d '{
"phone_number": "923001234567",
"template_name": "order_shipped",
"template_language": "en",
"header_image": "https://example.com/images/order.jpg",
"field_1": "{first_name}",
"field_2": "#1042",
"button_0": "1042"
}'
<?php
$ch = curl_init('https://wapiflux.com/api/YOUR_VENDOR_UID/contact/send-template-message');
curl_setopt_array($ch, [
CURLOPT_POST => true,
CURLOPT_RETURNTRANSFER => true,
CURLOPT_TIMEOUT => 30,
CURLOPT_HTTPHEADER => [
'Authorization: Bearer YOUR_API_TOKEN',
'Accept: application/json',
'Content-Type: application/json',
],
CURLOPT_POSTFIELDS => json_encode([
'phone_number' => '923001234567',
'template_name' => 'order_shipped',
'template_language' => 'en',
'header_image' => 'https://example.com/images/order.jpg',
'field_1' => '{first_name}',
'field_2' => '#1042',
'button_0' => '1042',
]),
]);
$response = json_decode(curl_exec($ch), true);
curl_close($ch);
if (($response['result'] ?? '') === 'success') {
print_r($response['data']);
} else {
echo 'Error: ' . ($response['message'] ?? 'no response');
}
use Illuminate\Support\Facades\Http;
$response = Http::withToken('YOUR_API_TOKEN')
->acceptJson()
->timeout(30)
->post('https://wapiflux.com/api/YOUR_VENDOR_UID/contact/send-template-message', [
'phone_number' => '923001234567',
'template_name' => 'order_shipped',
'template_language' => 'en',
'header_image' => 'https://example.com/images/order.jpg',
'field_1' => '{first_name}',
'field_2' => '#1042',
'button_0' => '1042',
]);
$data = $response->json();
if (($data['result'] ?? '') === 'success') {
// $data['data']
} else {
logger()->warning($data['message'] ?? 'API error');
}
import requests
response = requests.post(
"https://wapiflux.com/api/YOUR_VENDOR_UID/contact/send-template-message",
headers={"Authorization": "Bearer YOUR_API_TOKEN", "Accept": "application/json"},
json={
"phone_number": "923001234567",
"template_name": "order_shipped",
"template_language": "en",
"header_image": "https://example.com/images/order.jpg",
"field_1": "{first_name}",
"field_2": "#1042",
"button_0": "1042",
},
timeout=30,
)
data = response.json()
if data.get("result") == "success":
print(data["data"])
else:
print("Error:", data.get("message"))
// Node.js 18+ (built-in fetch). Never put your token in browser code.
const response = await fetch("https://wapiflux.com/api/YOUR_VENDOR_UID/contact/send-template-message", {
method: "POST",
headers: {
Authorization: "Bearer YOUR_API_TOKEN",
Accept: "application/json",
"Content-Type": "application/json",
},
body: JSON.stringify({
phone_number: "923001234567",
template_name: "order_shipped",
template_language: "en",
header_image: "https://example.com/images/order.jpg",
field_1: "{first_name}",
field_2: "#1042",
button_0: "1042",
}),
});
const data = await response.json();
if (data.result === "success") {
console.log(data.data);
} else {
console.error("Error:", data.message);
}
// Java 15+
import java.net.URI;
import java.net.http.HttpClient;
import java.net.http.HttpRequest;
import java.net.http.HttpResponse;
public class ApiExample {
public static void main(String[] args) throws Exception {
String body = """
{
"phone_number": "923001234567",
"template_name": "order_shipped",
"template_language": "en",
"header_image": "https://example.com/images/order.jpg",
"field_1": "{first_name}",
"field_2": "#1042",
"button_0": "1042"
}
""";
HttpRequest request = HttpRequest.newBuilder()
.uri(URI.create("https://wapiflux.com/api/YOUR_VENDOR_UID/contact/send-template-message"))
.header("Authorization", "Bearer YOUR_API_TOKEN")
.header("Accept", "application/json")
.header("Content-Type", "application/json")
.POST(HttpRequest.BodyPublishers.ofString(body))
.build();
HttpResponse<String> response = HttpClient.newHttpClient()
.send(request, HttpResponse.BodyHandlers.ofString());
System.out.println(response.body());
}
}
// .NET 7+ (C# 11)
using System.Net.Http.Headers;
using System.Text;
using var client = new HttpClient();
client.DefaultRequestHeaders.Authorization = new AuthenticationHeaderValue("Bearer", "YOUR_API_TOKEN");
client.DefaultRequestHeaders.Accept.Add(new MediaTypeWithQualityHeaderValue("application/json"));
var json = """
{
"phone_number": "923001234567",
"template_name": "order_shipped",
"template_language": "en",
"header_image": "https://example.com/images/order.jpg",
"field_1": "{first_name}",
"field_2": "#1042",
"button_0": "1042"
}
""";
var response = await client.PostAsync(
"https://wapiflux.com/api/YOUR_VENDOR_UID/contact/send-template-message",
new StringContent(json, Encoding.UTF8, "application/json"));
Console.WriteLine(await response.Content.ReadAsStringAsync());
package main
import (
"fmt"
"io"
"net/http"
"strings"
)
func main() {
body := strings.NewReader(`{
"phone_number": "923001234567",
"template_name": "order_shipped",
"template_language": "en",
"header_image": "https://example.com/images/order.jpg",
"field_1": "{first_name}",
"field_2": "#1042",
"button_0": "1042"
}`)
req, _ := http.NewRequest("POST", "https://wapiflux.com/api/YOUR_VENDOR_UID/contact/send-template-message", body)
req.Header.Set("Content-Type", "application/json")
req.Header.Set("Authorization", "Bearer YOUR_API_TOKEN")
req.Header.Set("Accept", "application/json")
res, err := http.DefaultClient.Do(req)
if err != nil {
panic(err)
}
defer res.Body.Close()
out, _ := io.ReadAll(res.Body)
fmt.Println(string(out))
}
Response
{
"result": "success",
"message": "Message processed for WhatsApp contact",
"data": {
"log_uid": "9f2c1a7e-3b1d-4c55-9a8e-6f0d2b7c4e11",
"contact_uid": "d4d2da1e-4292-4ac1-925a-39bbd298c6b6",
"phone_number": "923001234567",
"wamid": "wamid.HBgMOTIzMDAxMjM0NTY3FQIAERgSQjE2RkQ5QTk5NEQ3QzM0QkY3AA==",
"status": "accepted"
}
}
{
"message": "The field 1 field is required.",
"errors": {
"field_1": [
"The field 1 field is required."
]
}
}
{
"result": "failed",
"message": "Please complete your WhatsApp Cloud API Setup first",
"data": []
}
{
"result": "failed",
"message": "Your plan allows 1000 messages per month and 0 are left. Please upgrade or renew your plan to send more messages."
}
{
"result": "failed",
"message": "Invalid Token",
"data": []
}
{
"result": "failed",
"message": "API access is not available in your plan, please upgrade your subscription plan.",
"data": []
}
Create a contact
Adds a new contact to your account. The phone number must be unique in your account. Groups are matched by name and created when missing.
Parameters
| Name | Type | Description | |
|---|---|---|---|
| phone_number | string | required | Number with country code, digits only, min 9 digits, must not start with + or 0. |
| first_name | string | optional | First name. |
| last_name | string | optional | Last name. |
| optional | Email address. | ||
| country | string | optional | Country name, e.g. pakistan. |
| language_code | string | optional | Language code used to pick template languages, e.g. en. |
| groups | string | optional | Comma separated group names, e.g. VIP,Lahore |
Request
curl -X POST "https://wapiflux.com/api/YOUR_VENDOR_UID/contact/create" \
-H "Authorization: Bearer YOUR_API_TOKEN" \
-H "Accept: application/json" \
-H "Content-Type: application/json" \
-d '{
"phone_number": "923001234568",
"first_name": "Sara",
"last_name": "Ahmed",
"email": "sara@example.com",
"country": "pakistan",
"language_code": "en",
"groups": "VIP,Lahore"
}'
<?php
$ch = curl_init('https://wapiflux.com/api/YOUR_VENDOR_UID/contact/create');
curl_setopt_array($ch, [
CURLOPT_POST => true,
CURLOPT_RETURNTRANSFER => true,
CURLOPT_TIMEOUT => 30,
CURLOPT_HTTPHEADER => [
'Authorization: Bearer YOUR_API_TOKEN',
'Accept: application/json',
'Content-Type: application/json',
],
CURLOPT_POSTFIELDS => json_encode([
'phone_number' => '923001234568',
'first_name' => 'Sara',
'last_name' => 'Ahmed',
'email' => 'sara@example.com',
'country' => 'pakistan',
'language_code' => 'en',
'groups' => 'VIP,Lahore',
]),
]);
$response = json_decode(curl_exec($ch), true);
curl_close($ch);
if (($response['result'] ?? '') === 'success') {
print_r($response['data']);
} else {
echo 'Error: ' . ($response['message'] ?? 'no response');
}
use Illuminate\Support\Facades\Http;
$response = Http::withToken('YOUR_API_TOKEN')
->acceptJson()
->timeout(30)
->post('https://wapiflux.com/api/YOUR_VENDOR_UID/contact/create', [
'phone_number' => '923001234568',
'first_name' => 'Sara',
'last_name' => 'Ahmed',
'email' => 'sara@example.com',
'country' => 'pakistan',
'language_code' => 'en',
'groups' => 'VIP,Lahore',
]);
$data = $response->json();
if (($data['result'] ?? '') === 'success') {
// $data['data']
} else {
logger()->warning($data['message'] ?? 'API error');
}
import requests
response = requests.post(
"https://wapiflux.com/api/YOUR_VENDOR_UID/contact/create",
headers={"Authorization": "Bearer YOUR_API_TOKEN", "Accept": "application/json"},
json={
"phone_number": "923001234568",
"first_name": "Sara",
"last_name": "Ahmed",
"email": "sara@example.com",
"country": "pakistan",
"language_code": "en",
"groups": "VIP,Lahore",
},
timeout=30,
)
data = response.json()
if data.get("result") == "success":
print(data["data"])
else:
print("Error:", data.get("message"))
// Node.js 18+ (built-in fetch). Never put your token in browser code.
const response = await fetch("https://wapiflux.com/api/YOUR_VENDOR_UID/contact/create", {
method: "POST",
headers: {
Authorization: "Bearer YOUR_API_TOKEN",
Accept: "application/json",
"Content-Type": "application/json",
},
body: JSON.stringify({
phone_number: "923001234568",
first_name: "Sara",
last_name: "Ahmed",
email: "sara@example.com",
country: "pakistan",
language_code: "en",
groups: "VIP,Lahore",
}),
});
const data = await response.json();
if (data.result === "success") {
console.log(data.data);
} else {
console.error("Error:", data.message);
}
// Java 15+
import java.net.URI;
import java.net.http.HttpClient;
import java.net.http.HttpRequest;
import java.net.http.HttpResponse;
public class ApiExample {
public static void main(String[] args) throws Exception {
String body = """
{
"phone_number": "923001234568",
"first_name": "Sara",
"last_name": "Ahmed",
"email": "sara@example.com",
"country": "pakistan",
"language_code": "en",
"groups": "VIP,Lahore"
}
""";
HttpRequest request = HttpRequest.newBuilder()
.uri(URI.create("https://wapiflux.com/api/YOUR_VENDOR_UID/contact/create"))
.header("Authorization", "Bearer YOUR_API_TOKEN")
.header("Accept", "application/json")
.header("Content-Type", "application/json")
.POST(HttpRequest.BodyPublishers.ofString(body))
.build();
HttpResponse<String> response = HttpClient.newHttpClient()
.send(request, HttpResponse.BodyHandlers.ofString());
System.out.println(response.body());
}
}
// .NET 7+ (C# 11)
using System.Net.Http.Headers;
using System.Text;
using var client = new HttpClient();
client.DefaultRequestHeaders.Authorization = new AuthenticationHeaderValue("Bearer", "YOUR_API_TOKEN");
client.DefaultRequestHeaders.Accept.Add(new MediaTypeWithQualityHeaderValue("application/json"));
var json = """
{
"phone_number": "923001234568",
"first_name": "Sara",
"last_name": "Ahmed",
"email": "sara@example.com",
"country": "pakistan",
"language_code": "en",
"groups": "VIP,Lahore"
}
""";
var response = await client.PostAsync(
"https://wapiflux.com/api/YOUR_VENDOR_UID/contact/create",
new StringContent(json, Encoding.UTF8, "application/json"));
Console.WriteLine(await response.Content.ReadAsStringAsync());
package main
import (
"fmt"
"io"
"net/http"
"strings"
)
func main() {
body := strings.NewReader(`{
"phone_number": "923001234568",
"first_name": "Sara",
"last_name": "Ahmed",
"email": "sara@example.com",
"country": "pakistan",
"language_code": "en",
"groups": "VIP,Lahore"
}`)
req, _ := http.NewRequest("POST", "https://wapiflux.com/api/YOUR_VENDOR_UID/contact/create", body)
req.Header.Set("Content-Type", "application/json")
req.Header.Set("Authorization", "Bearer YOUR_API_TOKEN")
req.Header.Set("Accept", "application/json")
res, err := http.DefaultClient.Do(req)
if err != nil {
panic(err)
}
defer res.Body.Close()
out, _ := io.ReadAll(res.Body)
fmt.Println(string(out))
}
Response
{
"result": "success",
"message": "Contact created",
"data": {
"contact_uid": "ddf2f194-1ae0-44f5-b3e2-8dd7bdcb5432",
"first_name": "Sara",
"last_name": "Ahmed",
"phone_number": "923001234568",
"language_code": "en",
"country": "Pakistan"
}
}
{
"message": "The phone number has already been taken.",
"errors": {
"phone_number": [
"The phone number has already been taken."
]
}
}
{
"message": "The phone number field must have at least 9 digits. (and 1 more error)",
"errors": {
"phone_number": [
"The phone number field must have at least 9 digits.",
"The phone number field must not start with one of the following: +, 0."
]
}
}
{
"result": "failed",
"message": "Invalid Token",
"data": []
}
{
"result": "failed",
"message": "API access is not available in your plan, please upgrade your subscription plan.",
"data": []
}
Update a contact
Updates the contact with this phone number. Send only the fields you want to change. When groups is sent, the contact is placed in exactly those groups.
Parameters
| Name | Type | Description | |
|---|---|---|---|
| {phone_number} | path | required | Contact phone number in the URL. |
| first_name | string | optional | First name. |
| last_name | string | optional | Last name. |
| optional | Email address. | ||
| country | string | optional | Country name. |
| language_code | string | optional | Language code. |
| groups | string | optional | Comma separated group names. |
| whatsapp_opt_out | boolean | optional | true = do not send marketing campaigns to this contact. |
| enable_ai_bot | boolean | optional | true = AI chat bot may reply to this contact. |
Request
curl -X POST "https://wapiflux.com/api/YOUR_VENDOR_UID/contact/update/923001234567" \
-H "Authorization: Bearer YOUR_API_TOKEN" \
-H "Accept: application/json" \
-H "Content-Type: application/json" \
-d '{
"first_name": "Ali",
"last_name": "Raza",
"groups": "VIP,Karachi",
"whatsapp_opt_out": false,
"enable_ai_bot": true
}'
<?php
$ch = curl_init('https://wapiflux.com/api/YOUR_VENDOR_UID/contact/update/923001234567');
curl_setopt_array($ch, [
CURLOPT_POST => true,
CURLOPT_RETURNTRANSFER => true,
CURLOPT_TIMEOUT => 30,
CURLOPT_HTTPHEADER => [
'Authorization: Bearer YOUR_API_TOKEN',
'Accept: application/json',
'Content-Type: application/json',
],
CURLOPT_POSTFIELDS => json_encode([
'first_name' => 'Ali',
'last_name' => 'Raza',
'groups' => 'VIP,Karachi',
'whatsapp_opt_out' => false,
'enable_ai_bot' => true,
]),
]);
$response = json_decode(curl_exec($ch), true);
curl_close($ch);
if (($response['result'] ?? '') === 'success') {
print_r($response['data']);
} else {
echo 'Error: ' . ($response['message'] ?? 'no response');
}
use Illuminate\Support\Facades\Http;
$response = Http::withToken('YOUR_API_TOKEN')
->acceptJson()
->timeout(30)
->post('https://wapiflux.com/api/YOUR_VENDOR_UID/contact/update/923001234567', [
'first_name' => 'Ali',
'last_name' => 'Raza',
'groups' => 'VIP,Karachi',
'whatsapp_opt_out' => false,
'enable_ai_bot' => true,
]);
$data = $response->json();
if (($data['result'] ?? '') === 'success') {
// $data['data']
} else {
logger()->warning($data['message'] ?? 'API error');
}
import requests
response = requests.post(
"https://wapiflux.com/api/YOUR_VENDOR_UID/contact/update/923001234567",
headers={"Authorization": "Bearer YOUR_API_TOKEN", "Accept": "application/json"},
json={
"first_name": "Ali",
"last_name": "Raza",
"groups": "VIP,Karachi",
"whatsapp_opt_out": False,
"enable_ai_bot": True,
},
timeout=30,
)
data = response.json()
if data.get("result") == "success":
print(data["data"])
else:
print("Error:", data.get("message"))
// Node.js 18+ (built-in fetch). Never put your token in browser code.
const response = await fetch("https://wapiflux.com/api/YOUR_VENDOR_UID/contact/update/923001234567", {
method: "POST",
headers: {
Authorization: "Bearer YOUR_API_TOKEN",
Accept: "application/json",
"Content-Type": "application/json",
},
body: JSON.stringify({
first_name: "Ali",
last_name: "Raza",
groups: "VIP,Karachi",
whatsapp_opt_out: false,
enable_ai_bot: true,
}),
});
const data = await response.json();
if (data.result === "success") {
console.log(data.data);
} else {
console.error("Error:", data.message);
}
// Java 15+
import java.net.URI;
import java.net.http.HttpClient;
import java.net.http.HttpRequest;
import java.net.http.HttpResponse;
public class ApiExample {
public static void main(String[] args) throws Exception {
String body = """
{
"first_name": "Ali",
"last_name": "Raza",
"groups": "VIP,Karachi",
"whatsapp_opt_out": false,
"enable_ai_bot": true
}
""";
HttpRequest request = HttpRequest.newBuilder()
.uri(URI.create("https://wapiflux.com/api/YOUR_VENDOR_UID/contact/update/923001234567"))
.header("Authorization", "Bearer YOUR_API_TOKEN")
.header("Accept", "application/json")
.header("Content-Type", "application/json")
.POST(HttpRequest.BodyPublishers.ofString(body))
.build();
HttpResponse<String> response = HttpClient.newHttpClient()
.send(request, HttpResponse.BodyHandlers.ofString());
System.out.println(response.body());
}
}
// .NET 7+ (C# 11)
using System.Net.Http.Headers;
using System.Text;
using var client = new HttpClient();
client.DefaultRequestHeaders.Authorization = new AuthenticationHeaderValue("Bearer", "YOUR_API_TOKEN");
client.DefaultRequestHeaders.Accept.Add(new MediaTypeWithQualityHeaderValue("application/json"));
var json = """
{
"first_name": "Ali",
"last_name": "Raza",
"groups": "VIP,Karachi",
"whatsapp_opt_out": false,
"enable_ai_bot": true
}
""";
var response = await client.PostAsync(
"https://wapiflux.com/api/YOUR_VENDOR_UID/contact/update/923001234567",
new StringContent(json, Encoding.UTF8, "application/json"));
Console.WriteLine(await response.Content.ReadAsStringAsync());
package main
import (
"fmt"
"io"
"net/http"
"strings"
)
func main() {
body := strings.NewReader(`{
"first_name": "Ali",
"last_name": "Raza",
"groups": "VIP,Karachi",
"whatsapp_opt_out": false,
"enable_ai_bot": true
}`)
req, _ := http.NewRequest("POST", "https://wapiflux.com/api/YOUR_VENDOR_UID/contact/update/923001234567", body)
req.Header.Set("Content-Type", "application/json")
req.Header.Set("Authorization", "Bearer YOUR_API_TOKEN")
req.Header.Set("Accept", "application/json")
res, err := http.DefaultClient.Do(req)
if err != nil {
panic(err)
}
defer res.Body.Close()
out, _ := io.ReadAll(res.Body)
fmt.Println(string(out))
}
Response
{
"result": "success",
"message": "Contact details updated.",
"data": {
"contact_uid": "d4d2da1e-4292-4ac1-925a-39bbd298c6b6"
}
}
{
"result": "failed",
"message": "Contact not found.",
"data": {
"contact_uid": null
}
}
{
"result": "failed",
"message": "Invalid Token",
"data": []
}
{
"result": "failed",
"message": "API access is not available in your plan, please upgrade your subscription plan.",
"data": []
}
Plan and usage
Returns your current plan, expiry date and live usage: messages sent this month, remaining messages, connected WhatsApp numbers and contacts. A limit of -1 means unlimited.
Request
curl -X GET "https://wapiflux.com/api/YOUR_VENDOR_UID/account" \
-H "Authorization: Bearer YOUR_API_TOKEN" \
-H "Accept: application/json"
<?php
$ch = curl_init('https://wapiflux.com/api/YOUR_VENDOR_UID/account');
curl_setopt_array($ch, [
CURLOPT_HTTPGET => true,
CURLOPT_RETURNTRANSFER => true,
CURLOPT_TIMEOUT => 30,
CURLOPT_HTTPHEADER => [
'Authorization: Bearer YOUR_API_TOKEN',
'Accept: application/json',
],
]);
$response = json_decode(curl_exec($ch), true);
curl_close($ch);
if (($response['result'] ?? '') === 'success') {
print_r($response['data']);
} else {
echo 'Error: ' . ($response['message'] ?? 'no response');
}
use Illuminate\Support\Facades\Http;
$response = Http::withToken('YOUR_API_TOKEN')
->acceptJson()
->timeout(30)
->get('https://wapiflux.com/api/YOUR_VENDOR_UID/account');
$data = $response->json();
if (($data['result'] ?? '') === 'success') {
// $data['data']
} else {
logger()->warning($data['message'] ?? 'API error');
}
import requests
response = requests.get(
"https://wapiflux.com/api/YOUR_VENDOR_UID/account",
headers={"Authorization": "Bearer YOUR_API_TOKEN", "Accept": "application/json"},
timeout=30,
)
data = response.json()
if data.get("result") == "success":
print(data["data"])
else:
print("Error:", data.get("message"))
// Node.js 18+ (built-in fetch). Never put your token in browser code.
const response = await fetch("https://wapiflux.com/api/YOUR_VENDOR_UID/account", {
method: "GET",
headers: {
Authorization: "Bearer YOUR_API_TOKEN",
Accept: "application/json",
},
});
const data = await response.json();
if (data.result === "success") {
console.log(data.data);
} else {
console.error("Error:", data.message);
}
// Java 15+
import java.net.URI;
import java.net.http.HttpClient;
import java.net.http.HttpRequest;
import java.net.http.HttpResponse;
public class ApiExample {
public static void main(String[] args) throws Exception {
HttpRequest request = HttpRequest.newBuilder()
.uri(URI.create("https://wapiflux.com/api/YOUR_VENDOR_UID/account"))
.header("Authorization", "Bearer YOUR_API_TOKEN")
.header("Accept", "application/json")
.GET()
.build();
HttpResponse<String> response = HttpClient.newHttpClient()
.send(request, HttpResponse.BodyHandlers.ofString());
System.out.println(response.body());
}
}
// .NET 7+ (C# 11)
using System.Net.Http.Headers;
using System.Text;
using var client = new HttpClient();
client.DefaultRequestHeaders.Authorization = new AuthenticationHeaderValue("Bearer", "YOUR_API_TOKEN");
client.DefaultRequestHeaders.Accept.Add(new MediaTypeWithQualityHeaderValue("application/json"));
var response = await client.GetAsync("https://wapiflux.com/api/YOUR_VENDOR_UID/account");
Console.WriteLine(await response.Content.ReadAsStringAsync());
package main
import (
"fmt"
"io"
"net/http"
)
func main() {
req, _ := http.NewRequest("GET", "https://wapiflux.com/api/YOUR_VENDOR_UID/account", nil)
req.Header.Set("Authorization", "Bearer YOUR_API_TOKEN")
req.Header.Set("Accept", "application/json")
res, err := http.DefaultClient.Do(req)
if err != nil {
panic(err)
}
defer res.Body.Close()
out, _ := io.ReadAll(res.Body)
fmt.Println(string(out))
}
Response
{
"result": "success",
"message": "Account details",
"data": {
"plan": {
"id": "plan_4",
"title": "Pro",
"type": "paid",
"frequency": "monthly",
"is_active": true,
"expires_at": "2026-11-13T08:14:08+00:00",
"days_left": 30
},
"usage": {
"messages": {
"limit": 10000,
"used": 1250,
"remaining": 8750,
"cycle_started_at": "2026-10-14T00:00:00+00:00"
},
"whatsapp_numbers": {
"limit": 2,
"connected": 1,
"numbers": [
{
"phone_number_id": "106540352242922",
"display_phone_number": "+92 300 1234567",
"verified_name": "My Shop"
}
]
},
"contacts": {
"limit": 10000,
"used": 842
}
},
"whatsapp_ready": true
}
}
{
"result": "failed",
"message": "Invalid Token",
"data": []
}
{
"result": "failed",
"message": "API access is not available in your plan, please upgrade your subscription plan.",
"data": []
}
Receive messages on your server
Turn on the webhook in Integrations → API Integration and enter your HTTPS URL. For every incoming customer message and every status update (sent, delivered, read, failed) we send a POST request with this JSON body:
{
"contact": {
"status": "existing",
"phone_number": "923001234567",
"uid": "d4d2da1e-4292-4ac1-925a-39bbd298c6b6",
"first_name": "Ali",
"last_name": "Khan",
"email": "ali@example.com",
"language_code": "en",
"country": "Pakistan"
},
"message": {
"whatsapp_business_phone_number_id": "106540352242922",
"whatsapp_message_id": "wamid.HBgMOTIzMDAxMjM0NTY3FQIAEhggQTJDMEY1",
"replied_to_whatsapp_message_id": null,
"is_new_message": true,
"body": "Hi, is my order shipped?",
"status": null,
"media": null
},
"whatsapp_webhook_payload": {
"object": "whatsapp_business_account",
"entry": [
"..."
]
}
}POST /your/webhook HTTP/1.1
Content-Type: application/json
X-Webhook-Event: message.received (message.status for status updates)
X-Webhook-Timestamp: 1792058400
X-Webhook-Signature: sha256=5d41402abc4b2a76b9719d911017c592...- message.is_new_message = true means a new incoming message. message.status (sent / delivered / read / failed) is set for status updates.
- message.media is filled for images, videos, documents and audio (type, link, caption, mime_type, file_name).
- whatsapp_webhook_payload contains the original Meta webhook for advanced use.
- Answer quickly with HTTP 200. Slow endpoints (over 8 seconds) are skipped. Webhooks are not retried, so save the event first and process it after replying.
Verify the signature
Each webhook is signed with your API token: X-Webhook-Signature = "sha256=" + HMAC-SHA256(raw request body, API token). Compare it in constant time before trusting the data. When you generate a new token, the signature key changes too.
<?php
// webhook.php - your endpoint
$secret = 'YOUR_API_TOKEN'; // same token you use for the API
$rawBody = file_get_contents('php://input');
$signature = $_SERVER['HTTP_X_WEBHOOK_SIGNATURE'] ?? '';
$expected = 'sha256=' . hash_hmac('sha256', $rawBody, $secret);
if (!hash_equals($expected, $signature)) {
http_response_code(401);
exit('invalid signature');
}
$event = json_decode($rawBody, true);
if (!empty($event['message']['is_new_message'])) {
$from = $event['contact']['phone_number'];
$text = $event['message']['body'];
// save / reply / create a ticket ...
}
http_response_code(200);
echo 'ok';
// routes/api.php
use Illuminate\Http\Request;
Route::post('/whatsapp/webhook', function (Request $request) {
$expected = 'sha256=' . hash_hmac('sha256', $request->getContent(), config('services.whatsapp_api.token'));
abort_unless(hash_equals($expected, (string) $request->header('X-Webhook-Signature')), 401);
$event = $request->json()->all();
if (data_get($event, 'message.is_new_message')) {
// data_get($event, 'contact.phone_number'), data_get($event, 'message.body')
}
return response('ok');
});
// Express - keep the RAW body for the signature check
import express from "express";
import crypto from "crypto";
const app = express();
const SECRET = process.env.API_TOKEN;
app.post("/whatsapp/webhook", express.raw({ type: "application/json" }), (req, res) => {
const expected = "sha256=" + crypto.createHmac("sha256", SECRET).update(req.body).digest("hex");
const received = req.get("X-Webhook-Signature") || "";
if (expected.length !== received.length ||
!crypto.timingSafeEqual(Buffer.from(expected), Buffer.from(received))) {
return res.status(401).send("invalid signature");
}
const event = JSON.parse(req.body.toString("utf8"));
if (event.message?.is_new_message) {
console.log(event.contact.phone_number, event.message.body);
}
res.send("ok");
});
app.listen(3000);
# Flask
import hmac, hashlib, os
from flask import Flask, request, abort
app = Flask(__name__)
SECRET = os.environ["API_TOKEN"].encode()
@app.post("/whatsapp/webhook")
def webhook():
expected = "sha256=" + hmac.new(SECRET, request.get_data(), hashlib.sha256).hexdigest()
if not hmac.compare_digest(expected, request.headers.get("X-Webhook-Signature", "")):
abort(401)
event = request.get_json()
if event["message"].get("is_new_message"):
print(event["contact"]["phone_number"], event["message"]["body"])
return "ok"
Best practices
- Only message people who agreed to hear from you. Many blocks or reports can restrict your WhatsApp number.
- Use templates for anything outside the 24-hour window, free text inside it.
- Send from your server, with a timeout (30 seconds), and log the returned wamid to match later status webhooks.
- For many recipients use Campaigns in the dashboard - they are queued and respect your limits automatically.
- Watch usage with GET /account and renew before your plan expires.