Public Alpha. Easel is in early development, so expect rough edges.

Easel

← API Documentation

Reviews API

Customers who bought a product can rate it from 1 to 5 stars, with an
optional title and text. The storefront shows each product's average and its
reviews, newest first, marked as verified purchases. These endpoints let you
read reviews and moderate them.

Related resources:

  • Products for each product's review_count and
    rating_average
  • Sites for turning reviews on or off per storefront
  • Customers for banning and
    shadowbanning authors

Endpoints

There is no endpoint to create, edit, or delete a review. Only the customer
writes, edits, or deletes their own review, from the storefront.

Who May Review

A customer can review a product when all of these hold:

  • They are logged in to a storefront account,
    which requires a verified email.
  • The store hasn't banned them.
  • They bought the product in a paid order: one whose status is paid or
    fulfilled. A pending order was never paid and doesn't count.

A refund or a return doesn't change that. Refunds don't change an order's
status, so a customer who returned a product can still review it, and
refunding them doesn't hide a review they already wrote. Customers who
returned something often write the most useful reviews, and hiding them
would suppress the unfavorable ones.

Each customer can review a product once. The review records the variant
they bought, which the storefront shows beside it.

Visibility

Every review has a status:

Status Shown on the storefront Counts toward the rating
published To everyone Yes
hidden Not on the product page; its author sees it in their account, marked as hidden with your reason No
shadowbanned Only to its author, who sees it as usual No
banned To no one; its author can't log in No

A hidden review is hidden whatever its author's standing. Otherwise the
status follows the author: shadowbanned or banned when you shadowbanned
or banned them, and published when you lift it.

A product's review_count and rating_average count only published
reviews, and update as soon as a review is posted, edited, deleted, hidden,
or shown again, and as soon as you ban, shadowban, or lift either for its
author.

No Deletion

Stores can't delete reviews, from the API or the dashboard. To take one
down, hide it and pick a reason. Hiding keeps the review, its reason, and
when it happened, so unfavorable reviews are never removed without a record,
as consumer protection rules such as the FTC's 16 CFR Part 465 and the EU
Omnibus Directive expect. You can show a hidden review again at any time.

Reviews are removed only when their author deletes one, or when you
delete the customer to erase their personal data, which
deletes their reviews too.

Turning Reviews Off

Reviews are on by default. Set a site's reviews_enabled to false with
Update Site to turn them off for that storefront:
it then shows no reviews, ratings, or review structured data, and takes no
new ones. Its reviews are kept, still listed here, and can still be
moderated; turning reviews back on shows them again.

A server run with EASEL_REVIEWS=false has no reviews at all. Every
endpoint on this page then returns 404 Not Found.


List Reviews

List the store's reviews, newest first.

Endpoint: GET /api/v1/reviews/

Permission Required: Read

Query Parameters

Parameter Type Description
product string Only reviews of this product public ID
customer string Only reviews by this customer public ID
status string Only reviews with this status: published, hidden, shadowbanned, or banned
after string Cursor for pagination. Review public ID of the last item on the previous page
limit integer Number of reviews to return (default 10, max 100)

Pagination follows the same cursor rules as the
product list: pass the id of the last
review as after to get the next page, while has_more is true.

Request

curl -X GET "https://studio.easel.engineering/api/v1/reviews/?product=pro_d0b6fmv28q6vn14peun0&limit=20" \
  -H "Authorization: Bearer your_api_key_here"

Response

Status: 200 OK

{
  "data": [
    {
      "id": "rev_d0b6fmv28q6vn14peur0",
      "product_id": "pro_d0b6fmv28q6vn14peun0",
      "variant_name": "Green / Small",
      "customer_id": "cus_d0b6fmv28q6vn14peung",
      "author_name": "Bob S.",
      "rating": 5,
      "title": "So warm",
      "body": "The softest blanket I own.",
      "verified_purchase": true,
      "status": "published",
      "hidden_at": null,
      "hidden_reason": null,
      "hidden_note": null,
      "created_at": "2026-10-18T12:00:00Z",
      "updated_at": "2026-10-18T12:00:00Z"
    }
  ],
  "has_more": false
}

Error Responses

Invalid query parameter

Status: 400 Bad Request

A malformed after, an unknown status, or a limit over 100 is rejected:

{
  "error": "status must be published, hidden, shadowbanned, or banned",
  "code": "INVALID_FIELD"
}

Product or customer not found

Status: 404 Not Found

{
  "error": "Resource not found",
  "code": "NOT_FOUND"
}

Get Review

Endpoint: GET /api/v1/reviews/{review_id}/

Permission Required: Read

Request

curl -X GET "https://studio.easel.engineering/api/v1/reviews/rev_d0b6fmv28q6vn14peur0/" \
  -H "Authorization: Bearer your_api_key_here"

Response

Status: 200 OK

Returns the Review object.

Error Responses

Review not found

Status: 404 Not Found

{
  "error": "Resource not found",
  "code": "NOT_FOUND"
}

Hide Review

Hide a review from the storefront and take it out of its product's rating.
A reason is required. The optional note is for your team; the author sees
only the reason.

Endpoint: POST /api/v1/reviews/{review_id}/hide/

Permission Required: Write

Request Body

Field Type Required Description
reason string Yes spam, offensive, off_topic, personal_info, or other
note string No Up to 1,000 characters

Request

curl -X POST "https://studio.easel.engineering/api/v1/reviews/rev_d0b6fmv28q6vn14peur0/hide/" \
  -H "Authorization: Bearer your_api_key_here" \
  -H "Content-Type: application/json" \
  -H "Idempotency-Key: unique-request-id-24680" \
  -d '{"reason": "personal_info", "note": "Posted a phone number"}'

Response

Status: 200 OK

Returns the Review object with status hidden.
Hiding a review that is already hidden replaces its reason and note.

Error Responses

Missing or unknown reason

Status: 400 Bad Request

{
  "error": "reason is required: spam, offensive, off_topic, personal_info, or other",
  "code": "INVALID_FIELD"
}

Review not found

Status: 404 Not Found


Show Review

Show a hidden review again. It counts toward its product's rating once more,
unless its author is banned or shadowbanned.

Endpoint: POST /api/v1/reviews/{review_id}/unhide/

Permission Required: Write

Request

curl -X POST "https://studio.easel.engineering/api/v1/reviews/rev_d0b6fmv28q6vn14peur0/unhide/" \
  -H "Authorization: Bearer your_api_key_here" \
  -H "Idempotency-Key: unique-request-id-13579"

Response

Status: 200 OK

Returns the Review object.


Review Object

Field Type Description
id string Review public ID
product_id string Public ID of the product reviewed
variant_name string Name of the variant the customer bought, or empty when it no longer exists
customer_id string Public ID of the customer who wrote it
author_name string How the storefront credits the author: first name and last initial
rating integer Stars, from 1 to 5
title string Optional title, up to 120 characters
body string Optional text, up to 5,000 characters
verified_purchase boolean Whether the review is backed by a paid order. Always true for reviews posted on the storefront
status string published, hidden, shadowbanned, or banned (see Visibility)
hidden_at string|null When the store hid it
hidden_reason string|null Why: spam, offensive, off_topic, personal_info, or other
hidden_note string|null The store's note, if any
created_at string ISO 8601 timestamp
updated_at string ISO 8601 timestamp of the author's last edit