Reviews & Ratings
How reviews and ratings work in the Singularity Marketplace.
Jump to section
How reviews and ratings work in the Singularity Marketplace — the data model, the API surface, and what's planned for the web UI.
Overview
Reviews let any authenticated publisher rate and write about a package they've installed. Each review carries a 1-5 star rating, an optional title and body, and a created/updated timestamp. Publishers can respond to reviews on their own packages; readers can vote a review helpful or unhelpful; the community can flag reviews for moderation.
The review system is fully implemented in the registry backend (packages/registry/src/singularity_registry/api/reviews.py). Today it is reachable via the REST API; a web UI surface is in development.
UI Status
Note: The marketplace web UI does not yet render reviews on package detail pages. The API documented below is live and writable today — a web surface for reading and writing reviews is planned. Once it ships, this section will be replaced with click-through instructions.
If you're a publisher who wants to gather feedback in the meantime, point users at the API endpoints below or wait for the UI release.
Star Ratings
Reviews use a 1-to-5 integer star rating. The registry enforces this at the schema level (rating: int = Field(..., ge=1, le=5)), so values outside that range are rejected with a 400. There is no half-star rating today.
Aggregate ratings (the average that surfaces on the publisher's analytics dashboard as Avg Rating) are computed across all visible reviews on the publisher's packages.
Writing a Review
To create a review, send an authenticated POST to the package's reviews endpoint:
POST /api/v1/packages/{publisher_name}/{package_name}/reviews
Authorization: Bearer <token-or-api-key>
Content-Type: application/json
{
"rating": 4,
"title": "Solid tool — saved me hours",
"body": "Used this in production for two weeks; only nit is the verbose default logging."
}
Field rules:
rating— required integer, 1-5.title— optional, max 256 characters.body— optional, max 5000 characters.
Each publisher can have one review per package — POSTing again from the same publisher updates the existing review rather than creating a duplicate.
Listing Reviews
GET /api/v1/packages/{publisher_name}/{package_name}/reviews?page=1&per_page=20
The response is a paginated list with a rating_distribution summary:
{
"reviews": [{ "id": "...", "rating": 4, "title": "...", "body": "...", "reviewer_name": "...", "helpful_count": 3, ... }],
"total": 42,
"page": 1,
"per_page": 20,
"total_pages": 3,
"rating_distribution": { "5": 18, "4": 12, "3": 8, "2": 3, "1": 1 }
}
Each review object includes the rating, title, body, reviewer name/display name, helpful/unhelpful counts, the publisher's response (if any), and timestamps. No authentication is required to list reviews.
Updating or Deleting Your Review
PATCH /api/v1/reviews/{review_id}
DELETE /api/v1/reviews/{review_id}
PATCH accepts any subset of rating, title, body. The review is flagged with is_edited: true once changed. DELETE removes it permanently. Both require you to be the original author (or an admin).
Voting on Reviews
Readers can mark a review helpful or unhelpful:
POST /api/v1/reviews/{review_id}/vote
{ "helpful": true }
Vote tallies appear on the review object as helpful_count and unhelpful_count. The API records one vote per publisher per review; re-voting changes your existing vote rather than stacking.
Publisher Responses
If you're the publisher of the package being reviewed, you can attach a single response:
POST /api/v1/reviews/{review_id}/respond
{ "body": "Thanks for the feedback — the verbose logging is fixed in 1.3.0." }
The response body has a minimum of 1 character and maximum of 5000. Posting again updates the same response (one per review). Responses are visible inline with the review and surface response_body + response_at fields in the listing endpoint.
Publisher responses are a powerful trust signal — use them to acknowledge bugs, point at fixes, and answer follow-up questions.
Flagging Inappropriate Reviews
If a review violates the marketplace's content policy (spam, harassment, off-topic), flag it for moderator review:
POST /api/v1/reviews/{review_id}/flag
{ "reason": "This review contains personal attacks against the author." }
The reason field is required (5-1000 characters). Flagged reviews enter the moderation queue at GET /api/v1/admin/reviews/flagged; moderators can hide (with a public reason) or unflag (dismiss the report).
Don't flag a review because it's negative — flag it because it's abusive, fraudulent, or off-topic.
Aggregate Ratings
Average ratings flow into two places today:
- Publisher analytics — the Avg Rating stat card on
/dashboard/analyticsshows your portfolio-wide average. See the Analytics Dashboard guide. - Package metadata — packages carry their own rolling average, computed across visible reviews. This is what other surfaces will display when they're rolled out.
Once the package-page UI lands, expect to see the average plus a rating_distribution histogram on every package detail page.
Tips for Good Reviews
- Be specific. "Great tool!" is less useful than "Worked for me on macOS 14 with the default profile; documentation could be clearer about the
--strictflag." - Mention the version. Bugs and quirks are version-bound —
1.2.0may behave very differently from1.0.0. A version reference helps both the publisher and future readers. - Edit, don't pile on. If a maintainer fixes the thing you complained about, edit your review instead of leaving a stale negative one. The
is_editedflag makes your update visible. - Respect the response. Publisher responses count — give them a chance to react before re-rating downward.
- Don't review packages you haven't used. It's enforced socially, not technically; bad-faith reviews can be flagged.