WhatsApp Messaging – OptoSoft API
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.
WhatsApp Messaging
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.
Account configuration
POST /api/ClientWhatsAppConfig/List
Bearer tokenLists the WhatsApp Business Account configurations for a company, with paging. A multi-store chain typically has one configuration per branch.
Request body
| 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. |
Response
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.
Example request
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"
}'
Example response — 200 OK
{
"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
}
GET /api/ClientWhatsAppConfig/{id}
Bearer tokenReturns one WhatsApp Business Account configuration in full.
Path parameters
| Name | Type | Required | Description |
|---|---|---|---|
| id | string | Required | Encrypted WhatsApp configuration ID. |
Response
| 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. |
Example request
curl https://api.opto-soft.com/api/ClientWhatsAppConfig/ENCRYPTED_CONFIG_ID \
-H "Authorization: Bearer YOUR_TOKEN"
Example response — 200 OK
{
"ID": "Q2ZQdGhSZVhBaVlXTnpaWFF3TWk0d01B",
"WabaID": "123456789012345",
"PhoneNumberId": "987654321098765",
"AccessToken": "EAAxxxxxx...",
"DisplayName": "Vision Optics Support",
"IsActive": true,
"CreatedDate": "2024-01-15T10:30:00"
}
POST /api/ClientWhatsAppConfig/Save
Bearer token
Creates or updates a WhatsApp Business Account configuration. Supply
encryptedWhatsAppConfigID to update an existing
one; omit it to create.
Request body
| 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. |
Example request
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
}'
Example response — 200 OK
{
"success": true,
"message": "WhatsApp configuration saved successfully.",
"id": "Q2ZQdGhSZVhBaVlXTnpaWFF3TWk0d01B"
}
Message templates
WhatsApp requires business-initiated messages to use a template approved by Meta. These endpoints read the local template library and refresh its approval status.
GET /api/WhatsAppTemplateMaster/list
Bearer tokenLists 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.
Query parameters
| 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. |
Example request
curl "https://api.opto-soft.com/api/WhatsAppTemplateMaster/list?companyId=18&branchId=24&isActive=true&fromPage=1&toPage=50" \
-H "Authorization: Bearer YOUR_TOKEN"
Example response — 200 OK
[
{
"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"
}
]
GET /api/WhatsAppTemplateMaster/approved
Bearer tokenLists 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.
Query parameters
| 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.
Example request
curl "https://api.opto-soft.com/api/WhatsAppTemplateMaster/approved?companyId=18&branchId=24&category=UTILITY&language=en" \
-H "Authorization: Bearer YOUR_TOKEN"
Example response — 200 OK
[
{
"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"
}
]
GET /api/WhatsAppTemplateMaster/{id}
Bearer tokenReturns one template in full, including its body text and the placeholder variables it expects.
Path parameters
| Name | Type | Required | Description |
|---|---|---|---|
| id | string | Required | Encrypted template ID from /list or /approved. |
Example request
curl https://api.opto-soft.com/api/WhatsAppTemplateMaster/ENCRYPTED_TEMPLATE_ID \
-H "Authorization: Bearer YOUR_TOKEN"
Example response — 200 OK
{
"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"
}
POST /api/WhatsAppTemplateMaster/sync
Bearer tokenPulls 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.
Request body
None. Send an empty POST with the Authorization header.
Example request
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.
Related
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.
Example response — 200 OK
{
"success": true,
"message": "Template sync triggered successfully.",
"syncedCount": 12
}