Перейти к содержимому
СервисАпп API
На этой странице

Пагинация, фильтры и синхронизация

Параметры выборки

Обычные списки используют filter[имя]=значение, sort, page[size], page[cursor]. Допустимый набор свой у каждого метода. Например:

curl --fail-with-body --silent --show-error --globoff --get \
  --header "Authorization: Bearer $SERVICEAPP_TOKEN" \
  --data-urlencode 'filter[q]=Демонстрационный' \
  --data-urlencode 'page[size]=50' \
  --data-urlencode 'sort=id' \
  "$API/customers" | jq .

Массивы, когда они разрешены, передаются повторяемыми параметрами с []: filter[equipment_ids][]=101&filter[equipment_ids][]=102. Строка со значениями через запятую не заменяет массив. Булевы значения параметров запроса используйте как true/false. По умолчанию страница содержит 50 записей, допускается 1–100. q ограничен 200 символами. Обычно массив ограничен 100 уникальными ID; точный лимит указан у операции.

У GET-отчётов /maintenance-reports/* параметры передаются на верхнем уровне: from, to, equipment_ids[], workshop_ids[], customer_id и дополнительные параметры конкретного отчёта. Эти отчёты не поддерживают filter, sort и page. Некоторые специальные GET возвращают агрегат или сохранённый список внутри data; они используют собственную схему, а не обязательную пагинацию.

Сортировка обычного списка — id или -id. Только явно указанные ресурсы дополнительно поддерживают updated_at,id / -updated_at,-id. У остатков ключом является product_id внутри склада. include, произвольная сортировка, offset и номер страницы не входят в контракт. Неизвестный параметр даёт 422 UNKNOWN_QUERY_PARAMETER, неверное значение — VALIDATION_FAILED.

Обход страниц

У курсорного списка есть data, links={self,next,prev}, meta={per_page,has_more,next_cursor,server_time}. Пустой список — 200 с data=[]. Родительские карточки внутри data могут содержать свои links.edit/portal/public; они не связаны с внешними links пагинации.

Переходите по относительному links.next на том же домене организации. Завершайте обход при has_more=false, next_cursor=null и next=null. Не разбирайте и не изменяйте содержимое курсора. Он привязан к подключению, URL родителя, фильтрам, порядку, размеру страницы и условиям доступа.

# NEXT_PATH берётся ровно из links.next предыдущей страницы.
export NEXT_PATH='<RELATIVE_LINKS_NEXT>'
curl --fail-with-body --silent --show-error --globoff \
  --header "Authorization: Bearer $SERVICEAPP_TOKEN" \
  "$SERVICEAPP_ORIGIN$NEXT_PATH" | jq .

Перед следованием ссылке проверьте, что это относительный путь /api/v1/ без другого домена. Повреждённый/несовместимый курсор — 422 INVALID_CURSOR; после 24 часов — 409 CURSOR_EXPIRED. После смены доступа начните обход заново. Курсор не сохраняет право читать ранее доступные записи.

Периоды

Отчёт требует обе границы from/to, максимум 366 календарных дней. DATE-границы включительны и не меняют день из-за часового пояса. Временные интервалы используют нижнюю включительную и верхнюю исключительную границу. Конкретное применение к календарным дням и временным событиям описано у ресурса.

У журнала API-операций период по умолчанию — последние 30 дней, у доступности сотрудников — ближайшие 30 дней. Ответ сообщает применённый период. Для отчётов периода по умолчанию нет.

Выборка изменённых записей

Только ресурсы, у которых перечислены filter[updated_since] и filter[updated_before], поддерживают такую выборку. Нижняя граница включительна (>=), верхняя исключительна (<). Само наличие поля updated_at в ответе не означает наличие этих фильтров.

curl --fail-with-body --silent --show-error --globoff --get \
  --header "Authorization: Bearer $SERVICEAPP_TOKEN" \
  --data-urlencode 'filter[updated_since]=2026-11-04T08:55:00Z' \
  --data-urlencode 'filter[updated_before]=2026-11-04T09:00:00Z' \
  --data-urlencode 'sort=updated_at,id' \
  --data-urlencode 'page[size]=100' \
  "$API/customers" | jq .

updated_at имеет секундную точность и не является моментом завершения транзакции. Повторное состояние с той же версией нужно применять, если данные изменились. Ни максимальная дата выгрузки, ни meta.server_time не доказывают полноту всех изменений до этой даты. Полные ограничения.

Рекомендуемая процедура синхронизации

  1. До полной выгрузки включите нужные уведомления о событиях и начните сохранять в постоянном хранилище event_id. Запомните server_time первой страницы и выгрузите доступные записи по id, следуя next.
  2. Принимайте событие как повод перечитать актуальную карточку. Дедуплицируйте event_id, выполняйте чтения последовательно для одного ресурса. Не заменяйте новый GET старым телом события; событие содержит ссылки на ресурс, а не полную карточку.
  3. Для ресурсов с updated_since выбирайте интервал от прошлого маркера минус перекрытие до server_time начала нового прохода. Начальное рекомендуемое перекрытие — 5 минут. Обходите все страницы с sort=updated_at,id и повторно применяйте состояние по (type,id), даже при прежней версии. Продвигайте маркер только после сохранения всех страниц; при сбое повторите весь интервал.
  4. Обрабатывайте удаление, архивирование и восстановление через события и разрешённые архивные выборки. Для customers filter[deleted]=true означает только удалённых; требуются customers:read, customers:delete и оба права сотрудника. Для products/operations filter[archived]=true выбирает архивные записи и требует соответствующего права удаления. Неудалённые записи выбираются без фильтра или с false.
  5. Делайте полную сверку доступных ID не реже раза в сутки, а также после потери событий, смены доступа и истечения курсора. Пропавший ID перепроверьте отдельным GET. 404 означает текущее отсутствие доступа или записи; это не доказательство физического удаления и не основание безусловно стирать данные внешней системы.

Эта процедура обеспечивает сходимость к доступному текущему состоянию. Она не является транзакционным снимком или журналом каждого промежуточного значения. Долгая транзакция может выйти за интервал перекрытия; нужны события и полная сверка. Глобальный порядок событий не гарантируется. Позднее deleted-событие не должно стирать уже восстановленную карточку без проверки её текущего состояния.