Changelog

Публичный журнал изменений API. Аддитивные, обратно совместимые изменения (новые опциональные поля); ломающие изменения помечаются явно — существующие интеграции продолжают работать без правок.

2026-07-28 — Переименование в ChunkChef

Продукт теперь называется ChunkChef. На проводе видны три изменения, остальное внутреннее.

  • Ломающее — переименованы заголовки подписи вебхуков. X-Hotdoc-Timestamp и X-Hotdoc-Signature стали X-Chunkchef-Timestamp и X-Chunkchef-Signature. Схема подписи не изменилась — отличаются только имена заголовков. Обновите проверку на своей стороне.
  • Ломающее — изменён префикс API-ключа. Новые ключи выдаются в виде chunkchef_<id>.<secret> вместо hotdoc_<id>.<secret>. Прежние ключи перестают аутентифицировать — выпустите новый в кабинете.
  • Ломающее — изменён дискриминатор типизированной ошибки. Внутри Status.details поле @type теперь содержит type.googleapis.com/chunkchef.v1.billing.QuotaExceededDetail. Если вы сверяетесь с этой строкой, поправьте её.

Эндпоинты, форматы запросов и ответов, а также домены hotdoc.io / api.hotdoc.io не изменились.

2026-07-28 — Спецификация OpenAPI

  • Опубликована машиночитаемая спецификация по адресу /openapi.yaml — OpenAPI 3.0.3, генерируется из protobuf-определений сервиса и покрывает пять публичных операций Jobs (POST /v1/jobs/upload, POST /v1/jobs, GET /v1/jobs/{id}, GET /v1/jobs/{id}/result, GET /v1/jobs). Файл можно передать любому генератору клиентов, понимающему OpenAPI; этот рукописный справочник остаётся текстовой документацией.
  • Изменение поведения — размер страницы GET /v1/jobs теперь ограничен. pageSize по умолчанию равен 50 и не превышает 200. Раньше запрос без pageSize возвращал всю историю задач одним ответом. Если вы на это опирались, используйте постраничный обход через pageToken.
  • Изменение поведения — pageToken, который больше не разрешается, возвращает 400. Раньше такой токен молча начинал выдачу с первой страницы, из-за чего можно было получить уже виденные записи. Трактуйте 400 как «курсор больше не применим, начните заново без pageToken».
  • Исправлено — постраничный обход GET /v1/jobs больше не пропускает и не дублирует задачи. Курсор опирался не на ту колонку, по которой шла сортировка списка, поэтому обход в несколько страниц мог терять одни задачи и выдавать другие дважды.

2026-07-24 — Уверенность через консенсус (k-consensus)

  • Новое поле consensus (опциональное) в POST /v1/jobs — опциональное голосование, требует responseSchema (иначе отклоняется с 400). consensus.mode задаёт число прогонов: CONSENSUS_MODE_TWO_RUNS (2, проверка на нестабильность), CONSENSUS_MODE_THREE_RUNS (3, рекомендуется) или CONSENSUS_MODE_FIVE_RUNS (5, максимальная тщательность). hotdoc прогоняет каждую часть k раз на вашем ключе и голосует по каждому полю ответа (относительным большинством).
  • Новое результатное поле llm[].consensusk, runsVotable, minAgreement, incomplete и disagreements[] (конкурирующие variants[] со счётчиком прогонов и признаком, победил ли вариант в голосовании — included). Позволяет увидеть, в каких полях модель была стабильна, а в каких колебалась, ценой k-кратной стоимости токенов на вашем ключе. См. «Консенсус по нескольким запускам» в документации Job API.

2026-07-15 — Слияние частей

  • Новое поле merge (опциональное) в POST /v1/jobs — опциональное серверное слияние ответов модели по частям в один результат по всему документу. merge.scope выбирает слияние по файлу (MERGE_SCOPE_FILE, по умолчанию) или по всей задаче (MERGE_SCOPE_JOB); merge.conflictPolicy определяет, как разрешаются расходящиеся значения полей (MERGE_CONFLICT_POLICY_FIRST_NON_NULL по умолчанию, либо MERGE_CONFLICT_POLICY_MAJORITY); merge.dedupeBy включает дедупликацию по содержимому между файлами по именам JSON-полей (только JSON + responseSchema; пустое значение сохраняет безопасное поведение по умолчанию — только техническую дедупликацию).
  • Новое результатное поле merged[] — одна запись на файл (или одна на задачу при scope=job) с объединённым content, schemaValid (если задан responseSchema), conflicts[], счётчиками dedupeRemovedTechnical/dedupeRemovedContent и mergeIncomplete/incompleteChunks, если какую-то часть не удалось безопасно слить. Существующие построчные записи llm[] не меняются и остаются доступны. Это закрывает давнюю пометку «сервис по-прежнему не склеивает части» из записи от 2026-06-24 — слияние теперь доступно, опционально и по умолчанию выключено. См. «Слияние результатов по частям» в документации Job API.

2026-07-14 — Структурированный вывод (JSON Schema)

  • Новое поле responseSchema (опциональное) в POST /v1/jobs — самодостаточная JSON Schema (сырая строка; только внутренние #/$defs, ≤128 KiB, глубина ≤64, ≤10000 узлов), по которой hotdoc проверяет JSON-ответ модели. Для OpenAI/Grok схема должна быть совместима со strict-подмножеством (каждое свойство в required, опциональность через type: [..., "null"], additionalProperties: false) — такая схема работает без изменений у всех провайдеров. Невалидная схема отклоняется с 400 при создании задачи.
  • Новые результатные поля llm[].schemaValid / llm[].schemaErrors — сообщаются только для файлов из одной части. Несоответствующий ответ всё равно возвращается в content, но задача завершается статусом JOB_STATUS_PARTIAL вместо JOB_STATUS_COMPLETE. Для провайдеров, где hotdoc эмулирует структурированный вывод (DeepSeek, Xiaomi), выполняется одна автоматическая повторная попытка исправления перед оценкой.

2026-07-09 — Режим извлечения

  • Новое поле extractionMode (опциональное) в POST /v1/jobsEXTRACTION_MODE_HYBRID («Оптимизированное гибридное извлечение», по умолчанию) позволяет конвертеру самому решать по каждому файлу, извлекать текст напрямую или запускать OCR; EXTRACTION_MODE_OCR_ALWAYS принудительно включает нейросетевой OCR для каждого файла. Плюс новый дефолт на уровне аккаунта, настраиваемый в личном кабинете в разделе «Настройки», — применяется, когда задача не задаёт extractionMode.

2026-07-08 — Публичный playground

  • /playground на сайте — попробуйте hotdoc без регистрации: загрузите файл, запустите готовый промпт, посмотрите результат прямо в браузере.
  • Новые анонимные демо-эндпоинты, /v1/demo/*: загрузка файла, создание демо-задачи, опрос результата и привязка задачи к реальному аккаунту после регистрации. Сессии отслеживаются по cookie (без входа) и ограничены 3 запусками на сессию плюс общий дневной бюджет на всех анонимных посетителей; результаты усечены. Это аддитивное изменение — аутентифицированный API /v1/jobs не меняется.

2026-06-30 — Мульти-провайдерный OCR (BYOK)

Ломающее изменение. Этап OCR теперь принимает ocr.{provider, model, providerKey} (было ocr.mistralApiKey). Выберите любого поддерживаемого провайдера — Mistral используется по умолчанию (mistral-ocr-latest). Поле model обязательно. Новые маркеры ошибок OCR (provider_auth_failed, provider_key_required, rate_limited, ocr_timeout, ocr_backend_*, too_many_pages) заменяют mistral_key_required.

2026-06-26 — Идемпотентные ключи

POST /v1/jobs принимает idempotencyKey. Повторный запрос с тем же ключом и идентичными параметрами возвращает исходную задачу; тот же ключ с другими параметрами возвращает 400.

2026-06-24 — вебхуки о завершении задачи

  • Новые поля webhookUrl и webhookSecret (оба опциональные) при создании задачи. webhookUrl — абсолютный http/https-адрес вашего эндпоинта; сервис отправит на него POST-запрос с JSON-телом (job_id, account_id, status, finished_at) ровно один раз, когда задача достигнет терминального статуса. webhookSecret — HMAC-секрет: при его наличии к каждому запросу добавляются заголовки X-Hotdoc-Timestamp и X-Hotdoc-Signature (sha256=hex(hmac_sha256(secret, "<ts>.<body>"))). Оба поля принимаются только на вход, в ответах не появляются. Политика повторов: до 6 попыток с задержками 1 м / 5 м / 15 м / 30 м / 30 м. Подробнее — в разделе «Вебхуки».

2026-06-24 — структурно-осведомлённое разбиение на части и настраиваемый их размер

  • Структурно-осведомлённое деление текста на части. Длинный распознанный текст теперь режется по границам структуры формата (Markdown / HTML / XML / plain): таблицы не рвутся посреди строк (заголовок таблицы повторяется в каждой части), сохраняется контекст заголовков-секций. Прежнее поведение (части в отдельных строках llm[] по chunkIndex / chunkTotal) сохранено — сервис по-прежнему не склеивает части.
  • Новое поле neural.chunkBudgetTokens (опциональное) при создании задачи — бюджет одной части в токенах под контекстное окно вашей модели; диапазон 160002000000, по умолчанию — консервативное значение сервиса. В ответе эхается фактический эффективный бюджет.
  • Новое поле ocr[].outputFormat в результате задачи — формат распознанного текста (markdown / html / xml / plain).