# 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 `GET /api/message-templates` Lists the message templates of this location, newest first. Filter by channel, location, or category. ### Query parameters - `channel` (string) — Filter by channel. One of `sms`, `email`, `whatsapp`, etc. - `location_id` (integer) — Scope to a location. - `category` (string) — Optional grouping label. - `per_page` (integer) — Rows per page. Default 20, maximum 100. See [Lists, paging and filters](#lists-paging-and-filters). ### Example request ```bash 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" ``` ### Response `200` ```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 } } ``` ## Create a message template `POST /api/message-templates` 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. ### Body parameters - `location_id` (integer) — Scope to a specific location. - `name` (string, required) — Display name (max 120). - `channel` (string, required) — One of `sms`, `email`, `whatsapp`, `messenger`, `instagram`, `gmb`. - `body` (string, required) — Template body with `@{{variable}}` placeholders. - `category` (string) — Optional grouping label (max 60). ### Example request ```bash 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\" }" ``` ### Response `200` ```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 } } ``` ### Response `422` — A channel that does not exist ```json { "message": "Channel no es una opción válida.", "errors": { "channel": [ "Channel no es una opción válida." ] } } ``` ### Response `422` — An empty body ```json { "message": "Falta body.", "errors": { "body": [ "Falta body." ] } } ``` ## Fetch a message template `GET /api/message-templates/{messageTemplate_id}` 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. 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_id` (integer, required) — Template ID. ### Example request ```bash 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" ``` ### Response `200` ```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 } } ``` ### Response `404` — Does not exist, or belongs to another location ```json { "message": "No query results for model." } ``` ## Delete a message template `DELETE /api/message-templates/{messageTemplate_id}` 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. ### Path parameters - `messageTemplate_id` (integer, required) — Template ID. ### Example request ```bash 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" ``` ### Response `200` ```json { "message": "Template deleted." } ``` ## Render template against a contact `POST /api/message-templates/{messageTemplate_id}/render` 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). ### Path parameters - `messageTemplate_id` (integer, required) — Template ID. ### Body parameters - `contact_id` (integer, required) — Contact to render against. ### Example request ```bash 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 }" ``` ### Response `200` ```json { "rendered": "Hi Ada, your appointment is on 2026-06-08.", "missing": [], "channel": "whatsapp" } ``` ### Response `200` — unresolved variables ```json { "rendered": "Hi Ada, your appointment is on @{{appointment_date}}.", "missing": [ "appointment_date" ], "channel": "whatsapp" } ```