WriterHub API
WriterHub хранит посты Студии, библиотеки авторов, проектные скиллы и корзину отдельно для каждого профиля. Эта инструкция предназначена и для человека, и для AI-агента, которому передали ссылку на документацию и персональный API-ключ.
Production URL:
https://writerhub.tea-gpt.ru
Полезные ссылки:
- понятная HTML-документация:
/docs; - этот полный Markdown для AI:
/docs/ai.md; - краткая карта для AI:
/llms.txt; - OpenAPI:
/api/openapi.json; - ReDoc:
/api/redoc; - Swagger без отправки запросов:
/api/docs.
Быстрый старт для AI-агента
- Полностью прочитайте эту страницу.
- Получите от пользователя API-ключ WriterHub.
- Не помещайте ключ в URL, текст ответа, логи, файлы проекта или Git.
- Проверьте соединение через публичный
GET /api/v1/health. - Перед записью прочитайте текущий ресурс и его
revision, если она есть. - Выполните минимальную необходимую операцию.
- Перечитайте изменённый ресурс и проверьте результат.
- Не удаляйте и не очищайте данные без прямой команды пользователя.
Проверка:
curl --fail --silent --show-error \
https://writerhub.tea-gpt.ru/api/v1/health
Авторизация и изоляция профилей
Защищённые запросы используют персональный Bearer API-ключ:
Authorization: Bearer <WRITERHUB_PROFILE_API_KEY>
Пример:
curl --fail --silent --show-error \
-H "Authorization: Bearer $WRITERHUB_API_KEY" \
https://writerhub.tea-gpt.ru/api/v1/studio/drafts
API-ключ сам определяет профиль. В URL и теле запроса нет user_id, который
можно подменить. Ключ получает доступ только к данным своего владельца.
Не передавайте ключ:
- в query string;
- в ссылке на документацию;
- в prompt или публичном сообщении;
- в исходном коде;
- в скриншоте;
- в журнале команд.
В браузере ключи создаются через меню профиля → API-ключи. Там выбираются название, права и необязательный срок. Просмотр, замена и отзыв требуют пароль.
Права API-ключа
Права разделены на чтение и запись:
studio:read,studio:write;authors:read,authors:write;skills:read,skills:write;trash:read,trash:write.
Право write всегда сопровождается соответствующим read. Недостаточные права
возвращают 403.
Общие правила записи
Ревизии
Черновики, папки и редактируемые публикации имеют revision. Передавайте
полученное значение как if_revision. Если ресурс уже изменился, сервер вернёт
409, а не затрёт новое изменение.
Правильный порядок:
GETресурса;- сохранить его
revision; - отправить
PATCHсif_revision; - при
409снова выполнитьGET, объединить изменения и повторить.
Идемпотентность
Читающие запросы безопасно повторять. Повторный commit одного задания импорта идемпотентен. Создание ресурса без явно заданного ID может создать дубликат, поэтому после сетевой ошибки сначала проверьте список ресурсов.
Формат ответа и ошибок
JSON-ошибка:
{
"detail": "Описание ошибки"
}
Основные статусы:
200,201— операция выполнена;400— некорректные данные;401— авторизация отсутствует;403— ключ неверен или не имеет права;404— ресурс не найден;409— конфликт ревизий или дубликат;410— ключ отозван или истёк;413— импорт слишком большой;422— тело не соответствует OpenAPI;429— превышен лимит чувствительных auth-операций;503— серверная конфигурация не завершена.
Студия: папки и посты
Прочитать состояние
GET /api/v1/studio/state
GET /api/v1/studio/folders
GET /api/v1/studio/drafts
GET /api/v1/studio/state возвращает всё состояние Студии. Для обычной работы
предпочитайте точные folder/draft endpoints.
Создать папку
POST /api/v1/studio/folders
Content-Type: application/json
{
"name": "Идеи для канала"
}
Можно передать стабильный id, если интеграция заранее его контролирует:
{
"id": "content-plan",
"name": "Контент-план"
}
Переименовать папку
PATCH /api/v1/studio/folders/{folder_id}
{
"name": "Готово к публикации",
"if_revision": 0
}
Удалить папку
DELETE /api/v1/studio/folders/{folder_id}?if_revision=1
Посты из удалённой папки переходят в системный раздел «Без папки». Сами посты не удаляются.
Создать пост
POST /api/v1/studio/drafts
Content-Type: application/json
{
"title": "Рабочее название",
"customTitle": "Пост про AI-агентов",
"folderId": "content-plan",
"html": "<b>Заголовок</b><br><br>Текст поста",
"versions": [
{
"html": "<b>Заголовок</b><br><br>Текст поста",
"label": "Создано AI"
}
]
}
WriterHub принимает Telegram-compatible HTML. Не добавляйте <script>, CSS,
iframe или произвольные browser-теги.
Прочитать и изменить пост
GET /api/v1/studio/drafts/{draft_id}
PATCH /api/v1/studio/drafts/{draft_id}
Пример изменения текста и перемещения в папку:
{
"html": "<b>Обновлённый заголовок</b><br><br>Новый текст",
"folderId": "ready",
"if_revision": 3
}
Чтобы переместить пост в «Без папки», передайте:
{
"folderId": "",
"if_revision": 4
}
Удалить пост
DELETE /api/v1/studio/drafts/{draft_id}
Черновик переносится в корзину и может быть восстановлен.
Whole-state API
PUT /api/v1/studio/state
POST /api/v1/studio/migrate
PUT заменяет серверное состояние и нужен только для синхронизации полного
клиента. migrate объединяет старый browser state с серверным. AI-агенту для
обычной работы эти операции не нужны.
Авторы
Раздел авторов хранит реконструированные публикации из Telegram. Студия предназначена для новых пользовательских черновиков, а авторы — для источников, поиска, коллекций и AI-контекста.
Список и создание профиля
GET /api/v1/authors
POST /api/v1/authors
Создание пустого профиля:
{
"id": "new-author",
"name": "Имя автора",
"description": "Темы и особенности автора"
}
id — постоянный slug: строчные латинские буквы, цифры и дефисы.
Метаданные автора
GET /api/v1/authors/{author_id}
PATCH /api/v1/authors/{author_id}
{
"name": "Новое имя",
"description": "Обновлённое описание",
"avatar": "A"
}
Импорт Telegram Desktop JSON
Импорт всегда двухфазный. Он может создать нового автора или добавить новый канал существующему.
Анализ:
POST /api/v1/authors/imports/analyze
Content-Type: multipart/form-data
file=<Telegram Desktop result.json>
author_id=<author slug>
author_name=<display name>
channel_id=<channel slug>
description=<optional description>
Пример cURL:
curl --fail --silent --show-error \
-H "Authorization: Bearer $WRITERHUB_API_KEY" \
-F "file=@result.json;type=application/json" \
-F "author_id=new-author" \
-F "author_name=Имя автора" \
-F "channel_id=main-channel" \
https://writerhub.tea-gpt.ru/api/v1/authors/imports/analyze
Проверьте в ответе:
source_messages;posts;pending_review;external_messages;polls_skipped;source_sha256.
После осознанного подтверждения пользователя:
POST /api/v1/authors/imports/{job_id}/commit
Не выполняйте commit автоматически, если анализ показывает неожиданный файл, автора, канал или большое число элементов на проверке.
Поиск публикаций
GET /api/v1/authors/{author_id}/posts
Query parameters:
channel_id;collection_id;q— поиск по заголовку и тексту;date_from,date_to— ISO-даты;limit— 1–500;offset— пагинация.
/api/v1/authors/new-author/posts?q=агенты&limit=20&offset=0
Одна публикация
GET /api/v1/authors/{author_id}/posts/{post_id}
Ответ содержит метаданные и parts — исходные Telegram-сообщения, из которых
собрана публикация.
Редактирование публикации
PATCH /api/v1/authors/{author_id}/posts/{post_id}
Можно изменить заголовок, коллекцию, текст, форматирование, дату и доступные метаданные частей. Нельзя подменить принадлежность сообщения другому посту или каналу.
Простое изменение текста:
{
"title": "Уточнённый заголовок",
"parts": [
{
"id": 123,
"text": "Исправленный текст без специального форматирования."
}
],
"if_revision": 0
}
Структурированное форматирование:
{
"parts": [
{
"id": 123,
"segments": [
{"type": "bold", "text": "Важная мысль"},
{"type": "plain", "text": "\n\nПродолжение текста."},
{
"type": "text_link",
"text": "Источник",
"href": "https://example.com"
}
]
}
],
"if_revision": 1
}
Допустимые типы сегментов:
plain, bold, italic, underline, strikethrough, spoiler, code, pre,
blockquote, text_link, link, custom_emoji, hashtag, mention, bot_command
Сервер сам создаёт безопасные html и markdown. Не отправляйте готовый HTML
для author parts.
Удаление, merge и split
DELETE /api/v1/authors/{author_id}/posts/{post_id}
POST /api/v1/authors/{author_id}/posts/merge
POST /api/v1/authors/{author_id}/posts/split
Merge:
{
"post_id": "channel-000123",
"target_post_id": "channel-000124"
}
Объединяются только соседние публикации одного канала.
Split:
{
"post_id": "channel-000123",
"before_message_id": 124
}
Точка разделения должна быть одной из частей публикации, но не первой.
Очередь проверки
GET /api/v1/authors/{author_id}/review
POST /api/v1/authors/{author_id}/review/approve
POST /api/v1/authors/{author_id}/review/remove-foreign
{
"review_ids": ["review-item-id"]
}
approve переносит выбранные элементы в основную библиотеку.
remove-foreign исключает внешние пересылки и сохраняет связанные ответы
автора, когда это возможно.
Коллекции
POST /api/v1/authors/{author_id}/collections
PATCH /api/v1/authors/{author_id}/collections/{collection_id}
DELETE /api/v1/authors/{author_id}/collections/{collection_id}
POST /api/v1/authors/{author_id}/posts/collection
Создание:
{
"name": "AI-агенты",
"description": "Подборка публикаций по теме"
}
Назначение публикации:
{
"post_id": "channel-000123",
"collection_id": "ai-agenty"
}
Пустой collection_id убирает публикацию из коллекции.
AI-контекст и экспорт
GET /api/v1/authors/{author_id}/context.md
POST /api/v1/authors/{author_id}/exports/markdown
context.md принимает фильтры поиска и возвращает готовый Markdown.
Экспорт:
{
"post_ids": ["channel-000123", "channel-000124"],
"package": "combined"
}
package может быть combined или zip.
Удаление автора
DELETE /api/v1/authors/{author_id}
Автор переносится в корзину.
Проектные скиллы
API управляет только скиллами конкретного WriterHub-профиля. Он не изменяет личные Droid skills на компьютере пользователя.
Читать
GET /api/v1/skills
GET /api/v1/skills/{skill_id}
GET /api/v1/skills/{skill_id}/documents?path=SKILL.md
GET /api/v1/skills/{skill_id}/context.md
GET /api/v1/skills/{skill_id}/export.zip
Создать
POST /api/v1/skills
{
"manifest": {
"id": "my-skill",
"name": "My Skill",
"description": "Назначение скилла",
"version": "1.0",
"tags": ["writing"],
"documents": [
{
"path": "SKILL.md",
"label": "Инструкции",
"kind": "core",
"editable": true
}
]
},
"documents": {
"SKILL.md": "# My Skill\n\nИнструкции."
}
}
SKILL.md обязателен.
Изменить
PATCH /api/v1/skills/{skill_id}
PUT /api/v1/skills/{skill_id}/documents
{
"path": "SKILL.md",
"content": "# Обновлённые инструкции\n"
}
Удалить
DELETE /api/v1/skills/{skill_id}
Скилл переносится в корзину.
Корзина
GET /api/v1/trash
POST /api/v1/trash/{trash_id}/restore
DELETE /api/v1/trash/{trash_id}
Полное удаление требует точного подтверждения:
{
"confirm": "<trash_id>"
}
Элементы автоматически очищаются после 30 дней. До явного запроса пользователя предпочитайте восстановимое удаление и не выполняйте permanent delete.
Минимальный Python-клиент
import os
import requests
BASE_URL = "https://writerhub.tea-gpt.ru"
HEADERS = {
"Authorization": f"Bearer {os.environ['WRITERHUB_API_KEY']}",
"Content-Type": "application/json",
}
response = requests.get(
f"{BASE_URL}/api/v1/studio/drafts",
headers=HEADERS,
timeout=30,
)
response.raise_for_status()
print(response.json())
If requests is not installed yet:
python -m pip install "requests>=2,<3"
Минимальный PowerShell-клиент
$headers = @{
Authorization = "Bearer $env:WRITERHUB_API_KEY"
}
Invoke-RestMethod `
-Method Get `
-Uri 'https://writerhub.tea-gpt.ru/api/v1/studio/drafts' `
-Headers $headers
Чек-лист перед завершением задачи
AI-агент должен проверить:
- Использован правильный профильный ключ.
- Ключ имеет только необходимые права.
- Перед
PATCHпрочитана актуальная revision. - После записи ресурс перечитан.
- При
409чужое изменение не затёрто. - Удаление соответствовало прямой команде пользователя.
- Секрет не попал в ответ, лог, URL или файл.
- Пользователю сообщён фактический результат и выполненная проверка.