# Meta's Custom Templates API

### Overview

The WhatsApp Custom Template API allows you to send pre-approved WhatsApp message templates to your customers. This allows you to initiate conversation to a user, and the voiceflow project will take over from there. This is specially good for marketing and outreach as it allows you to message a user, and your voiceflow build will handle the responses.

**Some use-cases may be:**

* Sending a marketing related message about a service they may be interested in
* Follow up with a new lead after filling in their phone number on a website
* Notify the user about changes in their e-com purchase and allow an automated system to handle support
* Essentially this allows you make initiate any conversation with a whats app user

## How does this work?

This page is still in the making, though in short:

1. You must login to <https://business.facebook.com> and go to your WhatsApp Business Manager for the given WhatsApp business account
2. From here you can create "Custom Templates" from either pre-defined templates, or your own custom template.
3. Once you have a custom template, it needs to be approved by Meta before it can be used
4. Use the API information below to trigger the custom template to be sent using the ID and Language for the custom template created by you on the WhatsApp Business Manager platform<br>

## Where do I get an API token?

You can generate an API token on the Admin Panel of your FlowBridge Environment by clicking the `API Tokens` link on the side navigation.

## API Specifications

This API supports both Meta API (Facebook) and 360Dialog providers, and handles both named and positional template variables.

### Authentication

All requests must be authenticated using Laravel Sanctum API tokens.

#### Headers

```
Authorization: Bearer {your-api-token}
Content-Type: application/json
Accept: application/json
```

### Endpoint

```
POST /api/whatsapp/{client_integration}/custom-templates/send
```

#### Path Parameters

| Parameter            | Type    | Description                                |
| -------------------- | ------- | ------------------------------------------ |
| `client_integration` | integer | The ID of your WhatsApp client integration |

### Request Body

#### Required Fields

| Field           | Type         | Description                                                 |
| --------------- | ------------ | ----------------------------------------------------------- |
| `to`            | string       | Recipient phone number in E.164 format (e.g., +1234567890)  |
| `template_name` | string       | Name of the approved WhatsApp template (max 512 characters) |
| `variables`     | array/object | Template variables (see formats below)                      |

#### Optional Fields

| Field           | Type   | Default | Description                                        |
| --------------- | ------ | ------- | -------------------------------------------------- |
| `language_code` | string | `en_US` | Language code for the template (max 10 characters) |

### Template Variable Formats

The API supports two formats for template variables:

#### 1. Named Variables (Key-Value Pairs)

Use this format when your template uses named placeholders like `{{name}}`, `{{date}}`, etc.

```json
{  
	"to": "+1234567890",  
	"template_name": "welcome_message",  
	"language_code": "en_US",  
	"variables": {    
		"name": "John Doe",    
		"date": "January 15, 2024",    
		"company": "Acme Corp"  
	}
}
```

#### 2. Positional Variables (Array)

Use this format when your template uses positional placeholders like `{{1}}`, `{{2}}`, etc.

```json
{  
	"to": "+1234567890",  
	"template_name": "order_confirmation",  
	"language_code": "en_US",  
	"variables": ["John Doe", "ORD-12345", "$99.99", "January 15, 2024"]
}
```

### Response Format

#### Success Response (202 Accepted)

The API returns immediately after queuing the message for sending. The actual WhatsApp API call happens asynchronously in the background.

```json
{  
	"success": true,  
	"message": "Template message queued for sending",  
	"data": {    
		"status": "queued",    
		"recipient": "+1234567890",    
		"template_name": "welcome_message"  
	}
}
```

**Important Notes**:

* The message is queued for asynchronous processing to improve API response times
* The job will retry up to 3 times with a 10-second backoff if it fails
* Check the Integration Logs in your FlowBridge dashboard to:
* Verify successful delivery

#### Error Responses

#### Validation Error (422 Unprocessable Entity)

```json
{  
	"success": false,  
	"message": "The given data was invalid.",  
	"errors": {    
		"to": [      
			"The phone number must be in E.164 format (e.g., +1234567890)."    
		],    
		"template_name": [      
		"The template name is required."    
		]  
	}
}
```

#### Unauthorized (401 Unauthorized)

```json
{  "message": "Unauthenticated."}
```

#### Rate Limit Exceeded (429 Too Many Requests)

```json
{  "message": "Too Many Attempts.",  "exception": "Illuminate\\\\Http\\\\Exceptions\\\\ThrottleRequestsException"}
```

### Rate Limiting

The API is rate-limited to **60 requests per minute** per user. If you exceed this limit, you’ll receive a 429 status code.

### Error Codes

| Code                      | Description                                                        |
| ------------------------- | ------------------------------------------------------------------ |
| `INVALID_CHANNEL`         | The integration is not configured for WhatsApp                     |
| `UNAUTHORIZED`            | User doesn’t have permission to access this integration            |
| `MISSING_PHONE_NUMBER_ID` | Integration configuration is incomplete                            |
| `SEND_FAILED`             | Failed to send the template message (includes WhatsApp API errors) |

### Code Examples

#### PHP (using Guzzle)

```php
<?php

use GuzzleHttp\\Client;

$client = new Client([
    'base_uri' => '<https://your-sub-domain.flowbridge.app>',
    'headers' => [
        'Authorization' => 'Bearer your-api-token',
        'Content-Type'  => 'application/json',
        'Accept'        => 'application/json',
    ],
]);

// Named variables example
$response = $client->post('/api/whatsapp/123/custom-templates/send', [
    'json' => [
        'to'             => '+1234567890',
        'template_name'  => 'welcome_message',
        'language_code'  => 'en_US',
        'variables'      => [
            'name' => 'John Doe',
            'date' => 'January 15, 2024',
        ],
    ],
]);

$result = json_decode($response->getBody(), true);
echo "Message ID: " . $result['data']['message_id'];
```

#### JavaScript (using Axios)

```jsx
const axios = require('axios');

const sendTemplate = async () => {
  try {
    const response = await axios.post(
      '<https://your-sub-domain.flowbridge.app/api/whatsapp/123/custom-templates/send>',
      {
        to: '+1234567890',
        template_name: 'welcome_message',
        language_code: 'en_US',
        variables: {
          name: 'John Doe',
          date: 'January 15, 2024'
        }
      },
      {
        headers: {
          'Authorization': 'Bearer your-api-token',
          'Content-Type': 'application/json',
          'Accept': 'application/json'
        }
      }
    );

    console.log('Message ID:', response.data.data.message_id);
  } catch (error) {
    console.error('Error:', error.response.data);
  }
};

sendTemplate();
```

#### Python (using requests)

```python
import requests

url = '<https://your-sub-domain.flowbridge.app/api/whatsapp/123/custom-templates/send>'
headers = {
    'Authorization': 'Bearer your-api-token',
    'Content-Type': 'application/json',
    'Accept': 'application/json'
}

# Positional variables example
data = {
    'to': '+1234567890',
    'template_name': 'order_confirmation',
    'language_code': 'en_US',
    'variables': ['John Doe', 'ORD-12345', '$99.99']
}

response = requests.post(url, json=data, headers=headers)

if response.status_code == 200:
    result = response.json()
    print(f"Message ID: {result['data']['message_id']}")
else:
    print(f"Error: {response.json()}")
```

#### cURL

```bash
# Named variables example
curl -X POST <https://your-sub-domain.flowbridge.app/api/whatsapp/123/custom-templates/send> \\
  -H "Authorization: Bearer your-api-token" \\
  -H "Content-Type: application/json" \\
  -H "Accept: application/json" \\
  -d '{
    "to": "+1234567890",
    "template_name": "welcome_message",
    "language_code": "en_US",
    "variables": {
      "name": "John Doe",
      "date": "January 15, 2024"
    }
  }'

# Positional variables example
curl -X POST <https://your-domain.com/api/whatsapp/123/custom-templates/send> \\
  -H "Authorization: Bearer your-api-token" \\
  -H "Content-Type: application/json" \\
  -H "Accept: application/json" \\
  -d '{
    "to": "+1234567890",
    "template_name": "order_confirmation",
    "language_code": "en_US",
    "variables": ["John Doe", "ORD-12345", "$99.99"]
  }'
```

### Provider Support

This API works with both WhatsApp providers:

| Provider            | Supported | Notes            |
| ------------------- | --------- | ---------------- |
| Meta API (Facebook) | ✅         | Default provider |
| 360Dialog           | ✅         | Fully supported  |

The API automatically detects which provider your integration uses and sends the message accordingly.

### Best Practices

1. **Template Approval**: Ensure your templates are approved in Meta Business Manager before sending
2. **Phone Number Format**: Always use E.164 format (+\[country code]\[number])
3. **Variable Matching**: Ensure variable count and names match your template exactly
4. **Error Handling**: Implement proper error handling for all possible error codes
5. **Rate Limiting**: Implement exponential backoff if you hit rate limits
6. **Logging**: Monitor integration logs in your dashboard for debugging

### Testing

To test the API:

1. Create a WhatsApp integration in your dashboard
2. Generate an API token from your user settings
3. Use a test phone number registered with your WhatsApp Business account
4. Send a test template using one of the code examples above

### Support

For issues or questions:

* Check integration logs in your dashboard
* Review error codes and messages
* Contact support with the message\_id for specific message issues


---

# Agent Instructions: Querying This Documentation

If you need additional information that is not directly available in this page, you can query the documentation dynamically by asking a question.

Perform an HTTP GET request on the current page URL with the `ask` query parameter:

```
GET https://docs.flowbridge.app/documentation/social-integrations/whatsapp/metas-custom-templates-api.md?ask=<question>
```

The question should be specific, self-contained, and written in natural language.
The response will contain a direct answer to the question and relevant excerpts and sources from the documentation.

Use this mechanism when the answer is not explicitly present in the current page, you need clarification or additional context, or you want to retrieve related documentation sections.
