Review Monitor
Give it a watchlist of hotels, local businesses, apps or SaaS products (their pages on Booking.com, Agoda, Trip.com, Tripadvisor, Google Maps, Google Hotels, Yelp, Google Play, the App Store, Capterra or TrustRadius) and every run returns what changed since the last one: an alert row per new 1★ or 2★ review and a summary row per entity with rating drift, 30-day vs lifetime average, owner-reply rate and lag, review velocity and, for apps, per-version rating regressions.
Sample output
One row as the API returns it. Long text is shortened here; names inside text read [name].
| Field | Value |
|---|---|
| rowType | summary |
| status | changed |
| platform | appstore |
| entityId | 618783545-us |
| input | https://apps.apple.com/us/app/slack/id618783545 |
| name | Slack |
| url | https://apps.apple.com/us/app/slack/id618783545 |
| checkedAt | 2026-10-21T22:59:28.653Z |
| previousCheckAt | 2026-10-21T22:54:50.343Z |
| rating | 4.14 |
| previousRating | 4.14 |
| ratingChange | 0 |
Call it from code or from your agent
This is the request. Small runs answer in the same call; large ones return a run ID.
curl -X POST https://scrapers-api.arcadiumdata.io/v1/scrapers/reputation-monitor/runs \
-H "Authorization: Bearer $ARCADIUM_API_KEY" \
-H "Content-Type: application/json" \
-d '{
"input": {
"startUrls": [
"https://www.booking.com/hotel/gb/the-savoy.html",
"https://www.yelp.com/biz/katzs-delicatessen-new-york",
"https://apps.apple.com/us/app/slack/id618783545"
],
"maxReviewsPerEntity": 50
}
}'What each row holds
Every row says what it is in rowType: check rows are charged, coverage and error rows are free.
The check 53 fields
| Field | Type | What it holds |
|---|---|---|
| platform | string | Source: booking, tripadvisor, googleplay, appstore, yelp, capterra or trustradius. |
| entityId | string | Native id of the entity on its source (hotel id, place id, app id, business id, product id). |
| checkedAt | string | ISO timestamp of this run's check. |
| entityName | Alert rows: name of the hotel, business, app or product. | |
| entityUrl | Alert rows: public page of the entity. | |
| reviewId | Alert rows: stable review id '<Platform>___<native id>'. | |
| reviewUrl | Alert rows: public link to the review, null when the source has none. | |
| date | Alert rows: review date (YYYY-MM-DD). | |
| title | Alert rows: review title, null when the source has none. Personal data is redacted. | |
| text | Alert rows: review text. Emails, phone numbers and names in greetings are redacted. | |
| pros | Alert rows: what the reviewer liked (Booking, Capterra, TrustRadius), null elsewhere. | |
| cons | Alert rows: what the reviewer disliked (Booking, Capterra, TrustRadius), null elsewhere. | |
| language | Alert rows: review language code when the source states it. | |
| appVersion | Alert rows: app version the review was written for (app stores), null elsewhere. | |
| ownerReplied | Alert rows: true when the owner or developer has already replied. | |
| ownerReply | Alert rows: the owner's reply text (redacted), null when there is none. | |
| changeType | Alert rows: 'new' = first seen this run; 'edited' = a known review whose rating was edited down into the alert band. | |
| status | string | Summary rows: 'baseline' (first run, history recorded, no alerts), 'changed' (new or edited reviews) or 'unchanged'. |
| name | string | Summary rows: name of the hotel, business, app or product. |
| url | string | Summary rows: public page of the entity. |
| previousCheckAt | string | Summary rows: ISO timestamp of the previous run with this watchlist name, null on a baseline. |
| rating | number | Rating on 1-5 (Booking and TrustRadius 1-10 scores are halved) as the source states it now. Alert rows: the review's rating. |
| previousRating | number | Summary rows: the source's average rating at the previous run. |
| ratingChange | number | Summary rows: rating minus previousRating (stars). Negative = the average went down. |
| reviewCount | number | Summary rows: review count the source states (app stores: the number of star ratings). |
| previousReviewCount | number | Summary rows: reviewCount at the previous run. |
| reviewCountChange | number | Summary rows: reviewCount minus previousReviewCount, the true number of new reviews/ratings even beyond the read limit. |
| newReviews | number | Summary rows: reviews first seen this run (0 on a baseline). |
| editedReviews | number | Summary rows: known reviews whose text or rating changed since they were seen. |
| newNegativeReviews | number | Summary rows: alert rows written for this entity this run. |
| newReviewsAvgRating | number | Summary rows: average rating of this run's new and edited reviews, null when there are none. |
| avgRating30d | number | Summary rows: average rating of the reviews dated in the last 30 days (from the remembered history). |
| previousAvgRating30d | number | Summary rows: avgRating30d at the previous run. |
| reviews7d | number | Summary rows: reviews dated in the last 7 days. |
| reviews30d | number | Summary rows: reviews dated in the last 30 days (a lower bound when windowComplete30d is false). |
| reviewsPrior30d | Summary rows: reviews dated 31-60 days ago, to compare velocity. | |
| reviewsPerWeek | number | Summary rows: review velocity, reviews30d per week. |
| avgRatingLifetime | number | Summary rows: lifetime average: the source's stated rating, or for app stores (whose rating counts silent star ratings) the average of the remembered written reviews. |
| lifetimeSource | string | Summary rows: 'site' (the source's stated average) or 'sample' (average of the remembered reviews). |
| rating30dVsLifetime | number | Summary rows: avgRating30d minus avgRatingLifetime. Negative = recent reviews are worse than usual. |
| ownerReplyRate90d | number | Summary rows: share (0-1) of the last 90 days' reviews with an owner reply; null on TrustRadius (no replies). |
| replySample90d | Summary rows: number of reviews ownerReplyRate90d is based on. | |
| medianReplyLagDays | number | Summary rows: median days from review to owner reply (Tripadvisor, Yelp, app stores); null where the source does not date replies. |
| replyLagSample | Summary rows: number of replies medianReplyLagDays is based on. | |
| unansweredNegative30d | number | Summary rows: reviews of the last 30 days at or below the alert rating without an owner reply. |
| appVersions | array | Summary rows (apps): up to 5 newest versions in the history: [{ version, reviews, avgRating, firstSeen }]. |
| versionRegression | Summary rows (apps): { version, avgRating, reviews, previousVersion, previousAvgRating, previousReviews, delta } when the newest version (5+ reviews) averages 0.5+ stars below the one before; else null. | |
| windowComplete30d | boolean | Summary rows: true when the history reaches back 30 days, so the 30-day figures are exact; false = based on the newest reviews read. |
| windowComplete60d | Summary rows: same for 60 days (reviewsPrior30d). | |
| historyReviews | number | Summary rows: reviews remembered for this entity (facts only: date, rating, reply; no text). |
| historySince | string | Summary rows: date of the oldest remembered review. |
| flags | array | Summary rows: what needs attention: new_negative, rating_drop, recent_below_lifetime, version_regression, unanswered_negative, velocity_spike. Empty on a baseline. |
| scrapedAt | Error rows: ISO timestamp of the failure. |
Coverage rows, free 1 fields
| Field | Type | What it holds |
|---|---|---|
| stopReason | string | Summary rows: why reading stopped: 'onlyNew' (reached reviews seen before), 'limit' (max reviews per entity), 'end' (no more reviews), 'budget' or 'error'. |
Error rows, free 3 fields
| Field | Type | What it holds |
|---|---|---|
| input | string | The URL you entered for this entity. |
| code | Error rows: invalid_input, not_found, blocked, unavailable or no_match. | |
| message | Error rows: what went wrong, in plain words. |
What it can't do
- It does not return reviewer names, profile links or photos.
- It reads only what the site shows to a visitor without an account.
- Reviews the site has removed or hidden are not returned.
What you send
Every field is optional. The example request above fills the ones shown here.
| Field | Type | What it does |
|---|---|---|
| startUrls | array | Example: ["https://www.booking.com/hotel/gb/the-savoy.html", "https://play.google.com/store/apps/details?id=com.Slack"]. One URL per hotel, business, app or product. Sources: Booking.com, Agoda or Trip.com hotel, Tripadvisor place, Google Hotels hotel (google.com/travel/hotels/entity/...), Google Maps place (a place link, maps.app.goo.gl link or maps.google.com/?cid=...), Google Play app, App Store app, Yelp business, Capterra product, TrustRadius product. Max 2,000. Required. |
| maxReviewsPerEntity | integer | Example: 100. Newest reviews read per entity and run; the first run uses them as history for the 30-day and reply metrics. Later runs stop at the last seen review, usually after one page. Raise it for apps with hundreds of reviews a day. 10-2,000. Also accepted as `maxReviews`, `maxItemsPerQuery` or `maxReviewsPerHotel` (other review actors; clamped to 10-2,000). Default 100. |
More options (5)
| Field | Type | What it does |
|---|---|---|
| stateKey | string | Example: `hotels-london`. Names the saved state (1-40 letters, digits or dashes), so several watchlists run side by side. Each run is compared with the last run of the same name. A new name starts a new baseline.Default "default" |
| alertMaxRating | integer | Example: 2 = one alert row per new 1★ or 2★ review. Allowed 1-4. Booking, Agoda, Trip.com and TrustRadius 1-10 scores are halved to the 1-5 scale first.Default 2 |
| language | string | Example: `en`. Google Play shows reviews per language (code such as en, de, pt-BR). Other sources return every language.Default "en" |
| country | string | Example: `us`. Two-letter storefront for Google Play, and for App Store URLs without a country.Default "us" |
| includeErrorRows | boolean | Default on. Adds a free `error` row (code + message) for every URL that could not be read or is not supported, so a failure is never silent.Default true |
Questions people ask before they top up
What does a run cost?
Each check costs $0.01, which is $10.00 per 1,000. A run that delivers rows also pays a $0.001 start fee.
Negative review alerts: $1.50 per 1,000. First check of an entity: $9.00 per 1,000.
A run that returns rows costs at least $0.005, start fee included. Failed runs, empty runs and duplicate rows cost $0. You set the most a run may cost, and it stops there.
Do you ever return personal data?
Not about reviewers or users. Reviewer names, profile links, photos, emails and phone numbers are not collected. When a name appears inside a review or a reply, it is replaced with [name].
Job titles and company sizes stay where a site shows them, because they describe a role rather than a person. On YouTube, channel names and URLs are the publisher labels YouTube shows publicly.
How fresh is the data?
Each run reads the live site when you start it, so rows are as current as the site itself.
More from Reviews
Rating, sub-ratings, pros, cons, tenure, current or former employee
$3.00per 1,000 reviews
Score, pros, cons, traveler type, room, nights, hotel reply
$1.00per 1,000 reviews
Rating, title, text, sub-ratings, trip type, owner reply
$0.75per 1,000 reviews
Rating, room, service and location scores, translation, reply
$0.50per 1,000 reviews
Score, text, translation, traveler type, room, nights, reply
$1.00per 1,000 reviews
Rating, text, language, reactions, owner reply
$0.25per 1,000 reviews