---
title: "Асинхронная модель заказов"
url: https://lumean.app/developers/docs/guide/async
locale: ru
description: "POST /orders отвечает сразу, а результат появляется позже. Типы заказов, статусы, чанки и способы узнать о готовности."
updated: 2026-11-06
sources: [post-orders, get-orders, get-orders-order, get-orders-order-items, post-orders-order-cancel]
errors: [invalid-order-status, policy-flagged, service-not-found, storage-expired]
spec_version: 1.0.0
---

# Асинхронная модель заказов

`POST /orders` ничего не генерирует сам. Он проверяет запрос, блокирует средства и токен-квоту
ключа, ставит задачу в очередь и отвечает `201` со статусом `created`. Результат появляется
позже, через минуты.

## Ответ на создание заказа

| Поле | Значение в ответе `201` |
| --- | --- |
| `id` | UUID заказа. Все дальнейшие вызовы идут по адресу `/orders/{order}/…` |
| `status` | `created` |
| `result` | `null`. Полей `files[]` и `service_files[]` в этом ответе нет |
| `total_chunks` | Число фрагментов, на которые сервер разбил текст. `0` — разбиение ещё не выполнено |
| `completed_chunks`, `progress_percent` | `0` |
| `eta_seconds`, `eta_at` | `null`. Прогноз есть только у заказа в статусе `in_progress` |
| `price_units` | Заблокированная сумма в минорных единицах LMC. У чанка поле с тем же именем содержит токены |

Сохраните `id`: без него заказ можно найти только в списке.

### POST /orders

Создать заказ

Справочник: https://lumean.app/developers/docs/api/post-orders

## Типы заказов

`POST /orders` принимает `template_id` или `task_type`, одно из двух обязательно. Шаблон задаёт
сервис и все настройки, поэтому озвучка создаётся только по шаблону. Заказ без шаблона работает
там, где код сервиса совпадает с типом задачи.

| `task_type` | Как создаётся | Где параметры | Файлы в `result.files[]` |
| --- | --- | --- | --- |
| `tts` | только по `template_id` | `input_text` в корне запроса | 1 склеенная дорожка, субтитры — в `service_files[]` |
| `sfx` | без шаблона | `task_data.text`, а также `duration_seconds`, `prompt_influence`, `loop`, `output_format` | 1 |
| `music` | без шаблона | `task_data.prompt`, а также `n_variants` (1..4), `music_length_ms`, `lyrics_text`, `force_instrumental` | по файлу на вариант, без склейки |
| `voice_search` | без шаблона | аудио в `input_files`, `task_data.top` (1..50) | нет: результат — список похожих голосов |

```bash
curl -s -X POST "$BASE/orders" -H "X-API-KEY: $KEY" -H "Content-Type: application/json" -d '{
  "task_type": "music",
  "task_data": { "prompt": "Lo-fi hip hop, calm, rainy night", "n_variants": 3,
                 "music_length_ms": 30000, "force_instrumental": true }
}'
```

Описание звука у SFX передаётся в ключе `text`, у Music — в `prompt`. Ключи кладутся в корень
`task_data`. `GET /templates/config-options` показывает те же параметры внутри секций
`sfx_settings` и `music_settings`, но в запрос эти обёртки не переносятся. С обёрткой
обязательный ключ оказывается внутри неё, и шаблон или `task_data` получат `422` «поле
обязательно». В `config_override` заказа обёртка отбрасывается без ошибки.

Цена таких заказов зависит от числа генераций, а не от их длины. У `sfx` и `voice_search` одна
ставка за заказ, у `music` — ставка, умноженная на `n_variants`. Тридцатисекундный трек стоит
столько же, сколько десятисекундный.

Недостающие ключи сервер дополняет из `default_config` сервиса, присланные значения остаются
как есть. Поэтому в сохранённом `task_data` заказа бывают ключи, которых не было в запросе.
Флаг `skip_service_defaults: true` отключает это дополнение.

По API-ключу создаются только четыре типа из таблицы. Остальные значения `TaskType` — `image`,
`txt2img`, `remix`, `image_edit` и `voice_clone` — проходят валидацию, но заказ получает `422`
с `reason: service_not_found`. `cartesia_dub` и `elevenlabs_dub` — дубли готового заказа: их
тоже создаёт не `POST /orders`, а только `POST /orders/{order}/dub` (см.
[Дубляж](/developers/docs/guide/dubbing)). В фильтре `GET /orders?task_type[]=…` допустимы все
одиннадцать значений.

### 422 · `service_not_found` — service_not_found — сервис не найден

| Что произошло | Что делать |
| --- | --- |
| Заказ не создан. Ответ: 422 с `reason: "service_not_found"` и без `errors`. Запрос прошёл проверку полей, но сервис для него не нашёлся. | Отправляйте только те типы, которые создаются по ключу. |

`Retry-After`: нет. Разбор: https://lumean.app/developers/docs/errors/service-not-found

## Статусы заказа

Значения `OrderStatus` — в справочнике объектов: https://lumean.app/developers/docs/objects#o-OrderStatus

Терминальные статусы: `completed`, `result_delivered`, `failed`, `compensated`, `cancelled`.
Заказ в таком статусе больше не меняется, и опрашивать его дальше не нужно. С момента перехода
в терминальный статус отсчитывается срок хранения файлов, по умолчанию 7 дней.

Нетерминальные статусы: `created`, `pending`, `in_progress`, `partially_completed`.

```text
Девять статусов заказа. Опрашивать дальше имеет смысл только в НЕтерминальных.

АКТИВНЫЕ (не терминальные)
  created  →  pending  →  in_progress
                              │
                              ├─→ completed             ТЕРМИНАЛЬНЫЙ
                              │      └─→ result_delivered   ТЕРМИНАЛЬНЫЙ
                              │
                              ├─→ partially_completed   НЕ ТЕРМИНАЛЬНЫЙ ← ловушка:
                              │      часть чанков готова, сбойные ждут
                              │      POST /orders/{order}/items/retry-failed
                              │
                              ├─→ failed                ТЕРМИНАЛЬНЫЙ
                              │      └─→ compensated        ТЕРМИНАЛЬНЫЙ
                              │
                              └─→ cancelled             ТЕРМИНАЛЬНЫЙ

Отменить (cancelled) можно из любого активного статуса, а не только из in_progress.
Терминальные: completed, result_delivered, failed, compensated, cancelled.
```

| Статус | Терминальный | Что делать |
| --- | --- | --- |
| `created`, `pending` | нет | Ждать. В этих статусах заказ ещё можно отменить |
| `in_progress` | нет | Ждать и следить за `completed_chunks` и `progress_percent`. Отменить нельзя |
| `partially_completed` | нет | Обработка закончилась, часть чанков не выполнена. Готовые файлы можно забирать. Упавшие чанки можно повторить или закрыть заказ отменой |
| `completed` | да | Получить ссылки на `result.files[]` через `POST /storage/url` |
| `result_delivered` | да | То же, что `completed`: файлы доступны до конца срока хранения |
| `failed`, `compensated` | да | Файлов нет. В `result` может прийти только `user_message` — причина сбоя текстом для человека. Нужен новый заказ |
| `cancelled` | да | Заказ отменён через `POST /orders/{order}/cancel`. Из `created` и `pending` средства и квота возвращаются полностью. Из `partially_completed` готовые чанки остаются оплаченными, за упавшие средства возвращаются |

`failed` и `compensated` означают, что заказ завершился ошибкой. Обычный сбой выполнения
заканчивается статусом `compensated`: списанное к этому моменту уже возвращено. Текст
`user_message` переведён для показа человеку, ветвить по нему логику нельзя.

Отмена принимается в статусах `created`, `pending` и `partially_completed`. В остальных
статусах `POST /orders/{order}/cancel` отвечает `400`.

## Частично выполненный заказ

Заказ получает статус `partially_completed`, когда часть чанков не выполнена. Готовые фрагменты
сохранены, а упавшие ждут решения: повтора или отмены заказа. Этот статус не терминальный.
Если обработчик считает финальным всё, кроме `created`, `pending` и `in_progress`, такой заказ
останется недоделанным, хотя его можно довести до `completed`.

### 202 · `policy_flagged` — policy_flagged — чанк отклонён контентной политикой

| Что произошло | Что делать |
| --- | --- |
| Это не HTTP-ошибка. Код приходит как значение `OrderItem.status` и как `reason` в массиве `skipped[]` ответа 202 на `POST /orders/{order}/items/retry-failed`. Заказ при этом переходит в `partially_completed`. Этот статус не финальный: готовые чанки на месте, отклонённые ждут действия. | Получите текущий текст чанка, перефразируйте спорный фрагмент и повторите чанк отдельно с новым текстом. Причину отклонения API не сообщает, правьте по своему усмотрению. Ограничения повтора: не больше 5 попыток, для `sfx` и `music` повтор чанка недоступен. Пределы длины отдаёт `GET /orders/{order}/items/{item}/text`: в пределах `free_length` повтор бесплатен, до `max_billable_length` — с доплатой. `POST /orders/{order}/retry` здесь не подойдёт: он не принимает заказы в `partially_completed`. |

`Retry-After`: нет. Разбор: https://lumean.app/developers/docs/errors/policy-flagged

Как повторить упавшие чанки, описано в руководстве
[Ретраи и идемпотентность](/developers/docs/guide/retries). `POST /orders/{order}/retry` здесь
не подходит: он не принимает `partially_completed` и создаёт новый платный заказ.

## Чанки

Перед генерацией сервер делит текст на чанки (`OrderItem`), и работа идёт по ним. В этой
документации «чанк» и «фрагмент» — одно и то же. В полях API это `chunk_index`, `total_chunks`
и `completed_chunks`.

Статусы чанка отличаются от статусов заказа:

| Статус чанка | Значение |
| --- | --- |
| `pending` | Ждёт обработки |
| `processing` | В работе |
| `completed` | Готов |
| `failed` | Техническая ошибка |
| `policy_flagged` | Отклонён контентной политикой |

Чанки приходят в `items[]` у каждого заказа — и в `GET /orders/{order}`, и в списке
`GET /orders`. Отдельно их отдаёт `GET /orders/{order}/items`. Повторы и перегенерации
хранятся отдельными записями с тем же `chunk_index` и ссылкой `parent_item_id`, поэтому длина
`items[]` не совпадает с `total_chunks`. Прогресс считайте по `completed_chunks` и
`total_chunks`: в них входят только исходные чанки.

### GET /orders/{order}/items

Чанки заказа

Справочник: https://lumean.app/developers/docs/api/get-orders-order-items

## Как узнать о готовности

**Правильно**

Подписаться на `private-order.task.{orderId}` (один заказ) или `private-orders.{userId}`
(все заказы аккаунта) и слушать события `status.changed`, `item.status.changed` и `progress`.
Событие приходит в момент перехода, без лишних запросов.

**Неправильно**

Опрашивать `GET /orders/{order}` раз в секунду. Это десятки лишних запросов на каждый заказ,
они расходуют лимит частоты запросов ключа, а задержка до секунды всё равно остаётся.

Опрос тоже работает, особенно для коротких заказов. Интервал — 2–5 секунд: каждый запрос
расходует лимит частоты ключа. Паузу удобно выбирать по `eta_seconds` или `eta_at`. Несколько
заказов проверяются одним запросом `GET /orders?status=in_progress`. Ограничьте число попыток:
статус `failed` — тоже ответ.

Массовый повтор чанков работает так же. Ответ `202` значит, что план принят. Результат приходит
позже: событием `bulk_retry.completed` или в ответе `GET /orders/{order}/items`.

К заказам относятся три канала: `private-orders.{userId}`, `private-order.task.{orderId}` и
`private-chunks.preview.{userId}`. Остальные каналы и формат событий описаны в руководстве
[Realtime](/developers/docs/guide/realtime).

## Файлы результата

В `result.files[]` лежат пути к файлам, а не ссылки. Ссылку на скачивание выдаёт
`POST /storage/url`. Запрашивайте её вскоре после `completed`: файлы хранятся ограниченное
время. Как проверить, что файл ещё доступен, — в руководстве
[Файлы и хранение](/developers/docs/guide/files).

---

- Эта же страница в браузере: https://lumean.app/developers/docs/guide/async
- Машинный справочник целиком: https://api.lumean.app/docs/llm.md
