Base URL
https://connectapi.clickmaker.in/api/v1Status markers: endpoints shown in the API reference include a status. Anything marked planned is not yet available and must not be used in production.
Introduction
ClickMaker Connect is a multi-tenant WhatsApp Business infrastructure platform. Each organization connects its own WhatsApp Business Account through Meta Embedded Signup. ClickMaker operates the dashboard, API and event pipeline.
Responses use a consistent envelope. Success responses include data and requestId. Errors include error.code, error.message, optional error.details and requestId. Pagination uses an opaque cursor rather than page numbers.
{
"data": { "id": "org_01J8...", "name": "Lumina Clinics" },
"requestId": "req_01J8XK4T"
}Quickstart
Create an account and organization, then connect a WhatsApp Business Account before sending any message. A number that is not connected and verified cannot send.
- 1Create an account and organization.
- 2Connect a WhatsApp Business Account through Embedded Signup.
- 3Create an application and a scoped API key in the dashboard.
- 4Send an approved template or reply inside an open service window.
- 5Register a webhook endpoint and verify signatures.
Authentication
Browser sessions use an access token plus an HttpOnly, Secure, SameSite refresh cookie. Refresh tokens rotate; reuse of a rotated token revokes the session family. Browser clients must use withCredentials and send the CSRF header on state-changing requests.
Server-to-server integrations use API keys in the Authorization header. Keys are hashed at rest, bound to one organization and one application, and can only exercise granted scopes.
curl https://connectapi.clickmaker.in/api/v1/organizations \
-H "Authorization: Bearer cmc_live_xxxxxxxxxxxxxxxxx"import axios from "axios"
const connect = axios.create({
baseURL: "https://connectapi.clickmaker.in/api/v1",
headers: {
Authorization: `Bearer ${process.env.CLICKMAKER_API_KEY}`,
"Content-Type": "application/json",
},
})
const { data } = await connect.get("/whatsapp/connections")
// data.data[] — never contains Meta access tokensEnvironments
Use separate applications and keys for development and production. Test credentials cannot access production Meta assets.
Production messaging requires a Meta-verified business, an eligible number and approved templates. ClickMaker does not bypass Meta review, quality checks or policy decisions.
Development
Separate keys, restricted recipients and no production WABA unless explicitly intended.
Production
Verified business assets, approved templates and monitored webhook delivery.
Connect a WhatsApp account
Embedded Signup returns an authorization code to your callback. Exchange it server-side. ClickMaker validates the WABA and phone number, subscribes the application to the WABA webhook and stores the access token encrypted.
If the same WABA and number are returned again, the operation updates the existing connection rather than creating a duplicate. Treat the response as idempotent.
curl -X POST https://connectapi.clickmaker.in/api/v1/whatsapp/embedded-signup/exchange \
-H "Authorization: Bearer cmc_live_..." \
-H "Content-Type: application/json" \
-d '{
"code": "AQD...",
"state": "signed-state-value",
"wabaId": "102290129340398",
"phoneNumberId": "106540352242922"
}'Send messages
Free-form messages are allowed only inside the 24-hour customer service window that begins with the customer's last inbound message. Outside that window, use an approved template.
Outbound sends are asynchronous. A 202 response means the message was queued, not delivered. Delivery truth comes from Meta status webhooks and appears on GET /messages/:id.
Supply an Idempotency-Key header for retries. The same key returns the original result instead of creating a second send.
curl -X POST https://connectapi.clickmaker.in/api/v1/messages \
-H "Authorization: Bearer cmc_live_..." \
-H "Content-Type: application/json" \
-H "Idempotency-Key: order-4412-confirmation" \
-d '{
"phoneNumberId": "pn_01J8XK4T",
"to": "919876543210",
"type": "text",
"text": { "body": "Your order is confirmed." }
}'curl https://connectapi.clickmaker.in/api/v1/messages/msg_01J8XM2 \
-H "Authorization: Bearer cmc_live_..."
# {
# "data": {
# "id": "msg_01J8XM2",
# "status": "delivered",
# "providerMessageId": "wamid.HBg...",
# "events": [
# { "type": "queued", "at": "2026-11-07T06:12:01Z" },
# { "type": "sent", "at": "2026-11-07T06:12:02Z" },
# { "type": "delivered", "at": "2026-11-07T06:12:04Z" }
# ]
# }
# }Work with templates
Templates are reviewed by Meta. A locally created template is pending until Meta approves it. Never treat local creation as approval.
Use GET /whatsapp/templates to discover approved templates and their language variants. Rejected templates include a rejection reason where Meta provides one.
Template category is proposed by the business but decided by Meta. Misclassification can lead to rejection or quality penalties. ClickMaker does not override category decisions.
Errors and retries
Errors use a stable code plus a human-readable message. Do not branch on message text. Retry only 429 and 5xx responses, with exponential backoff and jitter.
Webhook deliveries are at-least-once. Verify the signature, reject stale timestamps, deduplicate by event ID and respond with 2xx quickly. Non-2xx responses are retried.
| Code | HTTP | Meaning |
|---|---|---|
| VALIDATION_ERROR | 400 | Request body, query or params failed validation. |
| UNAUTHENTICATED | 401 | Missing or invalid credentials. |
| TOKEN_EXPIRED | 401 | Access token expired; refresh the session. |
| FORBIDDEN | 403 | Authenticated but missing the required scope or role. |
| NOT_FOUND | 404 | Resource does not exist in this tenant or is not visible. |
| CONFLICT | 409 | Duplicate resource or invalid state transition. |
| RATE_LIMITED | 429 | Too many requests; retry with backoff. |
| PROVIDER_ERROR | 502 | Meta returned an error; see normalized details. |
| INTERNAL_ERROR | 500 | Unexpected server error. Use requestId when contacting support. |
Rate limits
Limits apply per application, per organization and per phone number. Responses include X-RateLimit-Limit, X-RateLimit-Remaining and X-RateLimit-Reset when a limit is active.
Messaging limits set by Meta also apply. ClickMaker surfaces the current messaging limit on the phone number record; it cannot increase Meta's limit.
Receive events
Register an HTTPS endpoint per application. ClickMaker signs each request with the endpoint secret. The signature covers the timestamp and raw body, and stale timestamps are rejected.
The full event catalogue and delivery policy are on the webhooks page.
import crypto from "node:crypto"
function verifyClickMakerSignature(input: {
rawBody: string
signature: string
timestamp: string
secret: string
}) {
const fiveMinutes = 5 * 60 * 1000
const age = Math.abs(Date.now() - Number(input.timestamp) * 1000)
if (!Number.isFinite(age) || age > fiveMinutes) return false
const expected = crypto
.createHmac("sha256", input.secret)
.update(`${input.timestamp}.${input.rawBody}`)
.digest("hex")
const received = input.signature.replace(/^v1=/, "")
if (received.length !== expected.length) return false
return crypto.timingSafeEqual(
Buffer.from(expected, "hex"),
Buffer.from(received, "hex"),
)
}Changelog
The API is versioned by path. Additive changes such as new optional fields do not break the version. Breaking changes ship under a new version with an overlap window.
This portal marks planned capabilities explicitly. Anything not marked available should not be treated as shipped.
Current version: v1. Deprecations are announced before removal where a breaking change is involved.
