REST API v1

Публичная документация API

Автоматическая загрузка книг, томов, глав и изображений. API отвечает JSON в UTF-8, использует Bearer-токены и проверяет права владельца на каждом запросе.

Авторизация

Токен не расширяет права аккаунта

Передавайте ключ только в заголовке Authorization: Bearer rhb_…. Обычный токен переводчика ограничен выбранными scope и назначенными книгами. content:manage является административным super-scope: он открывает Content Manager и все методы Translator API для всех книг без назначения команды; редактору этот scope недоступен.

curl --fail-with-body \
  -H "Authorization: Bearer $RANOBEHUB_TOKEN" \
  -H "Accept: application/json" \
  https://ranobehub.org/api/v1/translator/books

Создать, показать, скопировать, перевыпустить или отозвать ключ можно в разделе API панели управления.

Переводчикам

Книги, тома, главы и публикация

Существующие методы сохранены; новые возможности добавляются без переименования старых URL и полей.

GET/api/v1/translator/statusesbooks:read
Статусы книг и томов

Общий production-справочник с числовыми id и названиями статусов.

GET/api/v1/translator/booksbooks:read
Доступные книги

Книги с statusId, к которым у владельца токена есть редакционный доступ.

GET/api/v1/translator/books/:idbooks:read
Книга

Основные метаданные выбранной книги.

PATCH/api/v1/translator/books/:idbooks:write
Метаданные книги

Совместимый существующий метод частичного обновления.

GET/api/v1/translator/books/:id/volumesvolumes:read
Оглавление по томам

Список томов с номером, названием и statusId.

POST/api/v1/translator/books/:id/volumesvolumes:write
Создать том

Создаёт том; повтор номера возвращает 409.

PATCH/api/v1/translator/books/:id/volumes/:volumeIdvolumes:write
Изменить или переставить том

При смене номера moveChapters=true переносит главы вместе с томом.

DELETE/api/v1/translator/books/:id/volumes/:volumeIdvolumes:delete
Удалить том

Удаляется только пустой том; иначе возвращается 409.

GET/api/v1/translator/books/:id/chapterschapters:read
Оглавление

Главы по порядку со счётчиками и назначенными конкретной главе переводчиками.

GET/api/v1/translator/books/:id/chapter-hasheschapters:read
Хеши текста глав

Постраничные SHA-256 хеши канонического текста без HTML, изображений, медиа и форматирования.

POST/api/v1/translator/books/:id/chapterschapters:create
Создать главу

Санитайзит HTML, вычисляет метаданные и опционально принимает translatorIds.

GET/api/v1/translator/chapters/:idchapters:read
Получить главу

Полный HTML, метаданные, translatorIds и сведения о переводчиках главы.

GET/api/v1/translator/chapters/:id/hashchapters:read
Хеш одной главы

SHA-256 канонического текста конкретной главы без загрузки её HTML.

PATCH/api/v1/translator/chapters/:idchapters:update
Обновить или переставить главу

Можно менять содержимое и опционально заменять translatorIds; предыдущая версия сохраняется.

DELETE/api/v1/translator/chapters/:idchapters:delete
Удалить главу

Удаляет главу и связанные редакционные черновики, ревизии и комментарии.

POST/api/v1/translator/books/:id/imageschapters:images
Загрузить изображение

multipart/form-data, поле image; JPEG, PNG, WebP или GIF до 12 МБ.

DELETE/api/v1/translator/books/:id/images?mediaId=:mediaIdchapters:images
Удалить изображение

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

GET/api/v1/translator/chapters/:id/schedulechapters:read
Получить расписание

Возвращает будущую редакцию главы или null.

PUT/api/v1/translator/chapters/:id/schedulechapters:schedule
Отложить публикацию

Создаёт или заменяет будущую редакцию на срок до 366 дней.

DELETE/api/v1/translator/chapters/:id/schedulechapters:schedule
Отменить публикацию

Удаляет запланированную редакцию, не меняя текущую главу.

GET/POST/api/v1/translator/books/:id/translation-brancheschapters:read / chapters:update
Ветки перевода

Получение и создание независимых веток перевода.

POST/api/v1/translator/books/:id/ai-chapterschapters:create
AI-перевод

Запускает поддерживаемый сервером процесс AI-перевода главы.

Статусы

ID книг и томов

GET /api/v1/translator/statuses

{
  "data": [
    { "id": 1, "title": "В процессе" },
    { "id": 2, "title": "Завершено" }
  ],
  "appliesTo": ["books", "volumes"]
}

Книги и тома используют один production-справочник. Не фиксируйте соответствия в импортёре навсегда: получите их перед импортом и передавайте выбранный statusId. Списки и ответы создания также возвращают это поле.

Глава

Создание и пересчёт

POST /api/v1/translator/books/125/chapters
{
  "volume": 1,
  "number": 12,
  "title": "Глава 12",
  "html": "<p>Текст…</p><img src="/api/media/9001" alt="Карта">",
  "draft": false,
  "sourceId": "import:12",
  "source": {
    "provider": "ranobelib",
    "sourceId": "import:12",
    "sourceUrl": "https://source.example/chapter/12",
    "language": "ru",
    "sourceTitle": "Глава 12",
    "rawHtml": "<p>Оригинальная разметка источника…</p>"
  },
  "translatorIds": [12, 18]
}

HTML очищается на сервере. Количество Unicode-символов и hasImages пересчитываются при создании, обновлении, восстановлении и отложенной публикации. Необязательный объект source сохраняет приватный исходный HTML для повторного безопасного импорта; читателю он не выдаётся.

translatorIds необязателен. В PATCH отсутствие поля сохраняет прежнее авторство, массив заменяет его, а [] очищает явное авторство главы. Все ID должны заранее быть назначены книге через её taxonomy. Ответы GET содержат translatorIds и translators.

Изображения

Сначала файл, затем HTML

curl --fail-with-body \
  -H "Authorization: Bearer $RANOBEHUB_TOKEN" \
  -F "image=@map.webp" \
  https://ranobehub.org/api/v1/translator/books/125/images

Ответ содержит mediaId и относительный url. Этот URL вставляется в <img src>. Внешние HTTPS-изображения тоже допустимы, но управлять их жизненным циклом RanobeHub не может.

Синхронизация

Сравнение текста без скачивания HTML

GET /api/v1/translator/books/125/chapter-hashes?limit=100&cursor=0

{
  "data": [
    { "id": 436210, "volume": 1, "number": 12, "textHash": "57f516dcf9033f3914b87f6f43c3955c67b1a9fa1dbd47f746b65d4194a6b58f" }
  ],
  "hash": {
    "algorithm": "sha256",
    "normalization": "plain-text-v1"
  },
  "nextCursor": 436309
}

plain-text-v1 удаляет HTML-теги, изображения, SVG, скрипты и другие нетекстовые медиа, декодирует HTML-сущности, приводит Unicode к NFC и сворачивает пробелы. Поэтому косметическое форматирование не меняет хеш. Изменение видимого текста меняет его. Страница содержит до 200 глав; продолжайте по nextCursor, пока он не станет null. Для одной известной главы используйте лёгкий GET /api/v1/translator/chapters/:id/hash без HTML. Полный GET /api/v1/translator/chapters/:id возвращает тот же хеш вместе с содержимым.

Content Manager

Административный импорт новой книги

Этот раздел требует токен администратора со scope content:manage. Обычному переводчику он недоступен.

GET/api/v1/content/resources?type=tags|authors|translators|countries|statusescontent:manage
Справочники

Поиск и получение ID связей и общего справочника статусов книг/томов.

POST/api/v1/content/resourcescontent:manage
Создать ресурс

Создание тега, автора, команды переводчиков или страны.

PATCH/api/v1/content/resources/:type/:idcontent:manage
Изменить ресурс

Частичное обновление справочника.

DELETE/api/v1/content/resources/:type/:idcontent:manage
Удалить ресурс

Связанный с книгами ресурс защищён ответом 409.

GET/POST/api/v1/content/bookscontent:manage
Найти или создать книгу

Поиск по названию/slug и создание книги с начальными связями.

GET/api/v1/content/books/:idcontent:manage
Полные данные книги

Административное представление книги.

PATCH/api/v1/content/books/:idcontent:manage
Изменить книгу

Метаданные, состояние публикации, блокировка и тип произведения.

DELETE/api/v1/content/books/:idcontent:manage
Удалить книгу

Безопасное мягкое удаление без уничтожения глав и истории.

GET/PUT/api/v1/content/books/:id/taxonomycontent:manage
Связи книги

Полная замена тегов, авторов, переводчиков и стран; назначенные команды получают редакционные права.

GET/POST/DELETE/api/v1/content/books/:id/posterscontent:manage
Постеры книги

Получение галереи, загрузка multipart-постера и удаление по posterId.

GET/POST/api/v1/content/books/:id/linkscontent:manage
Справочные ссылки

Список ссылок и доступных источников; добавление ссылки по sourceId.

PATCH/DELETE/api/v1/content/books/:id/links/:linkIdcontent:manage
Изменить или удалить ссылку

Пустой url скрывает ссылку без удаления; DELETE удаляет запись.

GET/api/v1/content/books/:id/external-ratingscontent:manage
Внешние рейтинги

Снимки всех источников и текущий итог: локальные/внешние голоса, итоговая оценка и признак использования источников.

PUT/DELETE/api/v1/content/books/:id/external-ratings/:sourcecontent:manage
Обновить рейтинг источника

Идемпотентный снимок rating, ratingScale и votes; удаление источника сразу пересчитывает публичный рейтинг.

GET/PUT/PATCH/api/v1/content/books/:id/parsercontent:manage
Источник и парсер книги

Получение, идемпотентное создание/полная замена и частичное изменение конфигурации поставщика.

Постеры

Обложки после создания книги

curl --fail-with-body \
  -H "Authorization: Bearer $RANOBEHUB_TOKEN" \
  -F "poster=@cover.webp" \
  https://ranobehub.org/api/v1/content/books/125/posters

curl --fail-with-body -X DELETE \
  -H "Authorization: Bearer $RANOBEHUB_TOKEN" \
  "https://ranobehub.org/api/v1/content/books/125/posters?posterId=9002"

Поддерживаются JPEG, PNG и WebP до 12 МБ, не более 15 постеров на книгу. GET и ответы мутаций возвращают массив posters, активный posterUrl, количество и лимит.

Источники

Справочные ссылки книги

GET /api/v1/content/books/125/links

POST /api/v1/content/books/125/links
{
  "sourceId": 4,
  "url": "https://example.org/novel/slug"
}

PATCH /api/v1/content/books/125/links/81
{ "url": "" }

GET возвращает одновременно data со ссылками книги и sources с допустимыми sourceId. Для одного источника у книги допускается одна ссылка. Пустой url в PATCH сохраняет старое поведение панели и скрывает ссылку; DELETE удаляет её полностью.

Парсер

Конфигурация источника

PUT /api/v1/content/books/125/parser
{
  "url": "https://example.org/novel/slug",
  "provider": "novel-tl",
  "enabled": false,
  "config": {},
  "schedule": null,
  "canRefresh": false
}

PATCH /api/v1/content/books/125/parser
{ "provider": "ranobelib", "enabled": true }

provider определяет адаптер: legacy, ranobelib, rulate или novel-tl (Novel TL, ZNovel и RuRaNovel). PUT безопасно создаёт настройку или полностью заменяет первую запись книги; пропущенные provider и enabled равны legacy и false. PATCH меняет только переданные поля. Если в старой базе у книги несколько записей, ответ показывает остальные в additionalParserIds, но изменяется только первая — как в текущей панели.

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

Рейтинг

RanobeLib и другие источники

PUT /api/v1/content/books/125/external-ratings/ranobelib
{
  "rating": 4.63,
  "ratingScale": 5,
  "votes": 1842,
  "sourceBookId": "mushoku-tensei",
  "observedAt": "2026-08-20T10:00:00Z"
}

source — постоянный ASCII-ключ импортёра. ratingScale описывает исходную шкалу и по умолчанию равен 10: сервер сам преобразует 4,63/5 или 92/100 к шкале сайта. Повторный PUT полностью заменяет снимок только этого источника.

Пока на RanobeHub не больше 20 локальных оценок, итог является взвешенным средним всех локальных и внешних голосов, а счётчики суммируются. С 21-й локальной оценки внешние снимки остаются сохранены, но перестают влиять на публичные computedRating и computedRatingVotes.

Автоматический импорт

Рекомендуемая последовательность

  1. Получить или создать теги, авторов, переводчиков и страны.
  2. Создать книгу через Content Manager API.
  3. Назначить связи книги через PUT taxonomy, загрузить постеры, добавить справочные ссылки и снимок внешнего рейтинга.
  4. При необходимости сохранить выключенную конфигурацию поставщика через parser.
  5. Создать тома через Translator API.
  6. Загрузить изображения глав и использовать возвращённые URL в HTML.
  7. Создать главы как черновики, проверить оглавление и затем опубликовать либо настроить расписание.
POST /api/v1/content/books
{
  "title": "Название книги",
  "englishTitle": "English Book Title",
  "descriptionHtml": "<p>Аннотация</p>",
  "year": 2026,
  "statusId": 1,
  "state": "opened",
  "tagIds": [4, 18],
  "authorIds": [93],
  "translatorIds": [12],
  "countryIds": [3]
}

Если slug не передан, API сначала строит ASCII-slug из englishTitle. При отсутствии английского названия русское title транслитерируется; кириллица в автоматически созданный slug больше не попадает. Явно переданный ASCII slug сохраняется без изменения.

Ответы

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

400 — неверные поля, 401 — токен отсутствует или истёк, 403 — недостаточно scope/прав, 404 — объект не найден, 409 — конфликт номера или используемый ресурс, 413/415 — размер или формат изображения. Для автоматического импорта сохраняйте возвращённые ID и sourceId; не повторяйте POST после сетевой ошибки вслепую.