# Reviews

List Google Business Profile and Facebook reviews in one feed, filter by rating, reply, and react to new, edited and removed reviews by webhook.

Reviews from Google Business Profile locations and Facebook Pages land in one list. You can filter it by rating and reply status, answer from the API, and get a webhook the moment a Google review is posted, edited or removed.

## List reviews

```bash cURL
curl "https://api.pozy.ai/v1/inbox/reviews?profileId=6650c1e2a3b4c5d6e7f80911&maxRating=3&hasReply=false" \
  -H "Authorization: Bearer $POZY_API_KEY"
```
```ts Node
const res = await fetch("https://api.pozy.ai/v1/inbox/reviews?profileId=6650c1e2a3b4c5d6e7f80911&maxRating=3&hasReply=false", {
  headers: { Authorization: `Bearer ${process.env.POZY_API_KEY}` },
});
const data = await res.json();
if (!res.ok) throw new Error(data.error);

for (const r of data.data) {
  console.log(r.platform, r.locationName, r.rating, r.text);
}
```
```python Python
import os
import requests

resp = requests.get(
    "https://api.pozy.ai/v1/inbox/reviews",
    headers={"Authorization": f"Bearer {os.environ['POZY_API_KEY']}"},
    params={"profileId": "6650c1e2a3b4c5d6e7f80911", "maxRating": 3, "hasReply": "false"},
    timeout=30,
)
for r in resp.json()["data"]:
    print(r["platform"], r["rating"], r["text"])
```

```json
{
  "id": "accounts/1023/locations/4567/reviews/AbCdEf123",
  "platform": "googlebusiness",
  "accountId": "6650c1e2a3b4c5d6e7f80a22",
  "locationName": "Acme Coffee, Gran Via",
  "reviewer": { "id": null, "name": "Marta P.", "profileImage": null },
  "rating": 2,
  "text": "Great coffee, but we waited 20 minutes.",
  "created": "2026-10-28T18:42:00Z",
  "hasReply": false,
  "hasPhotos": false,
  "reply": null,
  "reviewUrl": "https://maps.google.com/?cid=1234567890"
}
```

| Parameter | What it does |
| --- | --- |
| `profileId`, `accountId` | One customer profile or one location/Page |
| `platform` | `googlebusiness` or `facebook` |
| `minRating`, `maxRating` | Star range, 1 to 5 |
| `hasReply` | `false` gives you the queue still waiting for an answer |
| `sortBy`, `sortOrder` | `date` (default) or `rating`, `desc` or `asc` |
| `limit`, `cursor` | Up to 50 per page |

Facebook recommendations have no stars: they come with `recommendationType` set to `positive` or `negative` instead of a numeric `rating`.

Each account's reviews are read from the platform within a fixed time budget per request and cached for up to a minute, so a location with thousands of reviews can come back truncated. Use the webhooks below to stay current and the list to backfill.

## Reply

```bash cURL
curl -X POST "https://api.pozy.ai/v1/inbox/reviews/accounts%2F1023%2Flocations%2F4567%2Freviews%2FAbCdEf123/reply" \
  -H "Authorization: Bearer $POZY_API_KEY" \
  -H "Content-Type: application/json" \
  -H "Idempotency-Key: 6a2e9b10-77f1-4b6a-9d3c-0c5e8f2a4b71" \
  -d '{
    "accountId": "6650c1e2a3b4c5d6e7f80a22",
    "message": "Thanks Marta, and sorry about the wait. We have added a second barista at lunchtime."
  }'
```
```ts Node
import { randomUUID } from "node:crypto";

// Google review ids contain slashes: encode the id so it stays one path segment
const reviewId = encodeURIComponent("accounts/1023/locations/4567/reviews/AbCdEf123");
const res = await fetch(`https://api.pozy.ai/v1/inbox/reviews/${reviewId}/reply`, {
  method: "POST",
  headers: {
    Authorization: `Bearer ${process.env.POZY_API_KEY}`,
    "Idempotency-Key": randomUUID(),
    "Content-Type": "application/json",
  },
  body: JSON.stringify({
    accountId: "6650c1e2a3b4c5d6e7f80a22",
    message: "Thanks Marta, and sorry about the wait. We have added a second barista at lunchtime.",
  }),
});
if (!res.ok) throw new Error((await res.json()).error);
```
```python Python
import os, uuid
from urllib.parse import quote

import requests

review_id = "accounts/1023/locations/4567/reviews/AbCdEf123"
resp = requests.post(
    f"https://api.pozy.ai/v1/inbox/reviews/{quote(review_id, safe='')}/reply",
    headers={"Authorization": f"Bearer {os.environ['POZY_API_KEY']}", "Idempotency-Key": str(uuid.uuid4())},
    json={"accountId": "6650c1e2a3b4c5d6e7f80a22", "message": "Thanks Marta, and sorry about the wait."},
    timeout=30,
)
print(resp.json())
```

Google review ids contain slashes, so URL-encode them in the path. To remove a reply, call `DELETE /v1/inbox/reviews/{reviewId}/reply` with the `accountId`; that works on Google Business Profile only.

`Idempotency-Key` works as for comments: the same key and body within 24 hours replays the first response, a different body answers `422`.

> **Write replies people will read:**
> 
> Answer the specific complaint, name what changes, and keep it short. Public replies are part of the listing that the next customer reads.

## Review webhooks

Google Business Profile reviews are reported in real time:

| Event | When |
| --- | --- |
| `review.new` | A new review was posted |
| `review.updated` | The reviewer edited text or rating, or a reply was added (through Pozy or Google's own tools) |
| `review.deleted` | Google stopped returning the review, for example after its spam filter removed it |
| `review.restored` | A review reported as deleted came back |

`review.deleted` is detected by checking, so it usually arrives 6 to 12 hours after the review disappears, and only for locations covered by a webhook subscribed to `review.deleted` or `review.restored`. It can name a review you never received `review.new` for; ignore ids you do not know.

## Google-specific management

For one location's reviews with Google's own paging and batch reads, use the [Google Business Reviews](https://pozy.ai/docs/google-business/reviews) endpoints under `/v1/accounts/{accountId}/gmb-reviews`.

## Endpoints

| Endpoint | What it does |
| --- | --- |
| [`GET /v1/inbox/reviews`](https://pozy.ai/docs/api/listInboxReviews) | List reviews |
| [`POST /v1/inbox/reviews/{reviewId}/reply`](https://pozy.ai/docs/api/replyToInboxReview) | Reply to review |
| [`DELETE /v1/inbox/reviews/{reviewId}/reply`](https://pozy.ai/docs/api/deleteInboxReviewReply) | Delete review reply |

## Webhook events

| Event | When it fires |
| --- | --- |
| [`review.new`](https://pozy.ai/docs/webhooks/events#review-new) | Review new. |
| [`review.updated`](https://pozy.ai/docs/webhooks/events#review-updated) | Review updated. |
| [`review.deleted`](https://pozy.ai/docs/webhooks/events#review-deleted) | Review deleted. |
| [`review.restored`](https://pozy.ai/docs/webhooks/events#review-restored) | Review restored. |
