DA Connect API

Send WhatsApp messages from your own software. Available on the Starter and Growth plans. Create a key in Developers → API keys.

Basics

Send a template — POST /v1/messages

Templates can be sent any time. Message charges are billed by Meta to your WhatsApp account.

curl -X POST https://chpxvjqfwoxtndilmpox.supabase.co/functions/v1/api/v1/messages \
  -H "Authorization: Bearer $DAC_KEY" -H "Content-Type: application/json" \
  -d '{
    "to": "919876543210",
    "type": "template",
    "template": {
      "name": "order_update",
      "language": "en",
      "params": {
        "header": "Order #1043",
        "body": ["Ravi", "#1043", "today 6 pm"],
        "buttons": { "0": "1043" }
      }
    },
    "contact": { "name": "Ravi Kumar" }
  }'

params.body fills {{1}}, {{2}}… in order. For a media header use "header": {"link":"https://…/invoice.pdf","filename":"Invoice.pdf"}. buttons maps a button's position to the URL ending or offer code. If you have several numbers, add "from": "<phone number ID or number>".

Response:

{ "id": "6f1c…", "wamid": "wamid.HBgM…", "status": "sent", "to": "919876543210" }

Send a free-form message

Only inside the 24-hour window after the customer's last message (otherwise you get 409 WINDOW_CLOSED).

{ "to": "919876543210", "type": "text", "text": "Your order is out for delivery 🚚" }
{ "to": "919876543210", "type": "document", "link": "https://…/bill.pdf", "filename": "Bill.pdf", "caption": "Your bill" }

Types: text, image, video, audio, document (media by public https link).

Message status — GET /v1/messages/{id}

{ "id": "6f1c…", "status": "read", "error": null, "pricing_category": "utility",
  "sent_at": "…", "delivered_at": "…", "read_at": "…" }

Status goes sent → delivered → read, or failed with a reason in error.

Create or update a contact — POST /v1/contacts

{ "phone": "919876543210", "name": "Ravi Kumar", "email": "ravi@example.com",
  "attributes": { "city": "Port Blair", "customer_id": "C-221" }, "tags": ["Website lead"] }

Tags are created if they don't exist. Send "opted_out": true to unsubscribe someone.

List templates — GET /v1/templates

Approved templates with their components, so you know which parameters to send.

List numbers — GET /v1/numbers

Your connected WhatsApp numbers with quality rating and daily limit.

Webhooks (Growth plan)

Add a URL in Developers → Webhooks. We send a POST with JSON for each event:

{ "event": "message.received", "workspace_id": "…", "created_at": "…",
  "data": { "id": "…", "wamid": "…", "from": "919876543210", "name": "Ravi", "type": "text",
            "text": "Is my order ready?", "message": { …raw WhatsApp message… } } }

Events: message.received, message.status (data: id, wamid, status, campaign_id, recipient, errors, pricing), contact.opted_out.

Check the signature: X-DA-Signature: sha256=<hex> is HMAC-SHA256 of the raw body using your webhook secret. Answer with any 2xx within 10 seconds; otherwise we retry after 1, 5, 30, 120 and 720 minutes.

// Node.js
const crypto = require('crypto');
const ok = req.headers['x-da-signature'] ===
  'sha256=' + crypto.createHmac('sha256', SECRET).update(rawBody).digest('hex');

Common errors