The layout is a JSON with the necessary information to send the messages.
The variables should be enclosed in double curly braces (ex: {{variable}}).
Important: Variable names can only contain letters, numbers, dots (.) and underscores (_). Spaces or special characters are not allowed inside variable placeholders (e.g. {{nombre cliente}} is invalid, use {{nombre_cliente}} instead).
The only required fields are contactCode + channelType, externalCode alone, or bsuid alone (inside the contact object).
You can use externalCode instead of contactCode to identify contacts by their external code. When using externalCode, channelType is not required. If multiple contacts share the same externalCode, a message will be sent to each of them.
You can also use bsuid instead of contactCode to identify contacts by their bsuid. channelType is not required: bsuid only applies to CLOUD_API (WhatsApp) contacts, so channelType is always treated as cloud_api. Unlike externalCode, bsuid is treated as a direct sending identifier (like contactCode).
Optionally, you can use the 'customFields' property to define which columns in the CSV correspond to the variables used in the campaign to be sent.
Other fields like sendType or messageContent are defined in the campaign, so you don't need to define them in the layout.
An examples of layouts:
Example 1: using both contact variables and custom fields
{
"contact": {
"contactCode": "{{contactCode}}",
"channelType": "{{channelType}}"
},
"customFields": {
"name": "{{nombre}}",
"ticketId": "{{ticket_id}}",
"age": "{{edad}}"
}
}
Example 2: It's not necessary to define a variable for the channelType property (if all recipients belong to the same channel). It's also not required to define the customFields property if the campaign doesn't have variables.
{
"contact": {
"contactCode": "{{contactCode}}",
"channelType": "cloud_api"
}
}
Example 3: you can use other names for the variables
{
"contact": {
"contactCode": "{{phoneNumber}}",
"channelType": "{{channel}}"
},
"customFields": {
"name": "{{nombre_cliente}}",
"age": "{{edad_cliente}}"
}
}
Example 4: It's not mandatory to define variables for custom fields; you can use fixed values instead.
{
"contact": {
"contactCode": "{{contactCode}}",
"channelType": "{{channelType}}"
},
"customFields": {
"name": "Dear client",
"discount": "10%"
}
}
Example 5: Using externalCode instead of contactCode to identify contacts. channelType is not required.
{
"contact": {
"externalCode": "{{externalCode}}"
},
"customFields": {
"name": "{{nombre}}"
}
}
Example 6: Using bsuid instead of contactCode to identify contacts. channelType is not needed (bsuid always targets cloud_api). bsuid is a direct sending identifier: the message is sent using the bsuid value itself (no contact lookup/swap like externalCode), and if the contact doesn't exist yet it's created with contactCode = bsuid.
{
"contact": {
"bsuid": "{{bsuid}}"
},
"customFields": {
"name": "{{nombre}}"
}
}
Optionally, you can include a context object to update the contact's context. Map context keys to CSV column variable placeholders:
"context": {
"preferred_store": "{{store_column}}",
"loyalty_level": "{{level_column}}"
}
Context updates are not allowed for scheduled or delayed sendings.