# Zacx > Turn Every Conversation Into a Connection and Every Connection Into Growth Index: https://zacx.io/llms.txt # Zacx Public API > The Zacx Public API lets you send WhatsApp Business API messages, look up and update contacts, tag and assign them, and pull reports and wallet credits for your workspace. **Authentication.** Every request carries your workspace API key as a bearer token: `Authorization: Bearer `. Find or generate the key in the Zacx dashboard under **Settings → API**. **Phone numbers.** Always include the country code, for example `919999999999` for an Indian number. Endpoints that accept a leading `+` say so. **Responses.** Successful calls return `"status": "success"` with the result under `data` or a human-readable `message`. Failures return `"status": "error"` with a stable `code` you can branch on and a `message` for logs. Source: https://zacx.io/api/ · Markdown: https://zacx.io/api/index.md The Zacx Public API lets you send WhatsApp Business API messages, look up and update contacts, tag and assign them, and pull reports and wallet credits for your workspace. **Authentication.** Every request carries your workspace API key as a bearer token: `Authorization: Bearer `. Find or generate the key in the Zacx dashboard under **Settings → API**. **Phone numbers.** Always include the country code, for example `919999999999` for an Indian number. Endpoints that accept a leading `+` say so. **Responses.** Successful calls return `"status": "success"` with the result under `data` or a human-readable `message`. Failures return `"status": "error"` with a stable `code` you can branch on and a `message` for logs. Version: 1.0 ## Servers - `https://api.zacx.io/v1` ## Sections - [Messages](/api/tags/Messages) - [Chats](/api/tags/Chats) - [Contacts](/api/tags/Contacts) - [Custom Fields](/api/tags/Custom-Fields) - [Users](/api/tags/Users) - [Tags](/api/tags/Tags) - [Reports](/api/tags/Reports) - [Wallet](/api/tags/Wallet) # Get chat active window status > Tells you whether the 24-hour customer service window is open for a contact on a given WhatsApp API number. Free-form and interactive messages are only delivered while the window is `active`. Identify the contact by `phoneNumber` or `email`. If you send both, `phoneNumber` takes precedence. Source: https://zacx.io/api/chat/active/ · Markdown: https://zacx.io/api/chat/active/index.md Path: Zacx Public API › Chats `GET /chat/active` Tells you whether the 24-hour customer service window is open for a contact on a given WhatsApp API number. Free-form and interactive messages are only delivered while the window is `active`. Identify the contact by `phoneNumber` or `email`. If you send both, `phoneNumber` takes precedence. ## Authentication - `bearerAuth`, http, header `Authorization` ## Query parameters - `getChatActiveWindowStatus.query.wabaNumber` (string, required) — Your WhatsApp API number, with country code. - `getChatActiveWindowStatus.query.phoneNumber` (string, optional) — The contact's phone number, with country code. - `getChatActiveWindowStatus.query.email` (string, optional) — The contact's email address. Ignored when `phoneNumber` is present. - format `email` ## Code samples ### cURL ```curl curl --request GET \ --url 'https://api.zacx.io/v1/chat/active?wabaNumber=string' \ --header 'Authorization: Bearer ' ``` ### TypeScript ```typescript const url = 'https://api.zacx.io/v1/chat/active?wabaNumber=string'; const options = {method: 'GET', headers: {Authorization: 'Bearer '}}; fetch(url, options) .then(res => res.json()) .then(json => console.log(json)) .catch(err => console.error(err)); ``` ### Python ```python import requests url = "https://api.zacx.io/v1/chat/active?wabaNumber=string" headers = {"Authorization": "Bearer "} response = requests.get(url, headers=headers) print(response.text) ``` ## Responses ### 200 The window state for this contact. #### Example ```json { "status": "success", "data": { "status": "active" } } ``` - `getChatActiveWindowStatus.response.200.status` (string, required) - `getChatActiveWindowStatus.response.200.data` (object, required) - `getChatActiveWindowStatus.response.200.data.status` (string, required) — `active` when the contact messaged this number within the last 24 hours. - one of `"active"`, `"inactive"` ### 400 One or more parameters are missing or invalid. #### Example ```json { "status": "error", "code": "VALIDATION_FAILED", "message": "Parameters are not valid" } ``` - `getChatActiveWindowStatus.response.400.status` (string, required) - `getChatActiveWindowStatus.response.400.code` (string, required) — Stable machine-readable error code. - `getChatActiveWindowStatus.response.400.message` (string, required) — Human-readable explanation. # Add tags to a contact > Adds one or more existing workspace tags to a contact. If the contact does not exist yet it is created. Tags must already exist in the workspace; create them from the dashboard first. Source: https://zacx.io/api/contact/add-tags/ · Markdown: https://zacx.io/api/contact/add-tags/index.md Path: Zacx Public API › Contacts `POST /tags/add` Adds one or more existing workspace tags to a contact. If the contact does not exist yet it is created. Tags must already exist in the workspace; create them from the dashboard first. ## Authentication - `bearerAuth`, http, header `Authorization` ## Request body - `addContactTags.phoneNumber` (string, required) — The contact's phone number with country code. A leading `+` is accepted. - example `"+11234567890"` - `addContactTags.tags` (array, required) — Tag names. - example `["test-tag"]` ## Example request ```json { "phoneNumber": "+11234567890", "tags": [ "test-tag" ] } ``` ## Code samples ### cURL ```curl curl --request POST \ --url https://api.zacx.io/v1/tags/add \ --header 'Authorization: Bearer ' \ --header 'Content-Type: application/json' \ --data ' { "phoneNumber": "+11234567890", "tags": [ "test-tag" ] } ' ``` ### TypeScript ```typescript const url = 'https://api.zacx.io/v1/tags/add'; const options = { method: 'POST', headers: {'Content-Type': 'application/json', Authorization: 'Bearer '}, body: JSON.stringify({phoneNumber: '+11234567890', tags: ['test-tag']}) }; fetch(url, options) .then(res => res.json()) .then(json => console.log(json)) .catch(err => console.error(err)); ``` ### Python ```python import requests url = "https://api.zacx.io/v1/tags/add" payload = { "phoneNumber": "+11234567890", "tags": ["test-tag"] } headers = { "Content-Type": "application/json", "Authorization": "Bearer " } response = requests.post(url, json=payload, headers=headers) print(response.text) ``` ## Responses ### 200 The tags were processed. #### Example ```json { "status": "success", "message": "Tag successfully added to the contact" } ``` - `addContactTags.response.200.status` (string, required) - `addContactTags.response.200.message` (string, required) - `addContactTags.response.200.code` (string, optional) — Present when the call succeeded but changed nothing, for example `TAG_ALREADY_ASSOCIATED`. ### 404 The tag does not exist in this workspace. #### Example ```json { "status": "error", "code": "TAG_NOT_FOUND", "message": "Tag not found in workspace, please login to workspace and create tags" } ``` - `addContactTags.response.404.status` (string, required) - `addContactTags.response.404.code` (string, required) — Stable machine-readable error code. - `addContactTags.response.404.message` (string, required) — Human-readable explanation. # Assign users to a contact > Assigns one or more team members to a contact, identified by their login phone numbers. If the contact does not exist yet it is created. Source: https://zacx.io/api/contact/assign-users/ · Markdown: https://zacx.io/api/contact/assign-users/index.md Path: Zacx Public API › Contacts `POST /users/assign` Assigns one or more team members to a contact, identified by their login phone numbers. If the contact does not exist yet it is created. ## Authentication - `bearerAuth`, http, header `Authorization` ## Request body - `assignContactUsers.phoneNumber` (string, required) — The contact's phone number with country code. - example `"919999999990"` - `assignContactUsers.users` (array, required) — Login phone numbers of the team members. - example `["919100110151"]` ## Example request ```json { "phoneNumber": "919999999990", "users": [ "919100110151" ] } ``` ## Code samples ### cURL ```curl curl --request POST \ --url https://api.zacx.io/v1/users/assign \ --header 'Authorization: Bearer ' \ --header 'Content-Type: application/json' \ --data ' { "phoneNumber": "919999999990", "users": [ "919100110151" ] } ' ``` ### TypeScript ```typescript const url = 'https://api.zacx.io/v1/users/assign'; const options = { method: 'POST', headers: {'Content-Type': 'application/json', Authorization: 'Bearer '}, body: JSON.stringify({phoneNumber: '919999999990', users: ['919100110151']}) }; fetch(url, options) .then(res => res.json()) .then(json => console.log(json)) .catch(err => console.error(err)); ``` ### Python ```python import requests url = "https://api.zacx.io/v1/users/assign" payload = { "phoneNumber": "919999999990", "users": ["919100110151"] } headers = { "Content-Type": "application/json", "Authorization": "Bearer " } response = requests.post(url, json=payload, headers=headers) print(response.text) ``` ## Responses ### 200 The assignment was processed. #### Example ```json { "status": "success", "message": "User successfully added to the contact" } ``` - `assignContactUsers.response.200.status` (string, required) - `assignContactUsers.response.200.message` (string, required) - `assignContactUsers.response.200.code` (string, optional) — Present when the call succeeded but changed nothing, for example `TAG_ALREADY_ASSOCIATED`. ### 404 The user does not exist in this workspace. #### Example ```json { "status": "error", "code": "USER_NOT_FOUND", "message": "User not found in workspace" } ``` - `assignContactUsers.response.404.status` (string, required) - `assignContactUsers.response.404.code` (string, required) — Stable machine-readable error code. - `assignContactUsers.response.404.message` (string, required) — Human-readable explanation. # Get a contact > Looks up one contact by phone number or email. Send the phone number with its country code and without the leading `+`. Source: https://zacx.io/api/contact/get/ · Markdown: https://zacx.io/api/contact/get/index.md Path: Zacx Public API › Contacts `GET /contact` Looks up one contact by phone number or email. Send the phone number with its country code and without the leading `+`. ## Authentication - `bearerAuth`, http, header `Authorization` ## Query parameters - `getContact.query.phoneNumber` (string, optional) — The contact's phone number with country code, without `+`. - `getContact.query.email` (string, optional) — The contact's email address. - format `email` ## Code samples ### cURL ```curl curl --request GET \ --url https://api.zacx.io/v1/contact \ --header 'Authorization: Bearer ' ``` ### TypeScript ```typescript const url = 'https://api.zacx.io/v1/contact'; const options = {method: 'GET', headers: {Authorization: 'Bearer '}}; fetch(url, options) .then(res => res.json()) .then(json => console.log(json)) .catch(err => console.error(err)); ``` ### Python ```python import requests url = "https://api.zacx.io/v1/contact" headers = {"Authorization": "Bearer "} response = requests.get(url, headers=headers) print(response.text) ``` ## Responses ### 200 The contact. #### Example ```json { "data": { "name": "Testing Contact", "email": "testingcontact@example.com", "phone": "919999999999", "customFields": [ { "name": "test field", "value": "custom field value" } ], "tags": [ "test-tag" ], "assignedUsers": [ { "name": "Meta Inc", "phoneNumber": "+918989898989", "email": "support@zacx.io" } ] } } ``` - `getContact.response.200.data` (object, required) - `getContact.response.200.data.name` (string, optional) - `getContact.response.200.data.email` (string, optional) - format `email` - `getContact.response.200.data.phone` (string, optional) — Phone number with country code. - example `"919999999999"` - `getContact.response.200.data.customFields` (array, optional) - `getContact.response.200.data.customFields.name` (string, optional) - example `"test field"` - `getContact.response.200.data.customFields.value` (string, optional) - example `"custom field value"` - `getContact.response.200.data.tags` (array, optional) - `getContact.response.200.data.assignedUsers` (array, optional) - `getContact.response.200.data.assignedUsers.name` (string, optional) - example `"Meta Inc"` - `getContact.response.200.data.assignedUsers.phoneNumber` (string, optional) - example `"+918989898989"` - `getContact.response.200.data.assignedUsers.email` (string, optional) - format `email`; example `"support@zacx.io"` ### 400 The phone number is not in a valid format. #### Example ```json { "status": "error", "code": "VALIDATION_FAILED", "message": "Invalid phone number format" } ``` - `getContact.response.400.status` (string, required) - `getContact.response.400.code` (string, required) — Stable machine-readable error code. - `getContact.response.400.message` (string, required) — Human-readable explanation. ### 404 No contact matches the given identifier. #### Example ```json { "status": "error", "code": "CONTACT_NOT_FOUND", "message": "Contact not found" } ``` - `getContact.response.404.status` (string, required) - `getContact.response.404.code` (string, required) — Stable machine-readable error code. - `getContact.response.404.message` (string, required) — Human-readable explanation. # Remove tags from a contact > Removes one or more tags from an existing contact. Source: https://zacx.io/api/contact/remove-tags/ · Markdown: https://zacx.io/api/contact/remove-tags/index.md Path: Zacx Public API › Contacts `POST /tags/remove` Removes one or more tags from an existing contact. ## Authentication - `bearerAuth`, http, header `Authorization` ## Request body - `removeContactTags.phoneNumber` (string, required) — The contact's phone number with country code. A leading `+` is accepted. - example `"+11234567890"` - `removeContactTags.tags` (array, required) — Tag names. - example `["test-tag"]` ## Example request ```json { "phoneNumber": "+11234567890", "tags": [ "test-tag" ] } ``` ## Code samples ### cURL ```curl curl --request POST \ --url https://api.zacx.io/v1/tags/remove \ --header 'Authorization: Bearer ' \ --header 'Content-Type: application/json' \ --data ' { "phoneNumber": "+11234567890", "tags": [ "test-tag" ] } ' ``` ### TypeScript ```typescript const url = 'https://api.zacx.io/v1/tags/remove'; const options = { method: 'POST', headers: {'Content-Type': 'application/json', Authorization: 'Bearer '}, body: JSON.stringify({phoneNumber: '+11234567890', tags: ['test-tag']}) }; fetch(url, options) .then(res => res.json()) .then(json => console.log(json)) .catch(err => console.error(err)); ``` ### Python ```python import requests url = "https://api.zacx.io/v1/tags/remove" payload = { "phoneNumber": "+11234567890", "tags": ["test-tag"] } headers = { "Content-Type": "application/json", "Authorization": "Bearer " } response = requests.post(url, json=payload, headers=headers) print(response.text) ``` ## Responses ### 200 The tags were processed. #### Example ```json { "status": "success", "message": "Tag successfully removed from the contact" } ``` - `removeContactTags.response.200.status` (string, required) - `removeContactTags.response.200.message` (string, required) - `removeContactTags.response.200.code` (string, optional) — Present when the call succeeded but changed nothing, for example `TAG_ALREADY_ASSOCIATED`. ### 404 The contact or the tag was not found. #### Example ```json { "status": "error", "code": "CONTACT_NOT_FOUND", "message": "The contact with given phoneNumber was not found." } ``` - `removeContactTags.response.404.status` (string, required) - `removeContactTags.response.404.code` (string, required) — Stable machine-readable error code. - `removeContactTags.response.404.message` (string, required) — Human-readable explanation. # Unassign users from a contact > Removes one or more team members from an existing contact. Source: https://zacx.io/api/contact/unassign-users/ · Markdown: https://zacx.io/api/contact/unassign-users/index.md Path: Zacx Public API › Contacts `POST /users/unassign` Removes one or more team members from an existing contact. ## Authentication - `bearerAuth`, http, header `Authorization` ## Request body - `unassignContactUsers.phoneNumber` (string, required) — The contact's phone number with country code. - example `"919999999990"` - `unassignContactUsers.users` (array, required) — Login phone numbers of the team members. - example `["919100110151"]` ## Example request ```json { "phoneNumber": "919999999990", "users": [ "919100110151" ] } ``` ## Code samples ### cURL ```curl curl --request POST \ --url https://api.zacx.io/v1/users/unassign \ --header 'Authorization: Bearer ' \ --header 'Content-Type: application/json' \ --data ' { "phoneNumber": "919999999990", "users": [ "919100110151" ] } ' ``` ### TypeScript ```typescript const url = 'https://api.zacx.io/v1/users/unassign'; const options = { method: 'POST', headers: {'Content-Type': 'application/json', Authorization: 'Bearer '}, body: JSON.stringify({phoneNumber: '919999999990', users: ['919100110151']}) }; fetch(url, options) .then(res => res.json()) .then(json => console.log(json)) .catch(err => console.error(err)); ``` ### Python ```python import requests url = "https://api.zacx.io/v1/users/unassign" payload = { "phoneNumber": "919999999990", "users": ["919100110151"] } headers = { "Content-Type": "application/json", "Authorization": "Bearer " } response = requests.post(url, json=payload, headers=headers) print(response.text) ``` ## Responses ### 200 The unassignment was processed. #### Example ```json { "status": "success", "message": "User successfully unassigned from the contact" } ``` - `unassignContactUsers.response.200.status` (string, required) - `unassignContactUsers.response.200.message` (string, required) - `unassignContactUsers.response.200.code` (string, optional) — Present when the call succeeded but changed nothing, for example `TAG_ALREADY_ASSOCIATED`. ### 404 The contact or the user was not found. #### Example ```json { "status": "error", "code": "CONTACT_NOT_FOUND", "message": "The contact with given phoneNumber was not found." } ``` - `unassignContactUsers.response.404.status` (string, required) - `unassignContactUsers.response.404.code` (string, required) — Stable machine-readable error code. - `unassignContactUsers.response.404.message` (string, required) — Human-readable explanation. # Create or update a contact > Creates the contact if it does not exist, otherwise updates it. The match is made on `phoneNumber` first, then `email`. `customFields` are addressed by `customFieldId`; get the ids from **List custom fields**. `assignedUsers` takes the login phone numbers of your team members. Source: https://zacx.io/api/contact/upsert/ · Markdown: https://zacx.io/api/contact/upsert/index.md Path: Zacx Public API › Contacts `PUT /contact/upsert` Creates the contact if it does not exist, otherwise updates it. The match is made on `phoneNumber` first, then `email`. `customFields` are addressed by `customFieldId`; get the ids from **List custom fields**. `assignedUsers` takes the login phone numbers of your team members. ## Authentication - `bearerAuth`, http, header `Authorization` ## Request body - `upsertContact.name` (string, optional) - example `"John Doe"` - `upsertContact.email` (string, optional) - format `email`; example `"john@example.com"` - `upsertContact.phoneNumber` (string, optional) — Phone number with country code. A leading `+` is accepted. - example `"+11234567890"` - `upsertContact.customFields` (array, optional) - `upsertContact.customFields.customFieldId` (string, required) — Id from **List custom fields**. - format `uuid` - `upsertContact.customFields.value` (string, required) - `upsertContact.tags` (array, optional) — Tag names. Must already exist in the workspace. - `upsertContact.assignedUsers` (array, optional) — Login phone numbers of team members to assign. ## Example request ```json { "name": "John Doe", "email": "john@example.com", "phoneNumber": "+11234567890", "customFields": [ { "customFieldId": "7149ce0d-616c-46ca-8e09-cd00129fe947", "value": "field value 1" }, { "customFieldId": "f6a3b468-3678-4c4d-bdd9-724e9f4c9fa9", "value": "field value 2" } ], "tags": [ "VIP", "Premium" ], "assignedUsers": [ "919100110151", "919100110152" ] } ``` ## Code samples ### cURL ```curl curl --request PUT \ --url https://api.zacx.io/v1/contact/upsert \ --header 'Authorization: Bearer ' \ --header 'Content-Type: application/json' \ --data ' { "name": "John Doe", "email": "john@example.com", "phoneNumber": "+11234567890", "customFields": [ { "customFieldId": "7149ce0d-616c-46ca-8e09-cd00129fe947", "value": "field value 1" }, { "customFieldId": "f6a3b468-3678-4c4d-bdd9-724e9f4c9fa9", "value": "field value 2" } ], "tags": [ "VIP", "Premium" ], "assignedUsers": [ "919100110151", "919100110152" ] } ' ``` ### TypeScript ```typescript const url = 'https://api.zacx.io/v1/contact/upsert'; const options = { method: 'PUT', headers: {'Content-Type': 'application/json', Authorization: 'Bearer '}, body: JSON.stringify({ name: 'John Doe', email: 'john@example.com', phoneNumber: '+11234567890', customFields: [ {customFieldId: '7149ce0d-616c-46ca-8e09-cd00129fe947', value: 'field value 1'}, {customFieldId: 'f6a3b468-3678-4c4d-bdd9-724e9f4c9fa9', value: 'field value 2'} ], tags: ['VIP', 'Premium'], assignedUsers: ['919100110151', '919100110152'] }) }; fetch(url, options) .then(res => res.json()) .then(json => console.log(json)) .catch(err => console.error(err)); ``` ### Python ```python import requests url = "https://api.zacx.io/v1/contact/upsert" payload = { "name": "John Doe", "email": "john@example.com", "phoneNumber": "+11234567890", "customFields": [ { "customFieldId": "7149ce0d-616c-46ca-8e09-cd00129fe947", "value": "field value 1" }, { "customFieldId": "f6a3b468-3678-4c4d-bdd9-724e9f4c9fa9", "value": "field value 2" } ], "tags": ["VIP", "Premium"], "assignedUsers": ["919100110151", "919100110152"] } headers = { "Content-Type": "application/json", "Authorization": "Bearer " } response = requests.put(url, json=payload, headers=headers) print(response.text) ``` ## Responses ### 200 The contact after the write. #### Example ```json { "status": "success", "data": { "name": "John Doe", "phoneNumber": "11234567890", "email": "john@example.com", "customFields": [ { "name": "Test Field", "value": "field value 1" }, { "name": "Custom Field 2", "value": "field value 2" } ], "tags": [ "VIP", "Premium" ], "assignedUsers": [ "User 1", "User 2" ] } } ``` - `upsertContact.response.200.status` (string, required) - `upsertContact.response.200.data` (object, required) - `upsertContact.response.200.data.name` (string, optional) - `upsertContact.response.200.data.phoneNumber` (string, optional) - `upsertContact.response.200.data.email` (string, optional) - format `email` - `upsertContact.response.200.data.customFields` (array, optional) - `upsertContact.response.200.data.customFields.name` (string, optional) - example `"test field"` - `upsertContact.response.200.data.customFields.value` (string, optional) - example `"custom field value"` - `upsertContact.response.200.data.tags` (array, optional) - `upsertContact.response.200.data.assignedUsers` (array, optional) — Display names of the assigned users. ### 400 One or more parameters are missing or invalid. #### Example ```json { "status": "error", "code": "VALIDATION_FAILED", "message": "Parameters are not valid" } ``` - `upsertContact.response.400.status` (string, required) - `upsertContact.response.400.code` (string, required) — Stable machine-readable error code. - `upsertContact.response.400.message` (string, required) — Human-readable explanation. # List custom fields > Returns every custom field (CRM column) in the workspace, with the ids you need for **Create or update a contact**. Source: https://zacx.io/api/custom-fields/list/ · Markdown: https://zacx.io/api/custom-fields/list/index.md Path: Zacx Public API › Custom Fields `GET /customFields` Returns every custom field (CRM column) in the workspace, with the ids you need for **Create or update a contact**. ## Authentication - `bearerAuth`, http, header `Authorization` ## Code samples ### cURL ```curl curl --request GET \ --url https://api.zacx.io/v1/customFields \ --header 'Authorization: Bearer ' ``` ### TypeScript ```typescript const url = 'https://api.zacx.io/v1/customFields'; const options = {method: 'GET', headers: {Authorization: 'Bearer '}}; fetch(url, options) .then(res => res.json()) .then(json => console.log(json)) .catch(err => console.error(err)); ``` ### Python ```python import requests url = "https://api.zacx.io/v1/customFields" headers = {"Authorization": "Bearer "} response = requests.get(url, headers=headers) print(response.text) ``` ## Responses ### 200 The custom fields. `data` is empty when none are configured. #### Example ```json { "status": "success", "data": [ { "id": "c79996c1-af9f-4353-810f-153417ec34cf", "name": "test field", "type": "single_line" } ] } ``` - `listCustomFields.response.200.status` (string, required) - `listCustomFields.response.200.data` (array, required) - `listCustomFields.response.200.data.id` (string, required) - format `uuid` - `listCustomFields.response.200.data.name` (string, required) - example `"test field"` - `listCustomFields.response.200.data.type` (string, required) — Field type as configured in the CRM. - example `"single_line"` - `listCustomFields.response.200.message` (string, optional) — Present only when the workspace has no custom fields. # Send a message > Sends one WhatsApp message to one recipient. The `type` field selects the message kind and decides which other fields apply: | `type` | When to use | Chat window required | |---|---|---| | `template` | Approved WhatsApp templates. Works at any time. | No | | `text`, `image`, `document`, `audio`, `location` | Free-form messages inside an open conversation. | Yes | | `interactive` | Reply buttons or a list menu inside an open conversation. | Yes | Media URLs (`url`) must be publicly accessible. For templates, only pass the `header` object when the template has a header, only pass `body` when the template has body variables, and only pass `buttons` when a button carries a variable (for example a dynamic **Visit website** URL). Source: https://zacx.io/api/message/send/ · Markdown: https://zacx.io/api/message/send/index.md Path: Zacx Public API › Messages `POST /message/send` Sends one WhatsApp message to one recipient. The `type` field selects the message kind and decides which other fields apply: | `type` | When to use | Chat window required | |---|---|---| | `template` | Approved WhatsApp templates. Works at any time. | No | | `text`, `image`, `document`, `audio`, `location` | Free-form messages inside an open conversation. | Yes | | `interactive` | Reply buttons or a list menu inside an open conversation. | Yes | Media URLs (`url`) must be publicly accessible. For templates, only pass the `header` object when the template has a header, only pass `body` when the template has body variables, and only pass `buttons` when a button carries a variable (for example a dynamic **Visit website** URL). ## Authentication - `bearerAuth`, http, header `Authorization` ## Request body One of: - [TemplateMessage](/api/schemas/TemplateMessage) - [TextMessage](/api/schemas/TextMessage) - [ImageMessage](/api/schemas/ImageMessage) - [DocumentMessage](/api/schemas/DocumentMessage) - [AudioMessage](/api/schemas/AudioMessage) - [LocationMessage](/api/schemas/LocationMessage) - [InteractiveMessage](/api/schemas/InteractiveMessage) Discriminator: `type` - `template` → [TemplateMessage](/api/schemas/TemplateMessage) - `text` → [TextMessage](/api/schemas/TextMessage) - `image` → [ImageMessage](/api/schemas/ImageMessage) - `document` → [DocumentMessage](/api/schemas/DocumentMessage) - `audio` → [AudioMessage](/api/schemas/AudioMessage) - `location` → [LocationMessage](/api/schemas/LocationMessage) - `interactive` → [InteractiveMessage](/api/schemas/InteractiveMessage) ## Example request ```json { "wabaNumber": "919705182126", "recipient": { "phoneNumber": "919999999999" }, "type": "template", "template": { "name": "confirmation", "language": "en", "header": { "text": "Welcome" }, "body": [ "John", "Premium Plan" ], "buttons": [ "button1_param" ] } } ``` ## Code samples ### cURL ```curl curl --request POST \ --url https://api.zacx.io/v1/message/send \ --header 'Authorization: Bearer ' \ --header 'Content-Type: application/json' \ --data ' { "wabaNumber": "919705182126", "recipient": { "phoneNumber": "919999999999" }, "type": "template", "template": { "name": "confirmation", "language": "en", "header": { "text": "Welcome" }, "body": [ "John", "Premium Plan" ], "buttons": [ "button1_param" ] } } ' ``` ### TypeScript ```typescript const url = 'https://api.zacx.io/v1/message/send'; const options = { method: 'POST', headers: {'Content-Type': 'application/json', Authorization: 'Bearer '}, body: JSON.stringify({ wabaNumber: '919705182126', recipient: {phoneNumber: '919999999999'}, type: 'template', template: { name: 'confirmation', language: 'en', header: {text: 'Welcome'}, body: JSON.stringify(['John', 'Premium Plan']), buttons: ['button1_param'] } }) }; fetch(url, options) .then(res => res.json()) .then(json => console.log(json)) .catch(err => console.error(err)); ``` ### Python ```python import requests url = "https://api.zacx.io/v1/message/send" payload = { "wabaNumber": "919705182126", "recipient": { "phoneNumber": "919999999999" }, "type": "template", "template": { "name": "confirmation", "language": "en", "header": { "text": "Welcome" }, "body": ["John", "Premium Plan"], "buttons": ["button1_param"] } } headers = { "Content-Type": "application/json", "Authorization": "Bearer " } response = requests.post(url, json=payload, headers=headers) print(response.text) ``` ## Responses ### 200 The message was accepted. Keep the returned message id to poll delivery status. #### Example ```json { "status": "success", "data": { "messageId": "wamid.HBgMOTE5Mjk2MzA0MjI0FQIAERgSMUZDNzgzMjJFNzEwMTkwRjY3AA==" } } ``` - `sendMessage.response.200.status` (string, optional) - `sendMessage.response.200.data` (object, optional) - `sendMessage.response.200.data.messageId` (string, optional) — The WhatsApp message id (`wamid`). Pass it to **Get message status**. - example `"wamid.HBgMOTE5Mjk2MzA0MjI0FQIAERgSMUZDNzgzMjJFNzEwMTkwRjY3AA=="` ### 400 One or more parameters are missing or invalid. #### Example ```json { "status": "error", "code": "VALIDATION_FAILED", "message": "Parameters are not valid" } ``` - `sendMessage.response.400.status` (string, required) - `sendMessage.response.400.code` (string, required) — Stable machine-readable error code. - `sendMessage.response.400.message` (string, required) — Human-readable explanation. ### 401 The API key is missing or invalid. #### Example ```json { "status": "error", "code": "VALIDATION_FAILED", "message": "string" } ``` - `sendMessage.response.401.status` (string, required) - `sendMessage.response.401.code` (string, required) — Stable machine-readable error code. - `sendMessage.response.401.message` (string, required) — Human-readable explanation. # Get message status > Returns the current delivery status of a message you sent through the API. The input is the WhatsApp message id (`wamid`) returned by **Send a message**. Source: https://zacx.io/api/message/status/ · Markdown: https://zacx.io/api/message/status/index.md Path: Zacx Public API › Messages `GET /message/status` Returns the current delivery status of a message you sent through the API. The input is the WhatsApp message id (`wamid`) returned by **Send a message**. ## Authentication - `bearerAuth`, http, header `Authorization` ## Query parameters - `getMessageStatus.query.messageId` (string, required) — The WhatsApp message id (`wamid`) returned when the message was sent. ## Code samples ### cURL ```curl curl --request GET \ --url 'https://api.zacx.io/v1/message/status?messageId=string' \ --header 'Authorization: Bearer ' ``` ### TypeScript ```typescript const url = 'https://api.zacx.io/v1/message/status?messageId=string'; const options = {method: 'GET', headers: {Authorization: 'Bearer '}}; fetch(url, options) .then(res => res.json()) .then(json => console.log(json)) .catch(err => console.error(err)); ``` ### Python ```python import requests url = "https://api.zacx.io/v1/message/status?messageId=string" headers = {"Authorization": "Bearer "} response = requests.get(url, headers=headers) print(response.text) ``` ## Responses ### 200 The message was found. #### Example ```json { "status": "success", "data": { "status": "delivered" } } ``` - `getMessageStatus.response.200.status` (string, required) - `getMessageStatus.response.200.data` (object, required) - `getMessageStatus.response.200.data.status` (string, required) — Delivery state of a message, in the order WhatsApp reports them. - one of `"queued"`, `"sent"`, `"delivered"`, `"read"`, `"failed"` ### 400 One or more parameters are missing or invalid. #### Example ```json { "status": "error", "code": "VALIDATION_FAILED", "message": "Parameters are not valid" } ``` - `getMessageStatus.response.400.status` (string, required) - `getMessageStatus.response.400.code` (string, required) — Stable machine-readable error code. - `getMessageStatus.response.400.message` (string, required) — Human-readable explanation. ### 404 No message matches the given id. #### Example ```json { "status": "error", "code": "MESSAGE_NOT_FOUND", "message": "Message was not found with the given messageId" } ``` - `getMessageStatus.response.404.status` (string, required) - `getMessageStatus.response.404.code` (string, required) — Stable machine-readable error code. - `getMessageStatus.response.404.message` (string, required) — Human-readable explanation. # AudioMessage > An audio clip from a public URL. Requires an active chat window. Source: https://zacx.io/api/schemas/AudioMessage/ · Markdown: https://zacx.io/api/schemas/AudioMessage/index.md Path: Zacx Public API An audio clip from a public URL. Requires an active chat window. ## Fields - `AudioMessage.wabaNumber` (string, required) — Your WhatsApp API number to send from, with country code. - example `"919705182126"` - `AudioMessage.recipient` (object, required) - `AudioMessage.recipient.phoneNumber` (string, required) — The contact's phone number, with country code. - example `"919999999999"` - `AudioMessage.recipient.name` (string, optional) — Optional display name, saved to the contact if it is new. - example `"Raj S"` - `AudioMessage.recipient.email` (string, optional) — Optional email, saved to the contact if it is new. - format `email` - `AudioMessage.type` (unknown, required) - `AudioMessage.url` (string, required) — Public URL of the audio file. - format `uri`; example `"https://example.com/sample.mp3"` # Contact Source: https://zacx.io/api/schemas/Contact/ · Markdown: https://zacx.io/api/schemas/Contact/index.md Path: Zacx Public API ## Fields - `Contact.name` (string, optional) - `Contact.email` (string, optional) - format `email` - `Contact.phone` (string, optional) — Phone number with country code. - example `"919999999999"` - `Contact.customFields` (array, optional) - `Contact.customFields.name` (string, optional) - example `"test field"` - `Contact.customFields.value` (string, optional) - example `"custom field value"` - `Contact.tags` (array, optional) - `Contact.assignedUsers` (array, optional) - `Contact.assignedUsers.name` (string, optional) - example `"Meta Inc"` - `Contact.assignedUsers.phoneNumber` (string, optional) - example `"+918989898989"` - `Contact.assignedUsers.email` (string, optional) - format `email`; example `"support@zacx.io"` # ContactTagsRequest Source: https://zacx.io/api/schemas/ContactTagsRequest/ · Markdown: https://zacx.io/api/schemas/ContactTagsRequest/index.md Path: Zacx Public API ## Fields - `ContactTagsRequest.phoneNumber` (string, required) — The contact's phone number with country code. A leading `+` is accepted. - example `"+11234567890"` - `ContactTagsRequest.tags` (array, required) — Tag names. - example `["test-tag"]` # ContactUpsertRequest > At least one of `phoneNumber` or `email` is required to identify the contact. Source: https://zacx.io/api/schemas/ContactUpsertRequest/ · Markdown: https://zacx.io/api/schemas/ContactUpsertRequest/index.md Path: Zacx Public API At least one of `phoneNumber` or `email` is required to identify the contact. ## Fields - `ContactUpsertRequest.name` (string, optional) - example `"John Doe"` - `ContactUpsertRequest.email` (string, optional) - format `email`; example `"john@example.com"` - `ContactUpsertRequest.phoneNumber` (string, optional) — Phone number with country code. A leading `+` is accepted. - example `"+11234567890"` - `ContactUpsertRequest.customFields` (array, optional) - `ContactUpsertRequest.customFields.customFieldId` (string, required) — Id from **List custom fields**. - format `uuid` - `ContactUpsertRequest.customFields.value` (string, required) - `ContactUpsertRequest.tags` (array, optional) — Tag names. Must already exist in the workspace. - `ContactUpsertRequest.assignedUsers` (array, optional) — Login phone numbers of team members to assign. # ContactUpsertResult Source: https://zacx.io/api/schemas/ContactUpsertResult/ · Markdown: https://zacx.io/api/schemas/ContactUpsertResult/index.md Path: Zacx Public API ## Fields - `ContactUpsertResult.name` (string, optional) - `ContactUpsertResult.phoneNumber` (string, optional) - `ContactUpsertResult.email` (string, optional) - format `email` - `ContactUpsertResult.customFields` (array, optional) - `ContactUpsertResult.customFields.name` (string, optional) - example `"test field"` - `ContactUpsertResult.customFields.value` (string, optional) - example `"custom field value"` - `ContactUpsertResult.tags` (array, optional) - `ContactUpsertResult.assignedUsers` (array, optional) — Display names of the assigned users. # ContactUsersRequest Source: https://zacx.io/api/schemas/ContactUsersRequest/ · Markdown: https://zacx.io/api/schemas/ContactUsersRequest/index.md Path: Zacx Public API ## Fields - `ContactUsersRequest.phoneNumber` (string, required) — The contact's phone number with country code. - example `"919999999990"` - `ContactUsersRequest.users` (array, required) — Login phone numbers of the team members. - example `["919100110151"]` # CustomField Source: https://zacx.io/api/schemas/CustomField/ · Markdown: https://zacx.io/api/schemas/CustomField/index.md Path: Zacx Public API ## Fields - `CustomField.id` (string, required) - format `uuid` - `CustomField.name` (string, required) - example `"test field"` - `CustomField.type` (string, required) — Field type as configured in the CRM. - example `"single_line"` # CustomFieldValue Source: https://zacx.io/api/schemas/CustomFieldValue/ · Markdown: https://zacx.io/api/schemas/CustomFieldValue/index.md Path: Zacx Public API ## Fields - `CustomFieldValue.name` (string, optional) - example `"test field"` - `CustomFieldValue.value` (string, optional) - example `"custom field value"` # DeliveryStats Source: https://zacx.io/api/schemas/DeliveryStats/ · Markdown: https://zacx.io/api/schemas/DeliveryStats/index.md Path: Zacx Public API ## Fields - `DeliveryStats.sent` (integer, optional) - `DeliveryStats.delivered` (integer, optional) - `DeliveryStats.read` (integer, optional) - `DeliveryStats.failed` (integer, optional) - `DeliveryStats.replied` (integer, optional) # DocumentMessage > A file from a public URL. Requires an active chat window. Source: https://zacx.io/api/schemas/DocumentMessage/ · Markdown: https://zacx.io/api/schemas/DocumentMessage/index.md Path: Zacx Public API A file from a public URL. Requires an active chat window. ## Fields - `DocumentMessage.wabaNumber` (string, required) — Your WhatsApp API number to send from, with country code. - example `"919705182126"` - `DocumentMessage.recipient` (object, required) - `DocumentMessage.recipient.phoneNumber` (string, required) — The contact's phone number, with country code. - example `"919999999999"` - `DocumentMessage.recipient.name` (string, optional) — Optional display name, saved to the contact if it is new. - example `"Raj S"` - `DocumentMessage.recipient.email` (string, optional) — Optional email, saved to the contact if it is new. - format `email` - `DocumentMessage.type` (unknown, required) - `DocumentMessage.url` (string, required) — Public URL of the document. - format `uri`; example `"https://example.com/document.pdf"` - `DocumentMessage.filename` (string, required) — File name shown to the contact. - example `"report.pdf"` - `DocumentMessage.caption` (string, optional) - example `"Here's the report you requested"` # Error Source: https://zacx.io/api/schemas/Error/ · Markdown: https://zacx.io/api/schemas/Error/index.md Path: Zacx Public API ## Fields - `Error.status` (string, required) - `Error.code` (string, required) — Stable machine-readable error code. - `Error.message` (string, required) — Human-readable explanation. # ImageMessage > An image from a public URL, with an optional caption. Requires an active chat window. Source: https://zacx.io/api/schemas/ImageMessage/ · Markdown: https://zacx.io/api/schemas/ImageMessage/index.md Path: Zacx Public API An image from a public URL, with an optional caption. Requires an active chat window. ## Fields - `ImageMessage.wabaNumber` (string, required) — Your WhatsApp API number to send from, with country code. - example `"919705182126"` - `ImageMessage.recipient` (object, required) - `ImageMessage.recipient.phoneNumber` (string, required) — The contact's phone number, with country code. - example `"919999999999"` - `ImageMessage.recipient.name` (string, optional) — Optional display name, saved to the contact if it is new. - example `"Raj S"` - `ImageMessage.recipient.email` (string, optional) — Optional email, saved to the contact if it is new. - format `email` - `ImageMessage.type` (unknown, required) - `ImageMessage.url` (string, required) — Public URL of the image. - format `uri`; example `"https://example.com/demo.png"` - `ImageMessage.caption` (string, optional) - example `"Check out this image!"` # InteractiveButtons Source: https://zacx.io/api/schemas/InteractiveButtons/ · Markdown: https://zacx.io/api/schemas/InteractiveButtons/index.md Path: Zacx Public API ## Fields - `InteractiveButtons.type` (string, required) - `InteractiveButtons.body` (object, required) - `InteractiveButtons.body.text` (string, required) - example `"Please select an option"` - `InteractiveButtons.action` (object, required) - `InteractiveButtons.action.buttons` (array, required) — Up to three reply buttons. - `InteractiveButtons.action.buttons.type` (string, required) - `InteractiveButtons.action.buttons.reply` (object, required) - `InteractiveButtons.action.buttons.reply.id` (string, required) — Returned to you when the contact taps the button. - example `"btn_1"` - `InteractiveButtons.action.buttons.reply.title` (string, required) - example `"Option 1"` # InteractiveList Source: https://zacx.io/api/schemas/InteractiveList/ · Markdown: https://zacx.io/api/schemas/InteractiveList/index.md Path: Zacx Public API ## Fields - `InteractiveList.type` (string, required) - `InteractiveList.body` (object, required) - `InteractiveList.body.text` (string, required) - example `"Please choose from our menu"` - `InteractiveList.action` (object, required) - `InteractiveList.action.button` (string, required) — Label of the button that opens the list. - example `"View Menu"` - `InteractiveList.action.sections` (array, required) - `InteractiveList.action.sections.title` (string, required) - example `"Main Dishes"` - `InteractiveList.action.sections.rows` (array, required) - `InteractiveList.action.sections.rows.id` (string, required) — Returned to you when the contact picks the row. - example `"item_1"` - `InteractiveList.action.sections.rows.title` (string, required) - example `"Pasta"` - `InteractiveList.action.sections.rows.description` (string, optional) - example `"Italian pasta with tomato sauce"` # InteractiveMessage > Reply buttons or a list menu. Requires an active chat window. Source: https://zacx.io/api/schemas/InteractiveMessage/ · Markdown: https://zacx.io/api/schemas/InteractiveMessage/index.md Path: Zacx Public API Reply buttons or a list menu. Requires an active chat window. ## Fields - `InteractiveMessage.wabaNumber` (string, required) — Your WhatsApp API number to send from, with country code. - example `"919705182126"` - `InteractiveMessage.recipient` (object, required) - `InteractiveMessage.recipient.phoneNumber` (string, required) — The contact's phone number, with country code. - example `"919999999999"` - `InteractiveMessage.recipient.name` (string, optional) — Optional display name, saved to the contact if it is new. - example `"Raj S"` - `InteractiveMessage.recipient.email` (string, optional) — Optional email, saved to the contact if it is new. - format `email` - `InteractiveMessage.type` (unknown, required) - `InteractiveMessage.interactive` (one of, required) - one of: [InteractiveButtons](/api/schemas/InteractiveButtons), [InteractiveList](/api/schemas/InteractiveList) - discriminator: `type` # LocationMessage > A map pin. Requires an active chat window. Source: https://zacx.io/api/schemas/LocationMessage/ · Markdown: https://zacx.io/api/schemas/LocationMessage/index.md Path: Zacx Public API A map pin. Requires an active chat window. ## Fields - `LocationMessage.wabaNumber` (string, required) — Your WhatsApp API number to send from, with country code. - example `"919705182126"` - `LocationMessage.recipient` (object, required) - `LocationMessage.recipient.phoneNumber` (string, required) — The contact's phone number, with country code. - example `"919999999999"` - `LocationMessage.recipient.name` (string, optional) — Optional display name, saved to the contact if it is new. - example `"Raj S"` - `LocationMessage.recipient.email` (string, optional) — Optional email, saved to the contact if it is new. - format `email` - `LocationMessage.type` (unknown, required) - `LocationMessage.latitude` (number, required) - example `37.7749` - `LocationMessage.longitude` (number, required) - example `-122.4194` - `LocationMessage.name` (string, optional) — Label shown above the address. - example `"San Francisco"` - `LocationMessage.address` (string, optional) - example `"California, USA"` # MessageBase Source: https://zacx.io/api/schemas/MessageBase/ · Markdown: https://zacx.io/api/schemas/MessageBase/index.md Path: Zacx Public API ## Fields - `MessageBase.wabaNumber` (string, required) — Your WhatsApp API number to send from, with country code. - example `"919705182126"` - `MessageBase.recipient` (object, required) - `MessageBase.recipient.phoneNumber` (string, required) — The contact's phone number, with country code. - example `"919999999999"` - `MessageBase.recipient.name` (string, optional) — Optional display name, saved to the contact if it is new. - example `"Raj S"` - `MessageBase.recipient.email` (string, optional) — Optional email, saved to the contact if it is new. - format `email` - `MessageBase.type` (string, required) — The message kind. Decides which other fields apply. - one of `"template"`, `"text"`, `"image"`, `"document"`, `"audio"`, `"location"`, `"interactive"` # MessageResult Source: https://zacx.io/api/schemas/MessageResult/ · Markdown: https://zacx.io/api/schemas/MessageResult/index.md Path: Zacx Public API ## Fields - `MessageResult.status` (string, required) - `MessageResult.message` (string, required) - `MessageResult.code` (string, optional) — Present when the call succeeded but changed nothing, for example `TAG_ALREADY_ASSOCIATED`. # MessagesReport Source: https://zacx.io/api/schemas/MessagesReport/ · Markdown: https://zacx.io/api/schemas/MessagesReport/index.md Path: Zacx Public API ## Fields - `MessagesReport.templateName` (string, optional) — Present only when the report was scoped with `template_name`. - `MessagesReport.reportGeneratedAt` (string, optional) - format `date-time` - `MessagesReport.channel` (string, optional) - example `"whatsapp"` - `MessagesReport.aggregateStats` (object, optional) - `MessagesReport.aggregateStats.sent` (integer, optional) - `MessagesReport.aggregateStats.delivered` (integer, optional) - `MessagesReport.aggregateStats.read` (integer, optional) - `MessagesReport.aggregateStats.failed` (integer, optional) - `MessagesReport.aggregateStats.replied` (integer, optional) - `MessagesReport.aggregateStats.totalCost` (object, optional) - `MessagesReport.aggregateStats.totalCost.amount` (number, required) - example `12.5` - `MessagesReport.aggregateStats.totalCost.currency` (string, required) - example `"INR"` - `MessagesReport.wabaBreakdown` (array, optional) — The same counts, split per WhatsApp API number. - `MessagesReport.wabaBreakdown.wabaNumber` (string, optional) - example `"15558047064"` - `MessagesReport.wabaBreakdown.sent` (integer, optional) - `MessagesReport.wabaBreakdown.delivered` (integer, optional) - `MessagesReport.wabaBreakdown.read` (integer, optional) - `MessagesReport.wabaBreakdown.failed` (integer, optional) - `MessagesReport.wabaBreakdown.replied` (integer, optional) - `MessagesReport.wabaBreakdown.cost` (object, optional) - `MessagesReport.wabaBreakdown.cost.amount` (number, required) - example `12.5` - `MessagesReport.wabaBreakdown.cost.currency` (string, required) - example `"INR"` # MessageStatus > Delivery state of a message, in the order WhatsApp reports them. Source: https://zacx.io/api/schemas/MessageStatus/ · Markdown: https://zacx.io/api/schemas/MessageStatus/index.md Path: Zacx Public API Delivery state of a message, in the order WhatsApp reports them. Type: `string` - one of `"queued"`, `"sent"`, `"delivered"`, `"read"`, `"failed"` # Money Source: https://zacx.io/api/schemas/Money/ · Markdown: https://zacx.io/api/schemas/Money/index.md Path: Zacx Public API ## Fields - `Money.amount` (number, required) - example `12.5` - `Money.currency` (string, required) - example `"INR"` # Recipient Source: https://zacx.io/api/schemas/Recipient/ · Markdown: https://zacx.io/api/schemas/Recipient/index.md Path: Zacx Public API ## Fields - `Recipient.phoneNumber` (string, required) — The contact's phone number, with country code. - example `"919999999999"` - `Recipient.name` (string, optional) — Optional display name, saved to the contact if it is new. - example `"Raj S"` - `Recipient.email` (string, optional) — Optional email, saved to the contact if it is new. - format `email` # SendMessageRequest Source: https://zacx.io/api/schemas/SendMessageRequest/ · Markdown: https://zacx.io/api/schemas/SendMessageRequest/index.md Path: Zacx Public API One of: - [TemplateMessage](/api/schemas/TemplateMessage) - [TextMessage](/api/schemas/TextMessage) - [ImageMessage](/api/schemas/ImageMessage) - [DocumentMessage](/api/schemas/DocumentMessage) - [AudioMessage](/api/schemas/AudioMessage) - [LocationMessage](/api/schemas/LocationMessage) - [InteractiveMessage](/api/schemas/InteractiveMessage) Discriminator: `type` - `template` → [TemplateMessage](/api/schemas/TemplateMessage) - `text` → [TextMessage](/api/schemas/TextMessage) - `image` → [ImageMessage](/api/schemas/ImageMessage) - `document` → [DocumentMessage](/api/schemas/DocumentMessage) - `audio` → [AudioMessage](/api/schemas/AudioMessage) - `location` → [LocationMessage](/api/schemas/LocationMessage) - `interactive` → [InteractiveMessage](/api/schemas/InteractiveMessage) # TemplateMessage > An approved WhatsApp template. Can be sent at any time, no active chat window needed. Source: https://zacx.io/api/schemas/TemplateMessage/ · Markdown: https://zacx.io/api/schemas/TemplateMessage/index.md Path: Zacx Public API An approved WhatsApp template. Can be sent at any time, no active chat window needed. ## Fields - `TemplateMessage.wabaNumber` (string, required) — Your WhatsApp API number to send from, with country code. - example `"919705182126"` - `TemplateMessage.recipient` (object, required) - `TemplateMessage.recipient.phoneNumber` (string, required) — The contact's phone number, with country code. - example `"919999999999"` - `TemplateMessage.recipient.name` (string, optional) — Optional display name, saved to the contact if it is new. - example `"Raj S"` - `TemplateMessage.recipient.email` (string, optional) — Optional email, saved to the contact if it is new. - format `email` - `TemplateMessage.type` (unknown, required) - `TemplateMessage.template` (object, required) - `TemplateMessage.template.name` (string, required) — The template name as approved in your workspace. - example `"confirmation"` - `TemplateMessage.template.language` (string, required) — Template language code. - example `"en"` - `TemplateMessage.template.header` (object, optional) — Only for templates whose header is not **None**. Pass `text` for a text header, `url` for an image, video, or document header, and `filename` for document headers. - `TemplateMessage.template.header.text` (string, optional) — Header text. Text-header templates only. - example `"Welcome"` - `TemplateMessage.template.header.url` (string, optional) — Public URL of the image, video, or document. - format `uri`; example `"https://example.com/header.jpg"` - `TemplateMessage.template.header.filename` (string, optional) — File name shown to the contact. Document-header templates only. - example `"invoice.pdf"` - `TemplateMessage.template.body` (array, optional) — Values for the body variables `{{1}}`, `{{2}}`, … in order. Omit when the template has no variables. - example `["John","Premium Plan"]` - `TemplateMessage.template.buttons` (array, optional) — Values for button variables, in button order. Only for templates with a dynamic button such as a **Visit website** URL. - example `["button1_param"]` # TemplatePayload Source: https://zacx.io/api/schemas/TemplatePayload/ · Markdown: https://zacx.io/api/schemas/TemplatePayload/index.md Path: Zacx Public API ## Fields - `TemplatePayload.name` (string, required) — The template name as approved in your workspace. - example `"confirmation"` - `TemplatePayload.language` (string, required) — Template language code. - example `"en"` - `TemplatePayload.header` (object, optional) — Only for templates whose header is not **None**. Pass `text` for a text header, `url` for an image, video, or document header, and `filename` for document headers. - `TemplatePayload.header.text` (string, optional) — Header text. Text-header templates only. - example `"Welcome"` - `TemplatePayload.header.url` (string, optional) — Public URL of the image, video, or document. - format `uri`; example `"https://example.com/header.jpg"` - `TemplatePayload.header.filename` (string, optional) — File name shown to the contact. Document-header templates only. - example `"invoice.pdf"` - `TemplatePayload.body` (array, optional) — Values for the body variables `{{1}}`, `{{2}}`, … in order. Omit when the template has no variables. - example `["John","Premium Plan"]` - `TemplatePayload.buttons` (array, optional) — Values for button variables, in button order. Only for templates with a dynamic button such as a **Visit website** URL. - example `["button1_param"]` # TextMessage > Plain text. Requires an active chat window. Source: https://zacx.io/api/schemas/TextMessage/ · Markdown: https://zacx.io/api/schemas/TextMessage/index.md Path: Zacx Public API Plain text. Requires an active chat window. ## Fields - `TextMessage.wabaNumber` (string, required) — Your WhatsApp API number to send from, with country code. - example `"919705182126"` - `TextMessage.recipient` (object, required) - `TextMessage.recipient.phoneNumber` (string, required) — The contact's phone number, with country code. - example `"919999999999"` - `TextMessage.recipient.name` (string, optional) — Optional display name, saved to the contact if it is new. - example `"Raj S"` - `TextMessage.recipient.email` (string, optional) — Optional email, saved to the contact if it is new. - format `email` - `TextMessage.type` (unknown, required) - `TextMessage.text` (string, required) - example `"Hello, this is a test message!"` # User Source: https://zacx.io/api/schemas/User/ · Markdown: https://zacx.io/api/schemas/User/index.md Path: Zacx Public API ## Fields - `User.name` (string, optional) - example `"Meta Inc"` - `User.phoneNumber` (string, optional) - example `"+918989898989"` - `User.email` (string, optional) - format `email`; example `"support@zacx.io"` # ValidationError Source: https://zacx.io/api/schemas/ValidationError/ · Markdown: https://zacx.io/api/schemas/ValidationError/index.md Path: Zacx Public API ## Fields - `ValidationError.status` (string, required) - `ValidationError.code` (string, required) — Stable machine-readable error code. - `ValidationError.message` (string, required) — Human-readable explanation. - `ValidationError.errors` (array, optional) — One entry per failing parameter. - `ValidationError.errors.type` (string, optional) - example `"parameter"` - `ValidationError.errors.field` (string, optional) - example `"from"` - `ValidationError.errors.message` (string, optional) - `ValidationError.errors.input` (unknown, optional) — The value that was received, or `null` when it was missing. # Chats > Conversation state for a contact. Source: https://zacx.io/api/tags/Chats/ · Markdown: https://zacx.io/api/tags/Chats/index.md Path: Zacx Public API Conversation state for a contact. ## Operations - [Get chat active window status](/api/chat/active) # Contacts > Read and update contacts, their tags, and their assigned users. Source: https://zacx.io/api/tags/Contacts/ · Markdown: https://zacx.io/api/tags/Contacts/index.md Path: Zacx Public API Read and update contacts, their tags, and their assigned users. ## Operations - [Get a contact](/api/contact/get) - [Create or update a contact](/api/contact/upsert) - [Add tags to a contact](/api/contact/add-tags) - [Remove tags from a contact](/api/contact/remove-tags) - [Assign users to a contact](/api/contact/assign-users) - [Unassign users from a contact](/api/contact/unassign-users) # Custom Fields > The custom columns configured in your CRM. Source: https://zacx.io/api/tags/Custom-Fields/ · Markdown: https://zacx.io/api/tags/Custom-Fields/index.md Path: Zacx Public API The custom columns configured in your CRM. ## Operations - [List custom fields](/api/custom-fields/list) # Messages > Send template, free-form, and interactive messages over the WhatsApp Business API, and check delivery status. **Free-form and interactive messages are only delivered inside an active chat window**: the contact must have messaged your WhatsApp API number in the last 24 hours. Call [Get chat active window status](/api/chat/active) first to avoid re-engagement errors. Template messages have no such limit. Source: https://zacx.io/api/tags/Messages/ · Markdown: https://zacx.io/api/tags/Messages/index.md Path: Zacx Public API Send template, free-form, and interactive messages over the WhatsApp Business API, and check delivery status. **Free-form and interactive messages are only delivered inside an active chat window**: the contact must have messaged your WhatsApp API number in the last 24 hours. Call [Get chat active window status](/api/chat/active) first to avoid re-engagement errors. Template messages have no such limit. ## Operations - [Send a message](/api/message/send) - [Get message status](/api/message/status) # Reports > Message delivery and cost reports. More reports are coming soon. Source: https://zacx.io/api/tags/Reports/ · Markdown: https://zacx.io/api/tags/Reports/index.md Path: Zacx Public API Message delivery and cost reports. More reports are coming soon. ## Operations - [Get messages report](/api/workspace/reports) # Tags > Tags available in your workspace. Source: https://zacx.io/api/tags/Tags/ · Markdown: https://zacx.io/api/tags/Tags/index.md Path: Zacx Public API Tags available in your workspace. ## Operations - [List tags](/api/workspace/tags) # Users > Team members in your workspace. Source: https://zacx.io/api/tags/Users/ · Markdown: https://zacx.io/api/tags/Users/index.md Path: Zacx Public API Team members in your workspace. ## Operations - [List users](/api/users/list) # Wallet > Workspace wallet credits. Source: https://zacx.io/api/tags/Wallet/ · Markdown: https://zacx.io/api/tags/Wallet/index.md Path: Zacx Public API Workspace wallet credits. ## Operations - [Get wallet credits](/api/workspace/wallet-balance) # List users > Returns every team member in the workspace. Source: https://zacx.io/api/users/list/ · Markdown: https://zacx.io/api/users/list/index.md Path: Zacx Public API › Users `GET /users` Returns every team member in the workspace. ## Authentication - `bearerAuth`, http, header `Authorization` ## Code samples ### cURL ```curl curl --request GET \ --url https://api.zacx.io/v1/users \ --header 'Authorization: Bearer ' ``` ### TypeScript ```typescript const url = 'https://api.zacx.io/v1/users'; const options = {method: 'GET', headers: {Authorization: 'Bearer '}}; fetch(url, options) .then(res => res.json()) .then(json => console.log(json)) .catch(err => console.error(err)); ``` ### Python ```python import requests url = "https://api.zacx.io/v1/users" headers = {"Authorization": "Bearer "} response = requests.get(url, headers=headers) print(response.text) ``` ## Responses ### 200 The users. #### Example ```json { "status": "success", "data": [ { "name": "Meta Inc", "phoneNumber": "+918989898989", "email": "support@zacx.io" }, { "name": "Test User", "phoneNumber": "+910000000000", "email": "test@example.com" } ] } ``` - `listUsers.response.200.status` (string, required) - `listUsers.response.200.data` (array, required) - `listUsers.response.200.data.name` (string, optional) - example `"Meta Inc"` - `listUsers.response.200.data.phoneNumber` (string, optional) - example `"+918989898989"` - `listUsers.response.200.data.email` (string, optional) - format `email`; example `"support@zacx.io"` # Get messages report > Returns sent, delivered, read, failed, and replied counts plus cost for a date range, in aggregate and per WhatsApp API number. Pass `template_name` to scope the report to one template. `from` and `to` accept either a plain date (`YYYY-MM-DD`) for daily reports or a UTC timestamp (`YYYY-MM-DDTHH:MM:SSZ`) for hourly ranges. Source: https://zacx.io/api/workspace/reports/ · Markdown: https://zacx.io/api/workspace/reports/index.md Path: Zacx Public API › Reports `GET /workspace/reports` Returns sent, delivered, read, failed, and replied counts plus cost for a date range, in aggregate and per WhatsApp API number. Pass `template_name` to scope the report to one template. `from` and `to` accept either a plain date (`YYYY-MM-DD`) for daily reports or a UTC timestamp (`YYYY-MM-DDTHH:MM:SSZ`) for hourly ranges. ## Authentication - `bearerAuth`, http, header `Authorization` ## Query parameters - `getMessagesReport.query.from` (string, required) — Start of the range, inclusive. A date or a UTC timestamp. - `getMessagesReport.query.to` (string, required) — End of the range, inclusive. A date or a UTC timestamp. - `getMessagesReport.query.template_name` (string, optional) — Restrict the report to one template, by its name in your workspace. ## Code samples ### cURL ```curl curl --request GET \ --url 'https://api.zacx.io/v1/workspace/reports?from=string&to=string' \ --header 'Authorization: Bearer ' ``` ### TypeScript ```typescript const url = 'https://api.zacx.io/v1/workspace/reports?from=string&to=string'; const options = {method: 'GET', headers: {Authorization: 'Bearer '}}; fetch(url, options) .then(res => res.json()) .then(json => console.log(json)) .catch(err => console.error(err)); ``` ### Python ```python import requests url = "https://api.zacx.io/v1/workspace/reports?from=string&to=string" headers = {"Authorization": "Bearer "} response = requests.get(url, headers=headers) print(response.text) ``` ## Responses ### 200 The report. #### Example ```json { "status": "success", "data": { "reportGeneratedAt": "2026-02-01T07:37:07Z", "channel": "whatsapp", "aggregateStats": { "sent": 14, "delivered": 9, "read": 7, "failed": 5, "replied": 3, "totalCost": { "amount": 12.5, "currency": "INR" } }, "wabaBreakdown": [ { "wabaNumber": "15558047063", "sent": 4, "delivered": 0, "read": 0, "failed": 4, "replied": 1, "cost": { "amount": 0, "currency": "INR" } }, { "wabaNumber": "15558047064", "sent": 10, "delivered": 9, "read": 7, "failed": 1, "replied": 2, "cost": { "amount": 12.5, "currency": "INR" } } ] } } ``` - `getMessagesReport.response.200.status` (string, required) - `getMessagesReport.response.200.data` (object, required) - `getMessagesReport.response.200.data.templateName` (string, optional) — Present only when the report was scoped with `template_name`. - `getMessagesReport.response.200.data.reportGeneratedAt` (string, optional) - format `date-time` - `getMessagesReport.response.200.data.channel` (string, optional) - example `"whatsapp"` - `getMessagesReport.response.200.data.aggregateStats` (object, optional) - `getMessagesReport.response.200.data.aggregateStats.sent` (integer, optional) - `getMessagesReport.response.200.data.aggregateStats.delivered` (integer, optional) - `getMessagesReport.response.200.data.aggregateStats.read` (integer, optional) - `getMessagesReport.response.200.data.aggregateStats.failed` (integer, optional) - `getMessagesReport.response.200.data.aggregateStats.replied` (integer, optional) - `getMessagesReport.response.200.data.aggregateStats.totalCost` (object, optional) - `getMessagesReport.response.200.data.aggregateStats.totalCost.amount` (number, required) - example `12.5` - `getMessagesReport.response.200.data.aggregateStats.totalCost.currency` (string, required) - example `"INR"` - `getMessagesReport.response.200.data.wabaBreakdown` (array, optional) — The same counts, split per WhatsApp API number. - `getMessagesReport.response.200.data.wabaBreakdown.wabaNumber` (string, optional) - example `"15558047064"` - `getMessagesReport.response.200.data.wabaBreakdown.sent` (integer, optional) - `getMessagesReport.response.200.data.wabaBreakdown.delivered` (integer, optional) - `getMessagesReport.response.200.data.wabaBreakdown.read` (integer, optional) - `getMessagesReport.response.200.data.wabaBreakdown.failed` (integer, optional) - `getMessagesReport.response.200.data.wabaBreakdown.replied` (integer, optional) - `getMessagesReport.response.200.data.wabaBreakdown.cost` (object, optional) - `getMessagesReport.response.200.data.wabaBreakdown.cost.amount` (number, required) - example `12.5` - `getMessagesReport.response.200.data.wabaBreakdown.cost.currency` (string, required) - example `"INR"` ### 400 A required parameter is missing or invalid. #### Example ```json { "status": "error", "code": "VALIDATION_FAILED", "message": "One or more required parameters are missing", "errors": [ { "type": "parameter", "field": "from", "message": "The from query parameter is required.", "input": null } ] } ``` - `getMessagesReport.response.400.status` (string, required) - `getMessagesReport.response.400.code` (string, required) — Stable machine-readable error code. - `getMessagesReport.response.400.message` (string, required) — Human-readable explanation. - `getMessagesReport.response.400.errors` (array, optional) — One entry per failing parameter. - `getMessagesReport.response.400.errors.type` (string, optional) - example `"parameter"` - `getMessagesReport.response.400.errors.field` (string, optional) - example `"from"` - `getMessagesReport.response.400.errors.message` (string, optional) - `getMessagesReport.response.400.errors.input` (unknown, optional) — The value that was received, or `null` when it was missing. ### 404 No template with that name exists in the workspace. #### Example ```json { "status": "error", "code": "TEMPLATE_NOT_FOUND", "message": "The requested template name 'nonexistent_template' could not be found." } ``` - `getMessagesReport.response.404.status` (string, required) - `getMessagesReport.response.404.code` (string, required) — Stable machine-readable error code. - `getMessagesReport.response.404.message` (string, required) — Human-readable explanation. # List tags > Returns every tag in the workspace. Source: https://zacx.io/api/workspace/tags/ · Markdown: https://zacx.io/api/workspace/tags/index.md Path: Zacx Public API › Tags `GET /tags` Returns every tag in the workspace. ## Authentication - `bearerAuth`, http, header `Authorization` ## Code samples ### cURL ```curl curl --request GET \ --url https://api.zacx.io/v1/tags \ --header 'Authorization: Bearer ' ``` ### TypeScript ```typescript const url = 'https://api.zacx.io/v1/tags'; const options = {method: 'GET', headers: {Authorization: 'Bearer '}}; fetch(url, options) .then(res => res.json()) .then(json => console.log(json)) .catch(err => console.error(err)); ``` ### Python ```python import requests url = "https://api.zacx.io/v1/tags" headers = {"Authorization": "Bearer "} response = requests.get(url, headers=headers) print(response.text) ``` ## Responses ### 200 The tag names. `data` is empty when none exist. #### Example ```json { "status": "success", "data": [ "test-tag", "test-tag-1" ] } ``` - `listTags.response.200.status` (string, required) - `listTags.response.200.data` (array, required) - `listTags.response.200.message` (string, optional) — Present only when the workspace has no tags. # Get wallet credits > Returns the current wallet balance of the workspace. Source: https://zacx.io/api/workspace/wallet-balance/ · Markdown: https://zacx.io/api/workspace/wallet-balance/index.md Path: Zacx Public API › Wallet `GET /workspace/wallet_balance` Returns the current wallet balance of the workspace. ## Authentication - `bearerAuth`, http, header `Authorization` ## Code samples ### cURL ```curl curl --request GET \ --url https://api.zacx.io/v1/workspace/wallet_balance \ --header 'Authorization: Bearer ' ``` ### TypeScript ```typescript const url = 'https://api.zacx.io/v1/workspace/wallet_balance'; const options = {method: 'GET', headers: {Authorization: 'Bearer '}}; fetch(url, options) .then(res => res.json()) .then(json => console.log(json)) .catch(err => console.error(err)); ``` ### Python ```python import requests url = "https://api.zacx.io/v1/workspace/wallet_balance" headers = {"Authorization": "Bearer "} response = requests.get(url, headers=headers) print(response.text) ``` ## Responses ### 200 The balance. #### Example ```json { "status": "success", "data": { "balance": 1234.23, "currency": "INR" } } ``` - `getWalletBalance.response.200.status` (string, required) - `getWalletBalance.response.200.data` (object, required) - `getWalletBalance.response.200.data.balance` (number, required) — Available credits. - `getWalletBalance.response.200.data.currency` (string, required) — ISO 4217 currency code. ### 401 The API key is missing or invalid. #### Example ```json { "status": "error", "code": "VALIDATION_FAILED", "message": "string" } ``` - `getWalletBalance.response.401.status` (string, required) - `getWalletBalance.response.401.code` (string, required) — Stable machine-readable error code. - `getWalletBalance.response.401.message` (string, required) — Human-readable explanation. # Our first blog post > Zacx went live in June 2025. What we built in the year since, why customers who left came back, and what we are committing to from here. Source: https://zacx.io/blog/our-first-blog-post/ · Markdown: https://zacx.io/blog/our-first-blog-post/index.md This is the first post on the Zacx blog. It comes more than a year after we went live, because the year went into the product. Zacx launched in June 2025 from Hyderabad, on the official WhatsApp Cloud API. The tools businesses in India were paying for at the time had a pattern. Expensive plans. Markups hidden inside Meta's message rates. Numbers lost to unofficial gateways. Support that stopped answering after the payment cleared. We built Zacx to be the platform where none of that happens. ## What a year of building looks like Most of the work was not visible. It was the inbox loading fast on a weak connection. A broadcast to 20,000 contacts landing without tripping Meta's limits. An automation builder a front desk can learn in an afternoon. Some features shipped, were used by real businesses, and were then rebuilt from scratch because the first version was not good enough. That cost us time. It was the right call every time. The result is a platform we are proud to put in front of anyone. Businesses and agencies across India run their customer conversations on Zacx, from single-owner shops to agencies managing dozens of client accounts. We are comfortable saying it is one of the easiest pieces of business software you can use in India, and the people who tell us that are the same customers who tell us, quickly, when something is not right. ## What reliability means here Reliability is not a feature on a list. It is the reason a business picks a platform and the reason it stays. So we hold ourselves to standards you can check. - **Official infrastructure only.** Every number on Zacx runs on the official WhatsApp Cloud API. No scraped sessions, no gateways, no risk to the number your customers already have saved. - **The bill reads the way it was quoted.** Meta's per-message rates are published on our pricing page and passed on without markup. Monthly means monthly. Nothing turns annual at checkout. - **Support that answers.** 10am to 6pm IST, staffed by people who know your account by name. We publish the hours rather than promise 24/7 and go quiet. - **Your data is yours.** Export it, delete it, take it anywhere. Government and regulated businesses can run Zacx on their own infrastructure. ## The customers who came back Businesses cancel. That is normal in software. What stood out this year is how many of the businesses that left came back within a few months. Some tried a cheaper tool. Some were promised more somewhere else. The reason they returned was almost always the same: the bill elsewhere did not match the quote, or a support ticket sat unanswered for two weeks, or a number got flagged on an unofficial gateway. They remembered that none of that happened here. We treat that as the clearest signal we have. *The things we chose to care about are the things that matter.* ## What we are committing to Starting today, we are going to talk more. **This blog will carry product updates, Meta pricing changes as they are announced, and practical guides** on running business communication well. The kind of writing we wish had existed when we were working this out ourselves. **Requested features are the roadmap.** The list our customers built over the year is long and specific. If you asked for something and have not seen it yet, it is in the queue, not forgotten. **We will build alongside the industry.** Business communication in India is moving fast, with Meta's pricing shifting, new channels arriving, and AI entering the inbox. We would rather help get this right, with the other companies working on the same problem, than compete on noise. ## Thank you To every business that trusted a young company with the line its customers call: thank you. To the ones who left and came back: it meant more than you know. If you are choosing a platform on reliability, we want to be the obvious answer. Start a free trial, or message support and talk to a person. Both are open today. # WhatsApp Business API replies cost money from 1 October 2026 > Service messages sent inside the 24 hour window will be billed at the Utility template rate. What changes, how bots are affected, and how to keep the cost down. Source: https://zacx.io/blog/whatsapp-business-api-replies-cost-money-from-1-october-2026/ · Markdown: https://zacx.io/blog/whatsapp-business-api-replies-cost-money-from-1-october-2026/index.md Replies to customers on WhatsApp have been free since November 2024. Meta confirmed on 2 September that this ends on 1 October 2026. From that date, every reply your business sends is a billable message. Nothing changes in how you use Zacx. What changes is the Meta charge on your account. ## What a service message is Every message a business sends on the WhatsApp Business API is one of two kinds. A **template message** is pre-approved by Meta and can be sent at any time, whether or not the customer has written to you recently. Broadcasts, OTPs and order confirmations are templates. Meta already charges for these, by category: Marketing, Utility or Authentication. A **service message** is everything else. When a customer messages you, a 24 hour window opens, and inside it you can send free-form messages without a template. A typed reply from your team, a chatbot response, a quick reply button, a photo or a PDF sent in the chat: all of these are service messages. They have been free since November 2024. ## What changes **Service messages are charged.** From 1 October, every service message is billed at the same rate as a Utility template. The current rate for India is on our [pricing page](/pricing). **Utility templates sent inside the window are charged too.** These have been free inside the window since July 2025. That ends on the same date. **Charges are per message, not per conversation.** Six replies in one chat are six charges. *This is the detail that decides your bill.* Each WhatsApp number gets its first 1,000 service messages free every month. Charging starts from the 1,001st. The count resets on the 1st and unused messages do not carry over. Monthly cost = (service messages sent − 1,000) × Utility rate. All charges exclude 18% GST. ## What stays the same - Messages from customers to you remain free. - Marketing and Authentication template rates are unchanged. - Replies inside the 72 hour window from a Click to WhatsApp ad remain free. - Your Zacx plan price is unchanged. Meta's rates are passed on as published, with no markup. - The 24 hour window itself works exactly as before. ## What this costs in practice How many messages become chargeable at different reply volumes from one number. Multiply the last column by the Utility rate on the pricing page for the monthly Meta charge. | Replies sent per month | Free tier | Chargeable messages | | --- | --- | --- | | 800 | 1,000 | 0 | | 2,500 | 1,000 | 1,500 | | 6,000 | 1,000 | 5,000 | | 15,000 | 1,000 | 14,000 | ## How this affects your chatbot A bot reply is a service message like any other. Meta does not distinguish between a person typing and an automation sending. Every step your bot sends is one message against the free tier. Take a bot with 20 steps: a greeting, a menu, a few questions, and a confirmation. One customer completing that flow costs 20 service messages. 500 customers a month is 10,000 messages, of which 9,000 are chargeable. The same bot cut to 8 steps sends 4,000 messages for the same 500 customers, and 3,000 of those are chargeable. It still does its job. It asks less and sends less. ## How to keep the cost down **Replace multi-step questions with a WhatsApp Form.** A Form collects name, preferred date, service and any other field in one interactive message. The 20-step bot above becomes two messages: the Form and a confirmation. 500 customers a month is 1,000 messages, *all inside the free tier*. Forms can be triggered from the automation builder. See the [Forms documentation](/docs/whatsapp/flows). **Send one complete reply instead of several short ones.** Opening hours, location and parking in one message is one charge. The same information sent as three messages is three. **Send Utility templates proactively.** A confirmation sent on its own costs the same as one sent inside the window from October, and it usually prevents the follow-up question. ## Meta Business Agent is billed separately Meta also sells its own AI assistant, Meta Business Agent, billed per token. It applies only if you enable it. Replies from your team or from Zacx automations are service messages and follow the pricing above. ## Questions about this change If you would like to know how this applies to your account, or want an estimate based on your current reply volume, contact us on WhatsApp or by email. We can review your numbers and suggest where a Form or a shorter flow would help. The current rates are on the [pricing page](/pricing). # New website, documentation, API reference, changelog and blog > Zacx has a new home. The website, documentation, API reference, this changelog and the blog all launch today. Source: https://zacx.io/changelog/2026-09-10-new-website/ · Markdown: https://zacx.io/changelog/2026-09-10-new-website/index.md Everything public about Zacx now lives in one place, rebuilt from the ground up. - **Website.** New [features](/features), [pricing](/pricing) and [about](/about) pages, with every rate published in full. - **Documentation.** Clear, searchable guides for every part of the product at [/docs](/docs). - **API reference.** Every endpoint documented at [/api](/api), always in step with the product. - **Changelog.** This page. Every update, improvement and fix, newest first. - **Blog.** Product news, pricing updates as they happen, and practical guides at [/blog](/blog). The [first post](/blog/our-first-blog-post) is up. The whole site is also built to be read by AI assistants, not just browsers. Ask ChatGPT or Claude about Zacx and it can read the same pages you do. # Zacx Documentation > Learn how to set up and use Zacx, the WhatsApp Business API platform. Source: https://zacx.io/docs/ · Markdown: https://zacx.io/docs/index.md Welcome to the Zacx docs. Everything you need to get your WhatsApp Business API account running and make the most of chats, broadcasts, automations, and more. ## Start here - [Overview](/docs/overview) — What Zacx is and what it can do - [WhatsApp API Pricing](/docs/wa-api-pricing) — Understand WhatsApp's per-message pricing - [Zacx Signup](/docs/signup-wa-api/zacx-signup) — Create your account and connect WhatsApp - [Connect Your Number](/docs/signup-wa-api/phone-number-setup) — Set up your WhatsApp phone number ## Modules - [Chats](/docs/chats) — Live multi-agent inbox for all conversations - [Contacts](/docs/contacts) — Contact data, custom fields, and segments - [Broadcasts](/docs/broadcasts) — WhatsApp marketing at scale - [Automations](/docs/automations) — Workflows that engage customers automatically - [WhatsApp Forms](/docs/whatsapp/flows) — Collect structured answers inside the chat - [WhatsApp Templates](/docs/whatsapp/templates) — High-converting message templates ## Need help? Reach our support team any time via [WhatsApp chat support](https://wa.me/919705182126). # Automations (Workflows) > Master automation workflows to engage customers at scale with WhatsApp Source: https://zacx.io/docs/automations/ · Markdown: https://zacx.io/docs/automations/index.md ## Overview **This video covers:** 1. What automations are and how they work 2. Understanding triggers and actions 3. Setting up your first automation 4. Managing automation workflows history and versioning --- ## Use Case Videos ### Keyword / DM Automation Trigger automated sequences based on keywords customers send, enabling intelligent conversational marketing at scale. --- ### Webhook Trigger Automation Integrate external systems and services with webhook triggers to create powerful cross-platform automation workflows. --- ### Webinar Confirmation + Reminders > **Coming soon** > > A video walkthrough for this use case is on the way. Set up automated workflows to send webinar confirmations immediately after registration and automatic reminders before the event starts. --- ### Appointment Confirmation + Reminders > **Coming soon** > > A video walkthrough for this use case is on the way. Automate appointment confirmations and reminder sequences to reduce no-shows and improve customer engagement. --- ## Explore More Use Cases Have a unique use case you'd like to explore? Our team is here to help! **Connect with our chat support** to discuss your specific automation needs and get personalized guidance on implementing custom workflows for your business. # Broadcasts > Level up your marketing game with your WhatsApp broadcasts Source: https://zacx.io/docs/broadcasts/ · Markdown: https://zacx.io/docs/broadcasts/index.md **The above video contains** 1. Segmenting the audience based on filters, tags or all contacts 2. Choosing the audience for the campaign 3. Choosing the phone number for the campaign 4. Choosing the Template and the filling the body variables with appropriate custom fields and Fall back values (for a better deliverability) 5. Checking Wallet balance and naming the broadcast 6. How to schedule a broadcast. # Chats > Live Chat Inbox - Chats let you manage all your WhatsApp conversations in one place Source: https://zacx.io/docs/chats/ · Markdown: https://zacx.io/docs/chats/index.md ## Understanding Chats (Live Multi-Agent Inbox) The above video contains: 1. How to access chats in Zacx 2. How to send templates via Zacx 3. What is Conversation window 4. Filters in Chats 5. How to add tags and assign team members to chats 6. How to block a conversation in Chats ### Types of Conversations in Zacx The above video contains: 1. Types of messages we can do in Zacx 2. Understanding Templates and their types 3. Understanding when we can send normal messages to leads # Contacts > Contacts helps you store contact data, add custom fields, import/export lists, and create smart segments for targeted messaging Source: https://zacx.io/docs/contacts/ · Markdown: https://zacx.io/docs/contacts/index.md ## Overview of Contacts in Zacx The above video contains: 1. Creating and importing Contacts. 2. Editing the Contact data 3. Assigning tags and team members to contacts in zacx 4. Adding new custom fields of different types with in Zacx 5. Editing the existing custom fields in Contacts 6. Creating and editing tags inside of Zacx ## Import Contacts **NOTE**: 1. Ensure the **number column** in your CSV has the country code **without the plus sign**, and no spaces or dashes. Format it as a custom number format without any decimals at the end. 2. If you are importing any Date fields make sure they are in DD-MM-YYYY or MM-DD-YYYY format. \ For time - Use HH:MM format or HH:MM AM/PM 3. Create **custom fields** for any additional columns in your CSV file. 4. **Map the CSV headers** to the appropriate system fields or custom fields during import. The Above Video Contains 1. Formatting contacts in the Google Sheet/Excel and saving as CSV file 2. Importing Contacts from a CSV file 3. Different methods to import new and update existing contacts 4. Assign tags and users while importing contacts # Welcome to Zacx! > About Zacx Source: https://zacx.io/docs/overview/ · Markdown: https://zacx.io/docs/overview/index.md Zacx is a powerful, user-friendly WhatsApp API platform designed to help businesses connect with their customers, streamline communication, and accelerate growth, all within WhatsApp. Whether you're a startup or an established brand, Zacx gives you the tools to manage customer conversations effortlessly. From automated support and personalized marketing to real-time updates and campaign tracking, Zacx turns WhatsApp into your most effective business channel. Built for scalability and ease of use, our platform empowers teams to automate interactions, boost engagement, and deliver a seamless customer experience, without the tech headaches. # Synamate Integration > Connecting Synamate with Zacx and Sending Template Messages Source: https://zacx.io/docs/settings/integrations/synamate/ · Markdown: https://zacx.io/docs/settings/integrations/synamate/index.md ## Connect Your Synamate with Zacx The above video contains: 1. Connecting Zacx with Synamate 2. Further steps after connecting Synamate with Zacx ## How to Send Template Messages from Synamate The above video contains: 1. Setting up automation in Synamate 2. Configuring the template 3. Passing the body variables using Custom fields in Synamate (Please contact at support@synamate.com if you need any support for the automations shown in the following videos) 1. [Sending templates and normal messages manually in conversations](https://help.synamate.com/docs/wa-integration/how-to-send-wa-messages-through-synamate-via-zacx#sending-templates-and-normal-messages-manually-in-conversations) 2. [Sending templates via automations in Synamate](https://help.synamate.com/docs/wa-integration/how-to-send-wa-messages-through-synamate-via-zacx#sending-templates-via-automations-in-synamate) # Teams & Roles > Adding team members, assigning roles & managing permissions Source: https://zacx.io/docs/settings/team-roles/ · Markdown: https://zacx.io/docs/settings/team-roles/index.md Create Roles with modular permissions, Onboard your team and assign them the Roles according to the Hierarchy The above video contains: 1. Creating a new role in Zacx workspace 2. Assigning modular permissions to team members 3. Giving access to "Only Assigned Contacts/Chats" 4. Inviting a New Team Member to Zacx 5. Removing Roles & Team members # Connecting Your Phone Number > Connect your WhatsApp phone number to Zacx Source: https://zacx.io/docs/signup-wa-api/phone-number-setup/ · Markdown: https://zacx.io/docs/signup-wa-api/phone-number-setup/index.md Follow this quick video guide to connect your WhatsApp Business API phone number with Zacx. ### 🚨 Before you begin: - Provide a phone number that is not currently on any WhatsApp app in mobile. - Ensure you can receive calls or SMS on the number you’ll provide for verification - Have your business information ready (name, address, website, etc.) - Contact us if you need any assistance at [https://zacx.io/wasupport](https://zacx.io/wasupport) The above video contains: 1. Creating/Migrating the WhatsApp Business account in Facebook Business Manager 2. Setting up Display Name for the Phone number 3. Verification of the Phone number 4. Connecting Phone Number with Zacx # Zacx Signup > Signup to Zacx Source: https://zacx.io/docs/signup-wa-api/zacx-signup/ · Markdown: https://zacx.io/docs/signup-wa-api/zacx-signup/index.md Follow this quick video guide to sign up and set up your account in just a few minutes. The above video contains: 1. Signing up to Zacx 2. Verifying your phone number via OTP 3. Onboarding to Zacx 4. Creating your first workspace in Zacx ## Here's a quick walkthrough 1. **Go to the Zacx Sign up page** Visit [app.zacx.io](https://app.zacx.io/) and Click on **Sign Up** to enter your WhatsApp Number. Make sure the WhatsApp number you are entering is your Personal/Business WhatsApp Number on which a WhatsApp/WhatsApp Business App already exists. Please Ensure that the device in which the number is, is Powered and Connected to the Internet. Also Keep the app updated to prevent any issues while signing up. 2. **Verify Your Number** Enter the OTP which you have got to your WhatsApp number and Sign Up to the Platform 3. **Enter Your Personal Information** Enter Your First Name, Last Name, Phone, Email and Time zone. Upload your profile picture as well (This profile picture is only for internal reference and will not be displayed anywhere publicly to your contacts) 4. **Create Your Workspace** Each workspace is considered as a separate organization in Zacx. Click on Create new Workspace to create your first workspace in Zacx. Make sure the name of your workspace is more than 4 characters. # WhatsApp API Pricing > Understanding WhatsApp's Per Message Pricing Policy Source: https://zacx.io/docs/wa-api-pricing/ · Markdown: https://zacx.io/docs/wa-api-pricing/index.md Follow this quick video guide to understand WhatsApp's new pricing policy for WhatsApp Business API. The above video contains: 1. How whatsapp templates are charged as per the new pricing policy 2. What are the costs of each template and when are they charged 3. Understanding what is session window 4. Exceptions in per message cost during the session window # Re-engagement Error (#131047) > WhatsApp Cloud API Re-engagement Error Explained Source: https://zacx.io/docs/wa-error/131047/ · Markdown: https://zacx.io/docs/wa-error/131047/index.md WhatsApp throws an error whenever a message is sent when a message(not template) is sent to the customer in a free form format, outside of the service window. The above video contains: 1. Understanding Re Engagement Error in Zacx 2. Probable solutions to tackle this error # Ecosystem Error (#131049) > WhatsApp Cloud API Ecosystem Error Explained Source: https://zacx.io/docs/wa-error/131049/ · Markdown: https://zacx.io/docs/wa-error/131049/index.md WhatsApp throws an Ecosystem error whenever enough number of marketing messages are sent to the customer in a given day/hour. This happens mostly to maintain the ecosystem of WhatsApp for the customer The above video contains: 1. Addressing Error #131049 2. Understanding when and why WhatsApp shows Ecosystem error when a template is sent 3. Facebook's Policy about Sending Marketing Templates 4. How to address the Ecosystem Error For more info check official Meta documentation here: [https://developers.facebook.com/docs/whatsapp/cloud-api/guides/send-message-templates#per-user-marketing-template-message-limits](https://developers.facebook.com/docs/whatsapp/cloud-api/guides/send-message-templates#per-user-marketing-template-message-limits) # Template Category Change > Automatic Change of template category when a template - how to appeal the same. Source: https://zacx.io/docs/wa-error/template-category-change/ · Markdown: https://zacx.io/docs/wa-error/template-category-change/index.md Watch this video to understand about what can be done when WhatsApp automatically switches your template category when applied. The above video contains: 1. Explaining why WhatApp changes the template categories automatically without informing 2. Changing the category of the template. 3. Precautions to be taken while changing the category # WhatsApp Forms (Flows) > Create, test, send, and automate WhatsApp Forms in Zacx Source: https://zacx.io/docs/whatsapp/flows/ · Markdown: https://zacx.io/docs/whatsapp/flows/index.md ## Overview WhatsApp Forms, built on Meta's WhatsApp Flows, let you collect structured information directly inside a chat, without sending customers to an external website. Use them for lead qualification, appointment booking, feedback, order details, and any scenario where you need clean, structured answers instead of free-text replies. --- ## Creating, Testing & Sending Forms **This video covers:** 1. Creating a WhatsApp Form in Zacx 2. Testing the form before it goes live 3. Sending the form to a customer --- ## Automating WhatsApp Forms Once your form is ready, the real power comes from automating how it's sent and how responses are handled. This is taught as a two-part lead qualification use case. ### Part 1: Sending Forms in Bulk & via Automation (incl. CTWA Ads) **This video covers:** 1. Sending forms to customers in bulk broadcasts 2. Triggering forms automatically through automations 3. Sending forms from Click-to-WhatsApp (CTWA) ad automations --- ### Part 2: Auto-Qualifying Leads from Form Responses **This video covers:** 1. Auto-tagging contacts based on their form answers 2. Branching automations based on specific responses 3. Filtering and reviewing form responses --- ## Explore More Use Cases Have a unique use case you'd like to explore? Our team is here to help! **Connect with our chat support** to discuss your specific forms and automation needs and get personalized guidance for your business. # WhatsApp Profile > How to manage your whatsapp business api profile Source: https://zacx.io/docs/whatsapp/profile/ · Markdown: https://zacx.io/docs/whatsapp/profile/index.md How to Upload and edit, profile picture, address of your business and contact info for your WhatsApp Business Profile The Above video contains: 1. How to change the WhatsApp profile picture in Zacx 2. How to change the Business Name and Business details (address, website, email and Category of the business in WhatsApp profile) 3. How to change the user profile within Zacx. # WhatsApp Templates > How to use create high converting WhatsApp message templates via Zacx Source: https://zacx.io/docs/whatsapp/templates/ · Markdown: https://zacx.io/docs/whatsapp/templates/index.md The above video con tains: 1. Creating templates in Zacx 2. Understanding Body Variables, Header and Footer in templates 3. Adding Buttons to Templates 4. Syncing templates to check if the template is approved