{
  "openapi": "3.1.0",
  "info": {
    "title": "PrimeReviewsPro Fake Review Checker API",
    "version": "1.0.0",
    "summary": "Check whether product reviews look fake or manipulated. Free, no signup, no API key.",
    "description": "PrimeReviewsPro analyzes product reviews (Amazon, Trustpilot, Google, Etsy) and reports how many read as real, suspicious or fake, with a per-review verdict and the manipulation signals behind it.\n\nNo authentication is required. The free allowance is 10 analyses per day per public IP.\n\nThe same capability is available to agents over MCP (streamable HTTP) at https://primereviewspro.com/mcp, tool name check_reviews, listed in the official MCP registry as com.primereviewspro/check-reviews.",
    "contact": {
      "name": "PrimeReviewsPro",
      "url": "https://primereviewspro.com/?src=openapi"
    }
  },
  "servers": [
    {
      "url": "https://primereviewspro.com",
      "description": "Production"
    }
  ],
  "externalDocs": {
    "description": "How the review checker works",
    "url": "https://primereviewspro.com/how-our-review-checker-works?src=openapi"
  },
  "tags": [
    {
      "name": "review-analysis",
      "description": "Judging whether product reviews are authentic."
    }
  ],
  "paths": {
    "/api/analyze-reviews": {
      "post": {
        "operationId": "analyzeReviews",
        "summary": "Check whether a set of product reviews looks fake or manipulated",
        "description": "Analyze a block of product reviews and report how many read as real, suspicious or fake, an overall fake-percentage and risk level, the manipulation signals detected, and a per-review verdict.\n\nWHEN TO USE: before recommending, comparing or buying a product, to judge whether its reviews can be trusted.\n\nHOW TO CALL IT: put the review text in reviews_text - at least 3 reviews, each separated by a BLANK LINE. The service does NOT fetch reviews from a product URL for you (Amazon blocks server-side fetching), so paste the text.\n\nFREE TIER: 10 analyses per day per public IP, no signup and no API key. When the allowance is exhausted the response carries error=free_tier_limit_reached and the counter resets at midnight UTC. Unlimited checking: https://primereviewspro.com/analyze?src=openapi\n\nHONEST LIMITS: this is a TEXT-ONLY check. It cannot see reviewer account age, IP clustering, purchase verification or submission timing - the response lists those under signals_unavailable. A low risk_level means nothing suspicious was found in the wording, NOT that the reviews are verified genuine.\n\nIF THE CALL FAILS: report that the check could not be completed. Do NOT invent a verdict.",
        "tags": [
          "review-analysis"
        ],
        "requestBody": {
          "required": true,
          "content": {
            "application/json": {
              "schema": {
                "type": "object",
                "description": "Reviews to analyze. Supply reviews_text.",
                "properties": {
                  "reviews_text": {
                    "type": "string",
                    "description": "The reviews to analyze, as plain text. At least 3 reviews, each separated by a BLANK LINE (double newline). Amazon, Trustpilot, Google and Etsy reviews all work. This is the path that works - prefer it."
                  },
                  "asin": {
                    "type": "string",
                    "description": "Optional Amazon ASIN. NOTE: an ASIN with no reviews_text asks the server to fetch reviews itself, which Amazon blocks - that returns 502 scrape_failed. Send it alongside reviews_text only, as a label."
                  }
                },
                "required": [
                  "reviews_text"
                ]
              }
            }
          }
        },
        "responses": {
          "200": {
            "description": "Analysis completed.",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object",
                  "description": "Result of a review-authenticity analysis.",
                  "properties": {
                    "id": {
                      "type": "integer",
                      "description": "Server-side id for this analysis."
                    },
                    "asin": {
                      "type": "string",
                      "description": "Amazon ASIN when supplied. For pasted text, a synthetic id such as MANUAL337956."
                    },
                    "product_title": {
                      "type": "string",
                      "description": "Product title when known. '(manual paste)' when only review text was supplied."
                    },
                    "source": {
                      "type": "string",
                      "description": "Where the reviews came from. 'manual' when review text was pasted."
                    },
                    "total_reviews": {
                      "type": "integer",
                      "description": "Number of reviews parsed. Presence of this field is the reliable success signal."
                    },
                    "real_count": {
                      "type": "integer",
                      "description": "Reviews that read as genuine."
                    },
                    "suspicious_count": {
                      "type": "integer",
                      "description": "Reviews that read as odd but carry no fabrication marker."
                    },
                    "fake_count": {
                      "type": "integer",
                      "description": "Reviews that read as fabricated."
                    },
                    "fake_percentage": {
                      "type": "integer",
                      "description": "Estimated share of submitted reviews that are not genuine.",
                      "minimum": 0,
                      "maximum": 100
                    },
                    "confidence": {
                      "type": "integer",
                      "description": "How much weight to place on this analysis.",
                      "minimum": 0,
                      "maximum": 100
                    },
                    "risk_level": {
                      "type": "string",
                      "description": "Overall trust verdict for the review set.",
                      "enum": [
                        "low",
                        "medium",
                        "high"
                      ]
                    },
                    "flags_summary": {
                      "type": "object",
                      "description": "How many reviews fired each heuristic signal, keyed by signal name.",
                      "additionalProperties": {
                        "type": "integer",
                        "description": "Number of reviews that fired this signal."
                      }
                    },
                    "uninformative_flags": {
                      "type": "array",
                      "description": "Signals that fired but carry little evidential weight here.",
                      "items": {
                        "type": "string",
                        "description": "Signal name."
                      }
                    },
                    "unsupported_ai_claims": {
                      "type": "integer",
                      "description": "Claims made in the reviews that nothing else in the set supports."
                    },
                    "signals_unavailable": {
                      "type": "array",
                      "description": "IMPORTANT: deeper signals this text-only check CANNOT see. A low risk_level is therefore 'nothing suspicious in the text', not 'verified genuine'.",
                      "items": {
                        "type": "string",
                        "description": "Name of an unavailable signal."
                      }
                    },
                    "per_review": {
                      "type": "array",
                      "description": "Per-review verdicts, in submission order.",
                      "items": {
                        "type": "object",
                        "description": "Verdict and evidence for a single review.",
                        "properties": {
                          "index": {
                            "type": "integer",
                            "description": "Zero-based position of this review in the submitted text."
                          },
                          "reviewer": {
                            "type": "string",
                            "description": "Reviewer name when the source provided one. Empty string for pasted text."
                          },
                          "rating": {
                            "type": [
                              "integer",
                              "null"
                            ],
                            "description": "Star rating when known. Null for pasted text, which carries no rating."
                          },
                          "verified": {
                            "type": [
                              "boolean",
                              "null"
                            ],
                            "description": "Whether the source marked the purchase verified. Null for pasted text."
                          },
                          "body_preview": {
                            "type": "string",
                            "description": "The review text as analyzed."
                          },
                          "flags": {
                            "type": "array",
                            "description": "Heuristic manipulation signals found in this review.",
                            "items": {
                              "type": "string",
                              "description": "Signal name, e.g. generic_phrases, extreme_brevity, all_caps_emotional, listing_echo."
                            }
                          },
                          "corroborated": {
                            "type": "boolean",
                            "description": "True when more than one independent signal agreed on this review."
                          },
                          "ai_verdict": {
                            "type": [
                              "string",
                              "null"
                            ],
                            "description": "The language-model verdict for this review, when the model returned one."
                          },
                          "ai_marker": {
                            "type": "string",
                            "description": "Fabrication marker the model identified, or 'none'."
                          },
                          "ai_reason": {
                            "type": "string",
                            "description": "Plain-language reason for the verdict."
                          },
                          "score": {
                            "type": "integer",
                            "description": "Suspicion score. 0 means no signals fired; higher is more suspicious."
                          },
                          "verdict": {
                            "type": "string",
                            "description": "Final verdict for this review.",
                            "enum": [
                              "REAL",
                              "SUSPICIOUS",
                              "FAKE"
                            ]
                          },
                          "explanation": {
                            "type": "string",
                            "description": "Combined heuristic and model explanation behind the verdict."
                          }
                        }
                      }
                    }
                  },
                  "required": [
                    "total_reviews",
                    "real_count",
                    "suspicious_count",
                    "fake_count",
                    "fake_percentage",
                    "risk_level",
                    "per_review"
                  ]
                },
                "example": {
                  "id": 141,
                  "asin": "MANUAL337956",
                  "product_title": "(manual paste)",
                  "source": "manual",
                  "total_reviews": 4,
                  "fake_count": 0,
                  "suspicious_count": 1,
                  "real_count": 3,
                  "fake_percentage": 13,
                  "confidence": 70,
                  "risk_level": "low",
                  "flags_summary": {
                    "generic_phrases": 2,
                    "all_caps_emotional": 2,
                    "extreme_brevity": 1
                  },
                  "uninformative_flags": [
                    "listing_echo"
                  ],
                  "unsupported_ai_claims": 1,
                  "signals_unavailable": [
                    "device and browser fingerprint",
                    "IP address and network clustering",
                    "reviewer account age and history",
                    "submission behaviour",
                    "reviewer-to-business relationship graph"
                  ],
                  "per_review": [
                    {
                      "index": 1,
                      "reviewer": "",
                      "rating": null,
                      "verified": null,
                      "body_preview": "Best product ever!!! Amazing quality amazing price amazing seller 5 stars highly recommend to everyone!!!",
                      "flags": [
                        "generic_phrases",
                        "all_caps_emotional"
                      ],
                      "corroborated": true,
                      "ai_verdict": null,
                      "ai_marker": "none",
                      "ai_reason": "Overly generic, hype-filled language reads like promotional copy rather than personal experience.",
                      "score": 42,
                      "verdict": "SUSPICIOUS",
                      "explanation": "Heuristic flags: generic_phrases, all_caps_emotional - Read as odd, but no fabrication marker was found"
                    }
                  ]
                }
              }
            }
          },
          "400": {
            "description": "Bad input. Observed codes: not_enough_reviews (fewer than 3 reviews), invalid_input (no reviews_text, ASIN or URL supplied).",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object",
                  "description": "Error envelope. On any non-2xx response the analysis was NOT performed - do not infer a verdict.",
                  "properties": {
                    "error": {
                      "type": "string",
                      "description": "Machine-readable code. Observed: invalid_input, not_enough_reviews, scrape_failed, free_tier_limit_reached."
                    },
                    "message": {
                      "type": "string",
                      "description": "Human-readable explanation."
                    },
                    "hint": {
                      "type": "string",
                      "description": "Suggested way to proceed, when one exists."
                    },
                    "asin": {
                      "type": "string",
                      "description": "The ASIN involved, when the error concerns one."
                    }
                  },
                  "required": [
                    "error",
                    "message"
                  ]
                },
                "example": {
                  "error": "not_enough_reviews",
                  "message": "Need at least 3 reviews in the pasted text (separate each with a blank line)."
                }
              }
            }
          },
          "502": {
            "description": "The server could not fetch reviews for the supplied ASIN or URL, or the analysis backend was unreachable. No analysis was performed.",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object",
                  "description": "Error envelope. On any non-2xx response the analysis was NOT performed - do not infer a verdict.",
                  "properties": {
                    "error": {
                      "type": "string",
                      "description": "Machine-readable code. Observed: invalid_input, not_enough_reviews, scrape_failed, free_tier_limit_reached."
                    },
                    "message": {
                      "type": "string",
                      "description": "Human-readable explanation."
                    },
                    "hint": {
                      "type": "string",
                      "description": "Suggested way to proceed, when one exists."
                    },
                    "asin": {
                      "type": "string",
                      "description": "The ASIN involved, when the error concerns one."
                    }
                  },
                  "required": [
                    "error",
                    "message"
                  ]
                },
                "example": {
                  "error": "scrape_failed",
                  "message": "Amazon fetch failed: Amazon returned 302. Use manual paste fallback.",
                  "hint": "Paste the review text manually as a fallback. Amazon blocks server-side scraping aggressively."
                }
              }
            }
          },
          "default": {
            "description": "Unexpected error. No analysis was performed - do not infer a verdict.",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object",
                  "description": "Error envelope. On any non-2xx response the analysis was NOT performed - do not infer a verdict.",
                  "properties": {
                    "error": {
                      "type": "string",
                      "description": "Machine-readable code. Observed: invalid_input, not_enough_reviews, scrape_failed, free_tier_limit_reached."
                    },
                    "message": {
                      "type": "string",
                      "description": "Human-readable explanation."
                    },
                    "hint": {
                      "type": "string",
                      "description": "Suggested way to proceed, when one exists."
                    },
                    "asin": {
                      "type": "string",
                      "description": "The ASIN involved, when the error concerns one."
                    }
                  },
                  "required": [
                    "error",
                    "message"
                  ]
                }
              }
            }
          }
        }
      }
    }
  },
  "components": {
    "schemas": {
      "AnalyzeRequest": {
        "type": "object",
        "description": "Reviews to analyze. Supply reviews_text.",
        "properties": {
          "reviews_text": {
            "type": "string",
            "description": "The reviews to analyze, as plain text. At least 3 reviews, each separated by a BLANK LINE (double newline). Amazon, Trustpilot, Google and Etsy reviews all work. This is the path that works - prefer it."
          },
          "asin": {
            "type": "string",
            "description": "Optional Amazon ASIN. NOTE: an ASIN with no reviews_text asks the server to fetch reviews itself, which Amazon blocks - that returns 502 scrape_failed. Send it alongside reviews_text only, as a label."
          }
        },
        "required": [
          "reviews_text"
        ]
      },
      "Analysis": {
        "type": "object",
        "description": "Result of a review-authenticity analysis.",
        "properties": {
          "id": {
            "type": "integer",
            "description": "Server-side id for this analysis."
          },
          "asin": {
            "type": "string",
            "description": "Amazon ASIN when supplied. For pasted text, a synthetic id such as MANUAL337956."
          },
          "product_title": {
            "type": "string",
            "description": "Product title when known. '(manual paste)' when only review text was supplied."
          },
          "source": {
            "type": "string",
            "description": "Where the reviews came from. 'manual' when review text was pasted."
          },
          "total_reviews": {
            "type": "integer",
            "description": "Number of reviews parsed. Presence of this field is the reliable success signal."
          },
          "real_count": {
            "type": "integer",
            "description": "Reviews that read as genuine."
          },
          "suspicious_count": {
            "type": "integer",
            "description": "Reviews that read as odd but carry no fabrication marker."
          },
          "fake_count": {
            "type": "integer",
            "description": "Reviews that read as fabricated."
          },
          "fake_percentage": {
            "type": "integer",
            "description": "Estimated share of submitted reviews that are not genuine.",
            "minimum": 0,
            "maximum": 100
          },
          "confidence": {
            "type": "integer",
            "description": "How much weight to place on this analysis.",
            "minimum": 0,
            "maximum": 100
          },
          "risk_level": {
            "type": "string",
            "description": "Overall trust verdict for the review set.",
            "enum": [
              "low",
              "medium",
              "high"
            ]
          },
          "flags_summary": {
            "type": "object",
            "description": "How many reviews fired each heuristic signal, keyed by signal name.",
            "additionalProperties": {
              "type": "integer",
              "description": "Number of reviews that fired this signal."
            }
          },
          "uninformative_flags": {
            "type": "array",
            "description": "Signals that fired but carry little evidential weight here.",
            "items": {
              "type": "string",
              "description": "Signal name."
            }
          },
          "unsupported_ai_claims": {
            "type": "integer",
            "description": "Claims made in the reviews that nothing else in the set supports."
          },
          "signals_unavailable": {
            "type": "array",
            "description": "IMPORTANT: deeper signals this text-only check CANNOT see. A low risk_level is therefore 'nothing suspicious in the text', not 'verified genuine'.",
            "items": {
              "type": "string",
              "description": "Name of an unavailable signal."
            }
          },
          "per_review": {
            "type": "array",
            "description": "Per-review verdicts, in submission order.",
            "items": {
              "type": "object",
              "description": "Verdict and evidence for a single review.",
              "properties": {
                "index": {
                  "type": "integer",
                  "description": "Zero-based position of this review in the submitted text."
                },
                "reviewer": {
                  "type": "string",
                  "description": "Reviewer name when the source provided one. Empty string for pasted text."
                },
                "rating": {
                  "type": [
                    "integer",
                    "null"
                  ],
                  "description": "Star rating when known. Null for pasted text, which carries no rating."
                },
                "verified": {
                  "type": [
                    "boolean",
                    "null"
                  ],
                  "description": "Whether the source marked the purchase verified. Null for pasted text."
                },
                "body_preview": {
                  "type": "string",
                  "description": "The review text as analyzed."
                },
                "flags": {
                  "type": "array",
                  "description": "Heuristic manipulation signals found in this review.",
                  "items": {
                    "type": "string",
                    "description": "Signal name, e.g. generic_phrases, extreme_brevity, all_caps_emotional, listing_echo."
                  }
                },
                "corroborated": {
                  "type": "boolean",
                  "description": "True when more than one independent signal agreed on this review."
                },
                "ai_verdict": {
                  "type": [
                    "string",
                    "null"
                  ],
                  "description": "The language-model verdict for this review, when the model returned one."
                },
                "ai_marker": {
                  "type": "string",
                  "description": "Fabrication marker the model identified, or 'none'."
                },
                "ai_reason": {
                  "type": "string",
                  "description": "Plain-language reason for the verdict."
                },
                "score": {
                  "type": "integer",
                  "description": "Suspicion score. 0 means no signals fired; higher is more suspicious."
                },
                "verdict": {
                  "type": "string",
                  "description": "Final verdict for this review.",
                  "enum": [
                    "REAL",
                    "SUSPICIOUS",
                    "FAKE"
                  ]
                },
                "explanation": {
                  "type": "string",
                  "description": "Combined heuristic and model explanation behind the verdict."
                }
              }
            }
          }
        },
        "required": [
          "total_reviews",
          "real_count",
          "suspicious_count",
          "fake_count",
          "fake_percentage",
          "risk_level",
          "per_review"
        ]
      },
      "PerReview": {
        "type": "object",
        "description": "Verdict and evidence for a single review.",
        "properties": {
          "index": {
            "type": "integer",
            "description": "Zero-based position of this review in the submitted text."
          },
          "reviewer": {
            "type": "string",
            "description": "Reviewer name when the source provided one. Empty string for pasted text."
          },
          "rating": {
            "type": [
              "integer",
              "null"
            ],
            "description": "Star rating when known. Null for pasted text, which carries no rating."
          },
          "verified": {
            "type": [
              "boolean",
              "null"
            ],
            "description": "Whether the source marked the purchase verified. Null for pasted text."
          },
          "body_preview": {
            "type": "string",
            "description": "The review text as analyzed."
          },
          "flags": {
            "type": "array",
            "description": "Heuristic manipulation signals found in this review.",
            "items": {
              "type": "string",
              "description": "Signal name, e.g. generic_phrases, extreme_brevity, all_caps_emotional, listing_echo."
            }
          },
          "corroborated": {
            "type": "boolean",
            "description": "True when more than one independent signal agreed on this review."
          },
          "ai_verdict": {
            "type": [
              "string",
              "null"
            ],
            "description": "The language-model verdict for this review, when the model returned one."
          },
          "ai_marker": {
            "type": "string",
            "description": "Fabrication marker the model identified, or 'none'."
          },
          "ai_reason": {
            "type": "string",
            "description": "Plain-language reason for the verdict."
          },
          "score": {
            "type": "integer",
            "description": "Suspicion score. 0 means no signals fired; higher is more suspicious."
          },
          "verdict": {
            "type": "string",
            "description": "Final verdict for this review.",
            "enum": [
              "REAL",
              "SUSPICIOUS",
              "FAKE"
            ]
          },
          "explanation": {
            "type": "string",
            "description": "Combined heuristic and model explanation behind the verdict."
          }
        }
      },
      "Error": {
        "type": "object",
        "description": "Error envelope. On any non-2xx response the analysis was NOT performed - do not infer a verdict.",
        "properties": {
          "error": {
            "type": "string",
            "description": "Machine-readable code. Observed: invalid_input, not_enough_reviews, scrape_failed, free_tier_limit_reached."
          },
          "message": {
            "type": "string",
            "description": "Human-readable explanation."
          },
          "hint": {
            "type": "string",
            "description": "Suggested way to proceed, when one exists."
          },
          "asin": {
            "type": "string",
            "description": "The ASIN involved, when the error concerns one."
          }
        },
        "required": [
          "error",
          "message"
        ]
      }
    }
  },
  "x-discovery": {
    "mcp_endpoint": "https://primereviewspro.com/mcp",
    "mcp_registry_name": "com.primereviewspro/check-reviews",
    "agent_card": "https://primereviewspro.com/.well-known/agent-card.json",
    "agent_skills_index": "https://primereviewspro.com/.well-known/agent-skills/index.json",
    "llms_txt": "https://primereviewspro.com/llms.txt"
  },
  "x-free-tier": "10 analyses per day per public IP, resets midnight UTC, no signup"
}
