API-пайплайн: добавить свои Telegram-группы, найти группы по ключевому слову, месту или рубрике, проверить их и подключить к кампании

Индекс: API-пайплайны — индекс

Цель: выбрать Telegram-группы, в которых работает кампания: добавить свои группы по юзернейму, найти ещё в открытом индексе по ключевому слову, месту или рубрике, проверить их, подключить к кампании группы или пресеты групп и исключить группы из неё.

Модель

A. Добавить свои группы

1. Отправьте юзернеймы. Один вызов создаёт новый пресет и вносит в него каждый юзернейм.

POST /v0/my/telegram_groups
Idempotency-Key: groups-phuket-1
{"title": "Phuket expats", "project": "<project nonce>",
 "telegram_group_handles": ["@example_expats", "https://t.me/example_market", "t.me/+AbCdEf"]}
→ {"workspace": {"nonce": "470350000000000001", "card_type": "workspace", "visibility": "Private", …},
   "handles": [
     {"handle": "t.me/+AbCdEf", "state": "rejected"},
     {"handle": "example_expats", "state": "contained", "nonce": "470350000000000002"},
     {"handle": "example_market", "state": "proposed", "nonce": "470350000000000003"}],
   "proposals_workspace": "470350000000000005"}

2. За кадром: проверка (асинхронно). Cabi.Chat проверяет каждый предложенный юзернейм: это должна быть публичная группа (не канал), не помеченная как scam. Прошедшие проверку добавляются в индекс и в ваш пресет; остальные не добавляются.

3. Посмотрите результат.

GET /v0/my/workspaces/470350000000000001?contained_limit=200
→ {"contained": [{"card_type": "telegram_group", "nonce": "…", "title": "Example market", …}], "contained_next_offset": null}

Один юзернейм: GET /v0/graph/resolve/@tgg.example_market отвечает, когда группа попала в индекс. Прошедшие проверку группы появляются в вашем пресете.

Добавить известную группу в любой свой пресет: POST /v0/my/workspaces/{ws}/{group nonce} → 204; убрать: DELETE по тому же пути.

B. Найти группы в индексе

Ключевое слово:

POST /v0/search/graph
{"query": "phuket", "card_type": "telegram_group", "limit": 20, "page": 1}
→ {"hits": [{"card_type": "telegram_group", "nonce": "…", "handle": "tgg.example_phuket",
            "title": "…", "item_count": 13934, "location": {…}, …}],
   "total_hits": 115, "page": 1, "total_pages": 6}

/v0/search/graph объединяет поиск по словам и по смыслу; /keyword и /vector работают только одной стороной. query обрезается до 200 символов.

Место. Фильтры принимают nonce мест (карточки рубрик вида place), а не geonameid или ISO-коды:

  1. GET /v0/search/geo/cities?q=phuket → {"geonameid": 1151254, "name": "Phuket", "country_iso": "TH", …}
  2. GET /v0/graph/resolve/@rub.geo-1151254 → {"card_type": "rubric", "nonce": "<place nonce>", "kind": "place"}. Страна — @rub.geo-<iso lowercase> (ISO-код в нижнем регистре), например @rub.geo-th.
  3. {"query": "", "card_type": "telegram_group", "filters": {"locations": ["<place nonce>"], "exclude_terms": ["rent"]}}

locations и places_in совпадают с местом и всем, что внутри него. Nonce мест ставятся только туда; внутри rubrics они ничего не находят.

Рубрика: "filters": {"rubrics": [["<rubric nonce>"]]}; внутренние массивы — OR, внешний — AND; rubrics_not исключает. Найти рубрику: {"query": "dating", "card_type": "rubric", "filters": {"kind": "tag"}}.

Внутри пресета: добавьте "workspace": "<preset nonce>".

Допустимые ключи фильтров: rubrics, rubrics_not, rubrics_in, locations, places_in, tags_in, project, preference_countries, preference_city {nonce, lat, lon}, radius_km, roots_only, kind, card_type, exclude_terms; любой другой → 400 unknown filter: <key>.

Число участников и оценки есть в обзоре каждой группы (ниже). Недавно добавленные группы лучше всего находятся по ключевому слову.

Проверить группу:

GET /v0/graph/telegram_groups/@tgg.example_phuket/overview
→ {"tile": {…}, "username": "example_phuket", "members_count": 13934,
   "stats": {"spam": 10.4, "density": 13.8, "openness": 60.9, "moderation": 17.0,
             "audience": 58.1, "pace": 34.0, "msgs_per_day": 221.5, "sample": 200, "rated_at": "…"},
   "mine": {"totals": {"sent": 0, "deleted": 0, "replied": 0, "joined": 0, …}, "timeline": […], "campaigns": […], "replies": […]}}

Оценки от 0 до 100; stats = null, пока группа не оценена. mine — ваша собственная история в этой группе. Страница группы без статистики: GET /v0/graph/telegram_groups/{nonce | @tgg.<username>}.

Готовые пресеты (GET /v0/graph/workspaces/{ident}?contained_limit=&contained_offset=): @ws.tgg.geo-<geonameid>.2026-09-12 (например, @ws.tgg.geo-1151254.2026-09-12, Пхукет) и @ws.tgg.iab-<topic>.2026-09-12 (например, @ws.tgg.iab-travel.2026-09-12): снимки на 2026-09-12.

Списки, которые обновляются сами. Некоторые публичные списки групп Cabi.Chat ведёт автоматически, и они меняются сами, например группы с большим количеством спама или группы, где удаляют много сообщений. Они отмечены рубрикой «Обновляется автоматически» (Auto-maintained; найдите её через {"query": "Auto-maintained", "card_type": "rubric"}, затем ищите воркспейсы с этой рубрикой). Используйте их как пресеты, например в not_tg_groups, чтобы кампания обходила такие группы.

C. Подключить группы к кампании

PATCH /v0/my/campaigns/<campaign nonce>
{"tg_groups": ["<preset nonce>", "<group nonce>"]}

Исключить группы. not_tg_groups перечисляет группы, которые кампания пропускает; принимает те же элементы, что и tg_groups. Удобно, чтобы убрать несколько групп из готового пресета:

PATCH /v0/my/campaigns/<campaign nonce>
{"tg_groups": ["<preset nonce>"], "not_tg_groups": ["<group nonce>", "<other preset nonce>"]}

Поверхность API

Эндпоинт Назначение FE ИИ / оракул
POST /v0/my/telegram_groups Отправить юзернеймы как новый пресет да (Отправить телеграм-группы) да, способ привести свои группы
GET /v0/my/workspaces/{ws} Прочитать пресет; какие группы пришли да да
POST / DELETE /v0/my/workspaces/{ws}/{group} Добавить / убрать известную группу да да
GET /v0/graph/resolve/{@handle} @tgg.<username> → группа; @rub.geo-<id> → место да да
POST /v0/search/graph (/keyword, /vector) Найти группы по слову, месту, рубрике, внутри пресета да да, основной поиск
GET /v0/search/geo/cities, /countries Поиск города или страны да да, затем resolve
GET /v0/graph/telegram_groups/{ident}, /overview Страница группы; участники, оценки, ваша история да да, проверка
GET /v0/graph/workspaces/{ident} Готовые пресеты да да
POST / PATCH /v0/my/campaigns… tg_groups, not_tg_groups Подключить или исключить группы или пресеты да да

Упомянуто