# Интеграция Тупика для Тунца и AI Semantica

Документ описывает, как внешние сервисы могут создавать аккаунты, заполнять профиль, публиковать статьи, создавать карточки спикеров, добавлять конференции и подписки на конференции в to-pick.ru.

## Что уже сделано

У Тупика есть серверный REST API:

```text
https://to-pick.ru/api/v1/
```

Через него можно:

- создать пользователя;
- получить пользовательский токен;
- обновить профиль автора;
- опубликовать статью с обложкой;
- создать или обновить карточку спикера;
- добавить конференцию/мероприятие;
- создать подписку на конференции.

Это уже достаточно, чтобы To-nets, AI Semantica или внутренний агент публиковали контент без браузера и без ручного входа на сайт.

## Чем это похоже на Publora

Publora показывает два уровня:

- REST API — обычный программный интерфейс для интеграций;
- MCP Server — обертка, через которую AI-клиенты видят эти действия как инструменты.

У Тупика сейчас есть оба слоя: REST API и MCP Server. REST API остается надежной основой для backend-интеграций, а MCP Server описывает эти действия как tools для AI-агентов.

Практически:

- для собственных сервисов Тунец / AI Semantica одного REST API достаточно;
- для подключения к Claude, Cursor, ChatGPT/Codex, n8n MCP-клиентам используйте MCP Server `https://to-pick.ru/mcp/server`;
- для людей и агентов есть страница `/mcp/` со списком функций, схемами и примерами.

## Правило для всех `slug`

`slug` — это человекопонятная часть URL. Во всех методах Тупика для `slug` разрешены только латинские буквы `a-z`, цифры и дефисы `-`.

Нельзя передавать русский язык, пробелы, слэши `/`, обратные слэши, кавычки и знаки препинания. Если агент не уверен в корректности `slug`, лучше не передавать этот параметр: API сам создаст безопасный адрес из названия и сделает его уникальным.

## Авторизация

Есть два уровня доступа.

### 1. API-ключ сервиса

Передается в заголовке:

```http
X-Tupik-Api-Key: <API_KEY>
```

API-ключ нужен для сервисных действий:

- создать пользователя;
- выдать пользовательский токен.

API-ключ должен храниться только на сервере Тунца / AI Semantica. Не отдавать его в браузер.

### 2. Пользовательский токен

После создания пользователя или запроса токена API возвращает:

```json
{
  "user_token": {
    "token": "tpu_...",
    "expires_at": "2027-06-16 12:00:00",
    "scopes": [
      "profile:write",
      "articles:create",
      "articles:publish",
      "speakers:write",
      "events:create",
      "events:subscribe",
      "stats:read"
    ]
  }
}
```

Дальше все действия от имени пользователя идут с заголовком:

```http
Authorization: Bearer <USER_TOKEN>
```

## Базовый сценарий для агента

1. Проверить, есть ли пользователь в Тупике по email.
2. Если нет — создать пользователя.
3. Получить `user_token`.
4. При необходимости заполнить профиль.
5. Опубликовать статью.
6. При необходимости создать карточку спикера.
7. При необходимости добавить конференцию.
8. При необходимости создать подписку на конференции.

## Создание пользователя

```http
POST /api/v1/users/create
X-Tupik-Api-Key: <API_KEY>
Content-Type: application/json
```

```json
{
  "email": "author@example.com",
  "name": "Иван Петров",
  "slug": "ivan-petrov",
  "accepted_terms": true,
  "accepted_privacy": true,
  "return_password": true,
  "profile": {
    "role": "SEO-специалист",
    "company": "AI Semantica",
    "about": "Пишу о поиске, нейросетях и контент-маркетинге.",
    "website": "https://example.com"
  }
}
```

Если пользователь уже есть, API не создает дубль, а возвращает существующего пользователя и новый токен.

## Получение токена существующего пользователя

```http
POST /api/v1/users/token
X-Tupik-Api-Key: <API_KEY>
Content-Type: application/json
```

```json
{
  "email": "author@example.com",
  "ttl_days": 365
}
```

## Обновление профиля автора

```http
POST /api/v1/users/profile
Authorization: Bearer <USER_TOKEN>
Content-Type: application/json
```

```json
{
  "name": "Иван Петров",
  "slug": "ivan-petrov",
  "about": "SEO-специалист, автор материалов о поиске и нейросетях.",
  "role": "SEO-специалист",
  "company": "AI Semantica",
  "website": "https://example.com"
}
```

## Публикация статьи с обложкой

```http
POST /api/v1/articles/create
Authorization: Bearer <USER_TOKEN>
Content-Type: application/json
```

```json
{
  "title": "Как нейросети меняют SEO в 2026 году",
  "slug": "kak-nejroseti-menyayut-seo-v-2026",
  "lead": "Разбираем, как AI Overviews, ChatGPT и поисковые агенты меняют требования к контенту и видимости бренда.",
  "content_html": "<h2>Что изменилось</h2><p>Поиск становится диалоговым, а контент должен отвечать на вопросы быстрее и точнее.</p>",
  "category_title": "AI и автоматизация",
  "status": "publish",
  "cover_image_url": "https://example.com/cover.jpg"
}
```

Варианты обложки:

- `cover_image_url` — URL картинки, API скачает и сожмет ее;
- `cover_image_base64` — картинка в base64;
- `cover_url` — готовый URL, если картинку не нужно скачивать.

Требования:

- `title` минимум 3 символа;
- `content_html` минимум 40 символов текста;
- если `lead` короткий, API сам возьмет начало статьи;
- если у пользователя отрицательная репутация, публикация запрещена правилами сайта.

## Создание или обновление карточки спикера

```http
POST /api/v1/speakers/create
Authorization: Bearer <USER_TOKEN>
Content-Type: application/json
```

```json
{
  "title": "Иван Петров",
  "slug": "ivan-petrov",
  "short_position": "SEO и GEO-специалист",
  "city": "Москва",
  "can_travel": true,
  "topics": ["SEO", "GEO / продвижение в нейросетях", "Контент-маркетинг"],
  "formats": ["Офлайн", "Онлайн", "Подкаст"],
  "video_url": "https://example.com/video",
  "about": "<p>Помогаю компаниям получать видимость в поиске и ответах нейросетей.</p>",
  "conditions": "<p>Выступаю с докладами, мастер-классами и стратегическими сессиями.</p>",
  "website": "https://example.com",
  "request_email": "speaker@example.com",
  "photo_image_url": "https://example.com/photo.jpg"
}
```

Особенность: у пользователя может быть только одна карточка спикера. Повторный вызов обновит существующую карточку.

Варианты фото:

- `photo_image_url`;
- `photo_image_base64`;
- `photo_url`, если фото уже где-то размещено.

## Добавление конференции / мероприятия

```http
POST /api/v1/events/create
Authorization: Bearer <USER_TOKEN>
Content-Type: application/json
```

```json
{
  "title": "Digital-конференция 2026",
  "slug": "digital-konferenciya-2026",
  "event_type": "Конференция",
  "date_start": "2026-08-01",
  "date_end": "2026-08-02",
  "format": "Офлайн",
  "city": "Москва",
  "topics": ["SEO", "GEO / продвижение в нейросетях"],
  "lead": "Конференция о поиске, нейросетях и продвижении брендов в AI-ответах.",
  "description": "<p>В программе доклады, панельные дискуссии и разборы кейсов.</p>",
  "source_url": "https://example.com/event",
  "cover_image_url": "https://example.com/event-cover.jpg",
  "needs_speakers": "yes",
  "speaker_terms": "free",
  "deadline": "2026-07-20",
  "organizer": "AI Semantica",
  "organizer_contact": "events@example.com",
  "conditions": "<p>Спикерам участие бесплатно.</p>"
}
```

После создания мероприятие уходит на модерацию.

Поля:

- `event_type`: конференция, вебинар, форум, митап, подкаст-запись и т.д.;
- `slug`: необязательный ЧПУ мероприятия. Разрешены только латинские буквы `a-z`, цифры и дефисы. Русский язык, пробелы, слэши `/`, кавычки и знаки препинания запрещены: API их заменит или удалит. Если не уверены — не передавайте `slug`, Тупик создаст его из названия сам;
- `date_start`: дата начала;
- `date_end`: дата окончания, если мероприятие идет несколько дней;
- `format`: онлайн, офлайн, гибрид;
- `needs_speakers`: `yes`, `no`, `unknown`;
- `speaker_terms` используется только если `needs_speakers = yes`:
  - `free` — бесплатно спикерам;
  - `speaker_pays` — спикеры платят;
  - `paid` — спикерам платят.

## Создание подписки на конференции

```http
POST /api/v1/events/subscribe
Authorization: Bearer <USER_TOKEN>
Content-Type: application/json
```

```json
{
  "title": "SEO и GEO онлайн",
  "topics": ["SEO", "GEO / продвижение в нейросетях"],
  "cities": ["Онлайн", "Москва"],
  "formats": ["Онлайн", "Гибрид"],
  "event_types": ["Конференция", "Вебинар"],
  "needs_speakers": "yes",
  "date_from": "2026-06-01",
  "date_to": "2026-12-31"
}
```

После сохранения:

- фильтр появляется в аккаунте пользователя;
- пользователь получает уведомление на сайте;
- API возвращает текущие подходящие мероприятия.

## Проверка текущего пользователя

```http
GET /api/v1/me
Authorization: Bearer <USER_TOKEN>
```

Ответ показывает пользователя и выданные права токена.

## Ошибки

API всегда отвечает JSON-ом:

```json
{
  "ok": false,
  "error": "event_topics_required"
}
```

Частые ошибки:

- `invalid_api_key` — неверный API-ключ сервиса;
- `user_token_required` — нет `Authorization: Bearer ...`;
- `scope_denied` — у токена нет нужного права;
- `category_not_found` — категория статьи не найдена;
- `speaker_topics_required` — у спикера не указаны темы;
- `event_source_url_required` — у мероприятия нет ссылки на источник;
- `event_topics_required` — у мероприятия не указаны темы;
- `subscription_filter_required` — подписка без параметров.

## Достаточно ли одного API для нейроагентов

Да, если агент работает внутри To-nets, AI Semantica, n8n, Make, собственного backend или любого сервиса, который умеет делать HTTP-запросы.

Один API закрывает главную задачу:

- создать аккаунт;
- получить токен;
- заполнить профиль;
- загрузить обложку;
- опубликовать статью;
- создать спикера;
- добавить конференцию;
- создать подписку.

Но если задача — чтобы внешний AI-клиент сам “увидел” инструменты Тупика как MCP tools, одного REST API мало. Тогда нужен один из двух следующих слоев.

## Следующий слой: MCP Server

MCP-сервер — это тонкая обертка над REST API Тупика.

Он должен объявить tools:

- `tupik_create_user`;
- `tupik_get_user_token`;
- `tupik_update_profile`;
- `tupik_publish_article`;
- `tupik_upsert_speaker`;
- `tupik_create_event`;
- `tupik_subscribe_events`;
- `tupik_get_me`.

Каждый tool внутри просто вызывает соответствующий REST API.

Такой MCP-сервер нужен, если мы хотим подключать Тупик в Claude Desktop, Cursor, Codex, внутренние агентные среды и другие MCP-клиенты.

## Следующий слой: WebMCP

WebMCP — это страница и JS-слой на самом сайте, где агент может обнаружить доступные функции.

Для Тупика логичная страница:

```text
https://to-pick.ru/mcp/
```

На ней нужно разместить:

- описание, что умеет Тупик;
- список tools;
- JSON-схемы входных параметров;
- примеры успешных сценариев;
- ссылку на API-документацию;
- ссылку из футера;
- ссылку в `llms.txt`.

WebMCP полезен для видимости и будущих браузерных агентов, но для To-nets и AI Semantica серверный REST API уже практичнее.

## Рекомендуемый план интеграции для Тунца / AI Semantica

1. Хранить API-ключ Тупика на backend.
2. При первом размещении автора вызвать `users/create`.
3. Сохранить `user_token` у себя в базе.
4. Перед публикацией проверять `/me`.
5. Публиковать статью через `articles/create`.
6. Если автор спикер — вызвать `speakers/create`.
7. Если сервис нашел мероприятие — вызвать `events/create`.
8. Если пользователь хочет мониторинг конференций — вызвать `events/subscribe`.
9. Позже добавить MCP-сервер, который обернет эти же методы.
