Prisma Reviews / Guides / Review data best practices
Best practices for handling review data via API and webhooks
Pulling reviews into your own product looks simple: call an API, save the rows, show them. The problems come later. A webhook arrives twice and a review is duplicated. A retry posts the same reply two times on Google. An edited 1-star review stays 1 star in your database after the customer changed it to 4. This guide collects the practices that avoid those problems, whatever reviews API you use. The examples use Prisma, where one JSON format covers 84 platforms, but the rules are the same with each platform’s own API.
1. Key every review on the platform’s id, and upsert
Each review needs one stable identifier. Use the id the API gives you as the primary key, and write with an upsert: insert the first time, update it every time after. Don’t build a key from the text, the author name or the date. Authors share names, texts get edited and dates get corrected.
Keep the platform and the location next to the id, so you can filter and delete by either. The Airtable guide shows an upsert on a Review ID field. The Google Sheets guide keeps a review export in a sheet.
2. Treat webhooks as a signal, then fetch the current state
A webhook tells you that something changed. It is not the best place to read what changed. Deliveries can be retried, so the same event can arrive twice. They can also arrive out of order, so an older update can land after a newer one.
The safe pattern:
- Verify the signature (next section).
- Store the event id and stop if you have already processed it.
- Answer
2xxquickly, before doing slow work. - Fetch the review with
GET /v1/reviews/{id}and upsert what the API returns.
Prisma’s webhooks carry ids only for this reason: a late event can’t overwrite newer data, because you always read the current review.
3. Verify every webhook signature
Anyone can send a POST to a public URL. Check the signature on every delivery before you trust it. With Prisma, the Prisma-Signature header holds a timestamp and an HMAC-SHA256 of the timestamp and the raw body, signed with your endpoint’s secret.
- Compute the HMAC over the raw body, before parsing JSON.
- Compare in constant time.
- Reject events whose timestamp is more than 5 minutes from your clock, to stop replays.
- Keep the secret in your secrets manager, never in the code.
4. Backfill once, then sync from webhooks
When a location is connected, read its history once with the list endpoint and cursor pagination, then rely on webhooks for what comes next. Keep the same filters on every page and stop when the API returns no next cursor. The reviews reference has the loop in JavaScript and Python.
Run a light reconciliation now and then, for example a daily read of the last few days with since. It catches anything your endpoint missed while it was down, and the upsert makes it harmless to read a review twice.
Know each platform’s limits. Google Play’s API only returns reviews from the last 7 days, so history before you connect is lost for good (why). Yelp’s public API returns 3 excerpts. Write down what “complete” means for each platform you show.
5. Handle edits and replies as updates, not new rows
Customers edit reviews, and businesses answer them on the platform itself. Both should update the existing row. Listen for review.updated, fetch the review again and overwrite rating, text, reply and updated_at. Never assume the first rating is final: a review that went from 1 to 4 stars is one of the best things that can happen to a business, and your reports should show it.
6. Make replies idempotent and track their status
Posting a reply is the one call that changes something in public. Make it safe to retry:
- Send an
Idempotency-Keywith every reply, generated once and stored with the reply. A retry with the same key returns the first response instead of posting again (replies reference). - Treat a reply as a state, not a single event: queued, then published or failed. Show that state to the person who wrote it.
- Listen for
reply.publishedandreply.failed. A failed reply needs a person, not an automatic retry with new text. - Keep platform limits in the form, not in an error message. eBay allows 80 characters, Google Play 350, and Huawei AppGallery 800.
If an AI drafts the answers, keep a person in the loop who approves each one. Prisma never writes replies itself. It publishes the text you send. The AI agents guide covers guardrails for this.
7. Watch sync health, not only new reviews
No new reviews can mean a quiet week or a broken connection. Tell them apart. Prisma returns a sync object on every location with failed checks in a row and the last error, and sends location.sync_failed after 3 failures in a row and location.sync_recovered when it works again. A connection that needs signing in again sends connection.updated. Alert on these instead of on silence.
Respect rate limits on your side too. On a 429, wait the seconds in Retry-After and retry. Platform limits are queued and retried by Prisma and never reach you as 429 (errors).
8. Keep personal data to what you need
A review carries personal data: at least the author’s name, sometimes a photo or a location. Under the GDPR and similar laws you need a reason to keep it and a limit on how long.
- Store only the fields you use.
- Delete the reviews of a location when you stop managing it. Prisma deletes them 30 days after a connection is removed.
- Honour deletion requests from the people who wrote the reviews.
- Only read the reviews of businesses and apps you own or manage. Reading competitors’ reviews through someone else’s account breaks platform terms and, often, the law.
The security page explains how Prisma stores tokens and what it deletes, and the DPA covers Prisma as your processor.
Checklist
| Practice | Why |
|---|---|
| Review id as primary key, upsert | No duplicates from retries or backfills |
| Verify signature, dedupe by event id | No forged or repeated events |
| Fetch after the webhook | No stale data from late events |
| Backfill once, reconcile daily | Nothing lost while your endpoint was down |
review.updated updates the row | Edited ratings and new replies show up |
Idempotency-Key on replies | No double replies in public |
| Alert on sync failures | A broken connection isn’t mistaken for a quiet week |
| Retention and deletion rules | GDPR and platform terms |
FAQ
Should I store the whole review from the webhook?
No. Treat the webhook as a signal and fetch the current review with the API. Events can arrive twice or out of order, and a late event should never overwrite newer data.
How do I avoid duplicate reviews in my database?
Use the review id from the API as the primary key and upsert: insert the first time, update every time after. Never key on text, author or date, which change or repeat.
How do I avoid posting the same reply twice?
Send an Idempotency-Key with every reply and keep it with the reply in your database. A retry with the same key returns the first response instead of replying again.
How long should I keep review data?
Only as long as you need it. Reviews include personal data such as the author’s name, so set a retention period, delete reviews of locations you no longer manage and honour deletion requests.
Skip the per-platform work
Prisma gives you one id, one JSON format and one signed webhook for reviews on 84 platforms, with idempotent replies where the platform allows them.
2 locations free · No card required · Test keys with sample data