---
title: "Пагинация"
url: https://lumean.app/developers/docs/guide/pagination
locale: ru
description: "Как листать списки API. Обычные списки и каталоги Cartesia и Fish Audio считают страницы с единицы, каталоги ElevenLabs и HeyGen — с нуля."
updated: 2026-11-06
sources: [get-orders, get-templates, get-templates-browse, get-voices, get-voices-elevenlabs-library, get-voices-heygen, get-voices-cartesia, get-voices-fishaudio, get-orders-chunks-preview-preview-id]
errors: ["422", "429"]
spec_version: 1.0.0
---

# Пагинация

Большинство списков API считает страницы с единицы и отвечает в одной форме. Каталоги
ElevenLabs и HeyGen считают страницы с нуля, и обёртка ответа у них другая. Превью разбиения
на чанки отдаёт счётчики в отдельном объекте. Код, написанный для `GET /orders`, на каталоге
ElevenLabs пропустит первую страницу.

## Обычные списки

```json
{
  "items": [ /* … */ ],
  "current_page": 1,
  "last_page": 5,
  "per_page": 20,
  "total": 93
}
```

Такой объект лежит в `data` у `GET /orders`, `GET /templates`, `GET /templates/browse`, `GET /voices`,
`GET /voices/library`, `GET /voices/public`, у каталогов Cartesia и Fish Audio
(`GET /voices/cartesia`, `GET /voices/fishaudio`) и у их списков клонов (`…/clones`). Счётчики
лежат рядом с `items`, отдельного `data.meta` нет.

Параметры запроса — `page` (с `1`) и `per_page`. Список закончился, когда `current_page`
равен `last_page`.

### GET /orders

Список заказов

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

`GET /templates` без параметров отвечает так же, как `?page=1&per_page=30`: первой страницей
корневых шаблонов, новые первыми. До 06.11.2026 такой запрос отдавал в `data` массив всех
шаблонов. Этот режим снят, и код, который читает `data` как массив, получит объект. Добавьте
`?page=1`, читайте `data.items` и обходите страницы. Найти шаблон по названию — `search`, по
сервису — `service`, внутри папки — `folder_id`.

### GET /templates

Список шаблонов

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

## Каталоги ElevenLabs и HeyGen

```json
{
  "voices": [ /* … */ ],
  "total": 1420,
  "page": 0,
  "page_size": 30,
  "has_more": true
}
```

`GET /voices/elevenlabs/library` и `GET /voices/heygen` проксируют API поставщиков и сохраняют
их соглашения.

| | Обычные списки | ElevenLabs и HeyGen |
| --- | --- | --- |
| Массив | `items` | `voices` |
| Размер страницы | `per_page` | `page_size` |
| Первая страница | `page=1` | `page=0` |
| Конец списка | `current_page` равен `last_page` | `has_more: false` |

Первая страница здесь — `page=0`, это же значение по умолчанию. `page=1` вернёт вторую
страницу, и первые голоса каталога выпадут из выдачи.

`total` у этих каталогов значит разное. У ElevenLabs это число голосов на текущей странице, у
HeyGen — сколько голосов подходит под фильтры на всех страницах. Поэтому выходите из цикла по
`has_more`.

Каталоги Cartesia и Fish Audio листаются как обычные списки: `items`, страницы с единицы.

`GET /voices/elevenlabs/library` зависит от внешнего API ElevenLabs и при его недоступности
отвечает `503`. Сохраняйте номер страницы, чтобы продолжить обход с того же места.

### `get-voices-heygen`

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

## Страницы превью разбиения

`GET /orders/chunks/preview/{previewId}` кладёт счётчики в отдельный объект `data.page`.

| Поле | Значение |
| --- | --- |
| `data.page.current_page` | номер страницы, с 1 |
| `data.page.per_page` | размер страницы: по умолчанию 100, максимум 500 |
| `data.page.total` | число чанков в разбиении на всех страницах |
| `data.page.has_more` | есть ли следующие страницы. `last_page` здесь нет |

Соседнее поле `data.summary` описывает весь текст, а не текущую страницу, поэтому складывать
его по страницам не нужно. `{previewId}` — это sha256 из 64 hex-символов, а не UUID.

## Списки без страниц

| Операция | Что в `data` |
| --- | --- |
| `GET /orders/{order}/items` | массив всех чанков заказа, включая повторы |
| `GET /usage`, `GET /voices/tags` | массив записей |
| `GET /voices/heygen/filters` | объект из списков значений со счётчиками: `voice_engines`, `genders`, `languages`, `accents`, `labels` |

Параметр `page` эти операции не учитывают.

## Размер страницы и значения по умолчанию

| Операция | Параметры | Диапазон | По умолчанию |
| --- | --- | --- | --- |
| `GET /orders` | `page`, `per_page` | `page ≥ 1`, `per_page` 1..100 | 20 |
| `GET /templates` | `page`, `per_page` | `page ≥ 1`, `per_page` 1..30 | 30 |
| `GET /templates/browse` | `page`, `per_page` | `page ≥ 1`, `per_page` 1..100 | 15 |
| `GET /orders/chunks/preview/{previewId}` | `page`, `per_page` | `page ≥ 1`, `per_page` 1..500 | 100 |
| `GET /voices/elevenlabs/library` | `page`, `page_size` | `page ≥ 0`, `page_size` 1..50 | 0 / 30 |
| `GET /voices/heygen` | `page`, `page_size` | `page ≥ 0`, `page_size` 1..200 | 0 / 55 |
| `GET /voices/cartesia`, `/voices/fishaudio` | `page`, `per_page` | `page ≥ 1`, `per_page` 1..200 | 50 |
| `GET /voices`, `/voices/library`, `/voices/public` | `page`, `per_page` | `page ≥ 1`, `per_page` 1..100 | 20 |

Значение вне диапазона возвращает `422` с полем в `errors`. Исключение — `per_page` у трёх
списков голосов LumVoice: значение вне 1..100 сервер без ошибки заменяет ближайшей границей.
Нецелое `per_page` и там вернёт `422`.

### 422 — 422 — запрос не принят

| Что произошло | Что делать |
| --- | --- |
| Запрос не принят, ничего не создано. Ошибка в полях приходит в общем конверте: `{"success": false, "message": "…", "errors": {"field": ["…"]}}`. | Сначала проверьте, есть ли в теле `errors`. Если есть, исправьте перечисленные поля. Если `errors` нет, а есть `reason`, поля запроса ни при чём: то же тело вернёт тот же отказ. Откройте страницу этого кода. |

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

## Курсорной пагинации нет

В ответах нет `cursor`, `next_cursor` и `next_page_url`. Параметр `pag=cursor` проходит
проверку и не вызывает `422`, но сервер его не учитывает и возвращает обычную постраничную
форму. Листайте через `page` и `per_page`.

## Как обойти список целиком

Постраничная выдача не даёт согласованного снимка: пока вы идёте по страницам, данные меняются.
`GET /orders` отдаёт новые заказы первыми. Один новый заказ сдвигает выдачу на одну позицию, и
запись на границе страниц попадёт в ответ дважды или не попадёт совсем.

1. Убирайте дубликаты по `id` на стороне клиента. Этот способ работает при любой форме ответа.
2. Сужайте выборку, чтобы она не пополнялась во время обхода. У `GET /orders` есть фильтры
   `status`, `task_type[]` и `template_id`. Выборка по терминальному статусу почти не
   меняется, а `status=in_progress` меняется постоянно.
3. Останавливайтесь по признаку конца, а не по счётчику: `current_page` равен `last_page` или
   `has_more: false`. `total` пересчитывается при каждом запросе. Он подходит для индикатора
   прогресса, но не для условия выхода.
4. Берите страницы крупнее. `per_page=100` вместо 20 сокращает число запросов в пять раз, а с
   ним и риск получить `429` во время обхода.
5. Делайте паузу между страницами. Обход большого каталога — частая причина `429` по лимиту
   частоты запросов ключа. Подробнее — в руководстве
   [Лимиты и код 429](/developers/docs/guide/limits).

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

Хранить множество уже полученных `id`, идти по страницам до `has_more: false` или до
`current_page`, равного `last_page`, а после `503` каталога продолжать с той же страницы.

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

Один раз вычислить число страниц как `Math.ceil(total / per_page)` и перебирать номера вслепую.
`total` устареет за время обхода, а у каталогов с отсчётом от нуля последняя страница имеет
номер на единицу меньше.

---

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