Docs / Whatixo API
Full examples
A small reusable client in your language, then concrete use cases to adapt.
A client in a few lines
// whatixo.js — Node.js 18+
const BASE = 'https://api.whatixo.com/api';
export async function whatixo(path, body = {}) {
const res = await fetch(BASE + path, {
method: 'POST',
headers: {
'x-api-key': process.env.WHATIXO_API_KEY,
'Content-Type': 'application/json',
},
body: JSON.stringify(body),
});
const data = await res.json().catch(() => ({}));
if (!res.ok) {
const err = new Error(data.error || `HTTP ${res.status}`);
err.status = res.status; err.code = data.code;
throw err;
}
return data;
}
export const DEVICE_ID = process.env.WHATIXO_DEVICE_ID;<?php
// whatixo.php — PHP 7.4+
const WHATIXO_BASE = 'https://api.whatixo.com/api';
function whatixo(string $path, array $body = []): array {
$ch = curl_init(WHATIXO_BASE . $path);
curl_setopt_array($ch, [
CURLOPT_POST => true,
CURLOPT_RETURNTRANSFER => true,
CURLOPT_TIMEOUT => 30,
CURLOPT_HTTPHEADER => [
'x-api-key: ' . getenv('WHATIXO_API_KEY'),
'Content-Type: application/json',
],
CURLOPT_POSTFIELDS => json_encode($body),
]);
$raw = curl_exec($ch);
$status = curl_getinfo($ch, CURLINFO_HTTP_CODE);
curl_close($ch);
$data = json_decode($raw ?: '{}', true) ?: [];
if ($status >= 400) {
throw new RuntimeException($data['error'] ?? "HTTP $status", $status);
}
return $data;
}# whatixo.py — Python 3.8+ (pip install requests)
import os
import requests
BASE = "https://api.whatixo.com/api"
SESSION = requests.Session()
SESSION.headers.update({"x-api-key": os.environ["WHATIXO_API_KEY"]})
class WhatixoError(Exception):
def __init__(self, status, message, code=None):
super().__init__(message)
self.status, self.code = status, code
def whatixo(path, body=None):
res = SESSION.post(BASE + path, json=body or {}, timeout=30)
data = res.json() if res.content else {}
if not res.ok:
raise WhatixoError(res.status_code, data.get("error", res.reason), data.get("code"))
return data
DEVICE_ID = os.environ.get("WHATIXO_DEVICE_ID").envBASH
WHATIXO_API_KEY=wtx_your_secret_key
WHATIXO_DEVICE_ID=8f2c1a7e-4b9d-4e21-9a6f-3c5d7e1b2a90
Order confirmation with invoice
import { whatixo, DEVICE_ID } from './whatixo.js';
export async function notifyOrder(order) {
// 1. Save / update the customer in the CRM (the tag can start a sequence)
await whatixo('/whatsapp/contacts/upsert', {
phone: order.customer.phone,
name: order.customer.name,
tags: ['customers'],
attributes: { last_order: String(order.id) },
});
// 2. Confirmation message
await whatixo('/whatsapp/messages/send', {
deviceId: DEVICE_ID,
to: order.customer.phone,
text: `Hi ${order.customer.name} 👋\nYour order *#${order.id}* of $${order.total} is confirmed.`,
});
// 3. The PDF invoice
await whatixo('/whatsapp/messages/send', {
deviceId: DEVICE_ID,
to: order.customer.phone,
type: 'document',
mediaUrl: order.invoiceUrl, // https://…/invoice-1042.pdf
fileName: `Invoice-${order.id}.pdf`,
});
}require 'whatixo.php';
function notifyOrder(array $order): void {
$device = getenv('WHATIXO_DEVICE_ID');
whatixo('/whatsapp/contacts/upsert', [
'phone' => $order['phone'], 'name' => $order['name'], 'tags' => ['customers'],
]);
whatixo('/whatsapp/messages/send', [
'deviceId' => $device,
'to' => $order['phone'],
'text' => "Hi {$order['name']} 👋\nYour order *#{$order['id']}* is confirmed.",
]);
whatixo('/whatsapp/messages/send', [
'deviceId' => $device,
'to' => $order['phone'],
'type' => 'document',
'mediaUrl' => $order['invoice_url'],
'fileName' => "Invoice-{$order['id']}.pdf",
]);
}from whatixo import whatixo, DEVICE_ID
def notify_order(order):
whatixo("/whatsapp/contacts/upsert", {
"phone": order["phone"], "name": order["name"], "tags": ["customers"],
})
whatixo("/whatsapp/messages/send", {
"deviceId": DEVICE_ID,
"to": order["phone"],
"text": f"Hi {order['name']} 👋\nYour order *#{order['id']}* is confirmed.",
})
whatixo("/whatsapp/messages/send", {
"deviceId": DEVICE_ID,
"to": order["phone"],
"type": "document",
"mediaUrl": order["invoice_url"],
"fileName": f"Invoice-{order['id']}.pdf",
})Verification code (OTP) over WhatsApp
Replace SMS with WhatsApp to verify your users’ numbers.
otp.jsJS
import crypto from 'node:crypto';
import { whatixo, DEVICE_ID } from './whatixo.js';
const pending = new Map(); // in production: Redis or a database
export async function sendOtp(phone) {
const code = String(crypto.randomInt(100000, 1000000));
const hash = crypto.createHash('sha256').update(code).digest('hex');
pending.set(phone, { hash, expires: Date.now() + 10 * 60_000, tries: 0 });
await whatixo('/whatsapp/messages/send', {
deviceId: DEVICE_ID,
to: phone,
text: `Your verification code: *${code}*\nIt expires in 10 minutes. Never share it with anyone.`,
});
}
export function verifyOtp(phone, code) {
const entry = pending.get(phone);
if (!entry || entry.expires < Date.now() || ++entry.tries > 5) return false;
const ok = crypto.createHash('sha256').update(String(code)).digest('hex') === entry.hash;
if (ok) pending.delete(phone);
return ok;
}
Appointment reminders (scheduled task)
reminders.py — run every morning (cron)PYTHON
from datetime import date, timedelta
import time
from whatixo import whatixo, DEVICE_ID, WhatixoError
tomorrow = date.today() + timedelta(days=1)
appointments = load_appointments(tomorrow) # your function: [{"name", "phone", "time"}]
for appt in appointments:
try:
whatixo("/whatsapp/messages/send", {
"deviceId": DEVICE_ID,
"to": appt["phone"],
"text": f"Hi {appt['name']}, reminder of your appointment tomorrow at {appt['time']} ⏰\n"
"Reply 1 to confirm, 2 to cancel.",
})
except WhatixoError as e:
print("Failed", appt["phone"], e.status, e)
time.sleep(5) # reasonable pace between two sends
To handle the “1” and “2” replies without code, create two keyword workflows (1 and 2, rule is exactly) that reply and tag the contact.
Questions? Message us from the app (Help & support) or at support@whatixo.com.Updated: November 2026