# WhatsApp Template Management

This documentation covers details of the WhatsApp API documentation

# REST API components & How to read them

REST APIs are the most prevalent and user-friendly type of APIs you will most likely encounter. As a product manager, you play a pivotal role in working with your engineering team to bring digital solutions to life, and a fundamental part of that collaboration is understanding REST APIs.

In this document, you’ll learn how to break down REST APIs into their essential components so you can confidently discuss, dissect, interact with, and debug them.

<section class="section section--body" id="bkmrk-a-brief-intro-to-res">## A brief intro to REST APIs

REST APIs are a **set of rules and conventions** that define a standardized way for requests and responses to be structured and exchanged. They are based on the principles of REST, a software architectural style for designing networked applications. You’ll also hear the term RESTful APIs in relation to REST APIs.

Here are a couple of examples of RESTful rules and conventions followed by REST APIs (not important to memorize, just to give you an idea of what these rules look like):

<div class="section-content"><div class="section-inner sectionLayout--insetColumn">1. **Client-server**: Separation of concerns whereby the user interface concerns (client) are separate from the data storage concerns (server).
2. **Stateless**: Each request from the client to the server must contain all of the information necessary to understand and complete the request. The server cannot use previously stored context information on the server.

</div></div>REST APIs make extensive use of HTTP (Hypertext Transfer Protocol) as the foundation for communication between clients (like web browsers or mobile apps) and servers (where the API is hosted).

The majority of what you need to know about APIs are related to HTTP and it’s components. We can broadly bucket the components into the API Request and API Response:

###### ![1*J8x84KaR0akEMweLIlyKIw.png](https://cdn-images-1.medium.com/max/1600/1*J8x84KaR0akEMweLIlyKIw.png)Components of an API Request and API Response

</section><section class="section section--body" id="bkmrk-%C2%A0-%C2%A0api-request-when-"><div class="section-divider"> </div><div class="section-divider">---

</div>##    
API Request

When you make a request to an API, you’re essentially saying, “I want to do something or get something from this endpoint.” Requests consist of the following components:

### 1/ API Endpoint

An endpoint is the specific location aka the access point to the API. Think of it as an address for a particular service or resource. These endpoints are usually represented as URLs (Uniform Resource Locators), making them easy to understand. The API endpoint is made up of the “ Base URL” plus the “path” of the API.

<div class="section-content"><figure class="graf graf--figure">![0*cYUsCUf5xOLQvOU9](https://cdn-images-1.medium.com/max/1600/0*cYUsCUf5xOLQvOU9)</figure></div>### 2/ HTTP Methods

HTTP (Hypertext Transfer Protocol) methods are the actions you can take when interacting with an API. There are 8 request types but 4 are the most commonly used:

<div class="section-content">- **GET**: This method is like asking for information. When you send a GET request to an API’s endpoint, you’re **requesting data**, like retrieving weather information for a specific location.
- **POST**: When you send a POST request, you’re submitting data to the API which **adds new data to the database**. This could be creating a new user account or adding a comment on a blog post.
- **PUT**: Use the PUT method to **update existing data**. For instance, you might change your profile picture on a social media app.
- **DELETE**: As the name suggests, the DELETE method is for **removing data**. If you want to delete a post or an account, you’d use this method.

</div>You’ll likely see all 4 HTTP methods being used at some point, but out of the 4, you’ll see the GET and POST method most frequently and those are the two that you should be most familiar with.

*Two quick side notes:*

<div class="section-content">- The POST and PUT methods are often used interchangeably. The difference has to do with something called *idempotency* which is very technical and not worth diving into.
- You’ll also see the same POST API sometimes used to both *add* new data and *update* existing data. Developers may decide to design the API this way to be more efficient as opposed to creating and managing two separate APIs in the business logic: one POST and the other PUT.

</div>### 3/ Request Headers

Request headers convey additional information about the API request, such as the format in which the client expects the response (e.g., JSON or XML), authentication credentials, caching instructions, and more.

Here’s an example using APIs on Amazon:

```
Accept-Language: en-US<br></br>Authorization: Bearer YourAccessTokenHere<br></br>Content-Type: application/json<br></br>Host: www.amazon.com<br></br>Origin: https://www.amazon.com<br></br>Referer: https://www.amazon.com<br></br>User-Agent: Mozilla/5.0 (Macintosh; Intel Mac OS X 10_15_7) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/117.0.0.0 Safari/537.36
```

Information in the request header can be used for a number of reasons including:

<div class="section-content">- **Authenticating the request:** There are various authentication methods, such as API keys, OAuth tokens, and username/password combinations. For example, credentials for your bank account so the API is authorized to make changes to your account.
- **Caching instructions:** Temporarily storing data in a cache for improved future performance/latency.
- **Logging:** All systems keep a log of events that occur in a computer system. Information stored in the headers (i.e. location of request origin, browser information, date &amp; time of request, etc..) are logged in log files. The information in the log files can then be used for a variety of reasons: debugging, metrics, and telemetry. Accept-Language: en-US  
    Authorization: Bearer YourAccessTokenHere

</div>### 4/ Request Body

When you need to send data to the server, you include it in the request body. The data is typically in a structured format like [JSON](https://www.w3schools.com/js/js_json_intro.asp) or [XML](https://www.w3schools.com/xml/xml_whatis.asp). This is common when creating new records or updating existing ones. The request body is akin to a letter with the information you want to submit.

For example: Amazon has an internal API that adds a new product into the database.

```
POST https://products.amazon.com/api/2017/add
```

```
{<br></br>  "product_name": "Smartphone",<br></br>  "price": 499.99,<br></br>  "description": "A high-quality smartphone with advanced features.",<br></br>  "category": "Electronics",<br></br>  "availability": true<br></br>}<br></br><br></br>
```

</section><section class="section section--body" id="bkmrk-%C2%A0-api-response-once-"><div class="section-divider">---

</div>###  

## API Response

Once you send a API request, you’ll receive an API response. This response contains the data or information you requested, as well as metadata about the response itself. It consists of the following components:

### 1/ Status Code

This is a three-digit number that tells you the outcome of your request. Status codes are like short, standardized messages that quickly convey whether your request was successful, encountered an issue, or faced an error. All status codes are divided into 5 categories but you’ll only really encounter 4 of them:

<div class="section-content"><div class="section-inner sectionLayout--insetColumn">- [**2xx: Success**](https://skiplevel.msnd37.com/tracking/lc/af0de232-35db-e9cb-8c7c-eb7e413108cb/e5153d34-3b62-4785-8649-09625e972de3/00000000-0000-0000-0000-000000000000/) — The API request was successful! *e.g. 200 OK, 201 Created*
- [**3xx: Redirection**](https://skiplevel.msnd37.com/tracking/lc/af0de232-35db-e9cb-8c7c-eb7e413108cb/4e6f662a-2d4e-4001-b9ca-97d910ca37d7/00000000-0000-0000-0000-000000000000/) — The API request has more than one response. *e.g. 301 Moved Permanently, 302 Found*
- [**4xx: Client Error**](https://skiplevel.msnd37.com/tracking/lc/af0de232-35db-e9cb-8c7c-eb7e413108cb/e1665142-690e-4366-a72b-1b7278c323c9/00000000-0000-0000-0000-000000000000/) — Some information provided in the request was wrong or missing. *e.g. 400 Bad Request, 401 Unauthorized*
- [**5xx: Server Error**](https://skiplevel.msnd37.com/tracking/lc/af0de232-35db-e9cb-8c7c-eb7e413108cb/82328843-b42d-498f-a78d-28469b087ebb/00000000-0000-0000-0000-000000000000/) — Something went wrong on the server and the request wasn’t successful. *e.g. 501 Internal Server Erorr, 502 Bad Gateway*

</div></div>Here are some examples of common status codes:

<div class="section-content"><div class="section-inner sectionLayout--insetColumn">- **200 OK**: Your request was successful, and you’ll find the data you wanted in the response.
- **201 Created**: This code typically appears after a successful POST request, indicating that the resource you requested has been created.
- **400 Bad Request**: If the API couldn’t understand your request, you might see this code.
- **401 Unauthorized**: When you lack proper authorization or credentials to access the requested data, this code appears.
- **404 Not Found**: This indicates that the endpoint or resource you’re looking for doesn’t exist.
- **500 Internal Server Error**: If something goes wrong on the other island (the API’s server), you might see this code.

</div></div>##### ![1*fTqd36d2IyWnwimm0RhcTA.png](https://cdn-images-1.medium.com/max/1600/1*fTqd36d2IyWnwimm0RhcTA.png)Common API status codes

### 2/ Response Headers

Similar to request headers, response headers provide additional information about the response, such as the type of data you’re receiving (e.g., JSON or XML), the server’s version, and more.

Here’s an example:

```
Access-Control-Allow-Origin: www.amazon.com<br></br>Content-Length: 22<br></br>Content-Type: application/json<br></br>Date: Mon, 30 Oct 2023 16:32:01 GMT
```

### 3/ Response Body

This is where you’ll find the actual data or information you requested. Like the request body, the response body is often in JSON format for easy readability and parsing.

Using the same API example as the one in the request body, here’s what a successful response where the product was successfully added to the database might look like. Notice the API response returned a newly created *product\_id* uniquely assigned to the added product.

```
200 OK POST https://products.amazon.com/api/2017/add
```

```
{<br></br>  "product_id": 12345,<br></br>  "message": "Product 'Smartphone' has been successfully added."<br></br>}
```

##   
Conclusion

We’ve covered the crucial parts of the API and you now have all the information you need to confidently discuss, dissect, interact with, and debug APIs.

##### ![1*mo5UFEREModhtJ48UfPUAg.png](https://cdn-images-1.medium.com/max/1600/1*mo5UFEREModhtJ48UfPUAg.png)REST API Model

</section>

# WhatsApp Templates - things to know

[![image.png](https://docs.versalence.online/uploads/images/gallery/2024-12/scaled-1680-/image.png)](https://docs.versalence.online/uploads/images/gallery/2024-12/image.png)

# **Templates**

Templates are used in template messages to open marketing and utility conversations with customers. Unlike free-form messages, template messages are the only type of message that can be sent to customers who have yet to message you, or who have not sent you a message in the last 24 hours.

Templates must be approved before they can be sent in template messages. In addition, templates may be disabled automatically based on customer feedback and engagement. Once disabled, a template cannot be sent in a template message until its quality rating has improved or it no longer violates our [business](https://l.facebook.com/l.php?u=https%3A%2F%2Fwww.whatsapp.com%2Flegal%2Fbusiness-policy%2F%3Ffbclid%3DIwZXh0bgNhZW0CMTEAAR2QPv-srwZ8ydgx11lM3wqmDd8L9WDVsIDRH4jYRN2r3c0l9FyM0DhMGkA_aem_LzRLU1UHpRlL-nP-yVNuCQ&h=AT2ugrHM8VV69I34QNPxxSruXBQ8liZeYC0ptwjec1GlPQf-BulaYic9gce8vmjpRXopDLrG8X9n8DHTSoK7bU_JokFuTZVDn_oAvqbr8PmxRb8zTNTJfvwKutP_uTBjquTPkA) or [commerce](https://l.facebook.com/l.php?u=https%3A%2F%2Fwww.whatsapp.com%2Flegal%2Fcommerce-policy%2F%3Ffbclid%3DIwZXh0bgNhZW0CMTEAAR3q8UOVHPxtacwrlDAoH4-Vj6pOaLMBqieHHkoKvhnAnvnfi_ZcY-tPfLE_aem_PlfYMbGAF8xTnX2hAhqIqA&h=AT1gZnmCfWQK7GqP85LJPy9PWApO2b3FeyQhFAzVUA_1tlXoicYctoCLOErrWK30I14dV3AFn9mw_6qv1fn-8JkNCt10VW_AYuo9VbD0zFuXZ-bzowqm5F2XXs9JQMAR7YuQSQ) policies.

## Creation

Use the template creation API to create templates.

## Approval Process

Once you have created your template you can submit it for approval. It can take up to 24 hours for an approval decision to be made. Once a decision has been made, a notification will appear in your Broadcast Templates Manager.

If your message template is approved, its status will be set to ✅<span style="background-color:rgb(191,237,210);">**Approved**</span> and you can begin sending it to customers. If it is rejected, its status will be set to ❌<span style="background-color:rgb(248,202,198);">**Rejected.**</span> The template has to be deleted and wait for 24 hours to reapply again with the same template name.

<p class="callout info">Multiple templates of the same name can be created by changing the template language</p>

### Samples

If your template uses variables you must include sample variable values (media assets, text strings, etc.) with your submission. This makes it easier for us to visualize how your template will appear to customers.

To include a sample with your submission in the WhatsApp Manager, first create your template, add any variables that it requires, and then click the Add Sample button. The preview pane will render any sample media assets or sample text values you provide.

[![image.png](https://docs.versalence.online/uploads/images/gallery/2024-12/scaled-1680-/NwYimage.png)](https://docs.versalence.online/uploads/images/gallery/2024-12/NwYimage.png)

<div class="_4-u2 _57mb _1u44 _3fw6 _4-u8 _3la3" id="bkmrk--2"><div class="_4-u3 _588p"><div>  
</div>  
</div></div>If using our APIs to create templates, include the `examples` property for each template component object in your request that uses a variable.

### Common Rejection Reasons

Submissions are commonly rejected for the following reasons, so make sure you avoid these mistakes.

<div class="_4-u2 _57mb _1u44 _3fw6 _4-u8 _3la3" id="bkmrk-variable-parameters-"><div class="_4-u3 _588p">- Variable parameters are missing or have mismatched curly braces. The correct format is `{{1}}`.
- Variable parameters contain special characters such as a `#`, `$`, or `%`.
- Variable parameters are not sequential. For example, `{{1}}`, `{{2}}`, `{{4}}`, `{{5}}` are defined but `{{3}}` does not exist.
- Template contains too many variable parameters relative to the message length. You need to decrease the number of variable parameters or increase the message length.
- The message template cannot end with a parameter.
- The message template contains content that violates WhatsApp’s Commerce Policy: When you offer goods or services for sale, we consider all messages and media related to your goods or services, including any descriptions, prices, fees, taxes and/or any required legal disclosures, to constitute transactions. Transactions must comply with the [WhatsApp Commerce Policy](https://www.whatsapp.com/legal/commerce-policy/?fbclid=IwZXh0bgNhZW0CMTEAAR1U4FKHxtBNjKPC0uiEITmNU_oGG-hzmRI6b-CmWdb_3c-EUrepuFJxeAw_aem_kd0u7liElb4oCjVu6yTL6A).
- The message template contains content that violates the [WhatsApps Business Policy](https://l.facebook.com/l.php?u=https%3A%2F%2Fwww.whatsapp.com%2Flegal%2Fbusiness-policy%2F%3Ffbclid%3DIwZXh0bgNhZW0CMTEAAR26hm74SbloYJsfDZAz2E5ao8enzHz5UaZpVrW2_N76xzCtn2i1QkzgT9k_aem_iTIpYnR3lzICa2H0pEJpkA&h=AT3OGlARr0szxHyp9T9Kr_1DGFFteT4KEMKuu0Mo9vqeHEObwj6VNzn19_V3uBoTQjJeMMDevAkVScGMeTWcNpN4AhynV14-uaVnOeoNsp1ph_1aClTz8wcNwtnoJETdp6liXg): Do not request sensitive identifiers from users. For example, do not ask people to share full length individual payment card numbers, financial account numbers, National Identification numbers, or other sensitive identifiers. This also includes not requesting documents from users that might contain sensitive identifiers. Requesting partial identifiers (ex: last 4 digits of their Social Security number) is OK.
- The content contains potentially abusive or threatening content, such as threatening a customer with legal action or threatening to publicly shame them.
- The message template is a duplicate of an existing template. If a template is submitted with the same wording in the body and footer of an existing template, the duplicate template will be rejected.

</div></div>

# WhatsApp Templates API Management

<p class="callout info">The template APIs allow you to create, delete, and fetch templates</p>

#### The templates API supports the following methods and are client specific

- GET
- POST
- DELETE

##### <span style="background-color:rgb(191,237,210);">Get all templates</span>

```bash
curl --location 'https://api.versal.one/<client-id>/templates' \
--header 'Authorization: Bearer <client-token>'
```

##### <span style="background-color:rgb(191,237,210);">Get a template by name</span>

```bash
curl --location 'https://api.versal.one/<client-id>/templates?name=order_delivery_1' \
--header 'Authorization: Bearer <client-token>'
```


##### <span style="background-color:rgb(191,237,210);">Create a template</span>

To create a template - the following components are required

> - name - template name <span style="background-color:rgb(248,202,198);">\[cannot contain Upper case, space, special characters\]</span> can contain underscore "\_" and a max of 25 characters
> - language - en \[English\], en\_US \[English US\]. [Click here](https://developers.facebook.com/docs/whatsapp/business-management-api/message-templates/supported-languages/) for the complete list
> - category - Marketing/Utility
> - components - Header, Body, Footer
> 
> for more details [check the official documentation](https://developers.facebook.com/docs/whatsapp/business-management-api/message-templates/) on the META website

```bash
curl --location 'https://api.versal.one/<client-id>/templates' \
--header 'Authorization: Bearer <client-token>' \
--data '{
    "name": "order_delivery_1",
    "language": "en_US",
    "category": "Marketing",
    "components": [
        {
            "type": "HEADER",
            "format": "Text",
            "text": "header text"
        },
        {
            "type": "BODY",
            "text": "This is a {{1}}",
            "example": {
                "body_text": [
                    [
                        "random text"
                    ]
                ]
            }
        },
        {
            "type": "FOOTER",
            "text": "lasadoasi"
        },
        {
            "type": "BUTTONS",
            "buttons": [
                {
                    "type": "PHONE_NUMBER",
                    "text": "Call",
                    "phone_number": "+918897229166"
                }
            ]
        }
    ]
}'
```

```bash
{
    "message": "Template created successfully",
    "response_text": "{\"id\":\"1179134613392693\",\"status\":\"APPROVED\",\"category\":\"MARKETING\"}",
    "status": "200"
}
```

# Template Components

Templates are made up of four primary components which you define when you create a template: header, body, footer, and buttons. The components you choose for each of your templates should be based on your business needs. The only required component is the body component.

Some components support variables, whose values you can supply when using the Cloud API or On-Premises API to send the template in a template message. If your templates use variables, you must include sample variable values upon template creation.

## Headers

Headers are optional components that appear at the top of template messages. Headers support text, media (images, videos, documents), and locations.

All templates are limited to one header component

### Text Headers

You can choose to add header text to your message template. The message text in the header component accepts parameters for programmatic configuration.

Text parameters can be configured in one of two formats:

<div class="_4-u2 _57mb _1u44 _3fw6 _4-u8 _3la3" id="bkmrk-positional%C2%A0%E2%80%94-pass-in"><div class="_4-u3 _588p">- **Positional** — Pass in an array of parameters that correspond to numeric positions in the body text with examples 
    - For example: `“Hello John, your account balance is {{1}}” | [ “$1,000” ]`
- **Named** — Pass in JSON objects that contain a parameter name and examples 
    - For example: `{ "param_name": "account_balance", "example": "$1,000" }`

  
</div></div>#### Component Syntax

Add this header component object into the `”components”[]` object array when calling the `POST <WHATSAPP_BUSINESS_ACCOUNT_ID>/message_templates` endpoint. Substitute the placeholder properties below using the properties table.

```
{
  "type": "HEADER",
  "format": "TEXT",
  "text": "<HEADER_TEXT>",

  "example": {
    "header_text": [
       // You must provide one of the inputs below when the <HEADER_TEXT> string contains parameters
       <POSITIONAL_PARAM_EXAMPLES>
       <BODY_TEXT_NAMED_PARAMS>
    ]
  }
}
```

#### Properties

<div class="_4-u2 _57mb _1u44 _3fw6 _4-u8 _3la3" id="bkmrk-placeholder-descript"><div class="_4-u3 _588p">  
<div class="_57-c"><table class="_4-ss _5k9x" style="width:100.002%;"><thead><tr><th style="width:15.9699%;">Placeholder</th><th style="width:46.9607%;">Description</th><th style="width:37.0598%;">Example Value</th></tr></thead><tbody class="_5m37" id="bkmrk-%3Cheader_text%3E-string"><tr class="row_0"><td style="width:15.9699%;">`<HEADER_TEXT>`

</td><td style="width:46.9607%;">*`String`* | **Required**

Plain text string. Can support 1 parameter.

If this string contains parameters, you must include the `example` property and example parameter values as shown in `<POSITIONAL_PARAM_EXAMPLES>` and `<HEADER_TEXT_NAMED_PARAMS>` below.

60 character maximum.

</td><td style="width:37.0598%;">`“Our Holiday sale starts December 1st!”`

`“Our new sale starts {{1}}”`

`“Our new sale starts {{sale_start_date}}!”`

</td></tr><tr class="row_1 _5m29"><td style="width:15.9699%;">`<POSITIONAL_PARAM_EXAMPLES>`

</td><td style="width:46.9607%;">*`[String]`* | *Optional*

Required when using positional parameters in your header text.

Array of `String` in which each string is meant to illustrate the text likely to be passed in as a parameter during message send time, for example a bank account balance, or a customer name.

The number of strings must match the number of variables included in the string.

</td><td style="width:37.0598%;">`["December 1st"]`

</td></tr><tr class="row_2"><td style="width:15.9699%;">`<HEADER_TEXT_NAMED_PARAMS>`

</td><td style="width:46.9607%;">*`[JSON Object]`* | *Optional*

Required when using named variables in your header text.

Array of JSON objects that contain `param_name` and `example` strings.

- `“param_name”` — Your custom parameter name. Must be lowercase letters and underscores only.
- `“example”` — The illustrative sample text for the parameter.

</td><td style="width:37.0598%;">```
[{
 "param_name": "sale_start_date",
 "example": "December 1st"
}]
          
```

</td></tr></tbody></table>

</div>  
</div></div>#### Positional Parameter Example

```
{
  "type": "HEADER",
  "format": "TEXT",
  "text": "Our new sale starts {{1}}!",
  "example": {
    "header_text": [
      "December 1st"
    ]
  }
}
```

<div class="_4-u2 _57mb _1u44 _3fw6 _4-u8 _3la3" id="bkmrk-"><div class="_4-u3 _588p">  
</div></div>#### Named Parameter Example

```
{
  "type": "HEADER",
  "format": "TEXT",
  "text": "Our new sale starts {{sale_start_date}}!",
  "example": {
    "header_text_named_params": [
      {
        "param_name": "sale_start_date",
        "example": "December 1st"
      }
    ]
  }
}
```

### Media Headers

Media headers can be an image, video, or a document such as a PDF. All media must be uploaded with the [Resumable Upload API](https://developers.facebook.com/docs/graph-api/guides/upload). The syntax for defining a media header is the same for all media types.

#### Syntax

```
{
  "type": "HEADER",
  "format": "<FORMAT>",
  "example": {
    "header_handle": [
      "<HEADER_HANDLE>"
    ]
  }
}
```

#### Properties

<div class="_4-u2 _57mb _1u44 _3fw6 _4-u8 _3la3" id="bkmrk-placeholder-descript-1"><div class="_4-u3 _588p">  
<div class="_57-c"><table class="_4-ss _5k9x"><thead><tr><th>Placeholder</th><th>Description</th><th>Example Value</th></tr></thead><tbody class="_5m37" id="bkmrk-%3Cformat%3E-indicates-m"><tr class="row_0"><td>`<FORMAT>`

</td><td>Indicates media asset type. Set to `IMAGE`, `VIDEO`, or `DOCUMENT`.

</td><td>`IMAGE`

</td></tr><tr class="row_1 _5m29"><td>`<HEADER_HANDLE>`

</td><td>Uploaded media asset handle. Use the [Resumable Upload API](https://developers.facebook.com/docs/graph-api/guides/upload) to generate an asset handle.

</td><td>`4::aW...`

</td></tr></tbody></table>

</div></div></div>#### Example

```
{
  "type": "HEADER",
  "format": "IMAGE",
  "example": {
    "header_handle": [
      "4::aW..."
    ]
  }
}
```

<div class="_4-u2 _57mb _1u44 _3fw6 _4-u8 _3la3" id="bkmrk--1"><div class="_4-u3 _588p">  
</div></div>## Body

The body component represents the core text of your message template and is a text-only template component. It is required for all templates.

The message text in the body component accepts parameters for programmatic configuration.

Text parameters can be configured in one of two formats:

<div class="_4-u2 _57mb _1u44 _3fw6 _4-u8 _3la3" id="bkmrk-positional%C2%A0%E2%80%94-pass-in-1"><div class="_4-u3 _588p">- **Positional** — Pass in an array of numbered positional parameters that correspond to numeric positions in the body text with examples 
    - For example: `“Hello {{1}}, your account balance is {{2}}” | [ “John”, “$1,000” ]`
- **Named** — Pass in JSON objects that contain a parameter name and examples 
    - For example: `{ "param_name": "order_id", "example": "335628"}`

</div></div>All templates are limited to one body component.

### Component Syntax

Add this body component object into the `”components”[]` object array when calling the `POST <WHATSAPP_BUSINESS_ACCOUNT_ID>/message_templates` endpoint. Substitute the placeholder properties below using the properties table.

```
{
  "type": "body",
  "text": "<BODY_TEXT>",
  "example": {
    "body_text": [
      [
       // You must provide one of the inputs below when the <BODY_TEXT> string contains parameters
       <POSITIONAL_PARAM_EXAMPLES>
       <BODY_TEXT_NAMED_PARAMS>
      ]
    ]
  }
}
```

### Properties

<div class="_4-u2 _57mb _1u44 _3fw6 _4-u8 _3la3" id="bkmrk-placeholder-descript-2"><div class="_4-u3 _588p"><div class="_57-c"><table class="_4-ss _5k9x" style="width:100.002%;"><thead><tr><th style="width:18.1129%;">Placeholder</th><th style="width:43.8598%;">Description</th><th style="width:38.0178%;">Example Value</th></tr></thead><tbody class="_5m37" id="bkmrk-%3Cheader_text%3E-string-1"><tr class="row_0"><td style="width:18.1129%;">`<HEADER_TEXT>`

</td><td style="width:43.8598%;">*`String`* | **Required**

Plain text string. Can support multiple parameters.

If this string contains parameters, you must include the `example` property and example parameter values as shown in `<POSITIONAL_PARAM_EXAMPLES>` and `<BODY_TEXT_NAMED_PARAMS>` below.

1024 character maximum.

</td><td style="width:38.0178%;">`“Shop our Holiday sale now!”`

`“Shop now through {{1}} and use code {{2}} to get {{3}} off of all merchandise.”`

`“Your {{order_id}}, is ready {{customer_name}}”`

</td></tr><tr class="row_1 _5m29"><td style="width:18.1129%;">`<POSITIONAL_PARAM_EXAMPLES>`

</td><td style="width:43.8598%;">*`[String]`* | *Optional*

Required when using positional parameters in your body text.

Array of string in which each string is meant to illustrate the text likely to be passed in as a parameter during message send time, for example a bank account balance, or a customer name.

The number of strings must match the number of variables included in the string.

</td><td style="width:38.0178%;">`["the end of August","25OFF","25%"]`

</td></tr><tr class="row_2"><td style="width:18.1129%;">`<BODY_TEXT_NAMED_PARAMS>`

</td><td style="width:43.8598%;">*`[JSON Object]`* | *Optional*

Required when using named variables in your body text.

Array of JSON objects that contain `param_name` and `example` strings.

- `“param_name”` — Your custom parameter name. Must be lowercase letters and underscores only.
- `“example”` — The illustrative sample text for the parameter.

</td><td style="width:38.0178%;">```
[{
 "param_name": "order_id",
 "example": "335628"
},
{
 "param_name": "customer_name",
 "example": "Shiva"
}]
          
```

</td></tr></tbody></table>

</div>  
</div></div>#### Positional Parameter Example

```
{
  "type": "BODY",
  "text": "Shop now through {{1}} and use code {{2}} to get {{3}} off of all merchandise.",
  "example": {
    "header_text": [
      "the end of August","25OFF","25%"
    ]
  }
}
```

<div class="_4-u2 _57mb _1u44 _3fw6 _4-u8 _3la3" id="bkmrk--2"></div>#### Named Parameter Example

```
{
  "type": "BODY",
  "text": "Your {{order_id}}, is ready {{customer_name}}.",
  "example": {
    "header_text_named_params": [
      {
        "param_name": "order_id",
        "example": "335628"
      },
      {
        "param_name": "customer_name",
        "example": "Shiva"
      }
    ]
  }
}
```

<div class="_4-u2 _57mb _1u44 _3fw6 _4-u8 _3la3" id="bkmrk--3"><div class="_4-u3 _588p"><div>  
</div></div></div>## Footer

Footers are optional text-only components that appear immediately after the body component. Templates are limited to one footer component.

### Syntax

```
{
  "type": "FOOTER",
  "text": "<TEXT>"
}
```

### Properties

<div class="_4-u2 _57mb _1u44 _3fw6 _4-u8 _3la3" id="bkmrk-placeholder-descript-3"><div class="_4-u3 _588p">  
<div class="_57-c"><table class="_4-ss _5k9x"><thead><tr><th>Placeholder</th><th>Description</th><th>Example Value</th></tr></thead><tbody class="_5m37" id="bkmrk-%3Ctext%3E-text-to-appea"><tr class="row_0"><td>`<TEXT>`

</td><td>Text to appear in template footer when sent.

  
60 characters maximum.

</td><td>`Use the buttons below to manage your marketing subscriptions`

</td></tr></tbody></table>

</div></div></div>### Example

```
{
  "type": "FOOTER",
  "text": "Use the buttons below to manage your marketing subscriptions"
}
```

<div class="_4-u2 _57mb _1u44 _3fw6 _4-u8 _3la3" id="bkmrk--4"><div class="_4-u3 _588p"><div>  
</div></div></div>## Buttons

Buttons are optional interactive components that perform specific actions when tapped. Templates can have a mixture of up to 10 button components total, although there are limits to individual buttons of the same type as well as combination limits. These limits are described below.

Buttons are defined within a single buttons component object, packed into a single `buttons` array. For example, this template uses a phone number button and a URL button:

```
{
  "type": "BUTTONS",
  "buttons": [
    {
      "type": "PHONE_NUMBER",
      "text": "Call",
      "phone_number": "15550051310"
    },
    {
      "type": "URL",
      "text": "Shop Now",
      "url": "https://www.luckyshrub.com/shop/"
    }
  ]
}
```

If a template has more than three buttons, two buttons will appear in the delivered message and the remaining buttons will be replaced with a **See all options** button. Tapping the **See all options** button reveals the remaining buttons.

<div class="_4-u2 _57mb _1u44 _3fw6 _4-u8 _3la3" id="bkmrk--5"><div class="_4-u3 _588p"><div>![](https://scontent.fblr24-2.fna.fbcdn.net/v/t39.2365-6/362692024_651522560374555_6131765669860446689_n.png?stp=dst-webp&_nc_cat=111&ccb=1-7&_nc_sid=e280be&_nc_ohc=nFisgvxiIuUQ7kNvgFOoahz&_nc_zt=14&_nc_ht=scontent.fblr24-2.fna&_nc_gid=A1GvJeovemXNsxIqfmPNETy&oh=00_AYBItmu-yevxCiEufYeE7Q6yJkvgKJkmN8lKw-QfJ58lsQ&oe=676E1D3B)</div></div></div>### Copy Code Buttons

Copy code buttons copy a text string (defined when the template is sent in a template message) to the device's clipboard when tapped by the app user. Templates are limited to one copy code button.

#### Syntax

```
{
  "type": "COPY_CODE",
  "example": "<EXAMPLE>"
}
```

#### Properties

<div class="_4-u2 _57mb _1u44 _3fw6 _4-u8 _3la3" id="bkmrk-placeholder-descript-4"><div class="_4-u3 _588p">  
<div class="_57-c"><table class="_4-ss _5k9x"><thead><tr><th>Placeholder</th><th>Description</th><th>Example Value</th></tr></thead><tbody class="_5m37" id="bkmrk-%3Cexample%3E-string-to-"><tr class="row_0"><td>`<EXAMPLE>`

</td><td>String to be copied to device's clipboard when tapped by the app user.

  
Maximum 15 characters.

</td><td>`250FF`

</td></tr></tbody></table>

</div></div></div>#### Example

```
{
  "type": "COPY_CODE",
  "example": "250FF"
}
```

##### <span style="background-color:rgb(191,237,210);">Delete a template</span>

```bash
curl --location --request DELETE 'https://api.versal.one/<client-id>/templates?name=harsh45021279' \
--header 'Authorization: Bearer <client-token>'
```

# Send Template Messages

<p class="callout info">While sending a template message, the template contents are not sent. To send a template message, its media link \[public link\] &amp; variable values \[if any\] are sent along with the template name and language</p>

<p class="callout danger">Broadcast with caution - Do not spam. Spamming will lead to the degradation of service and WhatsApp number getting blocked</p>

##### **Sending Message**

##### <span style="background-color:rgb(191,237,210);">The template has no parameter</span>

```bash
curl --location 'https://api.versal.one/<client-id>' \
--header 'Authorization: Bearer <client-token>' \
--header 'Content-Type: application/json' \
--data '{
    "purpose": "sendtemplate",
    "to": <recepient phone number>,
    "template": <template name>,
    "code": <language code>    
}'

sample data
--data '{
    "purpose": "sendtemplate",
    "to": "919999900000",
    "template": "conv_start_hi",
    "code": "en_US"    
}'
```

##### <span style="background-color:rgb(191,237,210);">The template has image media</span>

<p class="callout info">The image typically does not look like a regular parameter while creating the template. However, is a parameter</p>

```bash
curl --location 'https://api.versal.one/<client-id>' \
--header 'Authorization: Bearer <client-token>' \
--header 'Content-Type: application/json' \
--data '{
    "purpose": "sendtemplate",
    "to": <recepient>,
    "template": "schedule",
    "code": "en",
    "components": [
        {
            "type": "header",
            "parameters": [
                {
                    "type": "image",
                    "image": {
                        "link": "https://cdn.anuhealthyfood.in/images/missyourorders.png"
                    }
                }
            ]
        }
    ]
}'
```

<p class="callout warning">The link has to be publically accessible, or else the template won't be delivered to the user</p>

##### <span style="background-color:rgb(191,237,210);">The template has body parameters</span>

```bash
curl --location 'https://api.versal.one/<client-id>' \
--header 'Authorization: Bearer <client-token>' \
--header 'Content-Type: application/json' \
--data '{
    "purpose": "sendtemplate",
    "to": <recepient>,
    "template": "schedule",
    "code": "en",
    "components": [
        {
            "type": "body",
            "parameters": [
                {
                    "type": "TEXT",
                    "text": "Hemant Suryavanshi"
                },
                {
                    "type": "TEXT",
                    "text": "Blue USB Microphone"
                },
                {
                    "type": "TEXT",
                    "text": "12/12/2024"
                }
            ]
        }
    ]
}'
```

<span style="background-color:rgb(191,237,210);"></span>

<p class="callout info">In the above example, the template has three body variables. As depicted, only parameters are passed and not the entire body</p>

##### <span style="background-color:rgb(191,237,210);">The template has body parameters and </span><span style="background-color:rgb(191,237,210);">image media</span>

```bash
curl --location 'https://api.versal.one/<client-id>' \
--header 'Authorization: Bearer <client-token>' \
--header 'Content-Type: application/json' \
--data '{
    "purpose": "sendtemplate",
    "to": <recepient>,
    "template": "schedule",
    "code": "en",
    "components": [
        {
            "type": "header",
            "parameters": [
                {
                    "type": "image",
                    "image": {
                        "link": "https://cdn.anuhealthyfood.in/images/missyourorders.png"
                    }
                }
            ]
        },
        {
            "type": "body",
            "parameters": [
                {
                    "type": "TEXT",
                    "text": "Hemant Suryavanshi"
                },
                {
                    "type": "TEXT",
                    "text": "Blue USB Microphone"
                },
                {
                    "type": "TEXT",
                    "text": "12/12/2024"
                }
            ]
        }
    ]
}'
```

<p class="callout info">In the above example, there is an image and three body parameters in the template</p>

<p class="callout success">Response</p>

```bash
{
    "message": "Message sent successfully",
    "response_text": "{"messaging_product":"whatsapp","contacts":[{"input":"+16312924377","wa_id":"16312924377"}],"messages":[{"id":"wamid.HBgLMTYzMTI5MjQzNzcVAgARGBIxNEExODY3MjhGMDNGNDRBNjgA","message_status":"accepted"}]}",
    "status": "200"
}

```

# vCX WhatsApp Onboarding & Messaging

## [![Co-existence.png](https://docs.versalence.online/uploads/images/gallery/2026-07/scaled-1680-/LNJ4i3znkroBlq3J-co-existence.png)](https://docs.versalence.online/uploads/images/gallery/2026-07/LNJ4i3znkroBlq3J-co-existence.png)Base URL - Administration

```
https://backend.admin.versalence.online/api/v2
```

All protected endpoints require:

```
Authorization: Bearer <JWT_TOKEN>
```

---

## 1. Authenticate the customer admin

The customer’s admin user logs in with their vCX credentials. The returned JWT is used for all subsequent calls.

```
POST /api/v2/login
Content-Type: application/json

{
  "email": "admin@customer.com",
  "password": "CustomerAdminPassword"
}
```

Response:

```
{
  "success": true,
  "message": "Sign-in successful",
  "token": "<JWT_TOKEN>"
}
```

**Notes:**

- The user must have `email_verified = 'yes'`.
- The account must be `active`.
- The JWT expiry is controlled by the server (`JWT_EXPIRES_IN`).
- The JWT contains the company `uuid`. The backend uses this to identify which company to onboard.

---

## 2. Get Agency Customers

```markdown
GET /api/admin/v2/getCustomers
Authorization: Bearer <agency-jwt>
```

Response:

```json
{
  "success": true,
  "message": "Customers retrieved successfully.",
  "data": [
    {
      "uuid": "...",
      "company_name": "...",
      "company_email": "...",
      "company_id": "AGTSW000012026",
      "account_status": "active",
      "parent_agency_uuid": "...",
      "company_member_since": "...",
      "user_name": "...",
      "user_email": "...",
      "user_phone": "...",
      "user_role": "admin",
      "user_status": "active"
    }
  ]
}
```

---

## 3. Login to Sub Account using company\_id

```markdown
GET /api/admin/v2/clientAgentLogin?client_id=<SUB_ACCOUNT_COMPANY_ID>
Authorization: Bearer <agency-owner-jwt>
```

#### How it works

1. The agency owner logs in via `/api/admin/v2/adminLogin` to get their own JWT.
2. They call `/api/admin/v2/clientAgentLogin?client_id=<company_id>` with that JWT.
3. The backend validates that the requested account is actually a sub-account under the agency.
4. It returns a JWT for the sub-account’s first admin user.

#### Example

```markdown
GET /api/admin/v2/clientAgentLogin?client_id=AGTSW000012026
Authorization: Bearer <agency-owner-jwt>
```

Response:

```json
{
  "success": true,
  "message": "User successfully logged in.",
  "token": "<sub-account-jwt>"
}
```

---

## Base URL - Backend

```
https://backend.versalence.online
```

All protected endpoints require:

```
Authorization: Bearer <JWT_TOKEN>
```

---

## 4. Check WhatsApp integration status

Use this to decide whether the customer still needs to onboard WhatsApp.

```
GET https://backend.versalence.online/api/v2/getWaba
Authorization: Bearer <JWT_TOKEN>
```

**Not integrated response:**

```
{
  "success": true,
  "message": "no whatsapp data found"
}
```

**Already integrated response:**

```
{
  "success": true,
  "message": "whatsapp data found",
  "data": [
    {
      "app_id": "...",
      "waba_id": "...",
      "access_token": "[hidden]",
      "phone_id": "...",
      "phone_number": "919876543210",
      "display_phone_number": "+91 98765 43210",
      "onboarding_mode": "standard",
      "is_active": true,
      "webhook_subscription_status": "subscribed"
    }
  ]
}
```

---

## 5. Launch Meta Embedded Signup

The mobile app never sees the Meta App ID. It asks the vCX backend for the OAuth URL, opens it in a browser, and polls for the result after Meta redirects back to vCX.

### 5a. Initiate WhatsApp Embedded Signup

```
GET https://backend.versalence.online/api/v2/whatsappSignupInit?mode=coexistence
Authorization: Bearer <vCX_JWT_TOKEN>
```

Query parameters:

<table id="bkmrk-parameter-required-v"><thead><tr><th>Parameter</th><th>Required</th><th>Values</th><th>Default</th><th>Description</th></tr></thead><tbody><tr><td>`mode`</td><td>No</td><td>`standard`, `coexistence`</td><td>`standard`</td><td>WhatsApp onboarding mode. Use `coexistence` if the customer wants to keep their existing WhatsApp Business app running alongside vCX.</td></tr></tbody></table>

Response:

```
{
  "success": true,
  "data": {
    "oauth_url": "https://www.facebook.com/v20.0/dialog/oauth?client_id=...&redirect_uri=...&scope=whatsapp_business_management&response_type=code&state=...",
    "state": "<STATE_TOKEN>",
    "redirect_uri": "https://backend.versalence.online/api/v2/whatsappSignupCallback",
    "scope": "whatsapp_business_management",
    "mode": "coexistence"
  }
}
```

**Mobile app action:** Open `oauth_url` in an in-app browser or WebView. Do not extract or store the Meta App ID.

### 5b. Meta OAuth callback

After the user completes Meta’s flow, Meta redirects the browser to the vCX backend. The mobile app does **not** call this endpoint directly.

```
GET https://backend.versalence.online/api/v2/whatsappSignupCallback?code=<META_AUTH_CODE>&state=<STATE_TOKEN>
```

What the backend does:

1. Exchanges the code for a Meta access token.
2. Resolves the WABA ID and phone number.
3. Registers the phone number.
4. Configures the vCX webhook.
5. Persists the account.
6. For `coexistence` mode, requests `smb_app_state_sync` and `history` sync from Meta.

On success, the browser is redirected to:

```
https://backend.versalence.online/whatsapp-signup-success
```

On failure:

```
https://backend.versalence.online/whatsapp-signup-failure?error=<ERROR_MESSAGE>
```

These redirect URLs are configurable via environment variables.

### 5c. Check WhatsApp signup status

The mobile app should poll this endpoint after the browser is redirected back.

```
GET /api/v2/whatsappSignupStatus
Authorization: Bearer <vCX_JWT_TOKEN>
```

**Not connected response:**

```
{
  "success": true,
  "message": "No WhatsApp account connected",
  "data": {
    "is_connected": false,
    "onboarding_mode": "standard"
  }
}
```

**Connected response:**

```
{
  "success": true,
  "message": "WhatsApp account connected",
  "data": {
    "is_connected": true,
    "onboarding_mode": "coexistence",
    "is_active": true,
    "waba_id": "...",
    "phone_id": "...",
    "phone_number": "919876543210",
    "display_phone_number": "+91 98765 43210",
    "webhook_subscription_status": "subscribed",
    "expires_in": "...",
    "last_message_at": null,
    "last_smb_message_echo_at": null,
    "last_history_at": null,
    "last_smb_app_state_sync_at": null
  }
}
```

This endpoint can be queried at any time in the future to check whether WhatsApp is still connected.

---

## 6. Get messaging API configuration

```
GET /api/v2/whatsappApiConfig
Authorization: Bearer <vCX_JWT_TOKEN>
```

Response:

```
{
  "success": true,
  "data": {
    "send_messages_url": "https://api.versal.one",
    "create_templates_url": "https://api.versal.one",
    "message_status_url": "https://apiproxy.versal.one"
  }
}
```

Use these endpoints (documented separately) to send messages, create templates, and check message delivery status.

---

## 7. Existing account lookup (backward-compatible)

```
GET /api/v2/getWaba
Authorization: Bearer <vCX_JWT_TOKEN>>
```

This existing endpoint continues to work and returns the connected WhatsApp account data. The mobile app may use either `/getWaba` or `/whatsappSignupStatus`.

## Onboarding modes

### Standard mode

```
GET /api/v2/whatsappSignupInit?mode=standard
```

- Uses the Meta Cloud API onboarding.
- The customer’s WhatsApp Business app will be replaced by vCX for business messaging.Coexistence mode

```
GET /api/v2/whatsappSignupInit?mode=coexistence
```

- The customer’s existing WhatsApp Business app continues to work.
- vCX receives messages through webhooks while the customer keeps using their native WhatsApp Business app.
- The backend requests `smb_app_state_sync` and `history` sync from Meta during onboarding.

#### Environment variables

Add these to the vCX backend `.env`:

```
# Backend-driven OAuth signup flow for external mobile apps.
# WHATSAPP_OAUTH_REDIRECT_URI must be registered in the Meta app settings.
WHATSAPP_OAUTH_REDIRECT_URI=https://backend.versalence.online/api/v2/whatsappSignupCallback
WHATSAPP_OAUTH_SUCCESS_REDIRECT=https://backend.versalence.online/whatsapp-signup-success
WHATSAPP_OAUTH_FAILURE_REDIRECT=https://backend.versalence.online/whatsapp-signup-failure

# External WhatsApp messaging API endpoints exposed to mobile apps.
WHATSAPP_SEND_MESSAGES_URL=https://api.versal.one
WHATSAPP_CREATE_TEMPLATES_URL=https://api.versal.one
WHATSAPP_MESSAGE_STATUS_URL=https://apiproxy.versal.one
```

The following existing variables are also used:

```
APP_ID=
APP_SECRET=
META_API_VERSION=
```

#### Prerequisites

1. The customer account must already exist in vCX (created as a sub-account under the partner’s master account).
2. The customer must have an admin user with verified email and active account status.
3. The `WHATSAPP_OAUTH_REDIRECT_URI` must be registered in the Meta app settings.
4. Migration `009_add_whatsapp_coexistence_support.sql` must be applied to production. It creates the `onboarding_sessions` and `whatsapp_accounts` tables required by the new flow.

#### Coexistence with the existing web dashboard flow

The existing web dashboard flow is unchanged and continues to work:

- `POST /v2/whatsappSign`
- `POST /v2/whatsappWaba`
- `POST /v2/whatsappPhone`
- `POST /v2/embeddedSignup`
- `GET /v2/getWaba`
- `GET /v2/whatsapp-coexistence/status`

The new mobile-app flow is additive:

- <span style="background-color:rgb(248,248,248);font-family:'Lucida Console', 'DejaVu Sans Mono', 'Ubuntu Mono', Monaco, monospace;font-size:0.84em;white-space:pre-wrap;">GET /v2/whatsappSignupInit</span>
- `GET /v2/whatsappSignupCallback`
- `GET /v2/whatsappSignupStatus`
- `GET /v2/whatsappApiConfig`

The removed `/v2/whatsapp-coexistence/enable` and `/v2/whatsapp-coexistence/disable` endpoints are no longer needed because the mode is passed directly at signup time.

## Error handling

<table id="bkmrk-step-typical-failure"><thead><tr><th>Step</th><th>Typical failure</th><th>How the mobile app should handle</th></tr></thead><tbody><tr><td>Login</td><td>Invalid credentials</td><td>Show error and ask user to retry.</td></tr><tr><td>Initiate signup</td><td>Missing `APP_ID` / redirect URI</td><td>Backend misconfiguration. Contact vCX support.</td></tr><tr><td>Meta OAuth</td><td>User cancels</td><td>Browser redirects to failure page. Poll `/whatsappSignupStatus` to confirm not connected.</td></tr><tr><td>Callback</td><td>Invalid/expired `state`</td><td>Browser redirects to failure page with `error=Invalid or expired onboarding session`.</td></tr><tr><td>Callback</td><td>Missing WABA or phone number</td><td>Browser redirects to failure page. User must retry signup.</td></tr><tr><td>Status polling</td><td>`is_connected: false`</td><td>Continue polling or restart signup.</td></tr></tbody></table>

#### Summary of API endpoints

<table id="bkmrk-endpoint-method-auth"><thead><tr><th>Endpoint</th><th>Method</th><th>Auth</th><th>Purpose</th></tr></thead><tbody><tr><td>`/api/v2/login`</td><td>POST</td><td>Public</td><td>Authenticate and get JWT.</td></tr><tr><td>`/api/admin/v2/adminLogin`</td><td>POST</td><td>Public</td><td>Agency owner login.</td></tr><tr><td>`/api/admin/v2/getCustomers`</td><td>GET</td><td>Agency JWT</td><td>List sub-accounts.</td></tr><tr><td>`/api/admin/v2/clientAgentLogin`</td><td>GET</td><td>Agency JWT</td><td>Get sub-account JWT.</td></tr><tr><td>`/api/v2/getWaba`</td><td>GET</td><td>Any JWT</td><td>Check WhatsApp account.</td></tr><tr><td>`/api/v2/whatsappSignupInit`</td><td>GET</td><td>Admin JWT</td><td>Get Meta OAuth URL.</td></tr><tr><td>`/api/v2/whatsappSignupCallback`</td><td>GET</td><td>None (Meta calls this)</td><td>Complete signup after Meta OAuth.</td></tr><tr><td>`/api/v2/whatsappSignupStatus`</td><td>GET</td><td>Any JWT</td><td>Check if WhatsApp is connected.</td></tr><tr><td>`/api/v2/whatsappApiConfig`</td><td>GET</td><td>Any JWT</td><td>Get messaging API URLs.</td></tr></tbody></table>

## Appendix: Web dashboard 3-step flow

The following endpoints are used by the existing vCX web dashboard. They remain available but are **not** used by the mobile-app OAuth flow described above.

### A1. Exchange code for access token

```
POST /api/v2/whatsappSign
Authorization: Bearer <JWT_TOKEN>
Content-Type: application/json

{
  "code": "<META_AUTH_CODE>",
  "mode": "coexistence"
}
```

Response:

```
{
  "success": true,
  "message": "Access token updated successfully",
  "session_id": "<SESSION_ID>",
  "mode": "coexistence",
  "data": "<ACCESS_TOKEN>"
}
```

Save `session_id` and discard `data` (legacy field).

### A2. Resolve WABA ID

```
POST /api/v2/whatsappWaba
Authorization: Bearer <JWT_TOKEN>
Content-Type: application/json

{
  "session_id": "<SESSION_ID>"
}
```

Response:

```
{
  "success": true,
  "message": "WABA ID updated successfully",
  "data": {
    "waba_id": "<WABA_ID>"
  },
  "session_id": "<SESSION_ID>"
}
```

### A3. Resolve phone number and complete signup

```
POST /api/v2/whatsappPhone
Authorization: Bearer <JWT_TOKEN>
Content-Type: application/json

{
  "session_id": "<SESSION_ID>"
}
```

``

Response:

``

```
{
  "success": true,
  "message": "Whatsapp embedded signup complete with co-existence mode",
  "mode": "coexistence",
  "phone_number": "919876543210",
  "phone_id": "<PHONE_ID>",
  "webhook_config": "Webhook configured successfully"
}
```

``

**Role requirement:** Admin only for all three steps.

## Send messages via vCX

Once onboarding is complete, use the separately documented messaging API to send WhatsApp messages through the vCX platform.

The backend stores the access token and phone ID, so the send-message API only needs the vCX customer JWT (and the recipient/message payload).

## Important notes

``

- **Legacy endpoint `POST /api/v2/embeddedSignup`** exists as a single-call onboarding flow, but it always uses `standard` mode and does not support Coexistence. Use the 3-step flow in the appendix for Coexistence via the dashboard.
- **Token storage:** The 3-step flow uses `session_id` to keep the Meta access token server-side. The mobile-app OAuth flow keeps the token entirely server-side.
- **No login to vCX web UI required:** The mobile app can perform the entire flow via the API calls above.