Reviews
A review is one customer review on one of your connected locations, normalized to the same JSON shape on every platform. Prisma imports reviews when a location is connected and then checks for new and edited ones on a schedule set by the platform and your plan (see Platforms). You read them with two endpoints, and you get a webhook when one is created or updated.
The review object
{
"id": "rev_01KJ8Q2M4T7HX3VB9CWD6NRZ5E",
"platform": "google",
"location_id": "loc_01KJ8P9W2C4D6F8G0H2J4K6M8N",
"rating": 4,
"title": null,
"text": "Great flat white, a bit slow at lunchtime.",
"author": "Marta G.",
"language": "en",
"url": null,
"created_at": "2026-10-19T12:41:07.000Z",
"updated_at": "2026-10-19T12:41:07.000Z",
"reply": {
"text": "Thanks Marta! We have added a second barista at lunch.",
"created_at": "2026-10-21T09:02:11.000Z",
"status": "published",
"error": null
}
}| Field | Type | Description |
|---|---|---|
id | string | Prisma review ID (rev_…). Stable while the location stays connected. |
platform | enum | google, app_store, google_play, judge_me, trustpilot, yelp, tripadvisor, booking, yotpo, reviews_io, g2 |
location_id | string | The location the review belongs to. |
rating | integer | null | 1 to 5 stars. null if the platform gave no rating. |
title | string | null | Review title, on platforms that have one (App Store, Trustpilot, Judge.me…). |
text | string | null | Review body. null for rating-only reviews. |
author | string | null | Display name as shown by the platform. |
language | string | null | Language code when the platform provides one. |
url | string | null | Public link to the review when the platform provides one. On read-only platforms (Yelp, Tripadvisor, Booking.com, Yotpo, REVIEWS.io, G2) it is always set: the link to answer the review on the platform, which for some platforms is the listing or product page. |
created_at | timestamp | When the review was written on the platform. |
updated_at | timestamp | When it was last edited on the platform. |
reply | object | null | The business reply, or null if there is none. |
The reply object
| Field | Type | Description |
|---|---|---|
text | string | Reply text. |
status | enum | published (live on the platform), queued (sent through Prisma, waiting to be published), failed (the platform refused it; see error). |
created_at | timestamp | null | When the reply was published. null while it is queued. |
error | string | null | Why publishing failed, when status is failed. |
A reply that appears on the platform, whoever wrote it, comes back as published. How to create, replace and delete replies is on Replies.
List reviews
GET /v1/reviews
Returns the reviews of your workspace (in the mode of your key), newest first.
| Query param | Type | Description |
|---|---|---|
location_id | string | Only reviews of this location. Omit to list across all locations. |
platform | enum | Only reviews from this platform (one of the values above). |
since | ISO 8601 | Only reviews written at or after this time, by created_at. Either a date (2026-10-01, meaning midnight UTC) or a full timestamp with time zone offset (2026-10-01T00:00:00Z, 2026-10-01T02:00:00+02:00). |
has_reply | true | false | true: reviews with a reply in any status. false: reviews without one. |
limit | integer | Page size, 1 to 100. Default 50. |
cursor | string | The next_cursor of the previous page. |
curl "https://api.prismareviews.com/v1/reviews?location_id=loc_01KJ8P9W2C4D6F8G0H2J4K6M8N&has_reply=false&limit=20" \
-H "Authorization: Bearer $PRISMA_API_KEY"const params = new URLSearchParams({
location_id: "loc_01KJ8P9W2C4D6F8G0H2J4K6M8N",
has_reply: "false",
limit: "20",
});
const res = await fetch("https://api.prismareviews.com/v1/reviews?" + params, {
headers: { Authorization: "Bearer " + process.env.PRISMA_API_KEY },
});
const { data, next_cursor } = await res.json();
for (const review of data) console.log(review.rating, review.author, review.text);import os
import requests
resp = requests.get(
"https://api.prismareviews.com/v1/reviews",
params={"location_id": "loc_01KJ8P9W2C4D6F8G0H2J4K6M8N", "has_reply": "false", "limit": 20},
headers={"Authorization": f"Bearer {os.environ['PRISMA_API_KEY']}"},
timeout=30,
)
resp.raise_for_status()
for review in resp.json()["data"]:
print(review["rating"], review["author"], review["text"])Response 200
{
"data": [
{
"id": "rev_01KJ8Q2M4T7HX3VB9CWD6NRZ5E",
"platform": "google",
"location_id": "loc_01KJ8P9W2C4D6F8G0H2J4K6M8N",
"rating": 4,
"title": null,
"text": "Great flat white, a bit slow at lunchtime.",
"author": "Marta G.",
"language": "en",
"url": null,
"created_at": "2026-10-19T12:41:07.000Z",
"updated_at": "2026-10-19T12:41:07.000Z",
"reply": null
}
],
"next_cursor": "MjAyNi0xMC0xOVQxMjo0MTowNy4wMDBafHJldl8wMUtKOFEyTTRUN0hYM1ZCOUNXRDZOUlo1RQ"
}Paging through every review
Repeat the call with cursor set to the last next_cursor, keeping the same filters, until next_cursor is null.
let cursor = null;
do {
const params = new URLSearchParams({ limit: "100" });
if (cursor) params.set("cursor", cursor);
const res = await fetch("https://api.prismareviews.com/v1/reviews?" + params, {
headers: { Authorization: "Bearer " + process.env.PRISMA_API_KEY },
});
const page = await res.json();
for (const review of page.data) console.log(review.id);
cursor = page.next_cursor;
} while (cursor);import os
import requests
cursor = None
while True:
params = {"limit": 100}
if cursor:
params["cursor"] = cursor
page = requests.get(
"https://api.prismareviews.com/v1/reviews",
params=params,
headers={"Authorization": f"Bearer {os.environ['PRISMA_API_KEY']}"},
timeout=30,
).json()
for review in page["data"]:
print(review["id"])
cursor = page["next_cursor"]
if not cursor:
breaksince filters by when the review was written, not when it was edited. To keep a local copy in sync with edits, listen for review.updated webhooks and fetch the review again.
Get a review
GET /v1/reviews/{id}
curl https://api.prismareviews.com/v1/reviews/rev_01KJ8Q2M4T7HX3VB9CWD6NRZ5E \
-H "Authorization: Bearer $PRISMA_API_KEY"const res = await fetch(
"https://api.prismareviews.com/v1/reviews/rev_01KJ8Q2M4T7HX3VB9CWD6NRZ5E",
{ headers: { Authorization: "Bearer " + process.env.PRISMA_API_KEY } }
);
console.log(await res.json());resp = requests.get(
"https://api.prismareviews.com/v1/reviews/rev_01KJ8Q2M4T7HX3VB9CWD6NRZ5E",
headers={"Authorization": f"Bearer {os.environ['PRISMA_API_KEY']}"},
timeout=30,
)
print(resp.json())Returns 200 with one review object. If no review with that ID exists in your workspace and mode, you get 404 resource_not_found.
Good to know
- History. On the first sync Prisma imports up to 90 days of history on Spark, 365 days on Beam and everything the platform returns on Spectrum and Aurora. Some platforms return less: the Google Play API only returns reviews from the last 7 days, so the history is what Prisma has stored since you connected.
- Disconnected locations. When you delete a connection, its reviews stay readable until they are deleted 30 days later.
- Errors.
422 invalid_requestfor an unknownplatform, asincethat is neither a date nor a timestamp with offset, alimitout of range or a badcursor. Themessagenames the parameter. All codes are on Errors.
Read your reviews from every platform in one call.
2 locations free, then plans from €49 a month.