HTTP API

Send WhatsApp messages from your CRM

Use the Send API from CRMs, automations, backend jobs, and support tools. v1 supports direct text, image, and document messages from the connected WhatsApp account.

Authentication

Send a Send API bearer token with every request. Send API tokens are separate from MCP tokens and only grant message-send access. Personal API usage sends from the WhatsApp account attached to the token owner. Owners and admins can also use workspace sender mode by passing a from number that belongs to the same workspace.

Authorization header
Authorization: Bearer YOUR_SEND_API_TOKEN

Endpoint

Send message endpoint
POST https://whatan.app/api/v1/messages/send

Sender Rules

Request shapeWho can use itSender behavior
from + toWorkspace owners and adminsSends from the connected workspace number in from.
to onlyOwners, admins, and membersSends from the WhatsApp account attached to that token.

Workspace Sender Mode

Use this mode for Attio workflows and other workspace-level automations that need to choose the sender at runtime. Include both from and to. The from number must be one of the connected WhatsApp numbers in this workspace. This mode is available to owner/admin tokens.

curl workspace sender message
curl -X POST "https://whatan.app/api/v1/messages/send" \
  -H "Authorization: Bearer YOUR_SEND_API_TOKEN" \
  -H "Content-Type: application/json" \
  -H "Idempotency-Key: attio-workflow-123" \
  -d '{
    "from": "+917000000001",
    "to": "+917999709798",
    "type": "text",
    "text": "Following up from Attio."
  }'

The API normalizes from, finds the matching connected WhatsApp account in the workspace, and queues the send against that account. If the number is not part of the workspace, the request is rejected before sending.

Personal Sender Mode

This is the original Send API behavior and remains supported for backwards compatibility. Omit from; the bearer token determines the sender. Owners and members using this mode send only from their own connected WhatsApp account.

curl personal text message
curl -X POST "https://whatan.app/api/v1/messages/send" \
  -H "Authorization: Bearer YOUR_SEND_API_TOKEN" \
  -H "Content-Type: application/json" \
  -H "Idempotency-Key: invoice-123-reminder" \
  -d '{
    "to": "+917999709798",
    "type": "text",
    "text": "Your invoice is ready."
  }'

Send Text

Text messages support both sender modes. Use from for workspace automation, or omit it for personal-token sending.

curl text message with from
curl -X POST "https://whatan.app/api/v1/messages/send" \
  -H "Authorization: Bearer YOUR_SEND_API_TOKEN" \
  -H "Content-Type: application/json" \
  -H "Idempotency-Key: attio-workflow-123" \
  -d '{
    "from": "+917000000001",
    "to": "+917999709798",
    "type": "text",
    "text": "Following up from Attio."
  }'

Send Image

Image URLs must be public HTTPS URLs. Localhost and private network URLs are rejected.

curl image message
curl -X POST "https://whatan.app/api/v1/messages/send" \
  -H "Authorization: Bearer YOUR_SEND_API_TOKEN" \
  -H "Content-Type: application/json" \
  -H "Idempotency-Key: promo-image-456" \
  -d '{
    "to": "+917999709798",
    "type": "image",
    "image": {
      "url": "https://example.com/promo.png",
      "caption": "New arrivals are live."
    }
  }'

Send Document

Documents use public HTTPS URLs. Provide a file name and MIME type when your CRM knows them.

curl document message
curl -X POST "https://whatan.app/api/v1/messages/send" \
  -H "Authorization: Bearer YOUR_SEND_API_TOKEN" \
  -H "Content-Type: application/json" \
  -H "Idempotency-Key: quote-789" \
  -d '{
    "to": "+917999709798",
    "type": "document",
    "document": {
      "url": "https://example.com/quote.pdf",
      "fileName": "quote.pdf",
      "mimetype": "application/pdf",
      "caption": "Attached quote for review."
    }
  }'

Node Example

Node fetch
const response = await fetch("https://whatan.app/api/v1/messages/send", {
  method: "POST",
  headers: {
    Authorization: "Bearer YOUR_SEND_API_TOKEN",
    "Content-Type": "application/json",
    "Idempotency-Key": "attio-record-1001",
  },
  body: JSON.stringify({
    from: "+917000000001",
    to: "+917999709798",
    type: "text",
    text: "Thanks for contacting support. We are checking this now.",
  }),
});

const result = await response.json();

Idempotency

Include an Idempotency-Key header for every CRM event or automation run. If the CRM retries the same request with the same key, CRM returns the original send result instead of sending a duplicate WhatsApp message.

Rate Limits

v1 queues accepted API sends and paces delivery with a random 2-5 minute delay per connected WhatsApp account. The daily limit is 100 API messages per WhatsApp account. Repeating the same request with the same Idempotency-Key does not count as a new queued send.

The Send API is for transactional CRM messages, support replies, and expected automations. Bulk CSV/XLSX sending belongs in the upcoming Mass Messaging workflow, which will have campaign scheduling, reports, and dedicated safety controls.

Responses

Queued response
{
  "accepted": true,
  "sendAttemptId": "f1f7a5a0-2ff4-4ef7-b4bf-1a3b50ad6f53",
  "messageId": null,
  "remoteJid": null,
  "from": "+917000000001",
  "to": "+917999709798",
  "normalizedPhone": "917999709798",
  "status": "queued"
}

The Send API queues accepted requests. Use the send attempt ID to poll final status. Personal tokens can read their own send attempts. Owner/admin tokens can also read workspace sender mode attempts created from connected senders in the same workspace.

Status endpoint
GET https://whatan.app/api/v1/messages/SEND_ATTEMPT_ID
curl status
curl "https://whatan.app/api/v1/messages/SEND_ATTEMPT_ID" \
  -H "Authorization: Bearer YOUR_SEND_API_TOKEN"
Status response
{
  "sendAttemptId": "f1f7a5a0-2ff4-4ef7-b4bf-1a3b50ad6f53",
  "status": "accepted",
  "messageId": "BAE5...",
  "remoteJid": "[email protected]",
  "errorCode": null,
  "errorMessage": null,
  "createdAt": "2026-05-14T10:00:00.000Z",
  "updatedAt": "2026-05-14T10:00:04.000Z"
}

Error Codes

CodeMeaning
invalid_requestRequest JSON is missing required fields.
invalid_phone_numberPhone number must be international format.
whatsapp_not_connectedThe connected WhatsApp account is offline.
sender_selection_forbiddenThe token owner is not an owner or admin.
sender_not_allowedThe from number is not a sender in this workspace.
recipient_not_foundThe phone number is not reachable on WhatsApp.
invalid_media_urlMedia URL is not a safe public HTTPS URL.
idempotency_conflictThe key was reused with a different request.
rate_limitedThis WhatsApp account hit the v1 send limit.
WhatsApp can still limit or suspend accounts for unwanted or risky messaging. Start with expected, consent-based messages and avoid high-volume blasts from the Send API. Mass Messaging is an upcoming dedicated campaign feature with CSV/XLSX uploads, scheduling, reports, and additional safety controls.