EZWhatsApp Examples

Current examples

Use these examples for the current EZWhatsApp API.

These examples cover the supported public API paths: Channel API health, direct text, group text, conversation text, URL media, webhook setup, workspace sends, contacts, campaigns, inbox reads, and retry-safe receivers.

Check health before sending

curl 'https://app.ezw.solutions/api/v1/health?wakeup=false&channel_type=web' \
  -H 'Authorization: Bearer {lineApiToken}'

Send text

Direct phone recipient

curl -X POST 'https://app.ezw.solutions/api/v1/messages/text' \
  -H 'Authorization: Bearer {lineApiToken}' \
  -H 'Content-Type: application/json' \
  -H 'Idempotency-Key: order-123-ready' \
  -d '{
    "to": "+972501234567",
    "body": "Your order is ready.",
    "ctaUrlButton": {
      "displayText": "Open order",
      "url": "https://store.example.com/orders/123"
    }
  }'

Existing conversation

curl -X POST 'https://app.ezw.solutions/api/v1/messages/text' \
  -H 'Authorization: Bearer {lineApiToken}' \
  -H 'Content-Type: application/json' \
  -H 'Idempotency-Key: webhook-reply-123' \
  -d '{
    "conversationId": "{conversationId}",
    "body": "Thanks, I am checking this now."
  }'

WhatsApp group JID

curl -X POST 'https://app.ezw.solutions/api/v1/messages/text' \
  -H 'Authorization: Bearer {lineApiToken}' \
  -H 'Content-Type: application/json' \
  -H 'Idempotency-Key: group-update-123' \
  -d '{
    "groupId": "120363012345678901@g.us",
    "body": "Group update"
  }'

Send URL media

Channel API media must be reachable through an external HTTP/HTTPS URL. Use to or groupId; this route does not accept conversationId.

Direct document URL

curl -X POST 'https://app.ezw.solutions/api/v1/messages/media' \
  -H 'Authorization: Bearer {lineApiToken}' \
  -H 'Content-Type: application/json' \
  -H 'Idempotency-Key: invoice-123' \
  -d '{
    "to": "+972501234567",
    "type": "document",
    "media": {
      "url": "https://cdn.example.com/invoices/123.pdf",
      "mime_type": "application/pdf",
      "filename": "invoice-123.pdf"
    },
    "caption": "Invoice 123"
  }'

Group image URL

curl -X POST 'https://app.ezw.solutions/api/v1/messages/media' \
  -H 'Authorization: Bearer {lineApiToken}' \
  -H 'Content-Type: application/json' \
  -H 'Idempotency-Key: group-photo-123' \
  -d '{
    "groupJid": "120363012345678901@g.us",
    "type": "image",
    "mediaUrl": "https://cdn.example.com/photo.jpg",
    "contentType": "image/jpeg",
    "caption": "Photo update"
  }'

Configure a line webhook

curl -X POST 'https://app.ezw.solutions/api/v1/webhooks' \
  -H 'Authorization: Bearer {lineApiToken}' \
  -H 'Content-Type: application/json' \
  -d '{
    "targetUrl": "https://agency.example.com/ezw/webhook",
    "events": ["messages.post", "statuses.post", "chats.post"],
    "payloadFormat": "whapi",
    "enabled": true,
    "persistent": true
  }'

Send as a workspace user

Text reply

curl -X POST 'https://app.ezw.solutions/api/lines/{lineId}/send' \
  -H 'Authorization: Bearer {idToken}' \
  -H 'Content-Type: application/json' \
  -H 'Idempotency-Key: workspace-reply-123' \
  -d '{
    "conversationId": "{conversationId}",
    "bodyText": "Thanks, I am checking this now."
  }'

Direct phone send

curl -X POST 'https://app.ezw.solutions/api/lines/{lineId}/send' \
  -H 'Authorization: Bearer {idToken}' \
  -H 'Content-Type: application/json' \
  -H 'Idempotency-Key: workspace-direct-123' \
  -d '{
    "recipientPhoneNumber": "+972501234567",
    "bodyText": "Hello from the workspace."
  }'

One uploaded image

curl -X POST 'https://app.ezw.solutions/api/lines/{lineId}/send' \
  -H 'Authorization: Bearer {idToken}' \
  -H 'Idempotency-Key: image-send-123' \
  -F 'conversationId={conversationId}' \
  -F 'bodyText=Attached photo' \
  -F 'media=@/absolute/path/photo.jpg;type=image/jpeg'

Forward stored message

curl -X POST 'https://app.ezw.solutions/api/lines/{lineId}/send' \
  -H 'Authorization: Bearer {idToken}' \
  -H 'Content-Type: application/json' \
  -H 'Idempotency-Key: forward-123' \
  -d '{
    "recipientPhoneNumber": "+972501234567",
    "forwardedFromMessageId": "{messageId}"
  }'

Contacts

curl -X POST 'https://app.ezw.solutions/api/contacts' \
  -H 'Authorization: Bearer {idToken}' \
  -H 'Content-Type: application/json' \
  -d '{
    "sourceFilename": "customers.csv",
    "rows": [
      {
        "phoneNumber": "+972501234567",
        "displayName": "Dana Levi",
        "company": "Acme",
        "email": "dana@example.com",
        "tags": ["vip", "orders"],
        "externalId": "crm-123"
      }
    ]
  }'

Campaigns

Create draft

curl -X POST 'https://app.ezw.solutions/api/campaigns' \
  -H 'Authorization: Bearer {idToken}' \
  -F 'name=May offers' \
  -F 'lineId={lineId}' \
  -F 'bodyText=Hello, {name}. Your offer is ready.' \
  -F 'recipientsCsv=phone,name
+972501234567,Dana Levi' \
  -F 'sourceFilename=may-offers.csv' \
  -F 'minDelaySeconds=30' \
  -F 'maxDelaySeconds=120' \
  -F 'hourlyCap=60'

Launch and inspect

curl 'https://app.ezw.solutions/api/campaigns?limit=100' \
  -H 'Authorization: Bearer {idToken}'

curl -X POST 'https://app.ezw.solutions/api/campaigns/{campaignId}/launch' \
  -H 'Authorization: Bearer {idToken}'

curl 'https://app.ezw.solutions/api/campaigns/{campaignId}' \
  -H 'Authorization: Bearer {idToken}'

Read inbox data

curl 'https://app.ezw.solutions/api/conversations?lineId={lineId}&limit=25' \
  -H 'Authorization: Bearer {idToken}'

curl 'https://app.ezw.solutions/api/conversations/{conversationId}/messages?limit=50' \
  -H 'Authorization: Bearer {idToken}'

JavaScript fetch example

const response = await fetch("https://app.ezw.solutions/api/v1/messages/text", {
  method: "POST",
  headers: {
    "Authorization": `Bearer ${process.env.EZW_LINE_API_TOKEN}`,
    "Content-Type": "application/json",
    "Idempotency-Key": `order:${order.id}:ready`
  },
  body: JSON.stringify({
    to: order.customerPhone,
    body: `Your order ${order.number} is ready.`,
    ctaUrlButton: {
      displayText: "Open order",
      url: `https://store.example.com/orders/${order.id}`
    }
  })
});

if (!response.ok) {
  throw new Error(`EZWhatsApp send failed: ${response.status} ${await response.text()}`);
}

const queued = await response.json();

Webhook receiver example

export async function POST(request) {
  const deliveryId = request.headers.get("x-ezw-delivery-id");
  const event = request.headers.get("x-ezw-webhook-event");
  const lineId = request.headers.get("x-ezw-line-id");
  const payload = await request.json();

  if (!deliveryId || !event || !lineId) {
    return new Response("missing EZWhatsApp headers", { status: 400 });
  }

  if (await alreadyProcessed(deliveryId)) {
    return new Response("duplicate accepted", { status: 200 });
  }

  await saveEvent({ deliveryId, event, lineId, payload });
  return new Response("accepted", { status: 200 });
}