Yotpo Headless Integration Guide (API-Based)

This guide is for developers showing Yotpo reviews and star ratings through the API instead of the default Yotpo widgets. It fits custom headless storefronts (for example React, Vue or Hydrogen).

Every read in this guide uses the V3 storefront API on api-cdn.yotpo.com. It's public: your store ID in the path identifies the store, and no token is needed. For the full reference, see the V3 Reviews pages, starting with Retrieve product reviews. For a deeper playbook, see Building custom reviews widgets.


⭐ Get a product's star rating

Call Retrieve product rating bottomline. It returns the average score and the review count, with no review bodies.

Endpoint:

GET https://api-cdn.yotpo.com/v3/storefront/store/{storeId}/product/{productId}/ratings
curl --request GET \
     --url https://api-cdn.yotpo.com/v3/storefront/store/YOUR_STORE_ID/product/YOUR_PRODUCT_ID/ratings \
     --header 'accept: application/json'

Sample response:

{
  "bottomline": {
    "totalReviews": 757,
    "averageScore": 4.8758254,
    "totalOrganicReviews": 0,
    "organicAverageScore": 0.0
  }
}

totalReviews and averageScore count every review, including syndicated ones. The organic pair counts only reviews your own store collected. Pick one pair and use it everywhere on your site.

React example:

import { useEffect, useState } from 'react';

type Bottomline = { totalReviews: number; averageScore: number };

const useYotpoStarRating = (storeId: string, productId: string) => {
  const [bottomline, setBottomline] = useState<Bottomline>();

  useEffect(() => {
    fetch(`https://api-cdn.yotpo.com/v3/storefront/store/${storeId}/product/${productId}/ratings`)
      .then((res) => res.json())
      .then((data) => setBottomline(data.bottomline))
      .catch(console.error);
  }, [storeId, productId]);

  return bottomline;
};

Usage:


📝 Get reviews for a product

Call Retrieve product reviews. One request returns a page of reviews plus the rating summary and star distribution.

Endpoint:

GET https://api-cdn.yotpo.com/v3/storefront/store/{storeId}/product/{productId}/reviews?page=1&perPage=10&sort=smart
curl --request GET \
     --url 'https://api-cdn.yotpo.com/v3/storefront/store/YOUR_STORE_ID/product/YOUR_PRODUCT_ID/reviews?page=1&perPage=10&sort=smart' \
     --header 'accept: application/json'
ParameterValuesNotes
pageInteger, starting at 1
perPageIntegerDefault 5, maximum 150
sortsmart, date, badge, images, ratingsmart is AI-powered Smart Sorting (Pro and Premium plans)
directionasc, desc
langLanguage codeReturns translated review content

Sample response (one review shown, products shortened):

{
  "pagination": { "page": 1, "perPage": 10, "total": 757 },
  "bottomline": {
    "totalReview": 757,
    "averageScore": 4.8758254,
    "totalOrganicReviews": 0,
    "organicAverageScore": 0.0,
    "starDistribution": { "1": 2, "2": 3, "3": 12, "4": 53, "5": 687 },
    "customFieldsBottomline": null
  },
  "products": [
    { "id": 94562870, "domainKey": "YOUR_PRODUCT_ID", "name": "Leather Backpack" }
  ],
  "reviews": [
    {
      "id": 911166863,
      "score": 5,
      "votesUp": 0,
      "votesDown": 0,
      "content": "Fits a 15-inch laptop with room to spare.",
      "title": "Great everyday bag",
      "createdAt": "2026-10-24T09:32:19",
      "verifiedBuyer": true,
      "isIncentivized": false,
      "incentiveType": null,
      "customFields": null,
      "imagesData": null,
      "videosData": null,
      "comment": {
        "id": 41384957,
        "content": "Thanks for your review!",
        "createdAt": "2026-10-25T08:00:00",
        "displayName": "Store name",
        "commentsAvatar": null
      },
      "user": {
        "userId": 155028634,
        "displayName": "Dana L.",
        "socialImage": null,
        "userType": "User",
        "isSocialConnected": 0
      },
      "sourceReviewId": null,
      "language": "en",
      "translatedLanguage": null
    }
  ]
}

Note the singular totalReview in this response. The ratings endpoint above says totalReviews.

React example:

import { useEffect, useState } from 'react';

const useYotpoReviews = (storeId: string, productId: string, perPage = 10, page = 1) => {
  const [reviews, setReviews] = useState([]);
  const [total, setTotal] = useState(0);

  useEffect(() => {
    const url = `https://api-cdn.yotpo.com/v3/storefront/store/${storeId}/product/${productId}/reviews?page=${page}&perPage=${perPage}&sort=smart`;
    fetch(url)
      .then((res) => res.json())
      .then((data) => {
        setReviews(data.reviews);
        setTotal(data.pagination.total);
      })
      .catch(console.error);
  }, [storeId, productId, perPage, page]);

  return { reviews, total };
};

Usage:

  • Show a list of reviews per product, and page through them with page and perPage.
  • Use bottomline.starDistribution for a rating histogram.
  • To add search and star or photo filters, send a POST to the same path (Search product reviews).

🌍 Get site reviews

Site reviews are reviews about your store rather than a product. Yotpo keeps them under the reserved product ID yotpo_site_reviews, so you use the same two endpoints as for a product.

Site star rating and count:

GET https://api-cdn.yotpo.com/v3/storefront/store/{storeId}/product/yotpo_site_reviews/ratings
{
  "bottomline": {
    "totalReviews": 226,
    "averageScore": 4.9,
    "totalOrganicReviews": 0,
    "organicAverageScore": 0.0
  }
}

Site reviews list:

GET https://api-cdn.yotpo.com/v3/storefront/store/{storeId}/product/yotpo_site_reviews/reviews?page=1&perPage=10

The response has the same shape as product reviews, so the useYotpoStarRating and useYotpoReviews hooks above work with productId set to yotpo_site_reviews.

Don't use Retrieve store reviews for this. It returns every review in your store across all products, not just site reviews.


✍️ Collect reviews

To submit reviews from your own form, call Create review (POST https://api.yotpo.com/v1/widget/reviews) from your server, not from the browser. Review submission is still a v1 endpoint. Your server is where you validate input, block bots, and set the product title and URL from your own catalog. Use sku: "yotpo_site_reviews" to create a site review. New reviews go through your moderation settings before they appear.


🛠 Developer notes

  • Storefront endpoints are served from a CDN (api-cdn.yotpo.com) and need no token. Data can lag by up to 3 hours, and responses are sent with Cache-Control: no-store, so cache them on your side.
  • user.displayName is an empty string for anonymous reviewers. Show a fallback such as "Anonymous".
  • imagesData and videosData hold the shopper's photos and videos, or null.
  • verifiedBuyer marks reviews from confirmed customers. isIncentivized marks reviews written for an incentive; show a disclosure when it's true.
  • comment is the store's public reply, or null.
  • Consider lazy-loading further pages for better UX.
  • Already using the v1 storefront endpoints (/v1/widget/... and /products/.../bottomline)? They keep working. V3 uses camelCase fields and adds Smart Sorting, translated content and search filters.

If you're using any of the following frameworks, call these APIs from your server for the first page load, so the rating and reviews are in the HTML that search engines see, and cache the responses:

  • Next.js
  • Shopify Hydrogen
  • Vue Storefront
  • Gatsby

Did this page help you?