Developer API · v1

Build on CAAC Go

Send WhatsApp messages and generate AI replies from your own apps. The API is REST over HTTPS, JSON in and out, authenticated with a workspace API key.

AI coding tools & agents

Everything here is machine-readable. Point your agent at it instead of pasting docs by hand.

Install the agent skill

A portable SKILL.md that teaches Claude Code, Codex, Cursor or Gemini CLI how to install and verify the widget. No API key, works on every plan.

mkdir -p .agents/skills/caac-go && curl -sL https://caacgo.cresclab.com/caac-go-skill/SKILL.md -o .agents/skills/caac-go/SKILL.md
View SKILL.md ↗

Swap .agents/skills for .claude/skills if your agent reads that path instead.

Connect the MCP server

Lets an agent read your install snippet, run the install check, update the widget, and add knowledge sources. Authenticates with a workspace API key, so it needs the Growth plan or above — installing the widget itself needs neither a key nor an upgrade.

https://caacgo.cresclab.com/api/mcp
Authorization: Bearer cwa_your_key
Add to CursorCursor opens with the server prefilled — paste your key to finish.

Base URL & authentication

All requests go to the base URL below. Pass your key (created under Settings → API keys) in the Authorization header. Keep it secret — it grants access to your workspace.

Base URL   https://caacgo.cresclab.com
Header     Authorization: Bearer cwa_your_key

Endpoints

GET/api/v1/me

Verify a key and return the workspace it belongs to.

curl https://caacgo.cresclab.com/api/v1/me \
  -H "Authorization: Bearer cwa_your_key"

Response

{ "ok": true, "workspace": { "id": "…", "name": "Glow Skin Clinic", "plan": "free" } }
POST/api/v1/messages

Send a WhatsApp text message. Subject to WhatsApp's 24-hour customer-care window and template rules for proactive sends.

curl -X POST https://caacgo.cresclab.com/api/v1/messages \
  -H "Authorization: Bearer cwa_your_key" \
  -H "Content-Type: application/json" \
  -d '{"to":"+5511988887777","text":"Hi! Thanks for reaching out 👋"}'

Response

{ "ok": true }
POST/api/v1/ai/reply

Generate an AI reply from your business content. Pass url to read answers from a website, or context with raw text.

curl -X POST https://caacgo.cresclab.com/api/v1/ai/reply \
  -H "Authorization: Bearer cwa_your_key" \
  -H "Content-Type: application/json" \
  -d '{"message":"How much is a haircut?","url":"https://your-site.com"}'

Response

{ "reply": "A men's haircut is $30 and takes about 30 minutes — want me to book you in?" }

Webhooks

Get notified when things happen in your workspace. Add an endpoint in Settings → Webhooks and we’ll POST a signed JSON body to it when these events fire:

  • message.received — A visitor sent a message to your agent.
  • conversation.escalated — The AI flagged a conversation for a human to follow up.
  • contact.created — A new contact / lead was captured.
  • lead.captured — The AI saved a visitor as a lead (the money event).
  • appointment.requested — The AI recorded a booking request for your team to confirm.

Delivery

POST  https://yourapp.com/webhooks/caac
Content-Type:      application/json
X-CAAC-Event:      message.received
X-CAAC-Signature:  <hex HMAC-SHA256 of the raw body, keyed with your signing secret>

{
  "id": "5f1c…",
  "event": "message.received",
  "createdAt": "2026-06-23T08:00:00.000Z",
  "data": {
    "conversationId": "…", "contactId": "…",
    "channelType": "web", "body": "Hi! Do you ship overseas?",
    "contact": { "name": null, "phone": null, "externalId": "…" }
  }
}

More payloads

// conversation.escalated — AI handed off; open a ticket in your helpdesk.
// Carries the requester identity + recent transcript so you can create the
// ticket straight from this event (contact is null if the visitor gave none).
// contact.metadata holds attributes you passed via the widget identify() API
// (see below) — e.g. the logged-in user's plan / your member id — so you can
// reverse-look-up your own DB on handoff.
{ "event": "conversation.escalated", "data": {
  "conversationId": "…", "contactId": "…",
  "question": "Can I get a refund on order #1234?",
  "contact": {
    "name": "Alex Tan", "email": "alex@example.com", "phone": "+6591234567",
    "metadata": { "plan": "growth", "userId": "u_123" }
  },
  "transcript": [
    { "role": "visitor", "text": "Can I get a refund on order #1234?" },
    { "role": "agent",   "text": "Let me connect you with the team." }
  ]
} }

// lead.captured — the money event
{ "event": "lead.captured", "data": {
  "conversationId": "…", "contactId": "…",
  "name": "Alex Tan", "email": "alex@example.com",
  "phone": "+6591234567", "interest": "pricing"
} }

// appointment.requested
{ "event": "appointment.requested", "data": {
  "conversationId": "…", "contactId": "…",
  "service": "Consultation", "preferredTime": "Fri 3pm",
  "name": "Alex Tan", "phone": "+6591234567"
} }

Verify the signature (Node)

import crypto from "node:crypto";

const signature = req.headers["x-caac-signature"];
const expected = crypto.createHmac("sha256", WEBHOOK_SIGNING_SECRET)
  .update(rawBody) // the exact raw request body string
  .digest("hex");
const ok = signature.length === expected.length &&
  crypto.timingSafeEqual(Buffer.from(signature), Buffer.from(expected));

Respond 2xx to acknowledge. The last delivery status is shown next to each endpoint, and you can send a test event from the Webhooks page.

Pass visitor identity & context

Call caacgo("identify", …) with whatever you know about the visitor. email & name populate the contact; every other field lands in contact.metadata and — this is the powerful part — the AI sees these attributes when it answers. Combine with your agent's custom instructions to adapt by segment: “if plan is trial, mention the upgrade; if cart_items is set, help them check out.” The same fields also arrive on the conversation.escalated webhook, so on handoff you can reverse-look-up your own member DB. Values are asserted by your page — the AI uses them for tailoring only, and you should verify them against your own records before granting anything (signed identity verification is on the roadmap).

<script src="https://caacgo.cresclab.com/widget.js" data-key="wk_xxx"></script>
<script>
  // call with anything you know — logged-in identity, funnel stage, cart state:
  caacgo("identify", {
    email:  user.email,     // -> contact.email
    name:   user.fullName,  // -> contact.name
    plan:   user.plan,      // -> contact.metadata.plan  (visible to the AI)
    stage:  "trial",        // -> contact.metadata.stage (visible to the AI)
    userId: user.id         // -> contact.metadata.userId
  });
</script>

Errors

Errors return the matching HTTP status with a JSON body: { "error": "…" }. Each endpoint is rate-limited per key (/me 120, /messages 60, /ai/reply 20 requests per minute) — back off and retry on 429.

StatusMeaning
400Invalid or missing parameters.
401Missing or invalid API key.
422Could not read the provided URL.
429Rate limit exceeded — slow down and retry.
502Upstream WhatsApp or AI call failed.

OpenAPI spec

Browse the full API in the interactive reference, or import the machine-readable spec into Postman, Insomnia or Swagger UI:

Ready to start? Create your API key →