Update Product Review
About
The updateProductReview mutation edits an existing review in place. Use it to:
- Correct the title or comment of a review a shopper has already submitted
- Change the rating when the shopper reassesses the product
- Fix the reviewer name shown on the review
- Attach further images or video to an existing review
Every field except the review's id is optional, and omitted fields keep their current value. The mutation returns the review as it stands after the update.
A review can only be edited by the customer who wrote it. Send that customer's Bearer token — an unauthenticated request, a different customer's token, or a review submitted by a guest is refused.
Arguments
| Argument | Type | Required | Description |
|---|---|---|---|
id | ID! | ✅ Yes | Identifies the review. Accepts the IRI form (/api/shop/reviews/1) or a plain numeric ID. |
productId | Int | ❌ No | Moves the review to a different product. The product must exist. Rarely useful — omit it on a normal edit. |
title | String | ❌ No | New review headline. |
comment | String | ❌ No | New review body text. |
rating | Int | ❌ No | New star rating. Must be 1 to 5. |
name | String | ❌ No | New reviewer display name. |
email | String | ❌ No | Accepted by the schema but not stored on the review. |
status | Int | ❌ No | Leave unset — see Review Status. |
clientMutationId | String | ❌ No | Arbitrary string echoed back in the payload. |
Only the fields you send are written. Sending title alone changes the title and leaves the rating, comment, and name untouched.
Possible Returns
| Field | Type | Description |
|---|---|---|
productReview | updateProductReviewPayloadData | The review after the update. |
productReview.id | ID! | IRI-style review identifier. |
productReview._id | Int | Numeric review ID. |
productReview.name | String | Reviewer's name. |
productReview.title | String | Review title. |
productReview.rating | Int | Star rating, 1 to 5. |
productReview.comment | String | Review body text. |
productReview.status | String | Approval status — "pending", "approved", or "disapproved". |
productReview.attachments | String | JSON string of the stored attachments, each with a type and a url. |
productReview.createdAt | String | ISO 8601 timestamp of when the review was submitted. |
productReview.updatedAt | String | ISO 8601 timestamp of this update. |
clientMutationId | String | The clientMutationId sent with the request, echoed back. |
Review Status
A review's status is one of three strings:
| Status | Description |
|---|---|
"pending" | Awaiting moderation. Not shown on the storefront. |
"approved" | Published and visible on the product page. |
"disapproved" | Declined and never published. |
The status input takes an integer and is written to the review unchanged, so it cannot produce any of those three values — a review updated with status: 1 ends up holding 1, which no status filter matches and no storefront page displays. Approving or declining a review is an admin action; leave this field unset.
Identifying the Review
The id argument accepts either form — the trailing number is what identifies the review:
| Value | Result |
|---|---|
"/api/shop/reviews/92" | Resolves to review 92 |
"92" | Resolves to review 92 |
"reviews/92" | Resolves to review 92 |
"abc" | Resolves to review 0, which does not exist, so the mutation fails |
Prefer the IRI form: it is what the query and create responses hand back, so it round-trips without conversion.
Use Cases
1. Letting a shopper edit their own review
Send only the fields the edit form changed. Everything else on the review is left as it was.
mutation editReview($input: updateProductReviewInput!) {
updateProductReview(input: $input) {
productReview {
_id
title
comment
rating
status
updatedAt
}
}
}{
"input": {
"id": "/api/shop/reviews/74",
"comment": "Updated after a month of use — the fabric still looks new.",
"rating": 4
}
}2. Re-checking the review after an edit
The response carries the review's current status. An approved review that is edited keeps whatever status it held, so read the field back rather than assuming the edit sent it for re-moderation.
Best Practices
- Send only the fields being changed — omitted fields keep their stored value, so a partial input is the normal case rather than an optimisation
- Use the IRI form of
id— a numeric ID also resolves, but the IRI is what the query and create responses return, so it round-trips without conversion - Never send
status— the field takes an integer that cannot map topending,approved, ordisapproved, and writing it leaves the review in a state no query matches - Leave
productIdout — it exists to move a review to a different product, which is not something an edit form should do by accident - Attach media at creation time — this mutation takes no
attachmentsfield, so images and video can only be sent with Create Product Review - Read
updatedAtback — it confirms the write landed, since a partial update that changed nothing returns the same values it was sent
Error Scenarios
| Scenario | Cause |
|---|---|
| Missing ID | The id field was omitted from input. GraphQL rejects the document before the mutation runs. |
| Review not found | The ID resolves to a review that does not exist. |
| Not signed in | No customer Bearer token was sent, so ownership cannot be established. |
| Not your review | The review belongs to another customer, or was submitted by a guest and has no owner. |
| Rating out of range | rating was sent below 1 or above 5. |
| Product not found | productId was sent and no product has that ID. |
| Invalid attachment | A data URI is malformed, its Base64 will not decode, or a decoded file exceeds 5 MB. |
Related Resources
- Create Product Review - Create new product reviews
- Get Product Reviews - Query product reviews
- Get Product - Query product details
- Shop API Overview - Overview of Shop API resources

