Placeholders
Placeholders allow you to personalize messages with dynamic content.
Syntax
Use double curly braces to define placeholders:
{{placeholderName}}
Basic Example
Template:
Hello {{name}}! Your order #{{orderId}} is ready for pickup.
Placeholders:
{
"name": "John",
"orderId": "12345"
}
Result:
Hello John! Your order #12345 is ready for pickup.
Where Placeholders Work
Placeholders can be used in:
| Field | Supported | Example |
|---|---|---|
| templateContent | ✓ | Hello {{name}} |
| buttonUrl | ✓ | https://site.com/orders/{{orderId}} |
| fileUrl | ✓ | https://site.com/invoices/{{invoiceId}}.pdf |
| imageUrl | ✗ | Not supported |
| fileName | ✗ | Not supported |
Placeholder Rules
Naming
- Use alphanumeric characters and underscores
- Case-sensitive (
{{Name}}≠{{name}}) - No spaces allowed
✓ {{firstName}}
✓ {{order_id}}
✓ {{item1}}
✗ {{first name}}
✗ {{order-id}}
Missing Placeholders
If a placeholder in the template is not provided in the request, it will remain as-is:
Template: Hello {{name}}, your code is {{code}}
Placeholders: { "name": "John" }
Result: Hello John, your code is {{code}}
Always ensure all placeholders in your template have corresponding values in your request.
Per-Recipient Placeholders
Each recipient can have their own placeholders for personalized messages:
- cURL
- JavaScript
- Python
curl -X POST https://api.transformify.mk/api/v1/viber/send \
-H "X-API-Key: your-api-key" \
-H "Content-Type: application/json" \
-d '{
"templateId": "template-id",
"recipients": [
{
"phoneNumber": "38970111111",
"placeholders": { "name": "John", "discount": "25%" }
},
{
"phoneNumber": "38970222222",
"placeholders": { "name": "Jane", "discount": "20%" }
},
{
"phoneNumber": "38970333333",
"placeholders": { "name": "Bob", "discount": "15%" }
}
]
}'
const response = await fetch('https://api.transformify.mk/api/v1/viber/send', {
method: 'POST',
headers: {
'X-API-Key': 'your-api-key',
'Content-Type': 'application/json'
},
body: JSON.stringify({
templateId: 'template-id',
recipients: [
{
phoneNumber: '38970111111',
placeholders: { name: 'John', discount: '25%' }
},
{
phoneNumber: '38970222222',
placeholders: { name: 'Jane', discount: '20%' }
},
{
phoneNumber: '38970333333',
placeholders: { name: 'Bob', discount: '15%' }
}
]
})
});
import requests
response = requests.post(
'https://api.transformify.mk/api/v1/viber/send',
headers={
'X-API-Key': 'your-api-key',
'Content-Type': 'application/json'
},
json={
'templateId': 'template-id',
'recipients': [
{
'phoneNumber': '38970111111',
'placeholders': {'name': 'John', 'discount': '25%'}
},
{
'phoneNumber': '38970222222',
'placeholders': {'name': 'Jane', 'discount': '20%'}
},
{
'phoneNumber': '38970333333',
'placeholders': {'name': 'Bob', 'discount': '15%'}
}
]
}
)
Each recipient receives a personalized message with their own values.
Fallback Placeholders
Use request-level placeholders as defaults for recipients without their own:
{
"templateId": "template-id",
"recipients": [
{
"phoneNumber": "38970111111",
"placeholders": { "name": "John", "discount": "25%" }
},
{ "phoneNumber": "38970222222" }
],
"placeholders": {
"name": "Valued Customer",
"discount": "10%"
}
}
Precedence:
- Recipient-level placeholders are used first
- Request-level placeholders are used as fallback
Transactional Campaigns
For event-driven messages, use transactional campaigns with per-message placeholders:
- cURL
- JavaScript
- Python
curl -X POST https://api.transformify.mk/api/v1/sms/campaigns/{campaignId}/messages \
-H "X-API-Key: your-api-key" \
-H "Content-Type: application/json" \
-d '{
"phoneNumber": "38970123456",
"externalUserId": "order_12345",
"placeholders": {
"name": "John",
"orderId": "ORD-12345",
"trackingNumber": "TRK-987654"
}
}'
// Send personalized message when order ships
async function notifyShipment(order) {
await fetch(`https://api.transformify.mk/api/v1/sms/campaigns/${CAMPAIGN_ID}/messages`, {
method: 'POST',
headers: {
'X-API-Key': API_KEY,
'Content-Type': 'application/json'
},
body: JSON.stringify({
phoneNumber: order.customer.phone,
externalUserId: order.id,
placeholders: {
name: order.customer.name,
orderId: order.id,
trackingNumber: order.trackingNumber
}
})
});
}
import requests
def notify_shipment(order):
response = requests.post(
f'https://api.transformify.mk/api/v1/sms/campaigns/{CAMPAIGN_ID}/messages',
headers={
'X-API-Key': API_KEY,
'Content-Type': 'application/json'
},
json={
'phoneNumber': order['customer']['phone'],
'externalUserId': order['id'],
'placeholders': {
'name': order['customer']['name'],
'orderId': order['id'],
'trackingNumber': order['tracking_number']
}
}
)
return response
Common Patterns
Order Notifications
{
"templateContent": "Hi {{customerName}}, your order #{{orderId}} totaling ${{total}} has been {{status}}.",
"placeholders": {
"customerName": "John Smith",
"orderId": "ORD-2024-001",
"total": "149.99",
"status": "shipped"
}
}
Appointment Reminders
{
"templateContent": "{{greeting}} {{name}}, reminder: {{service}} on {{date}} at {{time}} with {{provider}}.",
"placeholders": {
"greeting": "Good morning",
"name": "Sarah",
"service": "Dental checkup",
"date": "January 20",
"time": "2:00 PM",
"provider": "Dr. Smith"
}
}
Dynamic Button URLs
Placeholders in buttonUrl are supported for ButtonPlusText and ImagePlusText message types:
{
"templateContent": "Track your order here:",
"typeSpecificConfig": {
"buttonText": "Track Order",
"buttonUrl": "https://tracking.example.com/{{carrier}}/{{trackingNumber}}"
},
"placeholders": {
"carrier": "fedex",
"trackingNumber": "123456789"
}
}
Placeholders in URLs are only supported for buttonUrl and fileUrl. Image URLs (imageUrl) do not support placeholders.
Best Practices
- Use descriptive names -
{{customerFirstName}}not{{n}} - Validate before sending - Ensure all placeholders have values
- Provide defaults - Handle missing data in your code
- Keep it simple - Don't over-complicate with too many placeholders
- Test thoroughly - Preview messages with sample data
- Document placeholders - Keep a list of required placeholders per template