WhatsApp Messaging API
Send and receive WhatsApp Business messages from your own backend. One HTTP endpoint, one API key, and none of Meta’s apparatus to stand up.
Base URL
Section titled “Base URL”https://vaarto.com/api/v1Every example on these pages uses it. It is also printed at the top of Dashboard → Using the API, alongside your own numbers and templates.
Transport
Section titled “Transport”HTTPS, JSON in and JSON out. Send Content-Type: application/json on every request that
has a body.
The response envelope
Section titled “The response envelope”Every response is wrapped. Success carries data; failure carries error.
{ "data": … } // success{ "error": { "code": "…", "message": "…" } } // failureLists add a meta block:
{ "data": [ … ], "meta": { "page": 1, "perPage": 20, "total": 134 } }The one exception is downloading an attachment, which answers with the file itself — see Media.
Quick start
Section titled “Quick start”1. Create an API key
Section titled “1. Create an API key”Dashboard → API Keys → Create key. Pick the scopes you need.
2. Find out what you can send
Section titled “2. Find out what you can send”Templates must be approved by Meta, and you can only send from a number registered to your workspace. Nothing needs hard-coding: ask.
# Approved templates, and the variables each one needs.curl "https://vaarto.com/api/v1/templates?status=APPROVED" \ -H "Authorization: Bearer $KEY"
# Numbers you may send from. isDefault is used when you omit "from".curl "https://vaarto.com/api/v1/numbers" \ -H "Authorization: Bearer $KEY"// Approved templates, and the variables each one needs.const templatesRes = await fetch("https://vaarto.com/api/v1/templates?status=APPROVED", { headers: { Authorization: `Bearer ${process.env.VAARTO_API_KEY}` },});
const { data: templates } = await templatesRes.json();
// Numbers you may send from. isDefault is used when you omit "from".const numbersRes = await fetch("https://vaarto.com/api/v1/numbers", { headers: { Authorization: `Bearer ${process.env.VAARTO_API_KEY}` },});
const { data: numbers } = await numbersRes.json();import os, requests
# Approved templates, and the variables each one needs.templates_res = requests.get( "https://vaarto.com/api/v1/templates?status=APPROVED", headers={"Authorization": f"Bearer {os.environ['VAARTO_API_KEY']}"}, timeout=10,)
templates = templates_res.json()["data"]
# Numbers you may send from. isDefault is used when you omit "from".numbers_res = requests.get( "https://vaarto.com/api/v1/numbers", headers={"Authorization": f"Bearer {os.environ['VAARTO_API_KEY']}"}, timeout=10,)
numbers = numbers_res.json()["data"]// Approved templates, and the variables each one needs.$templates = Http::withToken(env('VAARTO_API_KEY')) ->get('https://vaarto.com/api/v1/templates', [ 'status' => 'APPROVED', ]) ->json('data');
// Numbers you may send from. isDefault is used when you omit "from".$numbers = Http::withToken(env('VAARTO_API_KEY')) ->get('https://vaarto.com/api/v1/numbers') ->json('data');3. Send
Section titled “3. Send”curl -X POST "https://vaarto.com/api/v1/messages/whatsapp" \ -H "Authorization: Bearer $KEY" \ -H "Content-Type: application/json" \ -d '{ "to": "+919876543210", "template": { "name": "order_shipped", "language": "en_US", "variables": { "name": "Ravi", "order_id": "BLR-4471" } }, "idempotencyKey": "order-4471-shipped" }'const res = await fetch("https://vaarto.com/api/v1/messages/whatsapp", { method: "POST", headers: { Authorization: `Bearer ${process.env.VAARTO_API_KEY}`, "Content-Type": "application/json", }, body: JSON.stringify({ to: "+919876543210", template: { name: "order_shipped", language: "en_US", variables: { name: "Ravi", order_id: "BLR-4471", }, }, idempotencyKey: "order-4471-shipped", }),});
const { data } = await res.json();import os, requests
res = requests.post( "https://vaarto.com/api/v1/messages/whatsapp", headers={"Authorization": f"Bearer {os.environ['VAARTO_API_KEY']}"}, json={ "to": "+919876543210", "template": { "name": "order_shipped", "language": "en_US", "variables": { "name": "Ravi", "order_id": "BLR-4471", }, }, "idempotencyKey": "order-4471-shipped", }, timeout=10,)
data = res.json()["data"]$data = Http::withToken(env('VAARTO_API_KEY')) ->post('https://vaarto.com/api/v1/messages/whatsapp', [ 'to' => '+919876543210', 'template' => [ 'name' => 'order_shipped', 'language' => 'en_US', 'variables' => [ 'name' => 'Ravi', 'order_id' => 'BLR-4471', ], ], 'idempotencyKey' => 'order-4471-shipped', ]) ->json('data');201 Created comes back with the message id and status: "SENT" — which means Meta
accepted it, not that it has arrived. Delivery follows as a webhook.
That is the whole integration for a backend that sends order updates. Everything after this page is detail you reach for when you need it.