Send template message
Send an approved WhatsApp template to start a conversation with a customer. If a conversation is already open, the message is appended to it; otherwise, a new one is created.
This endpoint currently supports the WhatsApp channel only.
POST https://api.platica.mx/v1/messages/template Request body
{
"channelId": "521234567890",
"conversationId": "521234567890",
"campaignId": "pV6PvG2lc8ChQb2VmETr",
"template": {
"name": "bienvenida_cliente",
"params": ["Juan", "Premium"],
"type": "image",
"file": "https://cdn.assets.com/welcome_image.jpg",
"buttons": [
{
"index": 0,
"parameters": [{ "type": "text", "text": "promo/enero" }]
}
]
},
"client": {
"name": "José",
"customFields": {
"placas": "ABC123",
"id_recepcion": "REC001"
}
}
} Body parameters
| Field | Type | Description | Required |
|---|---|---|---|
channelId | string | Internal channel ID OR the agent's phone number (E.164 format without +) | ✓ |
conversationId | string | Customer phone number in E.164 format without + | ✓ |
campaignId | string | ID of the campaign the message is attributed to. If omitted, it is logged under the api campaign | — |
template.name | string | Name of the template to use | ✓ |
template.params | array | Variables for the template body. The count must exactly match the number of variables defined in the template | — |
template.type | enum | Header type: image, document, video. Required if the template has a media header | — |
template.file | string | Public https:// URL of the header file. Required if template.type is present | — |
template.buttons | array | Dynamic variables for the template buttons. Maximum 3 items | — |
delay | number | Delay in milliseconds (3,000 – 86,400,000) | — |
scheduleTime | string | Scheduled send date/time (ISO 8601). Maximum 1 year in the future | — |
client | object | Customer information to update (upsert) | — |
If the client object is sent, the customer profile is updated (or created if it does not exist), giving the AI agent immediate access to the new data.
Each item in the array represents a dynamic template button. Static buttons (no variables) do not need to be included.
| Field | Type | Description | Required |
|---|---|---|---|
index | integer | 0-based index of the button in the template. Must point to an existing button | ✓ |
sub_type | enum | url, phone_number, quick_reply, otp. Inferred automatically from the type defined in the template if omitted | — |
parameters | array | Exactly one item with { "type": "text", "text": "<value>" } | ✓ |
Important rules:
- Indexes must not repeat within the same array
- For URL buttons,
textmust be a path segment (e.g."promo/enero"), not a full URL. Sending"https://..."returns a 400 error - If
sub_typeis omitted, it is inferred from the button type defined in the template (URL→url,OTP→otp,PHONE_NUMBER→phone_number)
"buttons": [
{
"index": 0,
"parameters": [{ "type": "text", "text": "promo/enero" }]
},
{
"index": 1,
"sub_type": "otp",
"parameters": [{ "type": "text", "text": "482910" }]
}
] Delayed send (delay):
- Minimum:
3000ms (3 seconds) - Maximum:
86400000ms (24 hours) - Example:
"delay": 5000sends the message in 5 seconds
Scheduled send (scheduleTime):
- ISO 8601 format
- Must be a future date
- Cannot be more than 1 year in the future
- Examples:
"2025-07-01T18:40:00"— Mexico time (UTC-6)"2025-07-01T18:40:00Z"— UTC time"2025-07-01T18:40:00-06:00"— With a specific time zone
You cannot use delay and scheduleTime in the same request.
| Field | Type | Description |
|---|---|---|
client.name | string | Customer full name |
client.firstname | string | First name |
client.lastname | string | Last name |
client.email | string | Email address |
client.birthdate | string | Date of birth (dd/mm/yyyy) |
client.gender | enum | Gender: male or female |
client.company | string | Company name |
client.country | enum | ISO 3166-1 alpha-2 code (e.g. MX, US) |
client.state | string | State of residence |
client.city | string | City of residence |
client.address | string | Full address |
client.postalCode | string | Postal code |
client.customFields | map | Key-value object with the custom fields defined in the workspace. See Custom Fields for what's available. |
client.owners | array | Responsible-user emails |
Template validation
When the request is received, the API verifies that the payload is compatible with the template definition registered in WhatsApp. If there are mismatches, a 400 error is returned with the details of each issue.
Rules that are validated automatically:
- Param count: must exactly match the number of
{{1}},{{2}}... variables in the template body - Media header: if the template has an image, video, or document header,
template.typeandtemplate.fileare required andtypemust match the defined format - Button indexes: every
indexintemplate.buttonsmust correspond to an existing button in the template - URL button variables: the
textvalue must be a path segment, not a full URL
{
"message": "Template payload is incompatible with template configuration",
"template": "bienvenida_cliente",
"errors": [
{
"field": "template.params",
"message": "The number of params does not match the template definition",
"expected": 2,
"received": 1
},
{
"field": "template.type",
"message": "This template requires media header type",
"expected": "image",
"received": null,
"example": {
"type": "image",
"file": "https://example.com/your-media-file"
}
}
]
} Response
The response shape depends on whether the message is sent immediately, with a delay, or scheduled.
Immediate send:
{
"messageId": "msg_123xyz",
"status": "sent",
"timestamp": "2025-02-14T12:00:00Z"
} With delay:
{
"messageId": "msg_123xyz",
"status": "delayed",
"timestamp": "2025-02-14T12:00:00Z",
"executeAt": "2025-02-14T12:00:05.000Z",
"delayMs": 5000
} With scheduleTime:
{
"messageId": "msg_123xyz",
"status": "scheduled",
"timestamp": "2025-02-14T12:00:00Z",
"executeAt": "2025-07-01T00:40:00.000Z",
"scheduledTime": "2025-07-01T18:40:00"
} | Field | Type | Description |
|---|---|---|
messageId | string | ID of the created message. Use it to track its status in the campaign |
status | enum | sent, delayed, or scheduled |
timestamp | string | Date/time when the request was processed (ISO 8601 UTC) |
executeAt | string | Date/time when the message will be sent (ISO 8601 UTC). Only present in delayed or scheduled sends |
delayMs | number | Configured delay in milliseconds. Only present when delay was used |
scheduledTime | string | Original scheduleTime value sent in the request. Only present when scheduleTime was used |
WhatsApp rules
Templates are mandatory
You must use a pre-approved template to start a conversation. You cannot send free-form text messages until the customer replies.
24-hour window
Conversations stay active for 24 hours since the customer's last message.
If the customer does NOT reply:
- You send the template
- The customer does not reply
- You cannot send more messages until they reply
If the customer DOES reply:
- You send the template
- The customer replies
- You can send messages freely for 24 hours
- Each customer message resets the window
Delivery limitations
WhatsApp can block messages because of:
- The customer's country restrictions
- Numbers in WhatsApp experiments
- Customers who turned off marketing notifications
Checking status
Confirm your message was delivered:
- From the platform's inbox
- Using the Get Conversation endpoint