{
  "$schema": "https://json-schema.org/draft/2020-12/schema",
  "$id": "https://artifacts.apis.io/prismareviews/json-schema/prismareviews-review-schema.json",
  "title": "Review",
  "description": "One customer review, in the same shape on every platform.",
  "x-generated": "2026-11-02",
  "x-method": "derived",
  "x-generator": "derive-json-schema.py",
  "x-source": "openapi/prismareviews-openapi.json#/components/schemas/Review",
  "type": "object",
  "required": [
    "id",
    "platform",
    "location_id",
    "rating",
    "title",
    "text",
    "author",
    "language",
    "url",
    "created_at",
    "updated_at",
    "reply"
  ],
  "properties": {
    "id": {
      "type": "string",
      "description": "Review ID (`rev_…`)."
    },
    "platform": {
      "$ref": "#/$defs/PlatformId"
    },
    "location_id": {
      "type": "string",
      "description": "The location the review belongs to (`loc_…`)."
    },
    "rating": {
      "type": [
        "integer",
        "null"
      ],
      "minimum": 1,
      "maximum": 5,
      "description": "1 to 5 stars. `null` if the platform gave no rating."
    },
    "title": {
      "type": [
        "string",
        "null"
      ],
      "description": "Review title, on platforms that have one."
    },
    "text": {
      "type": [
        "string",
        "null"
      ],
      "description": "Review body. `null` for rating-only reviews."
    },
    "author": {
      "type": [
        "string",
        "null"
      ],
      "description": "Display name as shown by the platform."
    },
    "language": {
      "type": [
        "string",
        "null"
      ],
      "description": "Language code when the platform provides one."
    },
    "url": {
      "type": [
        "string",
        "null"
      ],
      "format": "uri",
      "description": "Public link to the review when the platform provides one. On read-only platforms, where to answer it."
    },
    "created_at": {
      "type": "string",
      "format": "date-time",
      "description": "When the review was written on the platform."
    },
    "updated_at": {
      "type": "string",
      "format": "date-time",
      "description": "When it was last edited on the platform."
    },
    "reply": {
      "oneOf": [
        {
          "$ref": "#/$defs/Reply"
        },
        {
          "type": "null"
        }
      ],
      "description": "The business reply, or `null`."
    }
  },
  "$defs": {
    "PlatformId": {
      "type": "string",
      "enum": [
        "google",
        "app_store",
        "google_play",
        "judge_me",
        "trustpilot",
        "google_maps",
        "yelp",
        "tripadvisor",
        "booking",
        "yotpo",
        "reviews_io",
        "g2",
        "ebay",
        "etsy",
        "steam",
        "okendo",
        "feefo",
        "trusted_shops",
        "ekomi",
        "loox",
        "proven_expert",
        "shopper_approved",
        "wordpress",
        "appexchange",
        "facebook",
        "opentable",
        "doordash",
        "angi",
        "checkatrade",
        "avvo",
        "capterra",
        "apartments",
        "gartner",
        "healthgrades",
        "vitals",
        "classpass"
      ],
      "description": "Platform ID.\n\n| ID | Platform | Connects with | Replies |\n| --- | --- | --- | --- |\n| `google` | Google Business Profile | oauth | by API |\n| `app_store` | App Store | credentials | by API |\n| `google_play` | Google Play | credentials | by API |\n| `judge_me` | Judge.me | credentials | by API |\n| `trustpilot` | Trustpilot | oauth | by API |\n| `google_maps` | Google Maps | listing_url | read only |\n| `yelp` | Yelp | listing_url | read only |\n| `tripadvisor` | Tripadvisor | listing_url | read only |\n| `booking` | Booking.com | listing_url | read only |\n| `yotpo` | Yotpo | credentials | read only |\n| `reviews_io` | REVIEWS.io | credentials | read only |\n| `g2` | G2 | credentials | read only |\n| `ebay` | eBay | oauth | by API |\n| `etsy` | Etsy | listing_url | read only |\n| `steam` | Steam | listing_url | read only |\n| `okendo` | Okendo | credentials | read only |\n| `feefo` | Feefo | credentials | read only |\n| `trusted_shops` | Trusted Shops | credentials | by API |\n| `ekomi` | eKomi | credentials | by API |\n| `loox` | Loox | credentials | read only |\n| `proven_expert` | ProvenExpert | credentials | read only |\n| `shopper_approved` | Shopper Approved | credentials | read only |\n| `wordpress` | WordPress.org | listing_url | read only |\n| `appexchange` | Salesforce AppExchange | listing_url | read only |\n| `facebook` | Facebook | listing_url | read only |\n| `opentable` | OpenTable | listing_url | read only |\n| `doordash` | DoorDash | listing_url | read only |\n| `angi` | Angi | listing_url | read only |\n| `checkatrade` | Checkatrade | listing_url | read only |\n| `avvo` | Avvo | listing_url | read only |\n| `capterra` | Capterra | listing_url | read only |\n| `apartments` | Apartments.com | listing_url | read only |\n| `gartner` | Gartner Peer Insights | listing_url | read only |\n| `healthgrades` | Healthgrades | listing_url | read only |\n| `vitals` | Vitals | listing_url | read only |\n| `classpass` | ClassPass | listing_url | read only |"
    },
    "Reply": {
      "type": "object",
      "required": [
        "text",
        "created_at",
        "status",
        "error"
      ],
      "description": "The business reply to a review.",
      "properties": {
        "text": {
          "type": "string",
          "description": "Reply text."
        },
        "created_at": {
          "type": [
            "string",
            "null"
          ],
          "format": "date-time",
          "description": "When the reply was published. `null` while a first reply is queued; when a reply is replaced, it keeps the previous value until the new one is published."
        },
        "status": {
          "type": [
            "string",
            "null"
          ],
          "enum": [
            "published",
            "queued",
            "failed",
            "unknown",
            null
          ],
          "description": "`published` (live on the platform, whoever wrote it), `queued` (sent through Prisma, waiting to be published), `failed` (the platform refused it; see `error`) or `unknown` (the request went out but the platform never answered and the reply can't be read back, so Prisma didn't retry; check the review on the platform before posting again; see `error`)."
        },
        "error": {
          "type": [
            "string",
            "null"
          ],
          "description": "Why publishing failed, when `status` is `failed`."
        }
      }
    }
  }
}