WACRM Developer API
Build chatbots and integrations on your WhatsApp inbox
A REST API for sending WhatsApp messages and managing contacts, plus a signed webhook that delivers every inbound message to your endpoint in real time. Everything your bot sends and receives appears in the WACRM inbox, so bots and human agents share one view of each conversation. Works with n8n, Make, Zapier webhooks, or any backend.
1. Get an API key
In your WACRM workspace, open Settings → Developers → Create API key. The key (format wak_live_…) is shown once — we store only a SHA-256 hash of it, so copy it immediately. Revoke and re-issue keys from the same panel at any time.
Send it on every request as a Bearer token:
Authorization: Bearer wak_live_XXXXXXXXXXXXXXXX
Base URL: https://wacrm.bitlancetechhub.com. All requests and responses are JSON. A key is scoped to the workspace that created it and can act only on that workspace's data.
2. Send a message
POST/api/v1/messages
Free-form text — allowed only inside the 24-hour customer service window (i.e. the customer messaged you within the last 24 hours):
curl -X POST https://wacrm.bitlancetechhub.com/api/v1/messages \
-H "Authorization: Bearer wak_live_XXXX" \
-H "Content-Type: application/json" \
-d '{
"to": "919876543210",
"type": "text",
"text": "Hi! Your order has shipped 🎉"
}'Template message — required outside the 24-hour window and for any first-touch message. The template must be Approved on Meta (list them with GET /api/v1/templates). params fills the body's {{1}}, {{2}}… variables in order; header_value is required when the template has a media header (public https URL) or a header variable:
curl -X POST https://wacrm.bitlancetechhub.com/api/v1/messages \
-H "Authorization: Bearer wak_live_XXXX" \
-H "Content-Type: application/json" \
-d '{
"to": "919876543210",
"type": "template",
"template_name": "order_update",
"language": "en_US",
"params": ["Rahul", "#1042"],
"header_value": "https://example.com/banner.jpg"
}'Success response:
{
"success": true,
"message_id": "wamid.HBgMOTE2Mzk4…",
"contact_id": "18fe6dff-…",
"conversation_id": "cc1a8c7f-…"
}The contact and conversation are created automatically if they don't exist yet, and the message appears in the inbox thread as a bot message.
Error responses
| Status | Code | Meaning |
|---|---|---|
| 401 | — | Missing or invalid API key. |
| 400 | TEMPLATE_HEADER_REQUIRED | The template has a media/variable header — pass header_value. |
| 402 | PAYMENT_METHOD_REQUIRED | The WhatsApp Business Account has no payment method — Meta refused the paid send. Fix in Meta's Billing Hub. |
| 429 | PAIR_RATE_LIMIT | WhatsApp allows ~1 message per 6 seconds to the same recipient. Honor the Retry-After header; back off exponentially (4^attempt seconds). |
| 502 | — | Meta rejected the send for another reason — the error text carries Meta's message and details. |
3. List templates
GET/api/v1/templates
Returns the Approved templates your key can send — name, language, category, header shape, body text (with its {{N}} placeholders), and footer. Use it to know how many params a template needs and whether it wants a header_value.
curl https://wacrm.bitlancetechhub.com/api/v1/templates \ -H "Authorization: Bearer wak_live_XXXX"
4. Contacts
GET/api/v1/contacts?phone=919876543210
Look up a contact by phone (country code required, no + needed). 404 when not found.
POST/api/v1/contacts
curl -X POST https://wacrm.bitlancetechhub.com/api/v1/contacts \
-H "Authorization: Bearer wak_live_XXXX" \
-H "Content-Type: application/json" \
-d '{ "phone": "919876543210", "name": "Rahul Saini" }'Idempotent by phone number — creating an existing contact returns it with "created": false.
5. Receive messages (webhook)
Set your endpoint URL in Settings → Developers → Webhook. You get a signing secret (format whsec_…). Every inbound WhatsApp message is then POSTed to your URL within moments of arriving:
POST <your-url>
Content-Type: application/json
X-Wacrm-Event: message.received
X-Wacrm-Signature: sha256=<hex HMAC-SHA256 of the raw body>
{
"event": "message.received",
"created_at": "2026-09-03T15:40:00.000Z",
"data": {
"contact": { "id": "…", "phone": "919876543210", "name": "Rahul" },
"conversation_id": "…",
"message": {
"whatsapp_message_id": "wamid.…",
"type": "text",
"text": "I want to order",
"media_url": null,
"interactive_reply_id": null,
"timestamp": "2026-09-03T15:39:58.000Z"
}
}
}Verify the signature before trusting a delivery — same pattern Meta uses for its own webhooks:
// Node.js / Express — use the RAW body, not re-serialized JSON
const crypto = require('crypto');
function verify(rawBody, signatureHeader, secret) {
const expected =
'sha256=' +
crypto.createHmac('sha256', secret).update(rawBody).digest('hex');
return crypto.timingSafeEqual(
Buffer.from(expected),
Buffer.from(signatureHeader || '')
);
}- Respond with a 2xx within 5 seconds — do slow work async.
- Delivery is best-effort (no retries yet); the last delivery error is shown in Settings → Developers for debugging.
- Button taps and WhatsApp Flow submissions arrive with
interactive_reply_id/ readable text, so bots can branch on them.
6. Rate limits
POST /api/v1/messages— 60 requests/minute per workspace.- Read endpoints — 120 requests/minute.
POST /api/v1/contacts— 60 requests/minute.
WhatsApp's own pair limit (~1 message / 6 s per recipient) applies on top — see the 429 handling above.
7. n8n chatbot in 3 nodes
- Webhook node (POST) — paste its URL into Settings → Developers. Every customer message triggers the flow.
- Your logic — an AI Agent node, a Switch on
{{$json.data.message.text}}, or anything else. - HTTP Request node — POST to
/api/v1/messageswith yourwak_live_…key in the Authorization header to reply.
The whole exchange — customer message and bot reply — is visible to your team in the WACRM inbox, and a human can take over the conversation at any point.
Ready to build?
Create your API key in Settings → Developers — or create a free account and connect your WhatsApp Business number in two minutes. Questions: ceo@bitlancetechhub.com.