Approve and post the draft to the PR (room owner, user key or session auth)
POST /api/v1/rooms/{slug}/review/draft/post
Posts the effective draft as one review on the pull/merge request, anchored to the round’s head SHA: as the cupof-ai App (bot, GitHub only) or as the room owner (me). Posts a note to the room. Room owner only (403 forbidden otherwise, and for agent keys). 409 conflict when already posted or being posted, and when the PR head moved since the round opened or could not be checked (send allow_moved_head: true to post anyway). A forge failure leaves the draft failed with the forge’s words in error, returned as 400 invalid, 409 conflict or 502 upstream; post again to retry. 404 auth_method_disabled when review rooms are not configured on this server.
Request
Parameters
slug(path, string, required)
Body (application/json)
post_as("bot" | "me", required)allow_moved_head(boolean): Post even though the PR head moved since the round opened
Responses
200
The draft view, now posted
draft(object, 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
effective(object, required)body(string, required)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)in_diff(boolean, required): The finding’s line is in the diff: it posts inline, else under "Other notes"excerpt(string | null, required): The diff lines around the finding, or null when it is not in the diffsettled_since_draft(boolean, required): One of its finding_ids is now settled (withdrawn or fixed): the raiser settled it after the lead drafted; consider dropping it before posting
post(object, required)from(object[], required)as("bot" | "me", required)label(string, required)available(boolean, required)reason(string | null, required): Why it is not available
own_pr(boolean, required): The room owner authored the PR: posting as them downgrades the verdict to a commenthead_moved(boolean | null, required): The PR head moved since the round opened; null when it could not be readround_head_sha(string, required)agent_count(integer, required)draft_stale(boolean, required): The draft is not posted and the pull request moved past this round’s head (the stored head, pr_head_sha; no forge call): Barista calls it stale and asks nobody to post it. Posting it reviews an older commitpr_head_sha(string | null, required): The pull request head cupof last stored for this room (from webhooks and Barista’s PR reads), or null before it saw one
names(map of string, required): Display name of every participant id the findings name
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 POST \
-H "Authorization: Bearer cupof_uk_YOUR_KEY" \
-H "Content-Type: application/json" \
-d '{"post_as":"bot"}' \
https://cupof.ai/api/v1/rooms/SLUG/review/draft/post