Moderate buyer star ratings, publish or reject reviews, and post replies
/admin/api/reviews
List product reviews for moderation, newest first, with page-based pagination. Optional filters narrow by moderation status, product, and star rating.
/admin/api/reviews/{id}/status
Set a review's moderation status. Setting a review to published makes it visible on the storefront; pending or rejected hide it. Recomputes the product's aggregate rating. Returns 204 No Content.
/admin/api/reviews/{id}/reply
Set or clear the single public merchant reply on a review. Passing null or an empty/whitespace-only reply clears any existing reply. Returns 204 No Content.
/admin/api/reviews/{id}
Permanently delete a review. This is a hard delete and recomputes the product's aggregate rating. Returns 204 No Content.
/admin/api/reviews
List product reviews for moderation, newest first, with page-based pagination. Optional filters narrow by moderation status, product, and star rating.
| Name | Type | Required | Description |
|---|---|---|---|
| page | integer | optional | Page number (1-indexed). Defaults to 1. |
| per_page | integer | optional | Items per page. Defaults to 20, clamped to a max of 100. |
| status | string | optional | Filter by moderation status: pending, published, or rejected. Other values are ignored. |
| product_id | integer | optional | Restrict to reviews of a single product. |
| rating | integer | optional | Restrict to a single star rating, 1–5. Out-of-range values are ignored. |
{
"data": [
{
"id": 1,
"product_id": 42,
"product_name": "Merino Wool Socks",
"customer_id": 1001,
"reviewer_name": "Jordan A.",
"rating": 5,
"title": "Cozy and durable",
"body": "Held up after a dozen washes, still warm.",
"status": "published",
"verified_purchase": true,
"merchant_reply": "Thanks for the kind words, Jordan!",
"merchant_reply_at": "2026-05-21T14:05:00Z",
"created_at": "2026-05-20T09:30:00Z"
},
{
"id": 2,
"product_id": 42,
"product_name": "Merino Wool Socks",
"customer_id": 1002,
"reviewer_name": "Sam P.",
"rating": 2,
"title": null,
"body": "Ran small for me.",
"status": "pending",
"verified_purchase": false,
"merchant_reply": null,
"merchant_reply_at": null,
"created_at": "2026-05-22T11:00:00Z"
}
],
"page": 1,
"per_page": 20,
"total": 2,
"total_pages": 1
}
curl "https://yourshop.zeroshop.io/admin/api/reviews?status=pending&page=1&per_page=20" \
-H "Authorization: Bearer zspat_..."
import requests
resp = requests.get(
"https://yourshop.zeroshop.io/admin/api/reviews",
headers={"Authorization": "Bearer zspat_..."},
params={"status": "pending", "page": 1, "per_page": 20}
)
reviews = resp.json()
const resp = await fetch("https://yourshop.zeroshop.io/admin/api/reviews?status=pending&page=1&per_page=20", {
headers: { "Authorization": "Bearer zspat_..." }
});
const reviews = await resp.json();
require "net/http"
require "json"
uri = URI("https://yourshop.zeroshop.io/admin/api/reviews")
uri.query = URI.encode_www_form(status: "pending", page: 1, per_page: 20)
req = Net::HTTP::Get.new(uri)
req["Authorization"] = "Bearer zspat_..."
resp = Net::HTTP.start(uri.hostname, uri.port, use_ssl: true) { |http| http.request(req) }
reviews = JSON.parse(resp.body)
/admin/api/reviews/{id}/status
Set a review's moderation status. Setting a review to published makes it visible on the storefront; pending or rejected hide it. Recomputes the product's aggregate rating. Returns 204 No Content.
{
"status": "published"
}
curl -X PATCH "https://yourshop.zeroshop.io/admin/api/reviews/1/status" \
-H "Authorization: Bearer zspat_..." \
-H "Content-Type: application/json" \
-d '{"status": "published"}'
import requests
requests.patch(
"https://yourshop.zeroshop.io/admin/api/reviews/1/status",
headers={"Authorization": "Bearer zspat_..."},
json={"status": "published"}
)
await fetch("https://yourshop.zeroshop.io/admin/api/reviews/1/status", {
method: "PATCH",
headers: {
"Authorization": "Bearer zspat_...",
"Content-Type": "application/json"
},
body: JSON.stringify({ status: "published" })
});
require "net/http"
require "json"
uri = URI("https://yourshop.zeroshop.io/admin/api/reviews/1/status")
req = Net::HTTP::Patch.new(uri)
req["Authorization"] = "Bearer zspat_..."
req["Content-Type"] = "application/json"
req.body = { status: "published" }.to_json
Net::HTTP.start(uri.hostname, uri.port, use_ssl: true) { |http| http.request(req) }
/admin/api/reviews/{id}/reply
Set or clear the single public merchant reply on a review. Passing null or an empty/whitespace-only reply clears any existing reply. Returns 204 No Content.
{
"reply": "Thanks for the kind words, Jordan!"
}
curl -X PUT "https://yourshop.zeroshop.io/admin/api/reviews/1/reply" \
-H "Authorization: Bearer zspat_..." \
-H "Content-Type: application/json" \
-d '{"reply": "Thanks for the kind words, Jordan!"}'
import requests
requests.put(
"https://yourshop.zeroshop.io/admin/api/reviews/1/reply",
headers={"Authorization": "Bearer zspat_..."},
json={"reply": "Thanks for the kind words, Jordan!"}
)
await fetch("https://yourshop.zeroshop.io/admin/api/reviews/1/reply", {
method: "PUT",
headers: {
"Authorization": "Bearer zspat_...",
"Content-Type": "application/json"
},
body: JSON.stringify({ reply: "Thanks for the kind words, Jordan!" })
});
require "net/http"
require "json"
uri = URI("https://yourshop.zeroshop.io/admin/api/reviews/1/reply")
req = Net::HTTP::Put.new(uri)
req["Authorization"] = "Bearer zspat_..."
req["Content-Type"] = "application/json"
req.body = { reply: "Thanks for the kind words, Jordan!" }.to_json
Net::HTTP.start(uri.hostname, uri.port, use_ssl: true) { |http| http.request(req) }
/admin/api/reviews/{id}
Permanently delete a review. This is a hard delete and recomputes the product's aggregate rating. Returns 204 No Content.
curl -X DELETE "https://yourshop.zeroshop.io/admin/api/reviews/1" \
-H "Authorization: Bearer zspat_..."
import requests
requests.delete(
"https://yourshop.zeroshop.io/admin/api/reviews/1",
headers={"Authorization": "Bearer zspat_..."}
)
await fetch("https://yourshop.zeroshop.io/admin/api/reviews/1", {
method: "DELETE",
headers: { "Authorization": "Bearer zspat_..." }
});
require "net/http"
uri = URI("https://yourshop.zeroshop.io/admin/api/reviews/1")
req = Net::HTTP::Delete.new(uri)
req["Authorization"] = "Bearer zspat_..."
Net::HTTP.start(uri.hostname, uri.port, use_ssl: true) { |http| http.request(req) }
We value your privacy
We use cookies for essential site functionality and, with your consent, analytics to understand how our platform is used. No personal data is shared with third parties. See our Privacy Policy for details.