Как обойти отзывы, товары или вопросы через Platform API
Постраничная выгрузка отзывов, товаров и вопросов по курсору методом «Обход данных» Platform API: параметры, цикл обхода, лимиты и ошибки.
Забирайте отзывы, товары или вопросы постранично по курсору, если их нужно регулярно синхронизировать с вашей базой, а ждать файл задачи на экспорт неудобно. Обход отдаёт записи в том же формате JSON API, что и обычные списки, но без ограничения на номер страницы.
Обход или экспорт
| Обход данных | Задача на экспорт | |
|---|---|---|
| Коллекции | Отзывы, товары, вопросы | Отзывы, вопросы, товары, заказы, клиенты, результаты опросов |
| Результат | Страницы JSON API по 1–100 записей | Файл CSV, XLSX или JSONL по ссылке |
| Когда данные готовы | Сразу, страница за страницей | Когда задача завершится, обычно через минуты |
| Объём | Без лимита на одну выгрузку | До 500 000 строк, товаров — до 800 000 |
| Суточная квота экспорта | Не расходует | Расходует, см. лимиты экспорта |
| Подходит | Частая синхронизация изменений, загрузка в свою базу или поиск | Разовые и суточные выгрузки, отчёты, состав колонок по формату экспорта |
Что понадобится
- Токен OAuth-приложения с доступом Platform API: см. как получить токен доступа к API.
- Базовый адрес
https://api.aplaut.io/v4. - Заголовок
Authorization: Bearer {TOKEN}в каждом запросе.
Метод целиком описан в справочнике Platform API, раздел Обход данных.
Шаг 1. Откройте обход
Отправьте GET /v4/scroll/{records_type}, где records_type — reviews, products или questions. Параметры обхода передаются только в этом первом запросе:
| Параметр | Значение по умолчанию | Что задаёт |
|---|---|---|
filter | updated_at за последние 30 дней | Какие записи попадут в обход. Синтаксис и поля — ниже |
sort | updated_at:asc | Порядок записей: updated_at:asc или created_at:asc. Только одно поле и только по возрастанию |
per_page | 100 | Записей на странице, от 1 до 100 |
include | — | Связанные объекты в included, через запятую. Отзывы: author, product, comments, state_changes. Товары: reviews_summary_item. Вопросы: author, product, answers |
curl -G -H "Authorization: Bearer {TOKEN}" \
--url https://api.aplaut.io/v4/scroll/reviews \
--data-urlencode "filter=updated_at:gte:2026-10-01T00:00:00Z,state:eq:published" \
--data-urlencode "include=product" \
--data-urlencode "per_page=100"
Шаг 2. Прочитайте страницу
Записи лежат в data, сведения об обходе — в meta и links:
{
"data": [ … ],
"meta": {
"has_more": true,
"count": 100,
"cursor": "eyJfcmFpbHMiOnsi…",
"total_count": 12840
},
"links": {
"next": "https://api.aplaut.io/v4/scroll/reviews?cursor=eyJfcmFpbHMiOnsi…"
}
}
| Поле | Что означает |
|---|---|
meta.has_more | true — за этой страницей есть следующая |
meta.count | Сколько записей на этой странице |
meta.cursor | Курсор для следующей страницы. На последней странице его нет |
meta.total_count | Сколько записей попало в обход. Приходит только на первой странице |
meta.applied_filter | Фильтр по умолчанию, который применился, потому что filter не передан. Приходит только на первой странице |
links.next | Готовый адрес следующей страницы. На последней странице его нет |
Шаг 3. Идите по курсору
Запрашивайте links.next — или GET /v4/scroll/{records_type}?cursor={CURSOR} — пока meta.has_more не станет false. Фильтр, сортировка, per_page и include запомнены в курсоре, повторять их не нужно. Если всё же передать их рядом с курсором, они должны совпасть с исходными, иначе запрос вернёт 400.
Последняя страница может прийти пустой: если на предыдущей было ровно per_page записей, сервер ещё не знает, что они последние.
Цикл обхода на bash с jq:
TOKEN="…"
URL="https://api.aplaut.io/v4/scroll/reviews?filter=updated_at:gte:2026-10-01T00:00:00Z"
while [ -n "$URL" ]; do
PAGE=$(curl -s -H "Authorization: Bearer $TOKEN" --url "$URL")
echo "$PAGE" | jq -c '.data[]' >> reviews.jsonl
URL=$(echo "$PAGE" | jq -r '.links.next // empty')
sleep 2 # не чаще 1 запроса в 2 секунды на токен
done
Скрипт для примера: в рабочем коде обработайте ответы 429 и 503 — см. Лимиты и ошибки.
Сервер держит место обхода 2 минуты после каждой страницы. Если пауза между запросами дольше, обход продолжится с последней отданной записи включительно, и несколько записей придут ещё раз. Курсор при этом остаётся рабочим. Отсеивайте дубли по id.
Фильтр
Фильтр — условия через запятую в формате поле:оператор:значение, все условия объединяются по И:
filter=updated_at:gte:2026-10-01T00:00:00Z,rating:in:4|5
| Оператор | Значение |
|---|---|
eq, neq | Равно, не равно |
gt, gte, lt, lte | Больше, больше или равно, меньше, меньше или равно |
in | Одно из значений через |, не больше 25 значений |
exists | Поле заполнено: true или false |
Даты передаются в ISO 8601, например 2026-10-01T00:00:00Z. Знак + в часовом поясе кодируйте как %2B или передавайте параметр через --data-urlencode.
| Тип | Поля фильтра |
|---|---|
reviews | created_at, updated_at, published_at, state, context_type, product_id, product_group_id, brand_id, category_id, rating, origin, syndication_source, order_number, lang, verified, featured, recommended |
products | created_at, updated_at, last_imported_at, summary_updated_at, external_id, group_id, brand_id, category_id, vendor_code, available, price, rating |
questions | created_at, updated_at, published_at, imported_at, state, context_type, product_id, product_external_id, product_group_id, brand_id, category_id, lang, origin, has_published_answers |
Условие product_id:eq:… отбирает записи всей группы товара, а не одного варианта.
Если filter не передан, в обход попадают записи, изменённые за последние 30 дней, — применённое условие придёт в meta.applied_filter. Любой свой фильтр снимает это ограничение целиком. Чтобы пройти данные за весь период, задайте границу явно, например filter=updated_at:gte:2015-01-01T00:00:00Z.
Синхронизация изменений
Чтобы забирать только изменения, открывайте обход с сортировкой updated_at:asc и фильтром updated_at:gte:{ВРЕМЯ}, где время — updated_at последней записи из предыдущего обхода. Граница включительная, поэтому последняя запись придёт снова — отсейте её по id.
Сводку отзывов о товаре берите через include=reviews_summary_item: она приходит в included вместе со своим статусом state — опубликованная, ожидающая модерации или забаненная. Отдельного атрибута со сводкой у товара нет.
Лимиты и ошибки
Сверх общих лимитов Platform API на обход действуют ограничения на токен:
| Ограничение | Значение |
|---|---|
| Запросы к обходу | 1 запрос в 2 секунды |
Открытие обходов, запросы без cursor | 5 в минуту |
Из-за первого лимита два обхода одним токеном параллельно не идут. Не открывайте обход заново на каждую страницу — идите по курсору.
| Код | Причина | Что делать |
|---|---|---|
400 | Курсор неверный, изменён, выдан другой компании или для другого типа записей; параметры рядом с курсором не совпадают с исходными; фильтр не разбирается | Откройте обход заново без курсора |
404 | Неизвестный records_type или товар из условия product_id:eq не найден | Используйте reviews, products или questions, проверьте идентификатор товара |
422 | Неизвестное поле в фильтре, неподдерживаемая сортировка, per_page вне диапазона 1–100 | Исправьте параметры по таблицам выше |
429 | Превышен лимит запросов | Подождите столько секунд, сколько указано в заголовке Retry-After, и повторите запрос |
503 | Временная перегрузка, заголовок Retry-After: 30 | Повторите запрос с тем же курсором через указанное число секунд |
Смотрите также: как выгрузить данные через Platform API, экспорт данных: коллекции, форматы и лимиты, как импортировать данные через Platform API.