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

Ретраи и идемпотентность

Идемпотентных ключей в API нет. Какой из четырёх «повторов» бесплатен, какой тарифицируется как новый заказ и какой бессмысленно вызывать вообще.

Идемпотентных ключей в публичном API нет. Ни заголовка Idempotency-Key, ни поля дедупликации в теле POST /orders, ни сервера, который узнал бы повторную отправку. Два одинаковых запроса — два заказа и две блокировки. Всё ниже исходит из этого.

Четыре «повтора», которые нельзя путать

ВызовРаботает сЧто делаетСтоимость
POST /orders/{order}/items/retry-failedвсеми failed-чанками сразуставит их на повтор одним вызовом: 202 + план queued/skippedбесплатно, из залоченного остатка
POST /orders/{order}/items/{item}/retryодним failed или policy_flagged чанкомповторяет чанк, опционально с новым textбесплатно в пределах free_length
POST /orders/{order}/items/{item}/regeneratecompleted-чанкомпеределывает готовый фрагмент новым текстомплатно, новая квота
POST /orders/{order}/retryзаказом целикомсоздаёт новый заказ теми же параметрамиплатно, как создание

Первые три работают по заказу в статусе partially_completed; последний, наоборот, этот статус не принимает.

Order-level retry — это не «повторить»

POST /orders/{order}/retry не воскрешает заказ. Он читает его параметры и создаёт по ним новый заказ: новый id, новая блокировка средств, новая проверка токен-квоты. Тарификация полная — это второй заказ, а не вторая попытка.

Условия: исходный в статусе completed или result_delivered и без failed-чанков. Тело такое же, как у создания: пустое в обычном случае, confirm_payg_topup + quote_token — только после 402. Биллинг-flow тот же, коды те же: 402 payg_topup_required, 409 quote_mismatch, 429 по токен-квоте.

Уместен он в одном сценарии: «нужен ещё один такой же результат» — например, файлы удалены по ретенции. Для доведения partially_completed он не годится ни технически, ни экономически.

Плейбук: partially_completed → completed

Шаг 1. Один вызов забирает все технические сбои. Тело пустое.

curl -X POST 'https://api.lumean.app/api/public/orders/{order}/items/retry-failed' \
  -H 'Accept: application/json' \
  -H 'X-API-KEY: YOUR_API_KEY'

Ответ 202 — план принят, работа идёт в фоне. В data придут queued[] (что поставлено) и skipped[] с машинной причиной на каждый пропуск:

reason в skipped[]Что делать
policy_flaggedПоштучный повтор с исправленным текстом — шаг 2
max_attempts_reachedПопыток было 5, шестой не будет — только новый заказ
insufficient_fundsЗалоченного остатка не осталось — только новый заказ
active_retry_existsПовтор уже идёт — дождаться
supersededУ чанка уже есть успешная версия — он здоров, делать нечего

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

Шаг 2. Каждый policy_flagged — поштучно и с другим текстом.

curl -s "$BASE/orders/<ORDER>/items/<ITEM>/text" -H "X-API-KEY: $KEY"
curl -s -X POST "$BASE/orders/<ORDER>/items/<ITEM>/retry" -H "X-API-KEY: $KEY" \
  -H "Content-Type: application/json" -d '{"text": "<исправленный текст>"}'

GET .../items/{item}/text отдаёт вместе с текстом пределы: free_length (в его границах повтор бесплатен), max_billable_length, max_raw_length (технический потолок куска, за ним 422) и флаг surcharge_applies — «за длину сверх нормы будет доплата». Поле original_text_length — синоним free_length, оставленный для совместимости.

К сведению

Справочник для LLM формулирует жёстче: «длина text ≤ original_text_length». Спека допускает более длинный текст — просто платный; ориентируйтесь на surcharge_applies и проверяйте его до отправки, чтобы списание не стало сюрпризом.

Шаг 3. Дождаться. Синхронного результата у массового повтора нет: опрашивайте GET /orders/{order}/items либо слушайте событие bulk_retry.completed.

422invalid_order_statusinvalid_order_status — заказ не в том статусе
Что произошло
Отказ уровня заказа у массового повтора: `POST /orders/{order}/items/retry-failed` → 422 `{"success": false, "message": "…", "reason": "invalid_order_status"}`. Ни один чанк не поставлен в очередь.
Что сделать прямо сейчас
Проверить статус заказа перед вызовом. Соседние отказы того же эндпоинта различаются по `reason`: 409 `stitch_in_progress` (по заказу идёт склейка — подождать и повторить), 422 `generative_not_supported` (`sfx`/`music`: у них поштучного повтора нет), 422 `nothing_to_retry` (сбойных чанков не нашлось).
Открыть страницу кода

retry против regenerate

retry берёт только сбойный чанк (failed или policy_flagged); text необязателен, без него повторяется тот же текст. Бесплатен в пределах уже оплаченной длины (free_length), за более длинный текст берётся доплата.

regenerate берёт только готовый (completed) чанк, text обязателен, и он всегда платный: блокируются новые средства, идёт pre-check квоты, при превышении 429.

Оба недоступны для sfx и music — генерация у них одноразовая.

Ловушка

Флаги can_retry / can_regenerate — не гарантия. Спека уверяет, что can_retry учитывает статус, тип задачи и исчерпание попыток; llm.md §7.11 это опровергает: флаг смотрит только на статус чанка. can_retry: true спокойно уживается с 400 на самом вызове.

content_blocked повторять бессмысленно

422content_blockedcontent_blocked — текст в блоклисте
Что произошло
Заказ не создан. Тело: `{"success": false, "message": "…", "reason": "content_blocked"}` — БЕЗ `errors`, потому что форма запроса тут ни при чём. Тот же `reason` отдают поштучный повтор и перегенерация чанка.
Что сделать прямо сейчас
Повторять бессмысленно и дорого: исход детерминирован, а каждая попытка расходует ресурс и двигает счётчик к `policy_cooldown_active`. Единственное рабочее действие — отредактировать спорный фрагмент; из-за сверки по чанкам достаточно поправить его один, не переписывая текст целиком. Почему сработала политика, API не сообщает: это admin-only, поля с причиной в ответе нет и не будет — не ищите его.
Открыть страницу кода

Текст уже отбивался политикой и лежит в глобальном блоклисте: повтор даст тот же 422. Хуже того, каждая попытка двигает счётчик к policy_cooldown_active — пять подряд заблокированных задач останавливают создание новых на 5 минут, дальше на 10 и 15.

Правильно

Отредактировать спорный фрагмент. Сверка идёт по чанкам и по точному совпадению, поэтому в длинном тексте достаточно поправить один кусок, а не переписывать всё.

Неправильно

Поставить тот же текст в очередь ретраев с экспоненциальным backoff. Через пять попыток будет кулдаун на весь аккаунт, а заказ так и не создастся.

Причину блокировки API не отдаёт ни в каком поле — не ищите её.

Сетевой обрыв после POST /orders

Ответа нет — заказ мог создаться, а мог и нет. Слепой повтор здесь и есть источник дублей и двойных списаний.

Проверять нужно до повтора, через GET /orders. Ловушки две: фильтра по времени у списка нет вовсе (только status, template_id, task_type[], page, per_page), а порядок выдачи спека не документирует. Забирайте первую страницу и сверяйте created_at сами.

Облегчить проверку заранее можно одним способом: класть свой идентификатор запроса в поле name. Оно ни на что, кроме имени файла, не влияет, — зато заказ узнаётся в списке однозначно.

# при создании
-d '{"template_id": "…", "input_text": "…", "name": "job-2026-09-04-0041"}'
# после обрыва, прежде чем повторять: ищем это имя в первой странице списка
curl -s "$BASE/orders?per_page=20" -H "X-API-KEY: $KEY"

Серверной дедупликации по name нет — это соглашение вашего клиента. И отдельный аргумент за подписку на private-orders.{userId}: событие created приходит независимо от того, дошёл ли до вас HTTP-ответ.

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

Открыть .mdllm.md

Обновлено 04.09.2026 · спека 0.0.1