API AIMen Inbox

Отправляйте и получайте сообщения WhatsApp, Instagram и Telegram из своей CRM, сайта или сервиса. Inbox сам работает с Meta и Telegram: вам не нужны токены Meta, своё приложение в Meta и приём их вебхуков — только ключ Inbox и адрес для событий.

Начало работы

Все адреса — от https://inbox.aimen.kz, данные — JSON в UTF-8. Есть два способа работы:

  • Своя интеграция. У вас аккаунт в Inbox, вы подключаете к нему CRM, сайт или бота. Нужен ключ организации и, если хотите получать входящие, вебхук.
  • Партнёр. Ваш продукт подключает WhatsApp своим клиентам: создаёт для каждого организацию в Inbox и показывает наш виджет подключения у себя. Нужен партнёрский ключ — см. Партнёрам.

Ключи

Ключ организации создаёт владелец аккаунта: Настройки → API-ключи → Создать ключ. Ключ показывается один раз — сохраните его в секретах своего сервера. Ключ действует только для своей организации; отозвать его можно там же.

Передавайте ключ в заголовке каждого запроса:

Authorization: Bearer aimen_live_...
Ключ даёт право писать вашим клиентам от имени компании. Не вставляйте его в код сайта или мобильного приложения — вызывайте API только со своего сервера.

Ответы и ошибки

Успешный ответ — объект с полем data. Ошибка — объект с полем error (текст на русском, его можно показать пользователю) и HTTP-статусом:

{ "data": { ... } }
{ "error": "Шаблон не найден или ещё не одобрен" }
ПолеТипОписание
400—Неверные параметры или их сочетание
401—Нет ключа, ключ неверный или отозван
404—Диалог или организация не найдены
409—Свободный текст вне 24-часового окна WhatsApp (нужен шаблон) или запрос с этим idempotencyKey ещё выполняется
429—Превышен лимит запросов
502—Meta или Telegram не приняли сообщение — причина в error
500—Ошибка на нашей стороне — повторите позже

Лимиты

300 запросов в минуту на ключ. При превышении — 429, повторите через минуту. Контакты загружайте пачками до 100 в одном запросе, а не по одному.

Каналы

GET/api/v1/channelsключ организации

Подключённые каналы организации и их состояние.

Ответ
{
  "data": [
    {
      "id": "8f0c…",
      "type": "whatsapp",
      "displayName": "+7 701 123 45 67",
      "status": "connected",
      "restrictionStatus": null,
      "restrictionDetail": null
    }
  ]
}
ПолеТипОписание
typestringwhatsapp, instagram, telegram или website (чат на сайте)
statusstringconnected — работает; error — нужно переподключить; disconnected — отключён
restrictionStatusstring | nullНе null — Meta ограничила или заблокировала аккаунт; подробности в restrictionDetail. Покажите это своим пользователям.

Сообщения

POST/api/v1/messagesключ организации

Отправка в существующий диалог (любой канал) по conversationId или новому клиенту WhatsApp по номеру телефона — тогда контакт и диалог создаются сами. Сообщение появляется во «Входящих», как отправленное сотрудником.

ПолеТипОписание
conversationIduuidДиалог — из события вебхука или прошлого ответа API
channel + phonestringВместо conversationId: "whatsapp" и номер в любом формате (+77011234567, 8 701 …)
bodystringТекст
templateIduuidОдобренный шаблон WhatsApp (см. Шаблоны)
templateParamsobjectbodyParams — значения {{1}}, {{2}}…; headerParam; buttonUrlParam
mediaUrl, mediaTypestringФайл по ссылке; mediaType — image, video, audio, document
mediaFilenamestringИмя файла для document
replyToMessageIduuidОтвет с цитатой на сообщение
idempotencyKeystringЗащита от двойной отправки при повторе запроса

В одном запросе — что-то одно: body, templateId или mediaUrl.

Ответ
{ "data": { "conversationId": "…", "messageId": "…" } }

Текст

curl https://inbox.aimen.kz/api/v1/messages \
  -H "Authorization: Bearer $INBOX_KEY" \
  -H "Content-Type: application/json" \
  -d '{ "conversationId": "8f0c…", "body": "Здравствуйте! Заказ готов к выдаче." }'
WhatsApp разрешает свободный текст только в течение 24 часов после последнего сообщения клиента. Позже — 409, и нужно отправить шаблон. В Instagram окно тоже 24 часа, в Telegram и чате на сайте ограничений нет.

Шаблон (WhatsApp)

Первое сообщение клиенту, напоминание или ответ после 24 часов — только одобренным шаблоном.

{
  "channel": "whatsapp",
  "phone": "+77011234567",
  "templateId": "c2a1…",
  "templateParams": { "bodyParams": ["Айгерим", "15:00", "12 октября"] }
}

В существующий диалог WhatsApp — { "conversationId": "…", "templateId": "…", "templateParams": {…} }. Шаблонные сообщения Meta оплачивает отдельно, по своим тарифам.

Файлы

Разместите файл по публичной ссылке — Inbox скачает его и отправит в канал.

{
  "conversationId": "8f0c…",
  "mediaUrl": "https://example.com/files/invoice-1042.pdf",
  "mediaType": "document",
  "mediaFilename": "Счёт 1042.pdf"
}

Ответ на конкретное сообщение

replyToMessageId — id сообщения клиента из вебхука. В WhatsApp и Telegram клиент увидит цитату; в Instagram цитата видна только в Inbox.

Повторы запроса

Передайте idempotencyKey — свою уникальную строку, например id напоминания в вашей базе. Повторный запрос с тем же ключом (после таймаута) не отправит сообщение второй раз, а вернёт результат первого. Если первый ещё выполняется — 409. Если отправка не удалась, ключ освобождается и запрос можно повторить.

Контакты

POST/api/v1/contactsключ организации

Загрузка своей базы клиентов — до 100 за запрос. Совпадение ищется по номеру телефона: существующий контакт не перезаписывается, ему только добавляются теги. Новые теги создаются сами — по ним потом удобно делать рассылки в разделе «Маркетинг».

{
  "contacts": [
    { "name": "Айгерим Сапарова", "phone": "+77011234567", "email": "a@example.com", "tags": ["VIP", "Макияж"] }
  ]
}
Ответ
{
  "data": {
    "created": 1,
    "updated": 0,
    "contacts": [{ "id": "…", "phone": "+77011234567", "created": true }],
    "errors": [{ "index": 3, "error": "Укажите корректный phone" }]
  }
}

Шаблоны WhatsApp

GET/api/v1/templatesключ организации
POST/api/v1/templatesключ организации
POST/api/v1/templates/{id}/submitключ организации
DELETE/api/v1/templates/{id}ключ организации

Шаблон создаётся черновиком, затем отправляется на проверку в Meta. Проверка занимает от нескольких минут до пары дней; статус меняется сам.

Создать
{
  "name": "Напоминание о записи",
  "category": "utility",
  "body": "Здравствуйте, {{1}}! Напоминаем о записи {{2}} в {{3}}.",
  "exampleParams": ["Айгерим", "12 октября", "15:00"],
  "footerText": "Салон «Ажар»",
  "buttons": [{ "type": "quick_reply", "text": "Подтверждаю" }]
}
ПолеТипОписание
categorystringutility — уведомления о заказе, записи; marketing — акции; authentication — коды входа
bodystringТекст с параметрами {{1}}, {{2}}… (не в начале и не в конце текста)
exampleParamsstring[]Примеры значений параметров — Meta требует их для проверки
headerText, footerTextstringЗаголовок и подпись (необязательно)
buttonsarrayquick_reply (до 10), url (до 2), phone_number (1)

Статусы в списке: draft — черновик, pending — на проверке, approved — можно отправлять, rejected — отклонён (причина в rejection_reason), paused — Meta приостановила за жалобы клиентов. Покажите статус своим пользователям — иначе непонятно, почему новый шаблон нельзя отправить сразу.

Вебхуки

Inbox отправляет события POST-запросом на ваш адрес. Укажите его в Настройки → API-ключи → Вебхук (только https) — там же выдаётся секрет для проверки подписи и есть кнопка тестового события. Партнёрам адрес настраиваем мы, он общий для всех их организаций.

События

message.created — новое сообщение клиента
{
  "event": "message.created",
  "organizationId": "…",
  "conversationId": "…",
  "isNewConversation": true,
  "message": {
    "id": "…",
    "direction": "inbound",
    "channel": "whatsapp",
    "body": "Здравствуйте, есть размер M?",
    "createdAt": "2026-10-10T09:15:00.000Z"
  },
  "contact": { "id": "…", "name": "Айгерим", "phone": "+77011234567" }
}
message.status_updated — статус отправленного сообщения (WhatsApp)
{
  "event": "message.status_updated",
  "organizationId": "…",
  "conversationId": "…",
  "message": { "id": "…", "status": "delivered", "errorDetail": null }
}

Статусы: sent, delivered, read, failed (причина в errorDetail). Тестовая кнопка в Настройках присылает { "event": "ping", … }. Неизвестные события пропускайте — со временем их станет больше.

Проверка подписи

В заголовке X-Inbox-Signature — sha256= и HMAC-SHA256 тела запроса вашим секретом. Проверяйте её на каждом запросе, по сырому телу, до разбора JSON:

Node.js
import crypto from "node:crypto";

export function isFromInbox(rawBody, signatureHeader, secret) {
  const expected = "sha256=" + crypto.createHmac("sha256", secret).update(rawBody).digest("hex");
  const a = Buffer.from(expected);
  const b = Buffer.from(signatureHeader ?? "");
  return a.length === b.length && crypto.timingSafeEqual(a, b);
}
Python
import hmac, hashlib

def is_from_inbox(raw_body: bytes, signature_header: str, secret: str) -> bool:
    expected = "sha256=" + hmac.new(secret.encode(), raw_body, hashlib.sha256).hexdigest()
    return hmac.compare_digest(expected, signature_header or "")

Повторы доставки

Отвечайте 2xx в течение 5 секунд, а тяжёлую обработку делайте в фоне. Если ваш сервер не ответил, событие не теряется: Inbox повторит его через 1 мин, 5 мин, 30 мин, 2 ч, 6 ч и 24 ч. Событие может прийти повторно — проверяйте message.id, чтобы не обработать его дважды.

Партнёрам

Для продуктов, которые подключают WhatsApp и Instagram своим клиентам: ваш клиент нажимает «Подключить WhatsApp» у вас, проходит вход Facebook в нашем виджете — и вы отправляете и получаете его сообщения через API. Интерфейс Inbox и отдельный логин вашему клиенту не нужны. Партнёрский ключ и вебхук выдаём по запросу на inbox_support@aimen.kz.

1. Организация для клиента

POST/api/partner/v1/organizationsпартнёрский ключ
{ "externalId": "clinic-42", "name": "Клиника «Шипагер»" }
Ответ
{ "data": { "organizationId": "…", "created": true, "apiKey": "aimen_live_…" } }

externalId — id клиента в вашей системе. Повторный вызов с тем же externalId вернёт ту же организацию с created: false и apiKey: null. Ключ организации выдаётся один раз — сохраните его сразу и дальше работайте с этим клиентом через разделы выше.

2. Виджет подключения канала

POST/api/partner/v1/embed-tokensпартнёрский ключ
{ "organizationId": "…", "channel": "whatsapp" }
Ответ
{ "data": { "embedUrl": "https://inbox.aimen.kz/embed/connect?token=…", "expiresAt": "…" } }

channel — whatsapp или instagram. Ссылка живёт 30 минут. Покажите её в iframe на странице настроек:

<iframe src="{embedUrl}" style="border:0;width:100%;height:120px" allow="popups"></iframe>

<script>
  window.addEventListener("message", (event) => {
    if (event.origin !== "https://inbox.aimen.kz") return;
    if (event.data?.type === "INBOX_CHANNEL_CONNECTED") {
      // event.data.channel: "whatsapp" | "instagram" — обновите статус через GET /api/v1/channels
    }
  });
</script>

Перед виджетом коротко объясните клиенту: откроется окно Facebook; нужен аккаунт, связанный с бизнесом; для WhatsApp — номер, на котором нет обычного приложения WhatsApp, и код из SMS; для Instagram — профессиональный аккаунт.

Первый запуск

  1. Создайте ключ в Настройках → API-ключи (партнёр — получите партнёрский ключ и создайте организацию).
  2. Проверьте ключ: GET /api/v1/channels — подключённый канал со статусом connected.
  3. Укажите адрес вебхука и нажмите «Отправить тестовое событие» — проверьте подпись на своей стороне.
  4. Напишите на подключённый номер с телефона — придёт message.created.
  5. Ответьте через POST /api/v1/messages с conversationId из события — следом придёт message.status_updated.