A clean REST API for WhatsApp messaging, contacts and conversations. Base URL: your Waclino origin.
Create an API key in Developer → API keys. Keys carry explicit scopes and a per-minute rate limit. Send the key as a bearer token:
curl https://app.example.com/api/v1/contacts \
-H "Authorization: Bearer wcl_live_xxxxxxxxxxxxxxxx"Every response uses the same envelope. Errors carry a stable code you can branch on:
{
"success": false,
"error": {
"code": "MESSAGE_WINDOW_CLOSED",
"message": "The 24-hour customer service window has closed…"
},
"requestId": "req_8f2…"
}Common codes: VALIDATION_ERROR (422), UNAUTHORIZED (401), FORBIDDEN (403, missing scope), RATE_LIMITED (429), MESSAGE_WINDOW_CLOSED (422), PLAN_LIMIT_REACHED (402). Rate-limited responses include a Retry-After header.
Send free-form messages inside the 24-hour customer window, or approved templates anytime.
POST/api/v1/messages/send
Send a text or media message. Requires the messages:send scope. Returns 422 MESSAGE_WINDOW_CLOSED when the 24-hour window has expired – send a template instead.
Request body
{
"to": "+919876543210",
"type": "text",
"text": "Your order has shipped!",
"clientId": "order-8231" // optional idempotency key
}Response
{
"success": true,
"data": {
"messageId": "9b2f…",
"conversationId": "c41a…",
"status": "QUEUED"
}
}GET/api/v1/messages/{id}
Fetch a message with its current delivery status (QUEUED → SENT → DELIVERED → READ, or FAILED with an error).
POST/api/v1/templates/send
Send an approved template by name or id with body variables. Works outside the 24-hour window.
Request body
{
"to": "+919876543210",
"templateName": "order_confirmation",
"bodyParams": ["Rahul", "#8231", "₹1,299"]
}Create and search the CRM. Contacts are deduplicated by phone number automatically.
GET/api/v1/contacts?search=&cursor=&limit=
Cursor-paginated contact list. Filter by search, tagIds or optInStatus.
POST/api/v1/contacts
Create or update (upsert by phone) a contact. Requires contacts:write.
Request body
{
"phone": "+919876543210",
"name": "Rahul Sharma",
"tags": ["VIP"],
"customFields": { "city": "Mumbai" }
}GET/api/v1/contacts/{id}
Fetch one contact with tags and custom fields.
Read threads and manage their lifecycle.
GET/api/v1/conversations
List conversations, newest activity first.
GET/api/v1/conversations/{id}/messages
Messages in a conversation (cursor-paginated, newest first).
POST/api/v1/conversations/{id}/status
Set status to OPEN, PENDING or RESOLVED. Requires conversations:write.
Request body
{ "status": "RESOLVED" }List your message templates and their WhatsApp review status.
GET/api/v1/templates?status=APPROVED
List templates. Filter by status, category or language.
Subscribe to events (message.received, message.delivered, contact.created, campaign.completed…) from the Developer page in the app. Every delivery is signed.
Each delivery includes X-Waclino-Timestamp and X-Waclino-Signature headers. The signature is an HMAC-SHA256 of `${timestamp}.${rawBody}` using your webhook secret:
import crypto from "node:crypto";
function verify(secret, timestamp, rawBody, signature) {
const expected = crypto
.createHmac("sha256", secret)
.update(`${timestamp}.${rawBody}`)
.digest("hex");
return crypto.timingSafeEqual(
Buffer.from(expected),
Buffer.from(signature),
);
}Reject deliveries older than 5 minutes to prevent replays. Failed deliveries are retried with exponential backoff.