← Все статьи

SiteGuard12 мин чтения

API возвращает не все записи: как проверить пагинацию, фильтры и полноту выгрузки

API ответил успешно, файл выгрузки создан, ошибок в журнале нет — но часть заказов или клиентов отсутствует. Такая ситуация опаснее явного отказа: данные выглядят достоверными, отчёт используется в работе, а интеграция незаметно обрабатывает только первую страницу или пропускает записи между запросами.

Если API возвращает не все данные, сначала нужно определить, где возникло расхождение: в условиях выборки, получении страниц, сохранении результата или самом ожидании «полного списка». Разберём пагинацию API через next, start и курсоры, особенности Битрикс24 и проверки, которые помогают отличить завершённую выгрузку от просто остановившегося цикла.

Сначала определите, какие записи должны попасть в выгрузку

Фраза «в CRM больше записей» пока не задаёт проверяемого условия. В интерфейсе может быть другой фильтр, административный доступ, иной тип сущности или включённый архив. Зафиксируйте портал, окружение, метод, пользователя интеграции, набор прав, фильтр, сортировку и временной интервал. Это паспорт конкретного запуска, с которым можно сравнивать результат.

Согласуйте смысл полноты. Для разового отчёта могут требоваться все доступные записи, созданные до определённого момента. Для синхронизации — изменения после последней подтверждённой точки. Для сверки заказов — конкретный согласованный список идентификаторов. Эти задачи требуют разных границ и не сводятся к одному запросу «получить всё».

Сохраните безопасное описание условий вместе с выгрузкой. Если спустя час фильтр поменялся, результат прежнего запуска нельзя сравнивать с новым экраном без учёта этого изменения. Не включайте в паспорт токены авторизации и персональные данные: для воспроизведения условий достаточно служебных параметров и ограниченного набора тестовых идентификаторов.

Договоритесь также, что считается итогом: полученная страница, записанные строки или успешно применённые изменения в другой системе. Успешное чтение источника ещё не подтверждает завершение всей интеграции.

Почему Битрикс24 API возвращает только 50 записей

Для описанных в документации Битрикс24 списочных методов одна страница содержит не более 50 элементов. Первый запрос выполняют без start, а полученное поле next передают как start следующего запроса. Стандартный обход продолжается, пока next не исчезнет. Число 50 относится к этому договору API, а не ко всем сервисам и любым методам.

Проверьте и структуру результата. У разных методов список находится в разных местах ответа; для приведённого в документации crm.item.list это result.items. Если код ожидает массив непосредственно в result, он может неверно посчитать элементы или принять объект-обёртку за одну запись. Ошибка декодирования структуры не исправляется увеличением размера страницы.

Откройте очищенный ответ первого вызова и найдите три вещи: фактический массив объектов, признак продолжения и сведения об ошибке. Затем проверьте журнал исходящих запросов: был ли действительно выполнен следующий вызов. Нередко обработчик корректно отображает первые 50 элементов, но вообще не содержит продолжения обхода.

HTTP 200 в этой диагностике подтверждает только транспортный результат конкретного обращения. Прикладной ответ, извлечённые записи и выполнение следующих страниц проверяют отдельно.

Чем отличаются смещение, курсор и ссылка на следующую страницу

Не подменяйте один протокол другим. Числовое смещение обычно задаёт позицию в выборке, курсор передаёт серверное состояние продолжения, а next URL содержит адрес следующего запроса. Внешне они решают похожую задачу, но правила формирования и завершения нужно брать из документации конкретного метода.

Например, Microsoft Graph предписывает использовать весь URL из @odata.nextLink. Не следует извлекать из него отдельный skiptoken и собирать другой запрос вручную. Размеры страниц и поддерживаемые параметры зависят от ресурса. Это хороший пример того, почему универсальная библиотека «прибавлять 50 к start» не подходит для любого API.

Что вернул серверЧто сохранятьЧего избегать
Число для следующего startИменно полученное значение и исходные условияПодмены смещения номером страницы
Непрозрачный cursor или page tokenЗначение без самостоятельного измененияДекодирования ради вычисления следующего курсора
Полный next URLСсылку в рамках разрешённого APIПроизвольной пересборки параметров

Для next URL предусмотрите проверку HTTPS и разрешённого хоста провайдера, включая его документированные региональные адреса. Не отправляйте авторизационные заголовки на произвольный домен из ответа или неожиданного перенаправления. Подозрительная ссылка должна остановить запуск с понятной ошибкой, а не превратить продолжение выгрузки в утечку доступа.

Как найти расхождение в фильтрах и правах

Сравнивайте одинаковые условия, а не только одинаковый URL метода. Проверьте тип сущности, статус, принадлежность подразделению, удалённые и архивные записи, часовой пояс, операторы сравнения и формат значений. Пустая строка, отсутствие параметра и явное значение null могут означать разное, если так устроен договор метода.

Для временного интервала заранее определите границы. Например, учебный отчёт включает события с 00:00:00 UTC первого дня включительно до 00:00:00 UTC следующего дня исключительно. Такую договорённость затем переводят в поддерживаемый синтаксис фильтра. Не заменяйте конец суток случайной точностью вроде 23:59:59, если источник хранит доли секунды.

Проверьте, не сравниваются ли административный интерфейс и API от имени сотрудника с ограниченными правами. Отсутствующая в ответе запись может быть недоступной именно этому пользователю. Проверка известного идентификатора через разрешённый метод помогает отличить ограничение доступа от ошибки пагинации, но её результат тоже нужно трактовать по правилам API.

Условия должны оставаться согласованными на всех страницах. Если первый запрос включает фильтр по нужному магазину, а второй его теряет, итоговый файл будет смесью выборок. Сохраняйте нормализованный набор параметров запуска и сверяйте с ним последующие обращения.

Почему порядок записей влияет на пропуски

У пагинации должна быть воспроизводимая сортировка. Поле вроде даты изменения может совпадать у нескольких объектов и меняться во время выгрузки. Если метод позволяет, задавайте дополнительный уникальный критерий для разрешения равенства. Названия полей и допустимые сочетания проверяйте для конкретного списка.

Рассмотрим учебный пример со смещением. Источник возвращает последовательность A, B, C, D, а размер страницы равен двум. Клиент получил A и B. Затем A удалили. Новый список стал B, C, D. Следующий запрос со смещением 2 пропускает первые две текущие позиции и возвращает D: объект C не попал в выгрузку.

Обратное изменение тоже мешает: вставка перед уже пройденной границей может привести к повтору ранее полученного элемента. Дедупликация уберёт повтор, но сама по себе не восстановит пропущенный объект. Поэтому стабильная сортировка необходима для понятного обхода, однако не превращает изменяющийся набор в неизменяемый.

В журнале полезно сохранять первый и последний идентификаторы страницы и значения сортировки в безопасном объёме. По ним легче заметить возврат назад, неожиданное пересечение диапазонов или изменение порядка после обновления API.

Курсор не обязательно означает снимок данных

Наличие cursor не доказывает, что сервер зафиксировал состояние всей коллекции на начало выгрузки. Курсор может описывать только позицию продолжения. Гарантию согласованного снимка нужно искать отдельно: какие изменения видны, как долго действует контекст и что происходит при удалении записей.

Если снимка нет, сформулируйте допустимую согласованность. Для ежедневной синхронизации часто нужен повторный проход по ограниченному периоду изменений с устранением дублей. Для строгого отчёта может потребоваться предусмотренный провайдером экспорт или иной способ получить зафиксированный набор. Нельзя обещать точное состояние на одну секунду только потому, что цикл дошёл до последней страницы.

Фиксированная верхняя граница времени или идентификатора помогает ограничить запуск, но не замораживает поля старых объектов, удаления и права доступа. Запись, существовавшая в начале, может перестать соответствовать фильтру до чтения своей страницы. Это ограничение следует отражать в результате и критериях приёмки.

Планируйте поздно появляющиеся изменения: если источник допускает задержку публикации данных, проход «до текущего времени» может их не увидеть. Размер перекрывающегося окна и способ повторной сверки выбирают по фактическому поведению источника, а не по универсальному числу минут.

По какому признаку завершать обход страниц

Условие завершения — часть договора API. Короткая страница не является универсальным доказательством конца. В Google AIP-158, например, допускается меньше запрошенного числа объектов, включая ноль, даже когда продолжение существует; окончание определяется пустым next_page_token. Сам токен предлагается считать непрозрачным. Это правило проектирования Google API нельзя автоматически переносить на другой сервис.

В стандартном режиме Битрикс24 используйте документированный признак продолжения. Не вычисляйте число запросов только по первому total и не заканчивайте цикл лишь потому, что очередная страница выглядит неполной. Вместе с тем предусмотрите защиту от технического зацикливания: повторившийся указатель, отсутствие продвижения и недопустимая структура ответа требуют отдельной диагностики.

Ограничение длительности или количества страниц полезно как предохранитель, но достижение этого ограничения означает прерванную выгрузку. Нельзя после аварийной остановки выставлять статус «полностью завершено». Сохраните причину, последнюю подтверждённую точку и количество обработанного материала.

Различайте пустой успешный ответ, ошибку API и сбой разбора. Если исключение преобразовано в пустой массив, обработчик может ошибочно принять отказ сервера за конец коллекции. Такое поведение особенно трудно заметить без отдельного счётчика неуспешных страниц.

Когда в Битрикс24 нужен обход по последнему ID

Для больших выгрузок Битрикс24 описывает отдельный способ: поддерживаемый метод сортируется по стабильному числовому идентификатору, фильтр ограничивает результат значениями больше последнего полученного ID, а start=-1 отключает подсчёт общего количества. Такой обход не использует next; в описанной схеме завершение определяется страницей короче 50 элементов. Применять её можно только к методам, поддерживающим соответствующие фильтр, сортировку и режим start.

Это не исправление любого списка одним параметром. Сначала убедитесь, что имя поля, регистр, оператор фильтра и структура результата соответствуют выбранному методу. Смешивать продолжение по ID и произвольное увеличение смещения внутри одного запуска не следует: критерий продвижения становится неоднозначным.

Сохраняйте последнюю подтверждённую границу после обработки страницы, а не после получения заголовков ответа. Верхнюю границу набора, если она нужна, задавайте отдельно поддерживаемым способом. Последовательность идентификаторов не обязана идти без пропусков: удаление объектов и особенности выделения ID делают арифметику «максимальный минус минимальный» непригодной для подсчёта записей.

Почему total и количество строк не доказывают полноту

Разделите как минимум три счётчика: сколько объектов получено с API, сколько уникальных идентификаторов встречено и сколько объектов сохранено в целевой системе. Если при повторах получено 123 объекта, среди которых восемь повторных вхождений, уникальных идентификаторов будет 115. Успешная запись 123 строк в файл не устраняет это расхождение.

Total полезен для сверки, когда известны его смысл, точность и условия вычисления. На изменяющемся наборе значение первой страницы может уже не соответствовать последней. Даже совпадение числа уникальных объектов с total не доказывает равенство множеств: один ожидаемый объект мог исчезнуть, а другой появиться вместо него.

Для идентификатора учитывайте область уникальности. Число 42 может одновременно обозначать клиента, сделку и объект другого портала. Ключ сверки должен включать источник и тип сущности, если API не гарантирует глобальную уникальность. Иначе дедупликация сама удалит нужные данные.

Когда есть независимый согласованный список ожидаемых объектов, сравнивайте множества ключей: отсутствующие, лишние и повторные. Если такого списка нет, честно укажите предел проверки: пройдено документированное продолжение, данные сохранены, но отсутствие всех возможных пропусков в живом источнике не доказано.

Как сохранять прогресс без потери страницы

Контрольная точка должна соответствовать надёжно обработанным данным. Опасная последовательность: сохранить указатель следующей страницы, затем начать запись текущей и завершиться при сбое. После перезапуска интеграция перескочит через объекты, которые так и не были сохранены.

Для собственного хранилища продумайте согласованную фиксацию страницы и её контрольной точки. При повторной обработке те же ключи не должны создавать дубли. Если данные передаются во внешнюю систему, отдельно учитывайте её подтверждение и неопределённый результат: локальный checkpoint не может одной транзакцией гарантировать чужую запись.

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

Правила сетевых повторов также сверяйте с провайдером. Не применяйте к любому курсору алгоритм, написанный для числового смещения. Неуспешная попытка должна оставлять выгрузку в контролируемом состоянии, а файл с частичным результатом — иметь явную отметку неполноты.

Учебная сверка: 123 объекта на трёх страницах

Допустим, тестовый набор содержит ровно 123 доступных объекта, фильтр и права зафиксированы, записи во время выгрузки не меняются. Метод следует стандартной схеме Битрикс24 с максимальной страницей 50 элементов. Все объекты имеют разные ключи, а приёмник успешно сохраняет каждый из них.

ЗапросstartПолученоnextУникальных накоплено
ПервыйНе передан505050
Второй5050100100
Третий10023Отсутствует123

Проверка арифметики проста: 50 + 50 + 23 = 123. Но приёмка опирается ещё и на предпосылки: получен признак конца, ключи сопоставлены с известным тестовым набором, все объекты подтверждены приёмником. Без этих условий таблица показывает только счётчики выполнения.

Проверьте два управляемых отказа: перед сохранением второй страницы и после её сохранения, но до фиксации контрольной точки. После перезапуска должны остаться те же 123 уникальных объекта, а не 73 из-за преждевременно сдвинутой точки и не 173 из-за повторного добавления пятидесяти строк. Эти тесты проверяют сохранение прогресса, а не только первый успешный проход.

Как расследовать отсутствие конкретной записи

Выберите один известный объект, который должен был попасть в выгрузку, и проверьте его путь. Соответствовал ли он условиям в момент чтения? Был ли доступен пользователю интеграции? Попал ли в сырой массив ответа? Прошёл ли преобразование? Получил ли подтверждение приёмника? Такой разбор локализует потерю быстрее, чем повторный запуск всей базы без изменения диагностики.

Если объект есть в ответе, ищите проблему в преобразовании типов, обязательных полях, фильтрации после загрузки или записи результата. Например, пропуск записи с неизвестным статусом должен быть видимым результатом обработки, а не молчаливым исключением из счётчика.

Если объекта нет ни на одной странице, проверяйте условия источника и границы обхода. Сохранённые параметры, последовательность указателей, времена запросов и безопасные ключи позволяют воспроизвести ситуацию. Полные тела с клиентскими данными для обычной диагностики чаще всего не нужны; доступ к подробным материалам ограничивайте задачей и ответственными.

Что включить в приёмку полной выгрузки

Проверяйте интеграцию на небольшом известном наборе, который заставляет перейти через границу страницы. Один объект или пустая база не выявляют отсутствие пагинации. Затем добавьте отказные ситуации и изменения источника, отдельно обозначив, какие гарантии выбранный API действительно предоставляет.

  • Набор больше одной страницы получен с теми же фильтрами и правами.
  • Список извлекается из правильного поля, ошибки не превращаются в пустую страницу.
  • Условие завершения соответствует конкретному режиму API.
  • Повтор указателя и предохранительное ограничение завершаются статусом ошибки, а не успеха.
  • Повторная обработка после сбоя не создаёт дублей и не пропускает сохранение.
  • Сверка учитывает уникальные ключи, ошибки обработки и подтверждение приёмника.
  • Изменения источника, недействительный курсор и неподходящий next URL обрабатываются предусмотренным способом.

Для рабочих запусков сохраняйте итоговый отчёт: условия, время начала и завершения, количество страниц, уникальных объектов, ошибок и причину остановки. Полезный статус «завершено» должен означать выполнение согласованных критериев, а не отсутствие необработанного исключения в программе.

Внешнюю HTTP-доступность сайта можно дополнительно наблюдать через SiteGuard. Полноту API-выгрузки команда подтверждает собственными счётчиками и сверкой данных: доступный веб-узел и завершённый обмен отвечают на разные рабочие вопросы.