К содержанию
Lumean API

POST/orders/chunks/preview

Dry-run разбиения текста на чанки и расчёта стоимости — БЕЗ создания заказа. Тот же расчёт, что использует POST /orders: сверяйте здесь разбиение/цену перед реальной отправкой. Не тратит токен-квоту ключа — preview бесплатен.

Поправки к спецификации · 2

  • Предпросмотр чанков доступен по API-ключу

    В машинной документации llm.md §12 сказано, что предпросмотр чанков — эндпоинт веб-кабинета и по ключу вернёт 401. Это неверно: три операции предпросмотра входят в публичный контур и требуют права orders.read — так их описывают и OpenAPI, и §7.1 той же llm.md. Если ИИ-ассистент сошлётся на §12 — он ошибается.

  • Тарификация разметки [шёпот] и <break/> не согласована

    Три места в спеке утверждают, что теги разметки ([шёпот], <break/>) не тарифицируются, а описание поля billable_length — что тарифицируются. Пока расхождение не разрешено бэкендом, считайте худший случай: закладывайте символы разметки в оценку стоимости. Точную цену конкретного текста даёт POST /orders/chunks/preview — он возвращает уже посчитанную длину.

Единый ready-конверт для sync и async путей:

  • 200 status=ready — TTS-текст ≤ 50 000 символов (и любой non-TTS): расчёт готов сразу, тело содержит summary (итоги по всему тексту) + первую страницу chunks[] + page (мета пагинации).
  • 202 status=processing — TTS-текст длиннее порога: расчёт уходит в фон, тело содержит только preview_id. Результат приходит WS-событием .ready на канал private-chunks.preview.{userId} (авторизация — POST /broadcasting/auth, как и для остальных приватных каналов), либо подтяните вручную GET /orders/chunks/preview/{previewId}.

Инкрементальный re-preview: передайте preview_id предыдущего ответа как previous_preview_id вместе с новым input_text — пересчитается только окрестность правки, результат идентичен полному расчёту.

Настройки заказа: передайте тот же config_override, что уйдёт в POST /orders, — превью режет по конфигу шаблона с ним, как заказ (настройки, влияющие на рез, действуют и здесь). Значение, которое создание заказа отбило бы 422, превью тоже отбивает.

Паузы/капы: превышение лимитов пауз (>500 шт., >3600с суммарно, >10с одна) или размера заказа (>1500 фрагментов) НЕ роняет запрос — приходит summary.caps_ok=false

  • caps_exceeded. Это отличает preview от POST /orders, где то же превышение даёт 422.

Кэш превью общий с веб-сессией того же аккаунта (если владелец ключа пользуется и сайтом): одинаковый текст+шаблон+режим, уже посчитанный в браузере, вернётся мгновенно.

Требуемое право ключа: orders.read (preview не мутирует данные — логически чтение).

На этой странице(4)

Тело запроса

application/jsonобязательно

Dry-run preview разбиения текста на чанки — без создания заказа. input_text обязателен (preview по inline-тексту; файлы — async-путь).

config_override — тот же объект, что уйдёт в POST /orders (с 25.09.2026): размер чанка и режим провайдера в нём меняют рез, и превью без него показывало границы конфига шаблона, а не боевого реза ({@see AcceptsConfigOverride}).

Пример тела
{
  "template_id": "9f8b2c1a-4d3e-4f5a-8b9c-0d1e2f3a4b5c",
  "task_type": "string",
  "input_text": "string",
  "previous_preview_id": "string",
  "text_hash": "string",
  "generation_mode": "default",
  "config_override": []
}

Поля

template_idобязательное
uuid
string
input_textобязательное
string
task_typeнеобязательное
может быть null
string
previous_preview_idнеобязательное

ID предыдущего preview для инкрементального ре-чанка (пересчёт только хвоста правки).

может быть null
string
text_hashнеобязательное

sha256(input_text) от фронта — необязательная серверная верификация целостности.

может быть nullшаблон: ^[a-f0-9]{64}$
string
generation_modeнеобязательное

Режим генерации ЭТОГО превью — то же значение, что уйдёт в config_override.generation_mode при создании заказа. Отсутствие = default. Сервис, не объявивший ключ в validation_schema, режим игнорирует (см. Service::resolveGenerationMode) — как и на боевом пути.

может быть null
Значенияdefaultparagraph
string
config_overrideнеобязательное

Настройки генерации поверх конфига шаблона — тот же JSON-объект, что уйдёт в создание заказа; настройки, влияющие на рез, применяются к превью так же, как к заказу. Посторонние ключи отбрасываются.

object

Возможные ответы

200

status=ready: summary + первая страница чанков + мета пагинации

Пример тела
"string"
Поля ответа
successобязательное

Признак успеха. Решение принимайте по HTTP-коду: у любого ответа 2xx здесь true, а ошибка приходит телом другой формы, где этого поля может не быть вовсе.

boolean
messageобязательное

Пояснение для человека, на языке аккаунта. Показать пользователю можно; разбирать программно — нет: формулировки меняются без предупреждения и кодом ошибки не являются.

string
dataобязательное

Полезная нагрузка ответа.

object
statusобязательное

Всегда ready у кода 200 — расчёт готов.

Значенияready
string
preview_idобязательное

Контентный идентификатор превью (sha256 от текста+шаблона+режима+версии алгоритма). Используйте для инкрементального re-preview (previous_preview_id) и для пагинации (GET .../{previewId}).

string
summaryобязательное

Итоги по всему тексту — не только по текущей странице чанков.

object
chunks_countобязательное

Сколько всего чанков в разбиении.

integer
total_effective_lengthобязательное

Суммарная billable-длина по всем чанкам, в символах (паузы и указания диктору не считаются).

integer
total_price_unitsобязательное

Суммарная стоимость в токенах — та же величина, что спишет POST /orders за идентичный текст.

integer
voiced_lengthобязательное

Фактически озвучиваемая длина ДО добора до минимального тарифицируемого объёма — для честного показа «сколько символов».

integer
min_billable_charsобязательное

Минимальный тарифицируемый объём (0 — минимума нет). Если voiced_length меньше этого порога, стоимость всё равно посчитана по порогу.

integer
pause_countобязательное

Число пауз в тексте ({{pause}}/<break/>). Паузы бесплатны — в стоимость не входят.

integer
total_pause_secondsобязательное

Суммарная длительность тишины, секунды.

number
caps_okобязательное

Санитарные капы заказа не превышены. false НЕ роняет превью (в отличие от POST /orders, где то же самое даёт 422) — только предупреждает.

boolean
caps_exceededобязательное

Какой именно кап превышен: count (пауз больше 500), single (одна пауза длиннее 10с), total (суммарная тишина больше 3600с) или chunks (заказ даёт больше 1500 фрагментов — столько система не соберёт в один файл). null — капы в порядке.

может быть null
string
voiced_emptyобязательное

В тексте не осталось ничего произносимого (только теги/паузы/скобочные ремарки). POST /orders с таким текстом вернёт 422.

boolean
blocked_chunksобязательное

Индексы чанков, чей текст уже отбивался контентной политикой и лежит в блоклисте. Пустой массив — блокировок нет.

array<integer>
has_blocked_contentобязательное

Есть ли хотя бы один заблокированный чанк — то же самое, что blocked_chunks !== [], в булевом виде для удобства.

boolean
paragraphsобязательное

null — превью не абзацное (то же значение generation_mode, что и в заказе, отвечает за это поле). В абзацном режиме — агрегат по каждому абзацу.

может быть null
array<object>
элемент массива
paragraph_indexобязательное

Порядковый номер абзаца, с нуля.

integer
chunks_countобязательное

Сколько чанков внутри этого абзаца (длинный абзац может занять несколько чанков).

integer
first_chunk_indexобязательное

Сквозной index первого чанка абзаца — по нему абзац находится в постраничном data.chunks, даже если его чанки попали на другую страницу.

integer
text_lengthобязательное

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

integer
effective_lengthобязательное

Billable-длина абзаца — минимальный тарифицируемый объём в абзацном режиме считается ПО КАЖДОМУ абзацу отдельно, поэтому короткие абзацы могут стоить дороже, чем тот же текст, разрезанный сплошняком.

integer
price_unitsобязательное

Стоимость абзаца в токенах.

integer
paragraphs_countобязательное

Число абзацев, или null вне абзацного режима. Остаётся числом даже когда paragraphs схлопнут по WS-капу.

может быть null
integer
cost_lmcнеобязательное

Стоимость в LMC (валюто-независимая база). Поле может ОТСУТСТВОВАТЬ (не null), если денежный якорь не удалось посчитать (best-effort, не критично для превью).

number
cost_displayнеобязательное

Стоимость, пересчитанная в валюту отображения аккаунта — та же мультивалютная разбивка, что и в остальном публичном API (amount/amount_formatted по коду валюты). Поле может ОТСУТСТВОВАТЬ, если cost_lmc не посчитан или курс недоступен.

может быть null
object
chunksобязательное

Только ТЕКУЩАЯ страница (см. data.page), не весь список — используйте пагинацию (GET .../{previewId}?page=) для остальных.

array<object>
элемент массива
indexобязательное

Сквозной номер чанка по всему тексту (не сбрасывается на границах абзацев).

integer
textобязательное

Текст чанка ровно в том виде, в каком его получит voice-провайдер.

string
startобязательное

Начало чанка в НОРМАЛИЗОВАННОМ входном тексте (символьное смещение). Нормализация — та же, что применяет POST /orders перед резом.

integer
endобязательное

Конец чанка в нормализованном тексте (полуинтервал: end не входит в чанк).

integer
text_lengthобязательное

Сырая длина текста чанка в символах, ВКЛЮЧАЯ теги/паузы.

integer
effective_lengthобязательное

Billable-длина чанка (без пауз, после добора до минимума при его наличии) — сумма по всем чанкам страницы не обязана совпадать с total_effective_length (та считается по ВСЕМ чанкам, не только странице).

integer
price_unitsобязательное

Стоимость чанка в токенах.

integer
paragraph_indexобязательное

Номер абзаца, которому принадлежит чанк, или null вне абзацного режима.

может быть null
integer
pageобязательное

Мета пагинации ТЕКУЩЕЙ страницы data.chunks.

object
current_pageобязательное

Номер текущей страницы, считая с 1.

integer
per_pageобязательное

Размер страницы (сколько чанков запрошено/использовано по умолчанию).

integer
totalобязательное

Всего чанков в разбиении (по всем страницам).

integer
has_moreобязательное

Есть ли ещё страницы после текущей.

boolean
202

status=processing: расчёт в фоне, вернётся preview_id (результат — WS .ready)

Пример тела
"string"
Поля ответа
successобязательное

Признак успеха. Решение принимайте по HTTP-коду: у любого ответа 2xx здесь true, а ошибка приходит телом другой формы, где этого поля может не быть вовсе.

boolean
messageобязательное

Пояснение для человека, на языке аккаунта. Показать пользователю можно; разбирать программно — нет: формулировки меняются без предупреждения и кодом ошибки не являются.

string
dataобязательное

Полезная нагрузка ответа.

object
statusобязательное

Всегда processing у кода 202 — расчёт идёт в фоне.

Значенияprocessing
string
preview_idобязательное

Идентификатор превью. Используйте для подписки на WS-канал private-chunks.preview.{userId} (событие .ready) либо для ручного поллинга GET /orders/chunks/preview/{previewId}.

string
401

Невалидный или отсутствующий X-API-KEY

Разобрать этот ответ
Пример тела
{
  "success": false,
  "message": "API key is missing. Provide it in the X-API-KEY header.",
  "data": null
}
Поля ответа
successобязательное

Всегда false в ответах об ошибке.

boolean
messageобязательное

Текст ошибки на языке ключа (задаётся заголовком X-Locale).

string
dataобязательное

Всегда null, когда запрос отклонён до обработки.

может быть null
null
403

У ключа нет права orders.read

Разобрать этот ответ
Пример тела
{
  "success": false,
  "message": "This API key does not have permission to perform this action."
}
Поля ответа
successобязательное

Всегда false в ответах об ошибке.

boolean
messageобязательное

Текст ошибки на языке ключа (задаётся заголовком X-Locale).

string
422

Ошибка валидации (input_text обязателен) или reason=template_model_outdated — шаблон или config_override несут настройки прежней схемы сервиса, как у создания заказа

Разобрать этот ответ
Пример тела
{
  "message": "string",
  "errors": {
    "key": [
      "string"
    ]
  }
}
Поля ответа
messageобязательное

Errors overview.

string
errorsобязательное

A detailed description of each field that failed validation.

object
*необязательное
произвольные ключи
array<string>
429

Превышен лимит запросов preview для этого ключа

Разобрать этот ответ
Пример тела
{
  "success": false,
  "message": "Too many attempts. Please wait a moment and try again.",
  "reason": "rate_limit_exceeded",
  "error_code": "rate_limit_exceeded",
  "retry_after": 30
}
Поля ответа
successобязательное

Всегда false в ответах об ошибке.

boolean
messageобязательное

Текст ошибки на языке ключа (задаётся заголовком X-Locale).

string
reasonобязательное

Машиночитаемая причина отказа — по ней ветвите обработку, а не по тексту сообщения.

string
error_codeобязательное

Тот же машинный код, что в reason, — второе имя поля. Значения всегда совпадают; ветвитесь по любому из них.

string
retry_afterнеобязательное

Через сколько секунд имеет смысл повторить запрос (то же значение — в заголовке Retry-After).

может быть null
integer

События, которые это порождает

Ход выполнения приезжает по WebSocket: опрашивать заказ в цикле не обязательно. Подписка требует того же права, что и чтение заказов.

Скормить страницу ИИ

Открыть .mdllm.md

спека 0.0.1