Reference
Message Templates
Reusable message bodies with @{{variable}} placeholders. Variables are
auto-detected on save and resolved against contact fields (and custom fields)
at render time. Templates are scoped per channel and optionally per location.
List message templates
Lists the message templates of this location, newest first. Filter by channel, location, or category.
GET
/api/message-templates
Query parameters
-
channelstringFilter by channel. One of
sms,email,whatsapp, etc.Example:
whatsapp -
location_idintegerScope to a location.
Example:
1 -
categorystringOptional grouping label.
Example:
appointment-reminders -
per_pageintegerRows per page. Default 20, maximum 100. See Lists, paging and filters.
Example:
20
curl --request GET \
--get "https://klozzo.com/api/message-templates?channel=whatsapp&location_id=1&category=appointment-reminders&per_page=20" \
--header "Authorization: Bearer {YOUR_API_TOKEN}" \
--header "Content-Type: application/json" \
--header "Accept: application/json"
const url = new URL(
"https://klozzo.com/api/message-templates"
);
const params = {
"channel": "whatsapp",
"location_id": "1",
"category": "appointment-reminders",
"per_page": "20",
};
Object.keys(params)
.forEach(key => url.searchParams.append(key, params[key]));
const headers = {
"Authorization": "Bearer {YOUR_API_TOKEN}",
"Content-Type": "application/json",
"Accept": "application/json",
};
fetch(url, {
method: "GET",
headers,
}).then(response => response.json());
$client = new \GuzzleHttp\Client();
$url = 'https://klozzo.com/api/message-templates';
$response = $client->get(
$url,
[
'headers' => [
'Authorization' => 'Bearer {YOUR_API_TOKEN}',
'Content-Type' => 'application/json',
'Accept' => 'application/json',
],
'query' => [
'channel' => 'whatsapp',
'location_id' => '1',
'category' => 'appointment-reminders',
'per_page' => '20',
],
]
);
$body = $response->getBody();
print_r(json_decode((string) $body));
import requests
import json
url = 'https://klozzo.com/api/message-templates'
params = {
'channel': 'whatsapp',
'location_id': '1',
'category': 'appointment-reminders',
'per_page': '20',
}
headers = {
'Authorization': 'Bearer {YOUR_API_TOKEN}',
'Content-Type': 'application/json',
'Accept': 'application/json'
}
response = requests.request('GET', url, headers=headers, params=params)
response.json()
{
"data": [
{
"id": null,
"location_id": null,
"user_id": 3787,
"name": "Template aut adipisci quidem",
"channel": "sms",
"body": "Hi {{contact.first_name}}, thanks for reaching out!",
"variables": [
"contact.first_name"
],
"category": "general",
"created_at": null,
"updated_at": null
},
{
"id": null,
"location_id": null,
"user_id": 3788,
"name": "Template quia officia est",
"channel": "sms",
"body": "Hi {{contact.first_name}}, thanks for reaching out!",
"variables": [
"contact.first_name"
],
"category": "general",
"created_at": null,
"updated_at": null
}
],
"links": {
"first": "/?page=1",
"last": "/?page=1",
"prev": null,
"next": null
},
"meta": {
"current_page": 1,
"from": 1,
"last_page": 1,
"links": [
{
"url": null,
"label": "« Previous",
"page": null,
"active": false
},
{
"url": "/?page=1",
"label": "1",
"page": 1,
"active": true
},
{
"url": null,
"label": "Next »",
"page": null,
"active": false
}
],
"path": "/",
"per_page": 20,
"to": 2,
"total": 2
}
}
-
dataobject[]-
idstring -
location_idstring -
user_idinteger -
namestring -
channelstring -
bodystring -
variablesstring[] -
categorystring -
created_atstring -
updated_atstring
-
-
linksobject-
firststring -
laststring -
prevstring -
nextstring
-
-
metaobject-
current_pageinteger -
frominteger -
last_pageinteger -
linksobject[]-
urlstring -
labelstring -
pagestring -
activeboolean
-
-
pathstring -
per_pageinteger -
tointeger -
totalinteger
-
Create a message template
Creates a message template for one channel. On save, @{{variable}}
tokens in body are extracted into the variables
column for fast lookup at render time. Re-extraction happens on every update.
POST
/api/message-templates
Body parameters
-
location_idintegerScope to a specific location.
Example:
1 -
namestring requiredDisplay name (max 120).
Example:
Appointment reminder -
channelstring requiredOne of
sms,email,whatsapp,messenger,instagram,gmb.Example:
whatsapp -
bodystring requiredTemplate body with
@{{variable}}placeholders.Example:
Hi @{{first_name}}, your appointment is on @{{appointment_date}}. -
categorystringOptional grouping label (max 60).
Example:
appointment-reminders
curl --request POST \
"https://klozzo.com/api/message-templates" \
--header "Authorization: Bearer {YOUR_API_TOKEN}" \
--header "Content-Type: application/json" \
--header "Accept: application/json" \
--data "{
\"location_id\": 1,
\"name\": \"Appointment reminder\",
\"channel\": \"whatsapp\",
\"body\": \"Hi @{{first_name}}, your appointment is on @{{appointment_date}}.\",
\"category\": \"appointment-reminders\"
}"
const url = new URL(
"https://klozzo.com/api/message-templates"
);
const headers = {
"Authorization": "Bearer {YOUR_API_TOKEN}",
"Content-Type": "application/json",
"Accept": "application/json",
};
let body = {
"location_id": 1,
"name": "Appointment reminder",
"channel": "whatsapp",
"body": "Hi @{{first_name}}, your appointment is on @{{appointment_date}}.",
"category": "appointment-reminders"
};
fetch(url, {
method: "POST",
headers,
body: JSON.stringify(body),
}).then(response => response.json());
$client = new \GuzzleHttp\Client();
$url = 'https://klozzo.com/api/message-templates';
$response = $client->post(
$url,
[
'headers' => [
'Authorization' => 'Bearer {YOUR_API_TOKEN}',
'Content-Type' => 'application/json',
'Accept' => 'application/json',
],
'json' => [
'location_id' => 1,
'name' => 'Appointment reminder',
'channel' => 'whatsapp',
'body' => 'Hi @{{first_name}}, your appointment is on @{{appointment_date}}.',
'category' => 'appointment-reminders',
],
]
);
$body = $response->getBody();
print_r(json_decode((string) $body));
import requests
import json
url = 'https://klozzo.com/api/message-templates'
payload = {
"location_id": 1,
"name": "Appointment reminder",
"channel": "whatsapp",
"body": "Hi @{{first_name}}, your appointment is on @{{appointment_date}}.",
"category": "appointment-reminders"
}
headers = {
'Authorization': 'Bearer {YOUR_API_TOKEN}',
'Content-Type': 'application/json',
'Accept': 'application/json'
}
response = requests.request('POST', url, headers=headers, json=payload)
response.json()
{
"data": {
"id": null,
"location_id": null,
"user_id": 3789,
"name": "Template et animi quos",
"channel": "sms",
"body": "Hi {{contact.first_name}}, thanks for reaching out!",
"variables": [
"contact.first_name"
],
"category": "general",
"created_at": null,
"updated_at": null
}
}
-
dataobject-
idstring -
location_idstring -
user_idinteger -
namestring -
channelstring -
bodystring -
variablesstring[] -
categorystring -
created_atstring -
updated_atstring
-
{
"message": "Channel no es una opción válida.",
"errors": {
"channel": [
"Channel no es una opción válida."
]
}
}
Every error shares the same shape — message and errors.
See Errors.
{
"message": "Falta body.",
"errors": {
"body": [
"Falta body."
]
}
}
Every error shares the same shape — message and errors.
See Errors.
Fetch a message template
Returns one message template by id, with the variables list extracted
from its body. Read that
list before rendering: it is the contract of what this template needs, and
it is derived from the body rather than declared, so it is never out of
date.
GET
/api/message-templates/{messageTemplate_id}
To get the finished text for a person, use
POST /api/message-templates/{id}/render instead of substituting on your
side — the CRM knows about custom fields and fallbacks, and your string
replace does not.
Path parameters
-
messageTemplate_idinteger requiredTemplate ID.
Example:
11
curl --request GET \
--get "https://klozzo.com/api/message-templates/11" \
--header "Authorization: Bearer {YOUR_API_TOKEN}" \
--header "Content-Type: application/json" \
--header "Accept: application/json"
const url = new URL(
"https://klozzo.com/api/message-templates/11"
);
const headers = {
"Authorization": "Bearer {YOUR_API_TOKEN}",
"Content-Type": "application/json",
"Accept": "application/json",
};
fetch(url, {
method: "GET",
headers,
}).then(response => response.json());
$client = new \GuzzleHttp\Client();
$url = 'https://klozzo.com/api/message-templates/11';
$response = $client->get(
$url,
[
'headers' => [
'Authorization' => 'Bearer {YOUR_API_TOKEN}',
'Content-Type' => 'application/json',
'Accept' => 'application/json',
],
]
);
$body = $response->getBody();
print_r(json_decode((string) $body));
import requests
import json
url = 'https://klozzo.com/api/message-templates/11'
headers = {
'Authorization': 'Bearer {YOUR_API_TOKEN}',
'Content-Type': 'application/json',
'Accept': 'application/json'
}
response = requests.request('GET', url, headers=headers)
response.json()
{
"data": {
"id": null,
"location_id": null,
"user_id": 3790,
"name": "Template nostrum qui commodi",
"channel": "sms",
"body": "Hi {{contact.first_name}}, thanks for reaching out!",
"variables": [
"contact.first_name"
],
"category": "general",
"created_at": null,
"updated_at": null
}
}
-
dataobject-
idstring -
location_idstring -
user_idinteger -
namestring -
channelstring -
bodystring -
variablesstring[] -
categorystring -
created_atstring -
updated_atstring
-
{
"message": "No query results for model."
}
Every error shares the same shape — message and errors.
See Errors.
Delete a message template
Deletes a message template by id, so it stops being offered when composing. Messages already sent from it are untouched — they were rendered to plain text at send time and do not reference it.
DELETE
/api/message-templates/{messageTemplate_id}
Path parameters
-
messageTemplate_idinteger requiredTemplate ID.
Example:
11
curl --request DELETE \
"https://klozzo.com/api/message-templates/11" \
--header "Authorization: Bearer {YOUR_API_TOKEN}" \
--header "Content-Type: application/json" \
--header "Accept: application/json"
const url = new URL(
"https://klozzo.com/api/message-templates/11"
);
const headers = {
"Authorization": "Bearer {YOUR_API_TOKEN}",
"Content-Type": "application/json",
"Accept": "application/json",
};
fetch(url, {
method: "DELETE",
headers,
}).then(response => response.json());
$client = new \GuzzleHttp\Client();
$url = 'https://klozzo.com/api/message-templates/11';
$response = $client->delete(
$url,
[
'headers' => [
'Authorization' => 'Bearer {YOUR_API_TOKEN}',
'Content-Type' => 'application/json',
'Accept' => 'application/json',
],
]
);
$body = $response->getBody();
print_r(json_decode((string) $body));
import requests
import json
url = 'https://klozzo.com/api/message-templates/11'
headers = {
'Authorization': 'Bearer {YOUR_API_TOKEN}',
'Content-Type': 'application/json',
'Accept': 'application/json'
}
response = requests.request('DELETE', url, headers=headers)
response.json()
{
"message": "Template deleted."
}
-
messagestring
Render template against a contact
Returns the template body with @{{variable}} placeholders replaced by the
contact's matching fields. missing lists variables that could not be
resolved (useful for UI hints before sending).
POST
/api/message-templates/{messageTemplate_id}/render
Path parameters
-
messageTemplate_idinteger requiredTemplate ID.
Example:
11
Body parameters
-
contact_idinteger requiredContact to render against.
Example:
42
curl --request POST \
"https://klozzo.com/api/message-templates/11/render" \
--header "Authorization: Bearer {YOUR_API_TOKEN}" \
--header "Content-Type: application/json" \
--header "Accept: application/json" \
--data "{
\"contact_id\": 42
}"
const url = new URL(
"https://klozzo.com/api/message-templates/11/render"
);
const headers = {
"Authorization": "Bearer {YOUR_API_TOKEN}",
"Content-Type": "application/json",
"Accept": "application/json",
};
let body = {
"contact_id": 42
};
fetch(url, {
method: "POST",
headers,
body: JSON.stringify(body),
}).then(response => response.json());
$client = new \GuzzleHttp\Client();
$url = 'https://klozzo.com/api/message-templates/11/render';
$response = $client->post(
$url,
[
'headers' => [
'Authorization' => 'Bearer {YOUR_API_TOKEN}',
'Content-Type' => 'application/json',
'Accept' => 'application/json',
],
'json' => [
'contact_id' => 42,
],
]
);
$body = $response->getBody();
print_r(json_decode((string) $body));
import requests
import json
url = 'https://klozzo.com/api/message-templates/11/render'
payload = {
"contact_id": 42
}
headers = {
'Authorization': 'Bearer {YOUR_API_TOKEN}',
'Content-Type': 'application/json',
'Accept': 'application/json'
}
response = requests.request('POST', url, headers=headers, json=payload)
response.json()
{
"rendered": "Hi Ada, your appointment is on 2026-06-08.",
"missing": [],
"channel": "whatsapp"
}
-
renderedstring -
missingarray -
channelstring
{
"rendered": "Hi Ada, your appointment is on @{{appointment_date}}.",
"missing": [
"appointment_date"
],
"channel": "whatsapp"
}
-
renderedstring -
missingstring[] -
channelstring