---
title: "Toggle the caller's \"helpful\" vote on a review"
method: PATCH
path: "/api/components/{id}/reviews"
tags: ["catalog"]
---

# Toggle the caller's "helpful" vote on a review

`PATCH /api/components/{id}/reviews`

## Request

- Base URL: `https://voltplan.app`
- URL: `https://voltplan.app/api/components/{id}/reviews`
- Auth: HTTP bearer

Adds the caller to the review's `helpful_by` voters, or removes them if they already voted, and returns the fresh thread.

## Request body

- ComponentReviewTargetRequest: Names the review a vote toggle or deletion applies to. Other keys are ignored.
  - `reviewId` string, required: Id of the `component_reviews` record (trimmed).

## Response `200`

Vote toggled; the updated thread and aggregate.

- ComponentReviewsResponse: Review thread of a component with its rating aggregate.
  - `success` unknown, required
  - `nodes` ComponentReviewNode[], required: Top-level reviews, newest first.
    - `id` string, required: Id of the `component_reviews` record.
    - `author_name` string, required: Display name captured when it was written.
    - `rating` integer, required: Stars 1–5; 0 for a reply.
    - `body` string, required: Text; may be ''.
    - `created` string, required: PocketBase creation timestamp, e.g. `2026-08-20 14:56:29.009Z`.
    - `helpful` integer, required: Number of "helpful" votes.
    - `helpfulByMe` boolean, required: The caller voted; false without a valid token.
    - `mine` boolean, required: The caller wrote it; false without a valid token.
    - `replies` ComponentReviewNode[], required: Replies, oldest first.
  - `aggregate` ComponentReviewAggregate, required: Rating summary over top-level reviews; replies never count.
    - `count` integer, required: Number of ratings.
    - `avg` number, required: Average rating rounded to one decimal; 0 without ratings.
    - `dist` ComponentReviewDistribution, required: Number of top-level ratings per star value.
      - `1` integer, required
      - `2` integer, required
      - `3` integer, required
      - `4` integer, required
      - `5` integer, required

## Other responses

- `400`: Body is not a JSON object or has no non-empty `reviewId`.
- `401`: Missing or malformed `Authorization: Bearer` header, or PocketBase rejected the token on `authRefresh`; `error` carries the reason.
- `404`: The component does not exist or is not published, or the referenced review does not exist, belongs to another component, or (as a reply `parent`) is itself a reply.
- `500`: Unexpected failure while recording the vote.

---

[API](https://skmtc.dev/voltplan/apis/voltplan-api.md) · [All operations](https://skmtc.dev/voltplan/apis/voltplan-api/llms.txt) · [OpenAPI document](https://skmtc.dev/voltplan/apis/voltplan-api/revisions/575b86a7af92?raw)
