Синхронизация отзывов
Поток изменений: отзывы, которые появились или изменились у нас после точки, на которой вы остановились. Нужен там, где у вас своя база и её надо держать в актуальном состоянии.
Обычная лента отзывов отвечает на вопрос «покажи»,
синхронизация – на вопрос «догони, ничего не потеряв». Поэтому здесь нет ни
фильтров, ни сортировки, ни offset.
Параметры
cursorстрокаКурсор из next_cursor предыдущего ответа. С ним остальные параметры можно не передавать.
modeстрокаЧто присылать: all – новые и изменения, new – только впервые появившиеся отзывы.
limitчисло1–1000Размер страницы, 1–1000. Запекается в курсор, дальше его можно не повторять.
object_id · folder_idчислоОбъект или папка целиком. В запросе должно быть ровно одно из двух, но только в первом запросе: дальше адресат хранится в курсоре.
Ответ
dataсписок объектовОтзывы, изменившиеся после вашей позиции.
data[].idчислоИдентификатор отзыва в Rewio. По нему и склеивайте у себя.
data[].link_idчислоСсылка, с которой собран отзыв.
data[].source_idчислоПлощадка, с которой собран отзыв.
data[].source_slugстрокаможет быть nullСлаг площадки (2gis, google, yandex_maps). Отвечать можно, если совпадает с provider отзыва.
data[].authorстрокаможет быть nullИмя автора так, как его показывает площадка. Фамилии маскируются.
data[].textстрокаможет быть nullТекст отзыва.
data[].review_dateдата и времяможет быть nullКогда отзыв опубликован: в UTC, если площадка позволяет пересчитать время, иначе – как показывает площадка.
data[].rating_originalстрокаможет быть nullОценка в шкале самой площадки, как есть.
data[].ratingчисломожет быть nullТа же оценка, приведённая к шкале 1–5.
data[].review_urlстрокаможет быть nullПрямая ссылка на отзыв на площадке.
data[].reply_textстрокаможет быть nullОтвет организации на отзыв.
data[].reply_dateдата и времяможет быть nullКогда организация ответила.
data[].providerстрокаможет быть nullПлощадка, на которой отзыв написан изначально (слаг в нижнем регистре: 2gis, google, tbank, booking, tripadvisor, …). У нативного отзыва совпадает с source_slug – только на такой отзыв можно опубликовать ответ.
data[].is_replyableда/нетможет быть nullМожно ли ответить на отзыв через PUT /v3/reviews/{review_id}/reply. Приходит только на площадках, где Rewio публикует ответы (can_publish_reply в GET /v3/sources); на остальных ключа нет. true – ответы на ссылке подключены, и отзыв родной для площадки (provider пуст или равен source_slug). false – ответ вернёт ошибку: отзыв другой площадки (2ГИС показывает отзывы Netmonet, Booking, Т-Банка – 409 reply_not_replyable) или ответы на ссылке не подключены. Тариф флаг не учитывает.
data[].is_deletedда/нетОтзыв пропал с площадки. В синхронизации такие приходят всегда.
data[].is_hiddenда/нетОтзыв скрыт в рамках объекта (приходит только когда true).
data[].is_pinnedда/нетОтзыв закреплён в рамках объекта (приходит только когда true).
data[].pin_positionчисломожет быть nullПозиция закреплённого отзыва: меньше – выше.
data[].prosстрокаможет быть nullБлок «достоинства» (только при split_pros_cons=true).
data[].consстрокаможет быть nullБлок «недостатки» (только при split_pros_cons=true).
data[].our_replyобъектможет быть nullВаш ответ, отправленный через Rewio, и его состояние – то же, что в GET /v3/reviews/{review_id}/reply. null – ответа через Rewio нет или тариф без ответов. Ответ, поставленный не через Rewio, – в reply_text.
data[].our_reply.statusстрокаpending / published / failed / deletedможет быть nullЧто с вашим ответом на карточке: null – отправлен, площадке ещё не передан; pending – площадка приняла, на карточке ещё не видели (проверяем через 15 с, 30 с, 1 мин … 4 ч); published – ваш текст стоит на карточке; deleted – вашего ответа на карточке нет: вы его удалили или он пропал (причина – в error); failed – не опубликован (почему – в error).
data[].our_reply.textстрокаТекст, который должен стоять на площадке. Пусто – ответ снимается.
data[].our_reply.submitted_atдата и времяможет быть nullКогда вы отправили этот текст (UTC).
data[].our_reply.published_atдата и времяможет быть nullКогда мы увидели ваш текст на карточке (UTC).
data[].our_reply.updated_atдата и времяКогда ответ меняли в последний раз (UTC).
data[].our_reply.errorобъектможет быть nullПочему ответ не опубликован или пропал с карточки.
data[].our_reply.error.codeстрокаМашинный код ошибки публикации.
data[].our_reply.error.messageстрокаПояснение для человека.
data[].is_skippedда/нетВы отметили отзыв «Пропустить» (PUT /v3/reviews/{review_id}/skip). На тарифе без ответов всегда false.
data[].complaintобъектможет быть nullПоследняя жалоба на отзыв. null – жалоб нет или тариф без жалоб.
data[].complaint.statusстрокаpending / accepted / rejected / failedможет быть nullnull – отправляется на площадку; pending – на рассмотрении; accepted – отзыв удалён; rejected – отзыв остался. Подробно – GET /v3/reviews/{review_id}/complaints.
data[].complaint.filed_atдата и времяможет быть nullКогда жалоба подана (UTC).
data[].complaint.is_oursда/нетtrue – подана через Rewio; false – найдена на площадке.
next_cursorстрокаПозиция, с которой продолжить. Приходит всегда – сохраните её у себя.
has_nextда/нетЕсть ли ещё изменения прямо сейчас.
accessобъектможет быть nullОграничение глубины выдачи. Приходит, только пока оно действует.
access.reasonстрокаПочему выдача ограничена. trial – пробный доступ, manual – ограничение, согласованное по вашему договору.
access.limit_per_linkчислоСколько последних отзывов показывается по каждой ссылке (площадке объекта).
access.hidden_totalчислоСколько отзывов уже собрано сверх показанных. Считается по всему архиву и не зависит от фильтров запроса.
access.messageстрокаГотовая формулировка для показа человеку.
Ещё 14 полей – нужны реже
data[].has_imagesда/нетЕсть ли у отзыва изображения.
data[].imagesсписок объектовИзображения отзыва.
data[].images[].template_urlстрокаURL изображения на CDN площадки в исходном виде. У части площадок содержит шаблон размера ({size} или {width}/{height}) и потому не предназначен для прямой вставки – для показа берите preview или image.
data[].images[].previewстрокаможет быть nullГотовый URL уменьшенной версии (превью) для списков и сеток.
data[].images[].imageстрокаможет быть nullГотовый URL полноразмерной версии для просмотра.
data[].has_videosда/нетЕсть ли у отзыва видео.
data[].videosсписок объектовВидео отзыва.
data[].videos[].kindстрокаembed / file / hlsТип вложения: embed – встраиваемый плеер площадки (открывать в sandbox-iframe), file – прямая ссылка на видеофайл, hls – HLS-поток (.m3u8).
data[].videos[].video_urlстрокаможет быть nullURL видео или встраиваемого плеера в зависимости от kind.
data[].videos[].thumbnailстрокаможет быть nullURL кадра-заставки (превью) видео.
data[].videos[].widthчисломожет быть nullШирина видео в пикселях, если известна.
data[].videos[].heightчисломожет быть nullВысота видео в пикселях, если известна.
data[].videos[].duration_msчисломожет быть nullДлительность видео в миллисекундах, если известна.
data[].deleted_atдата и времяможет быть nullКогда мы заметили пропажу.
curl -X GET "https://api.rewio.tech/v3/reviews/sync?object_id=20"{ "data": [ { "id": 143046, "link_id": 177, "source_id": 1, "author": "Сергей", "text": "Замечательно. Приеду ещё. ", "review_date": "2026-07-21T18:07:03", "rating_original": "5", "rating": 5, "review_url": "https://yandex.ru/maps/org/1020542995/reviews?reviews[publicId]=u182gzp1r9rg4urew906ky9dd0", "reply_text": "Уважаемый Гость,\nБлагодарим Вас за визит в гостиницу «Националь» и высокую оценку нашего обслуживания. Ждем Вас снова!\nС наилучшими пожеланиями,\t\nЕлена Позолотина\nДиректор по операционной деятельности.\n", "reply_date": "2026-07-23T13:27:07", "has_images": true, "images": [ { "template_url": "https://avatars.mds.yandex.net/get-altay/17743308/2a0000019f85dc34d7ee3b24b4b9ec82bdbd/{size}", "preview": "https://avatars.mds.yandex.net/get-altay/17743308/2a0000019f85dc34d7ee3b24b4b9ec82bdbd/M", "image": "https://avatars.mds.yandex.net/get-altay/17743308/2a0000019f85dc34d7ee3b24b4b9ec82bdbd/XXXL" }, { "template_url": "https://avatars.mds.yandex.net/get-altay/18473509/2a0000019f85dc42d3b7bbf4e10e375c612e/{size}", "preview": "https://avatars.mds.yandex.net/get-altay/18473509/2a0000019f85dc42d3b7bbf4e10e375c612e/M", "image": "https://avatars.mds.yandex.net/get-altay/18473509/2a0000019f85dc42d3b7bbf4e10e375c612e/XXXL" }, { "template_url": "https://avatars.mds.yandex.net/get-altay/20191917/2a0000019f85dc255b9c227cfbc55fc57724/{size}", "preview": "https://avatars.mds.yandex.net/get-altay/20191917/2a0000019f85dc255b9c227cfbc55fc57724/M", "image": "https://avatars.mds.yandex.net/get-altay/20191917/2a0000019f85dc255b9c227cfbc55fc57724/XXXL" } ], "has_videos": false, "videos": [] }, { "id": 143051, "link_id": 177, "source_id": 1, "author": "Марина", "text": "Номер не соответствовал описанию.", "review_date": "2026-07-19T09:14:00", "rating_original": "2", "rating": 2, "review_url": "https://yandex.ru/maps/org/1020542995/reviews?reviews[publicId]=u182gzp1r9rg4urew906ky9dd0", "has_images": false, "images": [], "has_videos": false, "videos": [], "is_deleted": true, "deleted_at": "2026-08-23T04:12:07" } ], "next_cursor": "eyJhIjoiMjAyNi0wOC0yM1QxNDowMzoxMSIsImQiOjE0MzA1MSwiaSI6MjAsImwiOjEwMCwibSI6ImFsbCIsInQiOiJnIiwidSI6MzAsInYiOjF9.k3Qw9x0nJ8Zr5wQfB2vLZA", "has_next": true}Как это работает
Первый запрос – с адресом объекта, дальше достаточно одного cursor:
GET /v3/reviews/sync?object_id=20&limit=200
→ 200 отзывов, next_cursor: "eyJ…", has_next: true
GET /v3/reviews/sync?cursor=eyJ…
→ следующие 200, next_cursor: "eyJ…", has_next: true
…
→ has_next: false — вы догнали текущее состояниеСохраните последний next_cursor у себя и вернитесь с ним завтра – придёт
только то, что изменилось за сутки.
cursor = load_cursor() # None при первом запуске
params = {"cursor": cursor} if cursor else {"object_id": 20, "limit": 200}
while True:
page = get("/v3/reviews/sync", params=params).json()
for review in page["data"]:
upsert(review) # склейка по review["id"]
cursor = page["next_cursor"]
save_cursor(cursor) # сохраняем ПОСЛЕ каждой страницы
if not page["has_next"]:
break
params = {"cursor": cursor}Курсор – это закладка, а не сохранённая выдача: он не устаревает и его можно хранить сколько угодно. Обрыв связи стоит одной страницы, а не всего обхода. Внутрь заглядывать не нужно и не получится – устройство курсора мы оставляем за собой, чтобы менять его, не ломая вашу интеграцию.
Один отзыв может прийти дважды
Если отзыв изменится, пока вы читаете страницы, он придёт ещё раз – уже с новым
содержимым и с тем же id: новой строки мы не заводим. Поэтому в режиме
all кладите к себе UPSERT по id, а не INSERT – иначе дубли или ошибка
уникальности. В режиме new повтор возможен после смены состава объекта (см. «Границы»), поэтому и здесь надёжнее UPSERT по id.
Потерять отзыв поток не может: это и есть его единственная твёрдая гарантия.
Что считается изменением
Правка текста или оценки на площадке, появившийся или изменившийся ответ
организации, изменившийся набор фотографий и видео, пропажа отзыва с площадки
(is_deleted: true) и обратное восстановление. Пересбор сам по себе изменением
не считается: если на площадке ничего не поменялось, отзыв в поток не попадёт.
Два режима
mode | Что приходит | Повторы | Как класть к себе |
|---|---|---|---|
all (по умолчанию) | новые отзывы и изменения | возможны | UPSERT по id |
new | только впервые появившиеся отзывы | после смены состава объекта | UPSERT по id |
Режим запекается в курсор: курсор одного режима не подходит другому – у них разные оси. Если нужны оба потока сразу, держите два курсора, это нормально.
mode=new удобен, когда отзывы уходят в CRM или в оповещения: правки и пропажи
вас не интересуют, а повторы бывают только после смены состава объекта.
Первый обход – всегда с начала истории
Переключателя «начать с сегодняшнего дня» нет: первый запрос отдаёт самые давние записи, и обход идёт до конца. Синхронизация – это сперва полная копия, потом приращения.
Если полная копия вам не нужна и интересны только новые отзывы по мере появления, используйте вебхуки: они и присылают только новое, без архива.
Свежесть
Изменения появляются в потоке с задержкой в несколько секунд. Это не запаздывание сбора, а защита от потери: отзыв, который в этот момент записывается, иначе оказался бы позади вашего курсора и не пришёл бы никогда.
Опрашивать чаще раза в минуту смысла нет – отзывы на площадках так быстро не появляются. Практичный режим для актуальной копии: раз в 5–15 минут.
Границы
- Об убранных ссылках синхронизация не сообщает. Убрали ссылку из объекта,
выключили объект или перенесли его – отзывы по нему просто перестанут
приходить, отдельного события об этом не будет. Такие строки чистите у себя
по
link_id. Любая смена набора ссылок (добавили, убрали, выключили, вернули) сбрасывает курсор: следующий запрос отдаёт все отзывы с начала. - Скрытые и закреплённые отзывы приходят обычными строками, без флагов
is_hiddenиis_pinned: скрытие и закрепление – настройка витрины объекта, а не свойство отзыва, и в поток изменений они не попадают. - Ограниченная выдача работает здесь ровно так же, как в ленте: не больше
access.limit_per_linkпоследних отзывов на каждую площадку объекта (на пробном доступе – 20), и в ответе появляется блокaccess. Пропажи отзывов, оставшихся за этой границей, в поток не попадают.
Ошибки курсора
| Статус | code | Когда |
|---|---|---|
400 | invalid_cursor | Курсор не читается: испорчен, изменён или выдан другому аккаунту. Начните обход заново, без cursor. |
400 | cursor_mismatch | Вместе с курсором передан object_id, folder_id или mode, не совпадающий с тем, для которого курсор выдан. Либо не передавайте их, либо передайте те же. |
Остальные коды общие для всего API и описаны на странице Ошибки.