Developer API

Build on top of
Wa-Wexa.

Connect your website, CRM, or internal tools to the WhatsApp customer engagement platform your team already uses.

01 · Quick start

Authenticate with your API key.

Wa-Wexa provides a secure application API for workspace data, messaging, automations, flows, and webhooks. Official Meta WhatsApp Business services power message delivery behind the scenes.

i
Authentication

Generate a key under Settings → API Keys, store it only on your application server, and send it in the Authorization: Bearer wawexa_live_...header. Each key is limited to its selected permissions.

Data layerWa-Wexa API

Workspace data, contacts, conversations, automations, and flows.

MessagingMeta API

Official WhatsApp text, template, media, and flow sends.

FormatJSON

Requests and responses use JSON over HTTPS.

02 · Messages

Send a WhatsApp message.

Send text, media, location, contact, or interactive messages through an existing conversation, or start a template conversation with an E.164 phone number.

POST/api/whatsapp/send

Sends a message through the workspace WhatsApp number and records it in the conversation. Use phone for a first approved-template send.

fetch('/api/whatsapp/send', {
  method: 'POST',
  headers: {
    'Authorization': 'Bearer wawexa_live_your_api_key',
    'Content-Type': 'application/json'
  },
  body: JSON.stringify({
    conversation_id: 'conversation-uuid',
    message_type: 'text',
    content_text: 'Hello from Wa-Wexa'
  })
})

Start with a phone number

For a first business-initiated message, send an E.164 phone instead of conversation_id. Wa-Wexa finds or creates the contact and its open conversation in the API key's workspace before sending the approved template. The optional name is used only when a new contact is created.

fetch('/api/whatsapp/send', {
  method: 'POST',
  headers: {
    'Authorization': 'Bearer wawexa_live_your_api_key',
    'Content-Type': 'application/json'
  },
  body: JSON.stringify({
    phone: '+919876XXXX',
    name: 'Aarav Sharma',
    message_type: 'template',
    template_name: 'welcome_message',
    template_params: ['Aarav', 'Wa-Wexa']
  })
})

Get the conversation_id from the response

You do not create this UUID yourself. The conversation-uuid text in examples is only a placeholder. When the phone-first template request succeeds, the response contains the workspace-scoped conversation_id. Save that returned value for later messages to the same conversation.

const response = await fetch('/api/whatsapp/send', {
  method: 'POST',
  headers: {
    'Authorization': 'Bearer wawexa_live_your_api_key',
    'Content-Type': 'application/json'
  },
  body: JSON.stringify({
    phone: '+919876XXXX',
    name: 'Raki',
    message_type: 'template',
    template_name: 'welcome_message',
    template_params: ['Aarav']
  })
});

if (!response.ok) {
  throw new Error(await response.text());
}

const result = await response.json();
const conversationId = result.conversation_id;
console.log('Save this ID for later messages:', conversationId);

Send the next message to the same number

For a text reply, pass the saved conversation_id. For another approved template, you can pass that ID too, or send the same phone again; Wa-Wexa will find the existing contact and conversation in the same workspace. Phone-only sends are for templates, not free-form text. Replace conversation-uuid below with the actual ID from the first successful response.

{
  "conversation_id": "conversation-uuid",
  "message_type": "text",
  "content_text": "Hello again"
}
await fetch('https://wawexa.com/api/whatsapp/send', {
  method: 'POST',
  headers: {
    'Authorization': 'Bearer wawexa_live_your_api_key',
    'Content-Type': 'application/json'
  },
  body: JSON.stringify({
    conversation_id: conversationId,
    message_type: 'text',
    content_text: 'Hello again'
  })
})
POST/api/whatsapp/conversations

API-key or session-authenticated shortcut that finds or creates a contact and conversation, then sends an approved template.

Required fields

  • conversation_id — existing conversation UUID, or phone — E.164 recipient number
  • message_type — text, image, video, audio, document, location, or contact
  • content_text — required for text messages

Response

{
  "success": true,
  "conversation_id": "conversation-uuid",
  "contact_id": "contact-uuid",
  "message_id": "message-uuid",
  "whatsapp_message_id": "wamid..."
}
Choose the recipient fieldUse conversation_id for replies and non-template messages in an existing thread. Use phone only with message_type: 'template'to start a conversation. Do not send both fields; all contact and conversation lookups remain scoped to the API key's workspace.

What each ID means

conversation_idis Wa-Wexa's UUID for the customer thread; use it as the recipient context for later sends. message_id identifies the saved message row in Wa-Wexa. whatsapp_message_idis Meta's wamid for that individual WhatsApp message and is useful for matching delivery-status callbacks. Do not use either message ID as a conversation_id. For template sends, use the approved template_name; the template UUID is for template management.

Existing customer threadUse conversation_id

Send conversation_id with template_name and the ordered template_params values.

fetch('/api/whatsapp/send', {
  method: 'POST',
  headers: {
    'Authorization': 'Bearer wawexa_live_your_api_key',
    'Content-Type': 'application/json'
  },
  body: JSON.stringify({
    conversation_id: 'conversation-uuid',
    message_type: 'template',
    template_name: 'welcome_message',
    template_params: ['Aarav']
  })
})
First message to a phone numberUse phone

Send an E.164 phone with message_type: 'template'. Wa-Wexa finds or creates the contact and conversation.

fetch('/api/whatsapp/send', {
  method: 'POST',
  headers: {
    'Authorization': 'Bearer wawexa_live_your_api_key',
    'Content-Type': 'application/json'
  },
  body: JSON.stringify({
    phone: '+919876XXXX',
    name: 'Aarav Sharma',
    message_type: 'template',
    template_name: 'welcome_message',
    template_params: ['Aarav', 'Wa-Wexa']
  })
})
Where template_id is usedUse the template UUID only for template management, such as POST /api/whatsapp/templates/submit with { template_id }. For sending, use the approved template's template_name; do not replace it with the template UUID.
Message request examplesChoose a framework and message type.
// app/api/wawexa/request/route.ts
export async function POST(request: Request) {
  const response = await fetch('https://wawexa.com/api/whatsapp/send', {
    method: 'POST',
      headers: {
        Authorization: `Bearer ${process.env.WAWEXA_API_KEY}`,
        'Content-Type': 'application/json',
      },
      body: JSON.stringify(await request.json()),
  });
  return Response.json(await response.json(), { status: response.status });
}
03 · Templates

Manage Marketing, Utility, and Authentication templates.

Create templates locally, submit them to Meta for review, synchronize approval status, and send approved templates using scoped API keys.

i
Required API-key permissions

Use templates:read to list templates, templates:write to create, submit, or synchronize them, and messages:send to send an approved template.

GET/api/whatsapp/templates

Lists Marketing, Utility, and Authentication templates. Optional query filters: category and status.

POST/api/whatsapp/templates

Creates a local Marketing, Utility, or Authentication template in Draft status.

POST/api/whatsapp/templates/submit

Submits a local template to Meta for review. Body: { template_id }.

POST/api/whatsapp/templates/sync

Synchronizes templates and approval statuses from Meta into Wa-Wexa.

POST/api/whatsapp/send

Sends an approved template with ordered values for {{1}}, {{2}}, and later placeholders. For phone-first sends, repeat the Idempotency-Key header after a timeout to receive the original result without sending twice.

Create a Utility template

const response = await fetch('/api/whatsapp/templates', {
  method: 'POST',
  headers: {
    'Authorization': 'Bearer wawexa_live_your_api_key',
    'Content-Type': 'application/json'
  },
  body: JSON.stringify({
    name: 'order_update',
    category: 'Utility',
    language: 'en_US',
    body_text: 'Order {{1}} will arrive on {{2}}.',
    variable_samples: ['ORD-1001', '25 Sep 2026']
  })
})

const { template, next_step } = await response.json()
Utility variablesMeta stores numbered placeholders, not field names. Supply them sequentially from {{1}}, and send actual order, delivery, appointment, invoice, or account values later in template_params.

Create an Authentication template

const response = await fetch('/api/whatsapp/templates', {
  method: 'POST',
  headers: {
    'Authorization': 'Bearer wawexa_live_your_api_key',
    'Content-Type': 'application/json'
  },
  body: JSON.stringify({
    name: 'login_code',
    category: 'Authentication',
    language: 'en_US',
    body_text: 'Your verification code is {{1}}.',
    authentication: {
      buttonType: 'copy_code',
      addSecurityRecommendation: true,
      codeExpirationMinutes: 10,
      copyCodeText: 'Copy Code'
    }
  })
})

const { template } = await response.json()

Authentication templates must contain exactly one {{1}} verification-code variable. Set buttonType to copy_code, one_tap, or none. One-tap also requires packageName and signatureHash.

Submit and synchronize

await fetch('/api/whatsapp/templates/submit', {
  method: 'POST',
  headers: {
    'Authorization': 'Bearer wawexa_live_your_api_key',
    'Content-Type': 'application/json'
  },
  body: JSON.stringify({ template_id: 'template-uuid' })
})

Submission returns Meta's template ID and review status. Call POST /api/whatsapp/templates/sync later to refresh Pending, Approved, or Rejected status.

Send an approved Utility template

fetch('/api/whatsapp/send', {
  method: 'POST',
  headers: {
    'Authorization': 'Bearer wawexa_live_your_api_key',
    'Content-Type': 'application/json'
  },
  body: JSON.stringify({
    conversation_id: 'conversation-uuid',
    message_type: 'template',
    template_name: 'welcome_message',
    template_params: ['Aarav', 'Wa-Wexa']
  })
})

Send an approved Authentication code

fetch('/api/whatsapp/send', {
  method: 'POST',
  headers: {
    'Authorization': 'Bearer wawexa_live_your_api_key',
    'Content-Type': 'application/json'
  },
  body: JSON.stringify({
    conversation_id: 'conversation-uuid',
    message_type: 'template',
    template_name: 'login_code',
    template_params: ['482913']
  })
})

Send a template from your framework

// app/api/wawexa/send/route.ts
export async function POST(request: Request) {
  const { template_name, template_params = [] } = await request.json();
  const response = await fetch(
    'https://wawexa.com/api/whatsapp/send',
    {
      method: 'POST',
      headers: {
        Authorization: `Bearer ${process.env.WAWEXA_API_KEY}`,
        'Content-Type': 'application/json',
      },
      body: JSON.stringify({
        phone: '+919876XXXX',
        message_type: 'template',
        template_name,
        template_params,
      }),
    },
  );
  return Response.json(await response.json(), { status: response.status });
}
Do not send the mobile number as a template parametertemplate_paramscontains only the values for the approved template's body variables. Forlogin_code, [482913] replaces{{1}}. The recipient phone number is supplied in phonefor a first send, or is already stored on the conversation's contact when usingconversation_id.
Parameter orderThe first entry in template_params replaces {{1}}, the second replaces {{2}}, and so on. The WhatsApp access token remains encrypted in the workspace configuration.
Template API examplesCreate, submit, synchronize, and send templates.
// app/api/wawexa/request/route.ts
export async function POST(request: Request) {
  const response = await fetch('https://wawexa.com/api/whatsapp/send', {
    method: 'POST',
      headers: {
        Authorization: `Bearer ${process.env.WAWEXA_API_KEY}`,
        'Content-Type': 'application/json',
      },
      body: JSON.stringify(await request.json()),
  });
  return Response.json(await response.json(), { status: response.status });
}
04 · Message status

Track delivery and read events.

Meta posts delivery lifecycle events to the webhook. Wa-Wexa mirrors them onto message and broadcast-recipient records.

POST/api/whatsapp/webhook

Receives signed Meta status events such as sent, delivered, read, and failed.

sentdeliveredreadfailedreplied
i
Status is event-driven, not CRUD

Meta sends status events to the configured webhook. Your application reads the resulting status from Wa-Wexa records; there is no customer-facing Create, Update, or Delete request for a delivery event.

For application data, read the messages.status or broadcast_recipients.status fields through the authenticated Wa-Wexa API.

05 · Contacts

Keep your audience in sync.

Contacts are managed in your Wa-Wexa workspace. Use the authenticated Wa-Wexa API so workspace permissions remain in control of every read and write.

GET/api/contacts

List contacts available to the authenticated workspace.

POST/api/contacts

Create a contact with a phone number and optional profile fields.

PATCH/api/contacts/:id

Update a contact profile.

DELETE/api/contacts/:id

Delete a contact permitted by workspace policy.

const response = await fetch('/api/contacts', {
  headers: {
    'Authorization': 'Bearer wawexa_live_your_api_key'
  }
})

const { contacts } = await response.json()

CRUD request examples

Choose a framework and operation. These examples use the Contacts API; the same authentication pattern applies to templates, automations, and flows.

Contacts CRUD examplesChoose your framework and request type.
// app/api/wawexa/contacts/route.ts
export async function POST(request: Request) {
  const body = await request.json();
  const response = await fetch('https://wawexa.com/api/contacts', {
    method: 'POST',
    headers: {
      Authorization: `Bearer ${process.env.WAWEXA_API_KEY}`,
      'Content-Type': 'application/json',
    },
    body: JSON.stringify(body),
  });
  return Response.json(await response.json(), { status: response.status });
}
Keep API keys privateReact, Angular, and Flutter apps must call your own backend proxy. Do not ship a Wa-Wexa API key in browser or mobile code. The Next.js examples use a server route andprocess.env.WAWEXA_API_KEY.
06 · Automations

Trigger actions without extra glue.

Create and manage keyword, event, and time-based automation rules. Activation validates the trigger and step configuration.

GET/api/automations

List automations in the authenticated workspace.

POST/api/automations

Create a draft or validated active automation.

GET/api/automations/:id

Fetch one automation and its step tree.

PATCH/api/automations/:id

Update automation settings or steps.

DELETE/api/automations/:id

Delete an automation.

fetch('/api/automations', {
  method: 'POST',
  headers: {
    'Authorization': 'Bearer wawexa_live_your_api_key',
    'Content-Type': 'application/json'
  },
  body: JSON.stringify({
    name: 'New lead follow-up',
    trigger_type: 'keyword',
    trigger_config: { keyword: 'pricing' },
    is_active: false,
    steps: []
  })
})
Automation CRUD examplesCreate, read, update, and delete automations.
// app/api/wawexa/request/route.ts
export async function POST(request: Request) {
  const response = await fetch('https://wawexa.com/api/automations', {
    method: 'POST',
      headers: {
        Authorization: `Bearer ${process.env.WAWEXA_API_KEY}`,
        'Content-Type': 'application/json',
      },
      body: JSON.stringify(await request.json()),
  });
  return Response.json(await response.json(), { status: response.status });
}

Trigger a personalized Utility automation

Create an automation with the External Eventtrigger and event name order.shipped. In its Send Template step, map {{1}} to {{vars.order_id}} and {{2}} to {{vars.delivery_date}}.

fetch('/api/automations/engine', {
  method: 'POST',
  headers: {
    'Authorization': 'Bearer wawexa_live_your_api_key',
    'Content-Type': 'application/json'
  },
  body: JSON.stringify({
    event_name: 'order.shipped',
    phone: '+919876XXXX',
    contact_name: 'Aarav',
    variables: {
      order_id: 'ORD-8451',
      delivery_date: '18 September 2026'
    }
  })
})

Trigger an Authentication template

Create an External Event automation named auth.otp_requested, select the approved Authentication template, and map {{1}} to {{vars.otp_code}}. Generate, expire, and verify the OTP in your authentication server; Wa-Wexa handles delivery.

fetch('/api/automations/engine', {
  method: 'POST',
  headers: {
    'Authorization': 'Bearer wawexa_live_your_api_key',
    'Content-Type': 'application/json'
  },
  body: JSON.stringify({
    event_name: 'auth.otp_requested',
    phone: '+919876XXXX',
    variables: {
      otp_code: '482913'
    }
  })
})
Contact handlingSupply either contact_id or an international phone. When phone is used, Wa-Wexa finds or creates the contact and conversation before running the automation.
07 · Flows

Build guided conversations.

Flows are structured conversation journeys with triggers and nodes. They can be created as drafts, updated, published, and deleted from the flow API.

GET/api/flows

List flows owned by the authenticated workspace.

POST/api/flows

Create a draft flow or clone a flow template.

GET/api/flows/:id

Fetch a flow and its nodes.

PUT/api/flows/:id

Replace flow settings and its node graph.

DELETE/api/flows/:id

Delete a flow and its related runs.

fetch('/api/flows', {
  method: 'POST',
  headers: {
    'Authorization': 'Bearer wawexa_live_your_api_key',
    'Content-Type': 'application/json'
  },
  body: JSON.stringify({
    name: 'Lead qualification',
    trigger_type: 'keyword',
    trigger_config: { keyword: 'start' }
  })
})
Flow CRUD examplesCreate, read, update, and delete guided flows.
// app/api/wawexa/request/route.ts
export async function POST(request: Request) {
  const response = await fetch('https://wawexa.com/api/flows', {
    method: 'POST',
      headers: {
        Authorization: `Bearer ${process.env.WAWEXA_API_KEY}`,
        'Content-Type': 'application/json',
      },
      body: JSON.stringify(await request.json()),
  });
  return Response.json(await response.json(), { status: response.status });
}
08 · Webhooks

Receive events securely.

Configure Meta to send WhatsApp messages and status updates to this endpoint. Wa-Wexa verifies the HMAC signature before processing the event.

GET/api/whatsapp/webhook

Handles Meta webhook verification using hub.mode, hub.verify_token, and hub.challenge.

POST/api/whatsapp/webhook

Accepts signed Meta webhook payloads and returns { status: 'received' }.

POST https://your-wa-wexa-domain.com/api/whatsapp/webhook

Headers:
x-hub-signature-256: sha256=<meta-signature>
Content-Type: application/json
Webhook directionThis is an inbound Meta-to-Wa-Wexa request. Configure the endpoint in Meta, and keep signature verification on. Do not call this endpoint directly from Flutter, React.js, or Angular client code.
Security noteNever disable signature verification or expose the Meta app secret in browser code. Keep webhook secrets and private server credentials on the server.