Руководства

Синхронизация данных

Доступ для AI:

Синхронизация нужна, когда отзывы живут не только у нас, но и в вашей базе: в CRM, в хранилище, в собственной аналитике. Метод – GET /v3/reviews/sync.

Если своей базы нет, эта страница вам не нужна: показать отзывы на сайте умеет лента, узнать о новом – вебхук.

Цикл

cursor = db.load_cursor()                       # None при первом запуске
params = {"cursor": cursor} if cursor else {"object_id": 20, "limit": 500}

while True:
    page = httpx.get(f"{API}/reviews/sync", headers=H, params=params).json()

    for review in page["data"]:
        db.upsert_review(review)                # склейка по review["id"]

    db.save_cursor(page["next_cursor"])         # ПОСЛЕ каждой страницы
    if not page["has_next"]:
        break
    params = {"cursor": page["next_cursor"]}

Первый прогон выгружает всю историю, следующие – только изменения.

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

Четыре правила

1. Курсор хранится в базе, а не в памяти процесса. Тогда следующий запуск продолжает с той же точки, а не выкачивает всё заново.

2. Сохранять после каждой страницы. Тогда обрыв связи стоит одной страницы, а не всего обхода.

3. В режиме all – UPSERT по id, не INSERT. Изменённый отзыв приходит со старым id: новой строки мы не заводим, поэтому вставка даст дубли или ошибку уникальности. В режиме new повтор возможен после смены состава объекта (см. «Границы»), поэтому UPSERT по id надёжнее и здесь. Потерять отзыв поток не может ни в одном из режимов.

4. next_cursor приходит всегда – и на последней странице, и на пустой. Признак «догнал» – это has_next: false, а не отсутствие курсора.

Что приходит

Изменением считается: правка текста или оценки на площадке, появившийся или изменившийся ответ организации, изменившийся набор фотографий, пропажа отзыва с площадки (is_deleted: true) и его возврат. Пересбор сам по себе – не изменение: если на площадке ничего не поменялось, отзыв в поток не попадёт.

modeЧто приходитКак класть к себе
all (по умолчанию)новые отзывы и измененияUPSERT по id
newтолько впервые появившиесяUPSERT по id: повтор возможен после смены состава объекта

Режим зашит в курсор: для второго режима нужен отдельный курсор.

Отдельного режима «только изменения» нет: после первого полного прохода режим all отдаёт только то, что появилось или изменилось с прошлого запроса.

Границы

  • Порядок задан режимом, и своего параметра сортировки у метода нет. В all строки идут по времени последнего изменения отзыва, в new – по времени, когда мы его впервые захватили. Дата публикации на площадке (review_date) порядок не задаёт ни там, ни там: отзыв 2019 года, у которого вчера появился ответ, придёт в all вместе со вчерашними изменениями, а не в хвосте истории. Нужен свой порядок – стройте его у себя.
  • Фильтров нет. Отзыв, который правкой перестал подходить под фильтр, пришлось бы присылать событием «выбыл» – такого события не существует, поэтому любой фильтр сделал бы поток дырявым. Отбирайте у себя.
  • Состав объекта поток не отслеживает. Убрали ссылку или выключили объект – его отзывы просто перестанут приходить, отдельного события об этом не будет. Чистите у себя по link_id. Любая смена состава – ссылку убрали, добавили или вернули, оплатили тариф после пробного периода – сбрасывает сохранённый курсор: поток проходит объект заново с начала истории. Уже полученные отзывы придут ещё раз, upsert по id их перезапишет.
  • Задержка несколько секунд. Это защита: отзыв, который прямо сейчас записывается, иначе оказался бы позади вашего курсора и не пришёл бы никогда.

Если курсор не принят

400 invalid_cursor – курсор испорчен, изменён или выдан другому аккаунту: начните обход заново, без cursor. 400 cursor_mismatch – вместе с курсором передан другой object_id, folder_id или mode: либо не передавайте их вовсе, либо передайте те же.

Полный список параметров и полей – в справочнике метода.

On this page