К содержанию
TelegaFirst

Для AI-агентов: markdown этой страницы — /docs/marketing.mdиндекс документации — /llms.txt

Сегменты, рассылки и цепочки

Обновлено

TelegaFirst помогает микробизнесу продолжать разговор с клиентом: выбрать аудиторию, подготовить сообщение, согласовать отправку и увидеть результат. Владелец и операторы управляют этим из Telegram, а собственный AI-агент владельца может работать через Hub с выданными правами. Клиенты получают сообщения в своём поддерживаемом канале; выбор аудитории и право доставить сообщение проверяются отдельно.

Результат работы — сохранённый сегмент, подготовленный черновик и, после подтверждения человеком, принятая задача отправки с доступным статусом. queued означает постановку в очередь. Итоговые счётчики показывают, сколько сообщений действительно отправлено и сколько завершилось ошибкой.

Перед началом

Подключите бизнес по инструкции запуска и проверьте активный slug и бота. Для MCP выполните авторизацию, обновите tools/list и получите схему нужной операции по руководству MCP. Наличие схемы ещё не означает установленный в вашем AI-клиенте инструмент.

Для REST ниже указаны относительные пути Hub. X-Api-Key и Authorization: Bearer tgf_* — альтернативные способы передать допустимый ключ. Owner/customer JWT нельзя подставлять вместо ключа на этих маршрутах. Нужные права и текущий доступ человека или credential проверяются при каждом вызове; права одной операции не заменяют права другой.

ЗадачаREST scope
Оси, цели, preview и чтение сохранённых сегментовbroadcasts:read
Выборка клиентов сегментаdialogs:read
Создание, изменение, удаление сохранённого сегмента; запись и запуск рассылкиbroadcasts:write
Чтение кампаний и источниковmarketing:read
Изменение кампаний и источниковmarketing:write
Чтение цепочек и шагов через MCPchains:read
Изменение цепочек, шагов и подготовка пакетного входаchains:write

Все required scopes операции обязательны одновременно. Тариф, readiness, актуальные permissions, лимиты и согласие на денежное действие сохраняют силу при наличии scope. Права и ограничения.

Примеры используют демонстрационные номера и контрактные ответы. Они не являются записью реальной рассылки. Перед записью получите номера из своего бизнеса: номер клиента, кампании, товара или цепочки — tenant-local seq_num, а не идентификатор базы данных. client_id приходит из аутентификации и не передаётся в JSON. Идентификаторы и страницы результатов.

Соберите и проверьте аудиторию

  1. Прочитайте GET /api/v1/tools/segments/axes (200), в MCP — describe_segment_axes. Выберите доступные kind/key и проверьте requiresTarget, targetEntity, periodSupported и available.

  2. Для условий с целью вызовите POST /api/v1/tools/segments/targets (201), в MCP — list_segment_targets. Возвращённый seq — строка с номером объекта вашего бизнеса. Здесь default/maximum limit — 50; строка поиска ограничена 200 символами.

  3. Соберите фильтр: внутри any условия объединяются через «ИЛИ», разные группы include — через «И», условия exclude вычитаются как объединение. Плоский старый список условий не подходит.

  4. Выполните POST /api/v1/tools/segments/reach (201), в MCP — preview_segment_reach. Прочитайте valid, issues, reachable и breakdown. Число 0 при valid:false не означает корректный пустой сегмент.

  5. После успешной проверки при необходимости вызовите POST /api/v1/tools/segments/sample (201), в MCP — sample_segment_audience. Default limit — 20, maximum — 50; результат содержит userSeqNums, без внешних chat IDs.

Пример запроса целей; для POST с непустым телом нужен отдельный Idempotency-Key:

POST /api/v1/tools/segments/targets
Content-Type: application/json
Idempotency-Key: audience-targets-1

{
  "kind": "commerce",
  "key": "bought_product",
  "search": "Course"
}

Контрактный ответ 201:

{
  "targets": [
    {
      "seq": "7",
      "title": "Course"
    }
  ]
}

Фильтр «Вся база», который можно передать в filter для preview и sample:

{
  "include": [
    {
      "any": [
        {
          "kind": "preset",
          "key": "all_subscribers"
        }
      ]
    }
  ],
  "exclude": []
}

Название all_subscribers обозначает базовое условие аудитории. Оно не доказывает рекламное согласие каждого человека. Получайте необходимое согласие на сообщения и учитывайте актуальные ограничения доставки; блокировка бота исключает получателя, а ограничения канала и поддерживаемых возможностей могут привести к пропуску. Preview не резервирует аудиторию и не гарантирует доставку каждому выбранному клиенту.

Например, структурно неверный фильтр в reach:

{
  "filter": {
    "malformed": true
  }
}

Этот запрос даёт диагностический ответ 201, а не разрешение отправлять:

{
  "valid": false,
  "issues": [
    "Malformed filter"
  ],
  "reachable": 0,
  "breakdown": {
    "valid": false,
    "issues": [
      "Malformed filter"
    ],
    "reachable": null,
    "include": [],
    "exclude": [],
    "excludedUnion": null
  }
}

Попытка получить sample с непригодным фильтром возвращает 422 INVALID_INPUT. Исправьте фильтр по описанию осей, снова выполните preview, затем sample. Ошибка выбора аудитории не должна превращаться в отправку всей базе.

Сохраните сегмент и работайте с его версией

POST /api/v1/tools/segments/saved создаёт сегмент и возвращает 201. Заголовок Idempotency-Key обязателен. Заголовок сегмента после обрезки пробелов должен содержать 1..120 символов.

{
  "title": " New audience ",
  "filter": {
    "include": [
      {
        "any": [
          {
            "kind": "preset",
            "key": "all_subscribers"
          }
        ]
      }
    ],
    "exclude": []
  }
}

Полный контрактный результат:

{
  "seqNum": 9,
  "title": "New audience",
  "filter": {
    "include": [
      {
        "any": [
          {
            "kind": "preset",
            "key": "all_subscribers"
          }
        ]
      }
    ],
    "exclude": []
  },
  "version": 1,
  "updatedAt": "2026-10-01T10:00:00.000Z"
}

Для чтения используйте GET /api/v1/tools/segments/saved/{seqNum}. Список GET /api/v1/tools/segments/saved?afterSeqNum=6&limit=1 возвращает segments и nextAfterSeqNum; следующий запрос получает возвращённый номер. Default limit — 100, maximum — 500. Не переносите этот параметр на списки рассылок или цепочек: у них другой контракт, без такой пагинации.

Изменение PATCH /api/v1/tools/segments/saved/7 требует текущего expectedVersion и хотя бы одного из title/filter. Например, после чтения версии 2:

{
  "expectedVersion": 2,
  "title": " Updated audience "
}

Успех 200 содержит тот же seqNum:7, обновлённое название Updated audience и version:3. При 409 CONFLICT с detail Saved segment version changed; reload and retry перечитайте сегмент, покажите изменения человеку и решите, нужна ли прежняя правка. Удаление DELETE /api/v1/tools/segments/saved/7 также принимает тело {"expectedVersion":2} для удаления именно прочитанной версии.

В рассылке saved_segment_seq_num — номер сохранённого сегмента. Не передавайте одновременно противоречащие друг другу источники аудитории. При подготовке запуска версия и содержимое сегмента входят в проверяемый снимок; изменение аудитории требует новой подготовки.

Подготовьте рассылку и отдельно согласуйте запуск

Черновик REST создаётся POST /api/v1/tools/broadcasts (201), меняется PATCH того же пути (200). Непустой POST требует Idempotency-Key. Пример создания:

{
  "title": "Autumn",
  "saved_segment_seq_num": null,
  "segment_labels": "Everyone",
  "message_ttl_minutes": 90,
  "button_title": "Open",
  "button_target": {
    "kind": "section_root",
    "section": "catalog"
  }
}

Полный контрактный результат:

{
  "seqNum": 3,
  "status": "draft",
  "title": "Autumn",
  "savedSegmentSeqNum": null,
  "target": {
    "kind": "section_root",
    "section": "catalog"
  },
  "isAwaitingReply": false,
  "segmentLabels": "Everyone",
  "segmentFilter": null,
  "scheduledAt": null,
  "scheduleEcho": null,
  "messageTtlMinutes": 90,
  "buttonTitle": "Open",
  "buttonTarget": {
    "kind": "section_root",
    "section": "catalog"
  }
}

Черновик ещё не отправляется. Текст/медиа и аудитория должны быть подготовлены до запуска; REST shell-запрос выше не заменяет подготовку rich content. У MCP create_broadcast отдельная rich-схема с обязательным content: не копируйте REST JSON в этот инструмент. Его описанный путь состоит из четырёх вызовов: create_broadcast, один get_content_draft, затем prepare_broadcast_launch и после окончательного подтверждения человеком — execute_broadcast_launch. Если единственная проверка draft ещё не вернула опубликованный seqNum, остановитесь и разберитесь с готовностью контента.

В REST при PATCH отсутствующий segment_filter сохраняет прежнюю аудиторию, а null сбрасывает её на всю базу. Проверьте это перед подтверждением. Для schedule передайте kind:"once" и at_local — локальное время бизнеса без offset/Z; абсолютное время разрешает сервер по часовому поясу бизнеса. Проверяйте возвращённый scheduleEcho. Нельзя подменять at_local произвольной UTC-строкой.

REST-порядок запуска:

  1. Прочитайте GET /api/v1/tools/broadcasts и проверьте черновик, содержание, аудиторию, время, срок сообщения и доступный баланс.

  2. Вызовите POST /api/v1/tools/broadcasts/prepare-launch с {"seq_num":3} и новым Idempotency-Key. Ответ 200 содержит seqNum, текущий status и revision — строку из 64 hex-символов. Подготовка не отправляет сообщения.

  3. Покажите человеку именно подготовленный сценарий и получите окончательное подтверждение запуска: отправка может расходовать баланс.

  4. Передайте тот же seq_num и точную возвращённую revision в POST /api/v1/tools/broadcasts/execute-launch, с отдельным новым Idempotency-Key. Успех 202:

{
  "seqNum": 3,
  "status": "queued"
}

Чтобы не перепечатать и не выдумать revision, сформируйте тело из сохранённого успешного ответа подготовки:

jq -c '{seq_num: .seqNum, revision: .revision}' preparation.json > launch.json

Передайте launch.json как JSON-тело execute только после подтверждения. Если черновик изменился после подготовки, сервер возвращает 409 CONFLICT: получите новую preparation и новое подтверждение, а не заменяйте hash вручную.

MCP использует серверную квитанцию: prepare_broadcast_launch возвращает preparation_id, payload_hash, expires_at, payload и launch. execute_broadcast_launch получает только точные preparation_id/payload_hash; REST revision-body не подходит вместо этой квитанции. Выполняйте пару из одного авторизованного контекста и не переносите подготовку между бизнесами или credential.

После запуска вызовите POST /api/v1/tools/broadcasts/status с {"seq_num":3} (201, scope broadcasts:read, отдельный Idempotency-Key); в MCP — get_broadcast_status. Читайте статус рассылки и последнюю execution вместе. Например, полный контрактный ответ показывает отдельные состояния и фактические счётчики:

{
  "seqNum": 3,
  "status": "draft",
  "execution": {
    "status": "completed",
    "totalRecipients": 21,
    "totalSent": 19,
    "failed": 2,
    "startedAt": "2026-09-30T11:00:00.000Z",
    "completedAt": "2026-09-30T11:01:00.000Z"
  }
}

Это демонстрация формы ответа, не продолжение реального запуска из примера. Для свежего status-read после изменения состояния используйте новый ключ: повтор прежнего идемпотентного POST может вернуть прежний ответ из кэша. В списке и карточке предусмотрены состояния draft, scheduled, sending, completed, failed, cancelled; execution:null означает отсутствие записанного запуска.

Цепочки сообщений

GET /api/v1/tools/chains читает цепочки, POST создаёт shell по {"title":"Welcome"}, PATCH меняет название по {"seq_num":7,"title":"Welcome"}, а POST /api/v1/tools/chains/delete удаляет по {"seq_num":7}. Создание/удаление возвращают 201; создание требует Idempotency-Key и даёт:

{
  "seqNum": 7,
  "title": "Welcome",
  "isActive": false,
  "deeplinkCode": null
}

Активность определяется настройкой шагов; поле isActive нельзя записать в shell-body. Через MCP используйте list_chain_steps, create_chain_step, update_chain_step, delete_chain_step с chain_seq_num и возвращённым номером шага. Оператор также настраивает цепочку в Telegram. У shell REST нет отдельного придуманного маршрута шагов или массового старта.

Для пакетного входа через MCP сначала вызовите prepare_chain_batch_entry. Пример аргументов, если указанные клиенты и цепочка существуют в выбранном бизнесе:

{
  "chain_seq_num": 7,
  "user_seq_nums": [
    17,
    18
  ],
  "on_active": "noop"
}

Допустимо 1..50 клиентов. on_active выбирается явно: noop сохраняет активный проход, deliver доставляет выбранный шаг без перемещения, restart прекращает активный проход перед новым. Покажите возвращённый неизменяемый сценарий человеку; после подтверждения execute_chain_batch_entry получает preparation_id и payload_hash из preparation. Повторно придумывать массив клиентов в execute нельзя. Проверка состояния, доставки и актуальных прав сохраняется при исполнении.

Кампании и ссылки на источники

Кампания связывает источник обращения с целевым содержимым и статистикой. GET /api/v1/tools/marketing и GET /api/v1/tools/marketing/links возвращают кампании/источники; для записи используйте POST/PATCH соответствующих путей. Например, новый источник в кампании 2:

{
  "campaign_seq_num": 2,
  "kind": "code_word",
  "title": "Summer source",
  "code_word": "summer",
  "comment": null,
  "is_active": true
}

POST /api/v1/tools/marketing/links с новым Idempotency-Key возвращает 201:

{
  "seqNum": 5,
  "campaignSeqNum": 2,
  "kind": "code_word",
  "title": "Summer source",
  "comment": null,
  "wordNormalized": "summer",
  "isActive": true,
  "qrUrl": "https://storage.example.test/qr/opaque.png?sig=signed",
  "qrUrlExpiresAt": "2026-09-30T10:15:00.000Z"
}

В примере домен .test и подпись демонстрационные; рабочий QR URL берите из ответа и учитывайте qrUrlExpiresAt. Истёкший signed URL нельзя считать постоянным публичным адресом. В управлении кампаниями цель {"kind":"deeplink","entity_type":"product","entity_seq":3} использует guarded номер товара. Публичную ссылку на товар, событие или цепочку берите по серверному opaque-коду; не превращайте entity_seq, campaignSeqNum или seqNum в анонимный URL. Единственная читаемая строка адреса бизнеса — Client.slug.

Ошибки и повтор запросов

ОтветЧто делать
400 VALIDATION_ERROR / INVALID_REQUESTИсправить конкретные поля, типы и строгую форму запроса; client_id и внутренние IDs не добавлять
400 IDEMPOTENCY_KEY_REQUIREDДобавить ключ к непустому POST; новый замысел получает новый ключ
401 INVALID_API_KEYПроверить допустимый транспорт credential; пройти нужную авторизацию
403 INSUFFICIENT_SCOPE, PUBLISHABLE_KEY_NOT_ALLOWED, NO_ACTIVE_BOTСверить scope, вид ключа, активного бота и актуальный доступ
404 NOT_FOUNDПолучить актуальный номер в выбранном бизнесе; чужой объект также недоступен
409 CONFLICTПрочитать detail: старая версия сегмента, изменённый launch-снимок или ещё выполняющийся HTTP-запрос требуют разных действий
422 INVALID_INPUTИсправить значение, которое называет detail, например фильтр или зарезервированное кодовое слово; исправленное тело отправить с новым ключом
422 IDEMPOTENCY_KEY_MISMATCHДля изменённого тела использовать новый ключ; прежний ключ повторяет прежний запрос
413 PAYLOAD_TOO_LARGE / ITEM_COUNT_EXCEEDEDУменьшить объём и размер пакета
429 RATE_LIMIT_EXCEEDED / RATE_LIMIT_UNAVAILABLEУчитывать Retry-After, если он возвращён; отказ лимитера не означает успешную отправку
500 INTERNAL_ERRORСохранить traceId, проверить состояние до повтора действия

REST HTTP-ответ хранится 86400 секунд для применимых идемпотентных запросов. У PATCH ключ необязателен; если он передан, изменённое тело с тем же ключом даёт 422. Заголовки X-Client-Slug/X-Bot-Username помогают сверить контекст, а X-RateLimit-* — бюджет запроса. ETag не заменяет expectedVersion сохранённого сегмента или launch revision. Идемпотентность, справочник ошибок.

Точные формы отдельных операций: сегменты, рассылки, цепочки REST, кампании, цепочки MCP, рассылки MCP. Сегменты посещения мероприятия связывают маркетинг с регистрациями и записями. Внутренние разговорные AI-агенты советуют и передают запрос человеку; операции с расходованием денег выполняет только собственный scoped агент клиента через разрешённый сценарий.