Updated Oct 2026
Review analytics by API: average rating, reply rate, response time, trends
Every review dashboard answers the same five questions: what’s our rating, how is it moving, how many reviews do we get, how many do we answer, and how fast. Computing that across Google, Trustpilot, the App Store and the rest means normalising five rating scales and tracking replies you didn’t send through your tool. This guide does it with one endpoint, GET /v1/stats, then builds a per-location report and a feed for Looker Studio or Google Sheets. Reference: stats.
1. The stats object
curl "https://api.prismareviews.com/v1/stats?since=2026-07-01&until=2026-10-01" \
-H "Authorization: Bearer $PRISMA_API_KEY"{
"since": "2026-07-01T00:00:00.000Z", "until": "2026-10-01T00:00:00.000Z", "location_id": null, "platform": null,
"reviews": 412, "average_rating": 4.31, "ratings": {"1": 18, "2": 21, "3": 35, "4": 97, "5": 241},
"replied": 268, "reply_rate": 0.65, "median_reply_hours": 19.4, "unreplied_negative": 11,
"by_month": [
{"month": "2026-07", "reviews": 131, "average_rating": 4.22, "replied": 80},
{"month": "2026-08", "reviews": 140, "average_rating": 4.35, "replied": 96},
{"month": "2026-09", "reviews": 141, "average_rating": 4.36, "replied": 92}
]
}What each field means, and the traps:
average_ratingis over 1-to-5 ratings only; reviews without a rating count inreviewsbut not here. Booking’s 10-point scores, Checkatrade’s 10, Steam’s thumbs and Facebook’s recommendations are already mapped to 5 stars, so the average is comparable across platforms.repliedcounts published replies whoever wrote them, through Prisma or on the platform; queued and failed replies don’t count. So the reply rate reflects reality, not your tool’s activity.median_reply_hoursis the median between review and published reply; it ignores reviews without a dated reply.unreplied_negativeis the list to work first: 1- and 2-star reviews with no published reply.- Filter with
location_idorplatform; the period is by when the review was written (created_at),sinceinclusive,untilexclusive, default last 12 months.
2. A report per location
pip install requestsimport os, requests
API = "https://api.prismareviews.com/v1"
H = {"Authorization": f"Bearer {os.environ['PRISMA_API_KEY']}"}
PERIOD = {"since": "2026-07-01", "until": "2026-10-01"}
locations = requests.get(f"{API}/locations", headers=H, params={"limit": 100}, timeout=30).json()["data"]
rows = []
for loc in locations:
s = requests.get(f"{API}/locations/{loc['id']}/stats", headers=H, params=PERIOD, timeout=30).json()
rows.append((loc["name"], loc["platform"], s["reviews"], s["average_rating"], s["reply_rate"], s["median_reply_hours"], s["unreplied_negative"]))
rows.sort(key=lambda r: (r[6], -(r[3] or 0)), reverse=True) # most unreplied negatives first
print(f"{'Location':30} {'Platform':12} {'Reviews':>7} {'Avg':>5} {'Reply%':>7} {'Median h':>9} {'Neg open':>8}")
for name, platform, n, avg, rr, med, neg in rows:
print(f"{name[:30]:30} {platform:12} {n:7} {avg or 0:5.2f} {100*(rr or 0):6.0f}% {med or 0:9.1f} {neg:8}")Per platform instead of per location: call GET /v1/stats?platform=google once per platform id from GET /v1/platforms.
3. Month-over-month trend
by_month is already there; the only arithmetic is the delta:
s = requests.get(f"{API}/stats", headers=H, params={"since": "2025-10-01"}, timeout=30).json()
prev = None
for m in s["by_month"]:
delta = "" if prev is None or m["average_rating"] is None or prev["average_rating"] is None else f"{m['average_rating'] - prev['average_rating']:+.2f}"
print(m["month"], m["reviews"], m["average_rating"], f"{m['replied']}/{m['reviews']}", delta)
prev = mA falling average with rising volume usually means one location, not the brand: run section 2 for that month to find it.
4. Feed a dashboard: Looker Studio or Google Sheets
Looker Studio reads Google Sheets natively, so the simplest pipeline is a sheet refreshed on a schedule. In Apps Script, with the key in Script properties:
function refreshStats() {
const key = PropertiesService.getScriptProperties().getProperty("PRISMA_API_KEY");
const h = { Authorization: "Bearer " + key };
const sheet = SpreadsheetApp.getActiveSpreadsheet().getSheetByName("Stats");
sheet.clear(); sheet.appendRow(["location", "platform", "reviews", "average_rating", "reply_rate", "median_reply_hours", "unreplied_negative"]);
const locs = JSON.parse(UrlFetchApp.fetch("https://api.prismareviews.com/v1/locations?limit=100", { headers: h }).getContentText()).data;
for (const l of locs) {
const s = JSON.parse(UrlFetchApp.fetch(`https://api.prismareviews.com/v1/locations/${l.id}/stats?since=2026-01-01`, { headers: h }).getContentText());
sheet.appendRow([l.name, l.platform, s.reviews, s.average_rating, s.reply_rate, s.median_reply_hours, s.unreplied_negative]);
}
}Add a daily time-driven trigger and point Looker Studio at the sheet. For a warehouse, the same loop writes rows through your loader; by_month gives the series without recomputing from raw reviews. Raw reviews for deeper analysis: Google reviews to Google Sheets.
Honest limits
- Stats cover the locations you’ve connected and the reviews Prisma has synced; a location connected yesterday has yesterday’s history on official APIs and whatever the public page shows elsewhere.
- Google reviews come from the Google Maps listing today, read-only, while Google reviews Prisma’s Business Profile API application.
- Public-page platforms are read every 6 to 24 hours by plan, so “today” is approximate there.
- Ratings mapped from other scales (10-point, thumbs) are rounded; keep the original from the review object if you report on it.
FAQ
How do I calculate a reply rate across review platforms?
Count reviews with a published reply, whoever wrote it, divided by reviews written in the period. GET /v1/stats returns it as reply_rate per workspace, location or platform, with replied and reviews so you can recompute it.
What’s a good median reply time for reviews?
Under 24 hours for negative reviews is the target most multi-location operators use; the median_reply_hours field in the stats object gives you the actual number per location so you can set it from your own data.
Can I get review stats per month?
Yes. The stats object includes by_month: one entry per calendar month with reviews, average rating and replies, oldest first, for any period you request with since and until.
Five numbers, every platform, one call.
2 locations free. Test keys return sample stats, so the report runs today.