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.

https://wapiflux.com/api Bearer token JSON

Introduction

The API lets your website, app, CRM or shop send WhatsApp messages through your connected WhatsApp Business number (official Meta Cloud API).

Base URLhttps://wapiflux.com/api/YOUR_VENDOR_UID
FormatJSON request and response bodies (form data also works).
AuthBearer token in the Authorization header.
ModeLive - every request sends a real WhatsApp message.

What 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.

  1. Create an account and choose a plan with API accessAPI and webhooks are included in plans that show "API and Webhook Access". Register
  2. Connect your WhatsApp Business numberSetup → WhatsApp Setup. The number must show as connected before messages can be sent.
  3. 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.
  4. 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.
  5. Send your first messageCopy the request below, put your token in it and run it.
Your first 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))
}

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
Keep the token on your server. Never put it in browser JavaScript, mobile apps or public repositories - anyone with the token can send messages from your number. If it leaks, generate a new token.

Phone number format

Always send the full international number: country code + number, digits only, without +, 00 or a leading 0.

Written asSend as
0300 1234567923001234567
+92 300 1234567923001234567
+1 (415) 555-010014155550100
+44 7700 900123447700900123

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 / messageMeaning and fix
Invalid TokenWrong, 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 firstConnect your WhatsApp number in Setup → WhatsApp Setup.
422A field is missing or invalid - see the errors object.
429 Your plan allows … messagesMonthly 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 messageMore than 24 hours since the customer last wrote. Send a template message instead.
Messages

Send a text message

POST https://wapiflux.com/api/{vendorUid}/contact/send-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

NameTypeDescription
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 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

POST /contact/send-message
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

Responses
HTTP 200
{
    "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"
    }
}
HTTP 200
{
    "result": "failed",
    "message": "Please complete your WhatsApp Cloud API Setup first",
    "data": []
}
HTTP 429
{
    "result": "failed",
    "message": "Your plan allows 1000 messages per month and 0 are left. Please upgrade or renew your plan to send more messages."
}
HTTP 200
{
    "result": "failed",
    "message": "Invalid Token",
    "data": []
}
HTTP 401
{
    "result": "failed",
    "message": "API access is not available in your plan, please upgrade your subscription plan.",
    "data": []
}

Send an image, video, document or audio

POST https://wapiflux.com/api/{vendorUid}/contact/send-media-message

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

NameTypeDescription
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 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

POST /contact/send-media-message
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

Responses
HTTP 200
{
    "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"
    }
}
HTTP 200
{
    "result": "failed",
    "message": "Please complete your WhatsApp Cloud API Setup first",
    "data": []
}
HTTP 429
{
    "result": "failed",
    "message": "Your plan allows 1000 messages per month and 0 are left. Please upgrade or renew your plan to send more messages."
}
HTTP 200
{
    "result": "failed",
    "message": "Invalid Token",
    "data": []
}
HTTP 401
{
    "result": "failed",
    "message": "API access is not available in your plan, please upgrade your subscription plan.",
    "data": []
}

Send a template message

POST https://wapiflux.com/api/{vendorUid}/contact/send-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

NameTypeDescription
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 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

POST /contact/send-template-message
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

Responses
HTTP 200
{
    "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"
    }
}
HTTP 422
{
    "message": "The field 1 field is required.",
    "errors": {
        "field_1": [
            "The field 1 field is required."
        ]
    }
}
HTTP 200
{
    "result": "failed",
    "message": "Please complete your WhatsApp Cloud API Setup first",
    "data": []
}
HTTP 429
{
    "result": "failed",
    "message": "Your plan allows 1000 messages per month and 0 are left. Please upgrade or renew your plan to send more messages."
}
HTTP 200
{
    "result": "failed",
    "message": "Invalid Token",
    "data": []
}
HTTP 401
{
    "result": "failed",
    "message": "API access is not available in your plan, please upgrade your subscription plan.",
    "data": []
}
Contacts

Create a contact

POST https://wapiflux.com/api/{vendorUid}/contact/create

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

NameTypeDescription
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.
email email 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

POST /contact/create
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

Responses
HTTP 200
{
    "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"
    }
}
HTTP 422
{
    "message": "The phone number has already been taken.",
    "errors": {
        "phone_number": [
            "The phone number has already been taken."
        ]
    }
}
HTTP 422
{
    "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."
        ]
    }
}
HTTP 200
{
    "result": "failed",
    "message": "Invalid Token",
    "data": []
}
HTTP 401
{
    "result": "failed",
    "message": "API access is not available in your plan, please upgrade your subscription plan.",
    "data": []
}

Update a contact

POST https://wapiflux.com/api/{vendorUid}/contact/update/{phone_number}

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

NameTypeDescription
{phone_number} path required Contact phone number in the URL.
first_name string optional First name.
last_name string optional Last name.
email email 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

POST /contact/update/{phone_number}
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

Responses
HTTP 200
{
    "result": "success",
    "message": "Contact details updated.",
    "data": {
        "contact_uid": "d4d2da1e-4292-4ac1-925a-39bbd298c6b6"
    }
}
HTTP 200
{
    "result": "failed",
    "message": "Contact not found.",
    "data": {
        "contact_uid": null
    }
}
HTTP 200
{
    "result": "failed",
    "message": "Invalid Token",
    "data": []
}
HTTP 401
{
    "result": "failed",
    "message": "API access is not available in your plan, please upgrade your subscription plan.",
    "data": []
}
Account

Plan and usage

GET https://wapiflux.com/api/{vendorUid}/account

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

GET /account
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

Responses
HTTP 200
{
    "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
    }
}
HTTP 200
{
    "result": "failed",
    "message": "Invalid Token",
    "data": []
}
HTTP 401
{
    "result": "failed",
    "message": "API access is not available in your plan, please upgrade your subscription plan.",
    "data": []
}
Webhooks

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:

POST your webhook URL
{
    "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.

Signature check
<?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.
Need help with your integration? Contact us.