Register a WhatsApp Business Account against a branch and manage the message-template library, including syncing approval status back from Meta.
7 endpoints in this module. Every request needs a JWT bearer token — see Authentication.
OptoSoft sends order updates, eye-test recalls, contact-lens refill reminders and promotional campaigns over the WhatsApp Business Platform. These seven endpoints manage the plumbing: which WhatsApp Business Account a branch sends from, and which approved message templates it can use.
Because WhatsApp business-initiated messages must use a template pre-approved by Meta, the template library is central. OptoSoft keeps a local copy and syncs approval status back from Meta on demand.
These endpoints handle Meta access tokens. A WhatsApp access token
grants the ability to send messages as your business. Never log the
accessToken field, never expose it to a browser
or mobile client, and call these endpoints only from a trusted server.
Configuration only. This module registers accounts and manages templates — it does not expose a "send message" endpoint. Messages are dispatched by OptoSoft automatically as orders and recalls progress.
Lists the WhatsApp Business Account configurations for a company, with paging. A multi-store chain typically has one configuration per branch.
| Field | Type | Required | Description |
|---|---|---|---|
| companyID | int64 | Required | Company (tenant). |
| branchID | int64 | Optional | Restrict to one branch. |
| displayName | string | Optional | Filter by the business display name shown to recipients. |
| phoneNumber | string | Optional | Filter by the sending number. |
| wabaID | string | Optional | Filter by WhatsApp Business Account ID. |
| phoneNumberID | string | Optional | Filter by Meta phone number ID. |
| accessToken | string | Optional | Present in the model as a filter. Do not send a real token here. |
| fromPage | int32 | Optional | First row of the range. |
| toPage | int32 | Optional | Last row of the range. |
| orderBy | string | Optional | Sort column, optionally with DESC. |
A paged envelope: Items plus
Total, PageNumber
and PageSize. Item fields are listed under
get by ID. Note the response is
PascalCase and returns fewer fields than the save model accepts.
curl -X POST https://api.opto-soft.com/api/ClientWhatsAppConfig/List \
-H "Authorization: Bearer YOUR_TOKEN" \
-H "Content-Type: application/json" \
-d '{
"companyID": 18,
"fromPage": 1,
"toPage": 20,
"orderBy": "DisplayName"
}'
{
"Items": [
{
"ID": "Q2ZQdGhSZVhBaVlXTnpaWFF3TWk0d01B",
"WabaID": "123456789012345",
"PhoneNumberId": "987654321098765",
"DisplayName": "Vision Optics Support",
"IsActive": true,
"CreatedDate": "2024-01-15T10:30:00"
}
],
"Total": 1,
"PageNumber": 1,
"PageSize": 20
}
Returns one WhatsApp Business Account configuration in full.
| Name | Type | Required | Description |
|---|---|---|---|
| id | string | Required | Encrypted WhatsApp configuration ID. |
| Field | Type | Description |
|---|---|---|
| ID | string | |
| WabaID | string | Meta WhatsApp Business Account ID. |
| PhoneNumberId | string | Meta phone number ID used on send calls. |
| AccessToken | string | Meta access token. Treat as a secret — never log or forward it. |
| DisplayName | string | Business name recipients see in WhatsApp. |
| IsActive | boolean | Whether OptoSoft will send through this account. |
| CreatedDate | date-time | Audit — when. |
curl https://api.opto-soft.com/api/ClientWhatsAppConfig/ENCRYPTED_CONFIG_ID \
-H "Authorization: Bearer YOUR_TOKEN"
{
"ID": "Q2ZQdGhSZVhBaVlXTnpaWFF3TWk0d01B",
"WabaID": "123456789012345",
"PhoneNumberId": "987654321098765",
"AccessToken": "EAAxxxxxx...",
"DisplayName": "Vision Optics Support",
"IsActive": true,
"CreatedDate": "2024-01-15T10:30:00"
}
Creates or updates a WhatsApp Business Account configuration. Supply
encryptedWhatsAppConfigID to update an existing
one; omit it to create.
| Field | Type | Required | Description |
|---|---|---|---|
| encryptedWhatsAppConfigID | string | Optional | Encrypted configuration ID. Omit to create a new one. |
| wabaID | string | Required | Meta WhatsApp Business Account ID. |
| wabaName | string | Optional | Account name as registered with Meta. |
| phoneNumberID | string | Required | Meta phone number ID. |
| phoneNumber | string | Required | Sending number in E.164 form, for example +919876543210. |
| accessToken | string | Required | Meta access token. Send over HTTPS from a server only. |
| displayName | string | Required | Business name shown to recipients. |
| isActive | boolean | Optional | Set false to suspend sending without deleting the configuration. |
| status | string | Optional | Connection status. |
| webhookURL | string | Optional | Delivery-receipt callback URL registered with Meta. |
| remarks | string | Optional | Internal notes. |
curl -X POST https://api.opto-soft.com/api/ClientWhatsAppConfig/Save \
-H "Authorization: Bearer YOUR_TOKEN" \
-H "Content-Type: application/json" \
-d '{
"wabaID": "102938475610293",
"wabaName": "OptoSoft Store",
"phoneNumberID": "109283746501928",
"phoneNumber": "+919876543210",
"accessToken": "META_ACCESS_TOKEN",
"displayName": "Vision Opticals",
"isActive": true
}'
{
"success": true,
"message": "WhatsApp configuration saved successfully.",
"id": "Q2ZQdGhSZVhBaVlXTnpaWFF3TWk0d01B"
}
WhatsApp requires business-initiated messages to use a template approved by Meta. These endpoints read the local template library and refresh its approval status.
Lists every message template known to OptoSoft for a company and branch, in any approval state. Use it for an admin screen where you need to see rejected and pending templates too.
| Name | Type | Required | Description |
|---|---|---|---|
| companyId | int64 | Required | Company (tenant). |
| branchId | int64 | Required | Branch. |
| templateName | string | Optional | Filter by template name. |
| category | string | Optional | Meta template category, for example UTILITY or MARKETING. |
| language | string | Optional | Language code, for example en or en_US. |
| isActive | boolean | Optional | Filter to active templates only. |
| fromPage | int32 | Optional | First row of the range. |
| toPage | int32 | Optional | Last row of the range. |
| orderBy | string | Optional | Sort column, optionally with DESC. |
curl "https://api.opto-soft.com/api/WhatsAppTemplateMaster/list?companyId=18&branchId=24&isActive=true&fromPage=1&toPage=50" \
-H "Authorization: Bearer YOUR_TOKEN"
[
{
"ID": 1,
"TemplateName": "order_confirmation",
"TemplateCode": "ORDER_CONF_01",
"Category": "TRANSACTIONAL",
"DisplayName": "Order Confirmation",
"ApprovalStatus": "APPROVED",
"CreatedDate": "2024-01-01T00:00:00"
},
{
"ID": 2,
"TemplateName": "welcome_message",
"TemplateCode": "WELCOME_01",
"Category": "MARKETING",
"DisplayName": "Welcome Message",
"ApprovalStatus": "PENDING",
"CreatedDate": "2024-01-10T00:00:00"
}
]
Lists only the templates Meta has approved — the ones you can actually send. This is the endpoint to call when populating a "choose a message" picker, so operators never select a template that will be rejected at send time.
| Name | Type | Required | Description |
|---|---|---|---|
| companyId | int64 | Required | Company (tenant). |
| branchId | int64 | Required | Branch. |
| templateName | string | Optional | Filter by template name. |
| category | string | Optional | Meta template category. |
| language | string | Optional | Language code. |
| fromPage | int32 | Optional | First row of the range. |
| toPage | int32 | Optional | Last row of the range. |
| orderBy | string | Optional | Sort column. |
There is no isActive parameter here —
approval status is the filter. That is the only difference from
/list.
curl "https://api.opto-soft.com/api/WhatsAppTemplateMaster/approved?companyId=18&branchId=24&category=UTILITY&language=en" \
-H "Authorization: Bearer YOUR_TOKEN"
[
{
"ID": 1,
"CompanyID": 5,
"BranchID": null,
"TemplateName": "order_confirmation",
"TemplateCode": "ORDER_CONF_01",
"Category": "TRANSACTIONAL",
"Language": "en",
"VariableCount": 3,
"DisplayName": "Order Confirmation",
"HeaderType": "TEXT",
"HeaderContent": "Your order is confirmed!",
"BodyContent": "Dear {{1}}, your order {{2}} worth ₹{{3}} has been confirmed.",
"FooterContent": "Vision Optics",
"ButtonConfig": null,
"MetaCategory": "UTILITY",
"MetaLanguage": "en_US",
"ApprovalStatus": "APPROVED",
"RejectionReason": null,
"SubmittedToMetaAt": "2024-01-01T00:00:00",
"LastStatusCheckAt": "2024-01-15T08:00:00",
"CreatedDate": "2024-01-01T00:00:00"
}
]
Returns one template in full, including its body text and the placeholder variables it expects.
| Name | Type | Required | Description |
|---|---|---|---|
| id | string | Required | Encrypted template ID from /list or /approved. |
curl https://api.opto-soft.com/api/WhatsAppTemplateMaster/ENCRYPTED_TEMPLATE_ID \
-H "Authorization: Bearer YOUR_TOKEN"
{
"ID": 1,
"CompanyID": 5,
"BranchID": null,
"TemplateName": "order_confirmation",
"TemplateCode": "ORDER_CONF_01",
"Category": "TRANSACTIONAL",
"Language": "en",
"VariableCount": 3,
"DisplayName": "Order Confirmation",
"HeaderType": "TEXT",
"HeaderContent": "Your order is confirmed!",
"BodyContent": "Dear {{1}}, your order {{2}} worth ₹{{3}} has been confirmed.",
"FooterContent": "Vision Optics",
"ButtonConfig": "[{\"type\":\"URL\",\"text\":\"View Order\",\"url\":\"https://example.com/order/{{1}}\"}]",
"MetaCategory": "UTILITY",
"MetaLanguage": "en_US",
"ApprovalStatus": "APPROVED",
"RejectionReason": null,
"SubmittedToMetaAt": "2024-01-01T00:00:00",
"LastStatusCheckAt": "2024-01-15T08:00:00",
"CreatedDate": "2024-01-01T00:00:00"
}
Pulls the current template list and approval statuses from Meta into OptoSoft. Run it after submitting a new template for review, or on a schedule, so the local library does not drift from what Meta will actually accept.
None. Send an empty POST with the Authorization header.
curl -X POST https://api.opto-soft.com/api/WhatsAppTemplateMaster/sync \
-H "Authorization: Bearer YOUR_TOKEN" \
-H "Content-Length: 0"
This call reaches out to Meta, so it is slower than the read endpoints and subject to Meta’s own rate limits. Once or twice a day is plenty — do not call it before every send.
Marketing consent lives on the customer record — the
dndForPromotionalMessage and
dndForTransactionalMessage flags documented under
Customers & Prescriptions.
Honour them in any campaign you build. The recall schedule that triggers eye-test
reminders is set on the sale — see
eyecheckupRecallModel under
Quick Sale.
{
"success": true,
"message": "Template sync triggered successfully.",
"syncedCount": 12
}