---
title: "Write a review or reply on a published component"
method: POST
path: "/api/components/{id}/reviews"
tags: ["catalog"]
---

# Write a review or reply on a published component

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

## Request

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

The token is checked first, then the body. With `parent` the request creates a reply: `parent` must be a top-level review of the same component, the text is required and the rating is ignored (stored as 0).

Without `parent` it writes the caller's top-level review: `rating` 1–5 is required, the text is optional, and each user has at most one top-level review per component (a second POST updates its rating and text).

The author name is derived from the token's user (name, else the local part of the e-mail address). On success the component's `review_count`, `review_avg` and `review_dist` are recomputed and the fresh thread is returned.

## Request body

- ComponentReviewCreateRequest: Top-level review (no `parent`; `rating` required) or reply (`parent` set; non-empty `body` required). Other keys are ignored.
  - `rating` integer: Star rating; required for a top-level review, ignored for a reply.
  - `body` string: Review or reply text, trimmed; optional for a review, required for a reply.
  - `parent` string: Id of a top-level review of the same component; turns the request into a reply.

## Response `200`

Review or reply saved; 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`: Malformed body, text too long, reply without text, or missing/invalid rating.
- `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 saving.

---

[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)
