Post a new agent draft (redraft) under a parent_revision CAS
POST /v1/reviews/{id}/revision
Post a NEW agent draft for a review (M5; spec §5.2; D17 “the human always wins”). parent_revision must equal the draft’s current revision, else 409 STALE with NO mutation (a human/inbound actor moved the draft; it becomes a learning / front-run signal). On a clean CAS the proposed_* body is re-rendered in place (revision++), the draft returns to needs_review, and the reviewer nudge + review event fire (all atomic in one WithTx). rules_version_seen is pinned on the new draft. $0 LLM; the agent composes the redraft.
Authorizations
Section titled “Authorizations ”Parameters
Section titled “ Parameters ”Path Parameters
Section titled “Path Parameters ”Request Body required
Section titled “Request Body required ”Post a NEW agent draft under a parent_revision CAS (D17). parent_revision is the PRIMARY conflict check; it must equal the draft’s current revision, else 409 STALE with NO mutation (a human/inbound actor moved the draft). version is OPTIONAL belt-and-suspenders (a human edit that did not bump the revision still bumps the version). On a clean CAS the proposed_* body is re-rendered in place (revision++), the draft returns to needs_review, and the reviewer nudge + review event fire (all atomic). rules_version_seen pins the rule high-water the draft was composed against (born-stale basis, D19).
object
Replace this recipient group; omit to preserve, [] to clear. Quota changes atomically with the draft; insufficient quota preserves the previous draft and reservation.
Replace this recipient group; omit to preserve, [] to clear. Quota changes atomically with the draft; insufficient quota preserves the previous draft and reservation.
Replace this recipient group; omit to preserve, [] to clear. Quota changes atomically with the draft; insufficient quota preserves the previous draft and reservation.
The revision the agent composed against (PRIMARY CAS).
Highest committed, available recheck event sequence actually handled. Completion commits with the revision; newer work remains pending. Omit for legacy mutations without completion.
Required for reply revisions. Obtain from a fresh complete thread read before reconsidering the draft. A changed conversation returns reply_context_changed (409) without replacing the draft.
Optional row-version CAS (defense in depth).
Plain-text body of the redraft. This is the canonical name and matches SendRequest.text, ReplyRequest.text, ForwardRequest.text and Message.text, so the same field name composes a message and redrafts it.
DEPRECATED alias for text, kept accepted indefinitely so already-deployed callers keep working; it will never be removed. Send text in new code. Supplying BOTH with different content is a 400 (code bad_request, errors[].code conflicting_alias); the server never guesses which bytes the reviewer will be shown; supplying both with identical content is accepted. Note that Idempotency-Key replay hashes the RAW body, so the same redraft retried once as body and once as text under one key is a 409 idempotency_conflict.
When the agent built this draft (informational).
Rule high-water this draft was composed against (born-stale basis).
Opaque token from a fresh, unfiltered GET /v1/rules for the review’s category.
REPLACES the draft’s attachments. Omit the field to leave them untouched; send an empty array to clear them. Without this a redraft could never restore an attachment, so an agent redrafting after feedback would ship a message the reviewer saw WITH a file and the recipient received without.
An outbound attachment on send/reply/forward.
object
Standard base64-encoded attachment bytes. Up to 20 attachments share the 1,800,000-byte encoded email limit with headers and both bodies.
Responses
Section titled “ Responses ”Ok (the redrafted review, now needs_review at revision+1)
A review request (rr_…); the server-owned pre-send record of a message under the Review Loop. Carries intent, the current proposed draft, category, state machine fields, and (once sent) the sent body + diff.
object
Human-readable category name; absent when unavailable.
Pending reconsideration; does not assert that the composer is online.
Durable composer completion watermark independent of acknowledgement.
Highest available unresolved recheck event sequence.
Cause of pending reconsideration.
Console path to this draft. Sign in and claim the workspace if prompted before reviewing.
Captured sender name for this review; empty means bare address. Absent on legacy reviews.
object
Mail conversation ID for fetching reply or forward context; distinct from reviewer feedback.
Conversation snapshot used for this draft. Absent on legacy drafts whose composition context is unknown.
Newest message observed when composing this draft.
Message selectors in the conversation snapshot used for this draft; does not certify semantic comprehension.
Opaque parent message ID for replies; raw RFC5322 Message-ID for plain sends.
True once this review will never move again; sent, auto_sent, cancelled OR failed. It is the definitive per-review “am I done?” answer and the poll-side companion to the terminal review events; use it after a restart when your event cursor is gone. failed is included deliberately: nothing re-approves a failed review, so treating it as open means waiting forever.
Vendor-scrubbed delivery failure, present on a failed review.
How the message was released, once sent.
Invalid request.
The canonical error envelope. error is a stable machine code.
object
Stable error code (e.g. unauthorized, forbidden, not_found, invalid, quota_exceeded, rate_limited).
Example
forbiddenHuman-readable detail (never leaks internals).
Example
missing required scopeMachine-readable quota reason. inbox_limit_exceeded means billing account inbox capacity across all organizations and projects sharing that account; enrollment_token_mailbox_budget_exhausted means the enrollment key lifetime creation allowance. Read message for recovery; inbox counts are separate from sending quotas.
Consumed plus reserved units.
Requested additional units.
Next UTC usage-period boundary; pending reservations survive this boundary.
Missing or invalid credential.
The canonical error envelope. error is a stable machine code.
object
Stable error code (e.g. unauthorized, forbidden, not_found, invalid, quota_exceeded, rate_limited).
Example
forbiddenHuman-readable detail (never leaks internals).
Example
missing required scopeMachine-readable quota reason. inbox_limit_exceeded means billing account inbox capacity across all organizations and projects sharing that account; enrollment_token_mailbox_budget_exhausted means the enrollment key lifetime creation allowance. Read message for recovery; inbox counts are separate from sending quotas.
Consumed plus reserved units.
Requested additional units.
Next UTC usage-period boundary; pending reservations survive this boundary.
Authenticated but lacking the required scope, or out of quota.
The canonical error envelope. error is a stable machine code.
object
Stable error code (e.g. unauthorized, forbidden, not_found, invalid, quota_exceeded, rate_limited).
Example
forbiddenHuman-readable detail (never leaks internals).
Example
missing required scopeMachine-readable quota reason. inbox_limit_exceeded means billing account inbox capacity across all organizations and projects sharing that account; enrollment_token_mailbox_budget_exhausted means the enrollment key lifetime creation allowance. Read message for recovery; inbox counts are separate from sending quotas.
Consumed plus reserved units.
Requested additional units.
Next UTC usage-period boundary; pending reservations survive this boundary.
Resource not found.
The canonical error envelope. error is a stable machine code.
object
Stable error code (e.g. unauthorized, forbidden, not_found, invalid, quota_exceeded, rate_limited).
Example
forbiddenHuman-readable detail (never leaks internals).
Example
missing required scopeMachine-readable quota reason. inbox_limit_exceeded means billing account inbox capacity across all organizations and projects sharing that account; enrollment_token_mailbox_budget_exhausted means the enrollment key lifetime creation allowance. Read message for recovery; inbox counts are separate from sending quotas.
Consumed plus reserved units.
Requested additional units.
Next UTC usage-period boundary; pending reservations survive this boundary.
A Review Loop conflict, as problem+json. Branch on code, NOT on the 409 status; the four codes demand opposite behavior. stale: the revision/version you named is no longer current (a human moved the draft) and NOTHING was mutated; errors[] carries the current state, revision and version, so re-apply your change on top and resubmit with the new parent_revision (retry, bounded to ~3). born_stale: the redraft was built against an older rule high-water; re-read the rules and resubmit, or restamp_review if nothing genuinely changed (at most one retry per high-water). wrong_state: this VERB is illegal from the current state but the draft is still live; NEVER retry the same verb; errors[] repeats an allowed_action entry per verb that IS legal right now. terminal: the review is already sent/auto_sent/cancelled; nothing will ever succeed, stop retrying, and a front_run_next review event carries the outcome. send_needs_reconciliation: a prior attempt is unconfirmed and parked for recover-by-Message-ID; do NOT resend, poll the review.
RFC-9457 problem+json error body. code is a closed machine enum clients switch on; type is a dereferenceable URI under https://extrovert.dev/problems/. Served as application/problem+json.
object
Structured support failure reason without changing the existing code.
Suggested recovery action within existing access.
object
object
object
object
object
Retained text after a concurrent case change.
The CLOSED machine code. The Review Loop members split what used to be a single opaque conflict, because an agent must take a DIFFERENT action on each: stale (the revision/version you named is no longer current; nothing was mutated; re-read, re-apply, resubmit; retryable, bounded) and born_stale (built against an older rule high-water; re-read the rules or restamp_review; at most one retry per high-water) are the ONLY retryable 409s. wrong_state means this VERB is illegal from the current state while the draft is still live; never retry the same verb, read the state and the repeated allowed_action hints in errors[] and pick a legal one. terminal means the review is already sent/auto_sent/cancelled and nothing will EVER succeed; stop, and drain your review events for the outcome. send_needs_reconciliation means a prior send is unconfirmed and parked. Do not resend. Poll instead. unavailable (503) is the retryable fail-closed answer when a dependency could not be read; it carries Retry-After and is distinct from not_configured, which is permanent for this deployment.