Message templates
Message templates are used to send structured, variable-driven messages outside the 24-hour free-form messaging window — primarily WhatsApp Business HSM templates that go through Meta moderation. The API covers template CRUD, submitting for approval (submit), archiving, and syncing approval status back from Meta.
Sending and variables
An approved template is sent to a contact via POST /messages/send-template (see the Messages group). Variables in the body are named — {{first_name}}, not {{1}} — and every one must be declared under parameters with a sample_value.
Logical template
For WhatsApp Business a "logical template" model applies: one template (by name/slug) can be rolled out across several WABA channels and languages — under the hood Aisar creates a separate instance per (channel × language) pair, and each one is submitted to Meta review independently.
Because of this, GET /v1/templates returns one row per logical group (template_group_id) with a logical_template aggregate: the overall Meta status plus a per-channel breakdown (meta_status / meta_status_reason / last_synced_at). Editing is master-content based — changes propagate to sibling instances of the same language. When a template is deleted, each WABA instance is also removed from Meta best-effort so a later sync cannot restore it.
Language versions
Language versions are managed separately from channels. POST /v1/templates/{template}/languages adds a new language (language, up to 12 chars; the body is the same content as on create: body, parameters, buttons, header/footer) to the logical group and creates one instance of that language for each already-assigned WABA channel of the group; if the group has no assigned channel yet it returns 422 ("assign a channel first"), and repeating an already-existing language also returns 422.
DELETE /v1/templates/{template}/languages/{language} removes all instances of that language (best-effort removing them from Meta), but refuses to delete the only remaining language — delete the whole template for that. Both responses return a versions aggregate — a flat list of the group instances shaped { id, language, channel_id, status, meta_status }.
Endpoints
| Method | Path | Summary |
|---|---|---|
| GET | /v1/templatesList templates (one row per logical group) with pagination, search, and facets by status/language/channel type. | List templates (one row per logical group) with pagination, search, and facets by status/language/channel type. |
| GET | /v1/templates/channel-typesChannel types that templates can be created for. | Channel types that templates can be created for. |
| GET | /v1/templates/{template}Get a template by id (body, parameters, buttons) and its language versions. | Get a template by id (body, parameters, buttons) and its language versions. |
| GET | /v1/templates/{template}/channelsLogical-template availability across WABA channels: per channel — Meta status (`meta_status` / `meta_status_reason` / `last_synced_at`) and an `added` / `not_added` flag. | Logical-template availability across WABA channels: per channel — Meta status (`meta_status` / `meta_status_reason` / `last_synced_at`) and an `added` / `not_added` flag. |
| GET | /v1/templates/{template}/eventsEvent history of the logical group: created/updated, submitted to Meta, moderation results, published/archived (with channel and actor). | Event history of the logical group: created/updated, submitted to Meta, moderation results, published/archived (with channel and actor). |
| POST | /v1/templatesCreate a draft template. For WhatsApp Business you can pass `channel_ids` — Aisar creates one instance per selected WABA channel and submits each to Meta. | Create a draft template. For WhatsApp Business you can pass `channel_ids` — Aisar creates one instance per selected WABA channel and submits each to Meta. |
| PATCH | /v1/templates/{template}Update a draft template (changes propagate to sibling instances of the same language). | Update a draft template (changes propagate to sibling instances of the same language). |
| POST | /v1/templates/{template}Update a draft template (POST variant of PATCH). | Update a draft template (POST variant of PATCH). |
| POST | /v1/templates/{template}/channelsAssign a WhatsApp Business template to more channels; body `{ channel_ids: number[] }`. Creates one instance per new channel and submits published ones to Meta. | Assign a WhatsApp Business template to more channels; body `{ channel_ids: number[] }`. Creates one instance per new channel and submits published ones to Meta. |
| POST | /v1/templates/{template}/languagesAdd a language version to the logical template (WhatsApp Business): creates one instance of that language per already-assigned channel. | Add a language version to the logical template (WhatsApp Business): creates one instance of that language per already-assigned channel. |
| DELETE | /v1/templates/{template}/languages/{language}Delete a language version (all its instances; the only language cannot be deleted). Each WABA instance is also removed from Meta (best-effort). | Delete a language version (all its instances; the only language cannot be deleted). Each WABA instance is also removed from Meta (best-effort). |
| DELETE | /v1/templates/{template}Delete the template and every instance of the logical group. For WhatsApp Business each instance is also removed from Meta (best-effort). | Delete the template and every instance of the logical group. For WhatsApp Business each instance is also removed from Meta (best-effort). |
| POST | /v1/templates/{template}/submitSubmit/resubmit all assigned WABA channel instances of the template to Meta moderation. | Submit/resubmit all assigned WABA channel instances of the template to Meta moderation. |
| POST | /v1/templates/{template}/publishPublish an approved template (make it available for sending). | Publish an approved template (make it available for sending). |
| POST | /v1/templates/{template}/archiveArchive a template. | Archive a template. |
| POST | /v1/templates/{template}/unarchiveUnarchive a template. | Unarchive a template. |
| POST | /v1/templates/syncSync moderation statuses of all company WABA templates from Meta. | Sync moderation statuses of all company WABA templates from Meta. |
Examples
Create a WhatsApp Business template on several channels
Request
# channel_ids раскатывает шаблон на выбранные WABA-каналы: Aisar создаёт по
# экземпляру на каждый канал (и язык) и отправляет каждый в Meta. В ответе —
# представитель логической группы (template_group_id). Переменные — именованные.
curl -X POST "https://api.aisar.app/v1/templates" \
-H "Authorization: Bearer YOUR_API_TOKEN" \
-H "Content-Type: application/json" \
-d '{
"channel_type": "whatsapp_business",
"channel_ids": [44, 45],
"name": "Order shipped",
"slug": "order_shipped",
"language": "ru",
"category": "utility",
"body": "Здравствуйте, {{first_name}}! Ваш заказ №{{order_number}} передан в доставку.",
"parameters": [
{ "name": "first_name", "type": "text", "sample_value": "Иван", "position": 1 },
{ "name": "order_number", "type": "text", "sample_value": "1045", "position": 2 }
]
}'Response
{
"data": {
"message": "Template created.",
"template": {
"id": 12,
"company_id": 1,
"template_group_id": 8,
"channel_type": { "id": 4, "key": "whatsapp_business", "name": "WhatsApp Business" },
"channel": { "id": 44, "name": "WABA — Sales", "account_name": "+7 700 000 12 34" },
"name": "Order shipped",
"slug": "order_shipped",
"status": "draft",
"meta_status": "local",
"meta_status_reason": null,
"last_synced_at": null,
"language": "ru",
"category": "utility",
"body": "Здравствуйте, {{first_name}}! Ваш заказ №{{order_number}} передан в доставку.",
"parameters": [
{ "id": 1, "name": "first_name", "type": "text", "sample_value": "Иван", "position": 1 },
{ "id": 2, "name": "order_number", "type": "text", "sample_value": "1045", "position": 2 }
],
"buttons": [],
"uses_count": 0,
"created_at": "2026-02-09T18:00:00Z",
"updated_at": "2026-02-09T18:00:00Z"
}
}
}List templates with filters, facets, and the logical_template aggregate
Request
curl -G "https://api.aisar.app/v1/templates" \
-H "Authorization: Bearer YOUR_API_TOKEN" \
--data-urlencode "status=published" \
--data-urlencode "language=ru" \
--data-urlencode "channelType=whatsapp_business" \
--data-urlencode "sortBy=updated_at" \
--data-urlencode "sortDir=desc" \
--data-urlencode "includeFacets=true"Response
{
"data": {
"items": [
{
"id": 12,
"template_group_id": 8,
"name": "Order shipped",
"status": "published",
"meta_status": "approved",
"language": "ru",
"category": "utility",
"body": "Здравствуйте, {{first_name}}! Ваш заказ №{{order_number}} передан в доставку.",
"channel_type": { "id": 4, "key": "whatsapp_business", "name": "WhatsApp Business" },
"channel": { "id": 44, "name": "WABA — Sales", "account_name": "+7 700 000 12 34" },
"logical_template": {
"instances_count": 3,
"assigned_channels_count": 2,
"uses_count": 34,
"languages": ["kk", "ru"],
"channels": [
{
"id": 44,
"name": "WABA — Sales",
"account_name": "+7 700 000 12 34",
"meta_status": "approved",
"meta_status_reason": null,
"last_synced_at": "2026-05-15T20:40:00Z"
},
{
"id": 45,
"name": "WABA — Support",
"account_name": "+7 700 000 56 78",
"meta_status": "pending",
"meta_status_reason": null,
"last_synced_at": "2026-05-15T20:41:00Z"
}
],
"meta_status_counts": { "approved": 2, "pending": 1 },
"meta_overall_status": "pending"
},
"labels": ["orders"],
"uses_count": 34,
"created_at": "2026-02-09T18:00:00Z",
"updated_at": "2026-02-10T09:15:00Z"
}
],
"pagination": { "page": 1, "perPage": 15, "total": 1, "lastPage": 1 },
"facets": {
"statuses": { "draft": 2, "published": 1, "archived": 0 },
"languages": { "ru": 3 },
"channel_types": { "whatsapp_business": 3 }
}
}
}Logical-template availability across channels
Request
curl -X GET "https://api.aisar.app/v1/templates/12/channels" \
-H "Authorization: Bearer YOUR_API_TOKEN"Response
{
"data": {
"items": [
{
"channel": {
"id": 44,
"name": "WABA — Sales",
"account_name": "+7 700 000 12 34",
"status": "connected",
"external_ids": {}
},
"template": {
"id": 12,
"external_id": "1180000000000012",
"status": "published",
"meta_status": "approved",
"meta_status_reason": null,
"last_synced_at": "2026-05-15T20:40:00Z"
},
"availability": "added"
},
{
"channel": {
"id": 46,
"name": "WABA — Marketing",
"account_name": "+7 700 000 90 12",
"status": "connected",
"external_ids": {}
},
"template": null,
"availability": "not_added"
}
]
}
}Assign the template to an additional WABA channel
Request
curl -X POST "https://api.aisar.app/v1/templates/12/channels" \
-H "Authorization: Bearer YOUR_API_TOKEN" \
-H "Content-Type: application/json" \
-d '{ "channel_ids": [46] }'Response
{
"data": {
"message": "Template channels updated.",
"items": [
{
"channel": { "id": 44, "name": "WABA — Sales", "account_name": "+7 700 000 12 34", "status": "connected", "external_ids": {} },
"template": { "id": 12, "external_id": "1180000000000012", "status": "published", "meta_status": "approved", "meta_status_reason": null, "last_synced_at": "2026-05-15T20:40:00Z" },
"availability": "added"
},
{
"channel": { "id": 46, "name": "WABA — Marketing", "account_name": "+7 700 000 90 12", "status": "connected", "external_ids": {} },
"template": { "id": 27, "external_id": null, "status": "published", "meta_status": "local", "meta_status_reason": null, "last_synced_at": null },
"availability": "added"
}
]
}
}Event history of the logical template
Request
curl -X GET "https://api.aisar.app/v1/templates/12/events" \
-H "Authorization: Bearer YOUR_API_TOKEN"Response
{
"data": {
"items": [
{
"id": 210,
"type": "meta_approved",
"meta_status": "approved",
"reason": null,
"metadata": null,
"channel": { "id": 44, "name": "WABA — Sales", "account_name": "+7 700 000 12 34" },
"actor": null,
"created_at": "2026-05-15T20:40:00Z"
},
{
"id": 208,
"type": "submitted",
"meta_status": null,
"reason": null,
"metadata": null,
"channel": { "id": 44, "name": "WABA — Sales", "account_name": "+7 700 000 12 34" },
"actor": { "id": 3, "name": "Айгуль Смагулова" },
"created_at": "2026-05-15T18:05:00Z"
},
{
"id": 205,
"type": "created",
"meta_status": null,
"reason": null,
"metadata": null,
"channel": { "id": 44, "name": "WABA — Sales", "account_name": "+7 700 000 12 34" },
"actor": { "id": 3, "name": "Айгуль Смагулова" },
"created_at": "2026-05-15T18:00:00Z"
}
]
}
}Template with a header, footer, and buttons
Request
curl -X POST "https://api.aisar.app/v1/templates" \
-H "Authorization: Bearer YOUR_API_TOKEN" \
-H "Content-Type: application/json" \
-d '{
"channel_type": "whatsapp_business",
"name": "Appointment reminder",
"slug": "appointment_reminder",
"language": "ru",
"category": "utility",
"body": "Здравствуйте, {{first_name}}! Напоминаем о записи {{appointment_at}}.",
"header_enabled": true,
"header_type": "text",
"header_text": "Напоминание о визите",
"footer_enabled": true,
"footer_text": "Клиника «Ромашка»",
"buttons_enabled": true,
"labels": ["reminders"],
"parameters": [
{ "name": "first_name", "type": "text", "sample_value": "Айгуль", "position": 1 },
{ "name": "appointment_at", "type": "text", "sample_value": "12 марта, 10:00", "position": 2 }
],
"buttons": [
{ "type": "quick_reply", "label": "Подтвердить", "value": null, "position": 1 },
{ "type": "url", "label": "Перенести", "value": "https://example.com/appointments/{{1}}", "position": 2 },
{ "type": "phone", "label": "Позвонить", "value": "+7 700 000 00 00", "position": 3 }
]
}'Response
{
"data": {
"message": "Template created.",
"template": {
"id": 15,
"company_id": 1,
"template_group_id": 9,
"channel_type": { "id": 4, "key": "whatsapp_business", "name": "WhatsApp Business" },
"channel": null,
"name": "Appointment reminder",
"slug": "appointment_reminder",
"status": "draft",
"meta_status": null,
"meta_status_reason": null,
"last_synced_at": null,
"language": "ru",
"category": "utility",
"body": "Здравствуйте, {{first_name}}! Напоминаем о записи {{appointment_at}}.",
"header_enabled": true,
"header_type": "text",
"header_text": "Напоминание о визите",
"footer_enabled": true,
"footer_text": "Клиника «Ромашка»",
"buttons_enabled": true,
"labels": ["reminders"],
"parameters": [
{ "id": 5, "name": "first_name", "type": "text", "sample_value": "Айгуль", "position": 1 },
{ "id": 6, "name": "appointment_at", "type": "text", "sample_value": "12 марта, 10:00", "position": 2 }
],
"buttons": [
{ "id": 7, "type": "quick_reply", "label": "Подтвердить", "value": null, "position": 1 },
{ "id": 8, "type": "url", "label": "Перенести", "value": "https://example.com/appointments/{{1}}", "position": 2 },
{ "id": 9, "type": "phone", "label": "Позвонить", "value": "+7 700 000 00 00", "position": 3 }
],
"uses_count": 0,
"created_at": "2026-03-01T08:00:00Z",
"updated_at": "2026-03-01T08:00:00Z"
}
}
}Submit a template for moderation
Request
curl -X POST "https://api.aisar.app/v1/templates/12/submit" \
-H "Authorization: Bearer YOUR_API_TOKEN"Response
{
"data": {
"message": "Template submitted to Meta.",
"submitted_count": 2,
"items": [
{
"channel": { "id": 44, "name": "WABA — Sales", "account_name": "+7 700 000 12 34", "status": "connected", "external_ids": {} },
"template": { "id": 12, "external_id": null, "status": "published", "meta_status": "local", "meta_status_reason": null, "last_synced_at": null },
"availability": "added"
},
{
"channel": { "id": 45, "name": "WABA — Support", "account_name": "+7 700 000 56 78", "status": "connected", "external_ids": {} },
"template": { "id": 20, "external_id": null, "status": "published", "meta_status": "local", "meta_status_reason": null, "last_synced_at": null },
"availability": "added"
}
]
}
}Publish, archive, and unarchive
Request
# Публикация одобренного шаблона (архивирование/разархивирование — аналогично, тело пустое)
curl -X POST "https://api.aisar.app/v1/templates/12/publish" \
-H "Authorization: Bearer YOUR_API_TOKEN"Response
{
"data": {
"message": "Template status updated.",
"template": {
"id": 12,
"status": "published"
}
}
}Add a language version to a template
Request
curl -X POST "https://api.aisar.app/v1/templates/12/languages" \
-H "Authorization: Bearer YOUR_API_TOKEN" \
-H "Content-Type: application/json" \
-d '{
"language": "en",
"body": "Hello, {{first_name}}! Your order #{{order_number}} has been shipped.",
"parameters": [
{ "name": "first_name", "type": "text", "sample_value": "John", "position": 1 },
{ "name": "order_number", "type": "text", "sample_value": "1045", "position": 2 }
]
}'Response
{
"data": {
"message": "Template language version created.",
"template": {
"id": 30,
"company_id": 1,
"template_group_id": 8,
"channel_type": { "id": 4, "key": "whatsapp_business", "name": "WhatsApp Business" },
"channel": { "id": 44, "name": "WABA — Sales", "account_name": "+7 700 000 12 34" },
"name": "Order shipped",
"slug": "order_shipped",
"status": "draft",
"meta_status": "local",
"language": "en",
"category": "utility",
"body": "Hello, {{first_name}}! Your order #{{order_number}} has been shipped.",
"parameters": [
{ "id": 40, "name": "first_name", "type": "text", "sample_value": "John", "position": 1 },
{ "id": 41, "name": "order_number", "type": "text", "sample_value": "1045", "position": 2 }
],
"buttons": [],
"uses_count": 0,
"created_at": "2026-03-01T09:00:00Z",
"updated_at": "2026-03-01T09:00:00Z"
},
"versions": [
{ "id": 12, "language": "ru", "channel_id": 44, "status": "published", "meta_status": "approved" },
{ "id": 20, "language": "ru", "channel_id": 45, "status": "published", "meta_status": "pending" },
{ "id": 30, "language": "en", "channel_id": 44, "status": "draft", "meta_status": "local" },
{ "id": 31, "language": "en", "channel_id": 45, "status": "draft", "meta_status": "local" }
]
}
}Delete a language version of a template
Request
curl -X DELETE "https://api.aisar.app/v1/templates/12/languages/en" \
-H "Authorization: Bearer YOUR_API_TOKEN"Response
{
"data": {
"message": "Template language version deleted.",
"versions": [
{ "id": 12, "language": "ru", "channel_id": 44, "status": "published", "meta_status": "approved" },
{ "id": 20, "language": "ru", "channel_id": 45, "status": "published", "meta_status": "pending" }
]
}
}