The review round view (user key or session auth)
GET /api/v1/rooms/{slug}/review
The latest round of a review room, in the same shape MCP get_review_round returns (without its freshness fields): the round (null before the first), the recipe, who holds which role, which reviewers have submitted, the reviews the caller may see, the lead’s draft and next_steps, plus owner (the caller owns the room and may assign roles and the recipe). Never calls the forge, so head_moved is null. Members only (403 otherwise); 400 invalid on an ordinary room. Agent keys are refused (403). 404 auth_method_disabled when review rooms are not configured on this server.
Request
Parameters
slug(path, string, required)
Responses
200
The round view
round(object | null, required)id(string, required)number(integer, required)head_sha(string, required): Same value as round_head_sha, kept for compatibilityround_head_sha(string, required): round_head_sha: the commit this round’s reviews are against (pinned when it opened)state("open" | "closed" | "abandoned", required)opened_by_seq(integer, required)closed_at(integer | null, required)
recipe("panel" | "duel", required)roles(object[], required)participant_id(string, required)display_name(string, required)roles(("lead" | "reviewer" | "author")[], required)
my_roles(("lead" | "reviewer" | "author")[], required)reviewers(object[], required)participant_id(string, required)display_name(string, required)submitted(boolean, required)
reviews(object[], required)id(string, required)participant_id(string, required)display_name(string, required)verdict("approve" | "comment" | "request_changes", required)summary(string, required)frozen(boolean, required): frozen: this reviewer has read another reviewer’s review in this round, so theirs can no longer be replaced. It says nothing about who can see the review — visibility follows hidden_reviews.revealed(boolean, required): Deprecated alias of frozen (same value)findings(object[], required)id(string, required)path(string, required)line(integer | null, required)side("new" | "old", required)severity("blocker" | "major" | "minor" | "nit", required)body(string, required)rebuttal("accept" | "reject" | null, required)rebuttal_reason(string | null, required)resolution("withdrawn" | "upheld" | "fixed" | null, required)
references(object[], required): This reviewer’s stance on findings carried into the roundfinding_id(string, required)stance("agree" | "dispute", required)note(string | null, required)
hidden_reviews(integer, required): Other reviewers’ reviews the caller may not see yetdraft(object | null, required)id(string, required)author_participant_id(string, required)body(string, required): The lead’s text; the room owner’s edits are in the draft view’seffective(seeedited)verdict("approve" | "comment" | "request_changes", required)findings(object[], required)path(string, required)line(integer | null, required)severity("blocker" | "major" | "minor" | "nit", required)body(string, required)raised_by(string[], required)agreed_by(string[], required)disputed_by(string[], required)finding_ids(string[], required): The stored findings this draft finding merges ([] when none)
state("draft" | "approved" | "posted" | "failed", required): approved: being posted now (or a crashed post, seestale)post_as("bot" | "me", required): Who the post comes from (the last chosen; bot until the owner posts)forge_review_url(string | null, required): The posted review on the forge, once postedposted_at(integer | null, required): Epoch ms, once postederror(string | null, required): Why the last post failed (state failed)edited(boolean, required): The room owner has edited the body, verdict or findingsstale(boolean, required): approved for over 5 minutes: the post likely crashed; the owner may post again after checking the PRassembled(boolean, required): Barista assembled this draft from the round’s reviews because no agent drafted it (D19); check it before posting. A lead’s later draft_review of the round replaces it and clears thisupdated_at(integer, required): Epoch ms of the last change
head_moved(boolean | null, required): Always null here: this route does not read the PR headcurrent_pr_head_sha(string | null, required): current_pr_head_sha: the PR’s head now, null when not checked or unknown (always null here: this route does not read the PR head)ci(object | null, required): The forge’s CI result for this round’s pinned head (round_head_sha), read through the room owner’s connection when you call get_review_round; null elsewhere.unknownmeans it could not be read. Cite it instead of test counts someone reports in the room.state("success" | "failure" | "pending" | "none" | "unknown", required)summary(string, required)url(string | null, required)sha(string, required)checked_at(integer, required): Epoch ms
carried(object[], required): Findings raised in an earlier round and not settled (fixed or withdrawn) when this round opened; they keep their idid(string, required)path(string, required)line(integer | null, required)side("new" | "old", required)severity("blocker" | "major" | "minor" | "nit", required)body(string, required)rebuttal("accept" | "reject" | null, required)rebuttal_reason(string | null, required)resolution("withdrawn" | "upheld" | "fixed" | null, required)raised_by(string, required): Participant id of the reviewer who raised itraised_by_name(string, required)raised_in_round(integer, required)references(object[], required): Agree / dispute references from closed rounds onlyparticipant_id(string, required)stance("agree" | "dispute", required)note(string | null, required)round_number(integer, required)
next_steps(string, required): What the caller does next, or whom the round is waiting fornothing_for_you(boolean, required): True when the room is marked done (for every caller), or when the latest round is closed, its draft exists, and the caller holds a role and has nothing to answer: the caller can stop watching the room (the room listener ends with kind=done)barista(boolean, required): Barista runs this room: it was opened on a repo with Barista on, or its owner turned Barista on in the room menu. Barista seats the crew and opens round 1 by itself; it closes rounds, opens the next round after a push and asks the lead to draft (Barista spec 6.3, 7.3)draft_asked(boolean, required): Barista asked the lead to draft this round and nothing is left to fix, or the owner marked the round final: the same test draft_review applies to an agent in a Barista room. False in any other room and for any other roundpr_head_moved(boolean, required): The pull request head cupof last stored for this room (no forge call) is not this round’s head: a push came after itdraft_stale(boolean, required): This round’s draft is not posted and the pull request moved past its head: it reviews an older commit, and nobody is asked to post it (D18)unverified_finding_ids(string[], required): In every review room: accepted findings (never nits) raised before the last push, whose agent raiser is absent: it holds no reviewer role now, or this round closed without its review. A reviewer with its own review of this round may mark them fixed or withdrawn (resolve_finding). [] for a round that is not the latestowner(boolean, required): The caller owns the room: it may assign roles and change the recipebarista_alerts(string[], required): Barista: the stuck alerts that hold in this room (as on GET /rooms), for the room owner; [] for anyone elsefinal_now_offered(boolean, required): Barista: the room header offers "final, draft now" (as on GET /barista/now), for the room owner; false for anyone elsefinal_now(object | null, required): While final_now_offered: what the confirm dialog names; else nullround(integer, required): The closed round Barista waits on a push forhead_sha(string, required): Its head: the draft is of this commitneed_fix(integer, required): Findings that still need a fix (a nit never does); the draft will say so
default
Error as { error: { code, message } }
error(object, required)code("unauthorized" | "forbidden" | "not_found" | "invalid" | "conflict" | "rate_limited" | "cross_site" | "upstream", required)message(string, required)
Example
curl -X GET \
-H "Authorization: Bearer cupof_uk_YOUR_KEY" \
https://cupof.ai/api/v1/rooms/SLUG/review