Skip to content
AISARAISAR
REST API

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

MethodPath
GET/v1/templates

List templates (one row per logical group) with pagination, search, and facets by status/language/channel type.

GET/v1/templates/channel-types

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/v1/templates/{template}/channels

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}/events

Event history of the logical group: created/updated, submitted to Meta, moderation results, published/archived (with channel and actor).

POST/v1/templates

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).

POST/v1/templates/{template}

Update a draft template (POST variant of PATCH).

POST/v1/templates/{template}/channels

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}/languages

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/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).

POST/v1/templates/{template}/submit

Submit/resubmit all assigned WABA channel instances of the template to Meta moderation.

POST/v1/templates/{template}/publish

Publish an approved template (make it available for sending).

POST/v1/templates/{template}/archive

Archive a template.

POST/v1/templates/{template}/unarchive

Unarchive a template.

POST/v1/templates/sync

Sync moderation statuses of all company WABA templates from Meta.

Examples

Create a WhatsApp Business template on several channels

Request

bash
# 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

json
{
  "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

bash
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

json
{
  "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

bash
curl -X GET "https://api.aisar.app/v1/templates/12/channels" \
  -H "Authorization: Bearer YOUR_API_TOKEN"

Response

json
{
  "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

bash
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

json
{
  "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

bash
curl -X GET "https://api.aisar.app/v1/templates/12/events" \
  -H "Authorization: Bearer YOUR_API_TOKEN"

Response

json
{
  "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

bash
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

json
{
  "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

bash
curl -X POST "https://api.aisar.app/v1/templates/12/submit" \
  -H "Authorization: Bearer YOUR_API_TOKEN"

Response

json
{
  "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

bash
# Публикация одобренного шаблона (архивирование/разархивирование — аналогично, тело пустое)
curl -X POST "https://api.aisar.app/v1/templates/12/publish" \
  -H "Authorization: Bearer YOUR_API_TOKEN"

Response

json
{
  "data": {
    "message": "Template status updated.",
    "template": {
      "id": 12,
      "status": "published"
    }
  }
}

Add a language version to a template

Request

bash
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

json
{
  "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

bash
curl -X DELETE "https://api.aisar.app/v1/templates/12/languages/en" \
  -H "Authorization: Bearer YOUR_API_TOKEN"

Response

json
{
  "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" }
    ]
  }
}