Accept selected fields of the pending draft, or reject it
const url = 'https://beta-api.plune.ai/v1/test-cases/2489E9AD-2EE2-8E00-8EC9-32D5F69181C0/draft';const options = { method: 'PATCH', headers: {Authorization: 'Bearer <token>', 'Content-Type': 'application/json'}, body: '{"state":"accepted","fields":{"description":"Opens the checkout page with an empty cart and asserts the empty-state message.","precondition":"A logged-in user with an empty cart."}}'};
try { const response = await fetch(url, options); const data = await response.json(); console.log(data);} catch (error) { console.error(error);}curl --request PATCH \ --url https://beta-api.plune.ai/v1/test-cases/2489E9AD-2EE2-8E00-8EC9-32D5F69181C0/draft \ --header 'Authorization: Bearer <token>' \ --header 'Content-Type: application/json' \ --data '{ "state": "accepted", "fields": { "description": "Opens the checkout page with an empty cart and asserts the empty-state message.", "precondition": "A logged-in user with an empty cart." } }'Mirrors PATCH /v1/review-items/{id}’s { state } shape. state: accepted takes fields — the final text of description and/or precondition (as the draft read it, or edited); a field left out of fields is not taken and the case keeps what it had (AC-03) — and so is a field sent empty or holding only whitespace: a field the member cleared takes nothing, and an accept with nothing left to take answers 400. Only the member who requested the pending draft may decide it (AC-19); a bearer token gets the same 403 as on POST. The server compares the CURRENT case text against the fingerprint it took when the draft was requested — the client never sends one (ADR-0002): a field someone changed in between answers 409 with the new text, and the draft is neither consumed nor billed again (AC-04). Accepting when the code changed since the request (not just whitespace) still succeeds; the accepted field is marked as drafted from a previous version of the code (AC-04b, AC-16) rather than refused. A draft is decided once: of two decisions arriving together — accept and reject from two tabs, or a double click on accept — one decides and the other answers 409, and the case carries only what the one that decided wrote.
Authorizations
Section titled “Authorizations ”Parameters
Section titled “ Parameters ”Path Parameters
Section titled “Path Parameters ”Request Body required
Section titled “Request Body required ”state: accepted requires fields with at least one of description/precondition — the final text to store, exactly as the member wants it kept (draft text verbatim, or edited). state: rejected takes no fields.
object
object
Examples
AC-02 — take both fields as the draft wrote them
{ "state": "accepted", "fields": { "description": "Opens the checkout page with an empty cart and asserts the empty-state message.", "precondition": "A logged-in user with an empty cart." }}AC-02, AC-03 — take one field, edited; the other stays as it was
{ "state": "accepted", "fields": { "precondition": "A logged-in user whose cart was emptied by the previous test." }}AC-03 — decline the whole draft
{ "state": "rejected"}Responses
Section titled “ Responses ”Decided — testCase is the updated case on accepted, null on rejected
object
One call record (ADR-0002), as returned to a project member. When mine is false — a pending draft somebody else requested — every field below requestedAt is withheld (AC-19): content, tokens and cost are for the requester alone until a decision is made.
object
Whether the caller is the member who requested this call.
userId of the member who asked — resolve through GET /v1/members like TestCaseMeta.createdBy.
The drafted description, present while there is one to show (mine, and state carries text).
«Чого чернетка не бачила» — fixtures, hooks, helpers (AC-14). Never a field of the case.
Whether the case’s code snapshot changed, beyond whitespace, since this call was requested (AC-04b).
The average price per token of this call (costUsd ÷ tokens) — input and output tokens are priced apart. null means “ціна невідома” (the model has no price) or that the provider reported no tokens to price; never 0 (SAD §8 rule 6, AC-15).
null exactly when unitPriceUsd is null.
Present exactly when state is failed.
The updated case on accepted (unchanged TestCase shape, TestCaseMeta.textOrigin included); null on rejected — the case did not change (AC-03).
object
Examples
{ "call": { "id": "6f1c2b3a-0000-4000-8000-0000000000c1", "state": "accepted", "mine": true, "requestedBy": "u-member1", "requestedAt": "2026-09-16T09:12:04.151Z" }, "testCase": { "id": "6f1c2b3a-0000-4000-8000-0000000000c1", "description": "Opens the checkout page with an empty cart and asserts the empty-state message." }}{ "call": { "id": "6f1c2b3a-0000-4000-8000-0000000000c1", "state": "rejected", "mine": true, "requestedBy": "u-member1", "requestedAt": "2026-09-16T09:12:04.151Z" }, "testCase": null}Invalid body — unknown state, fields empty on accepted, or a field over 16384 bytes (AC-18)
object
Examples
{ "error": "validation failed — fields: at least one of description, precondition is required when accepting"}{ "error": "validation failed — fields.description: must be at most 16384 bytes"}No / invalid token or session
A bearer token asked, or a different member than the one who requested this draft
object
Examples
{ "error": "requires a human session — a token cannot request or decide a draft"}{ "error": "only the member who requested this draft may decide it"}Not found or not yours
object
Example generated
{ "error": "example"}AC-04 — the draft is not (or no longer) awaiting a decision, OR a field being taken changed on the case after the draft was requested, OR the case kept changing while the draft was being accepted (#1019): someone else saved it again and again, and nothing was written. The second carries current — the fields that changed, with their text as the case holds it now — so the client shows it beside the draft, per AC-04. The third carries current too, with every field being taken as it stands, which may be the very text the draft was requested against: what moved is the case, not necessarily those fields. The draft stays waiting, and accepting it again is the retry.
object
The field(s) that changed, as the case holds them now (AC-04) — present only on the field-conflict branch, absent on “not awaiting a decision”.
object
Examples
Already decided (a moment ago, from another tab, too), expired, or superseded by a newer request
{ "error": "this draft is no longer awaiting a decision"}AC-04 — someone saved a change to a field being taken
{ "error": "precondition changed after the draft was requested", "current": { "precondition": "A logged-in user with two items already in the cart." }}#1019 — the case was saved by someone else again and again while the draft was being accepted; nothing was written and the draft is still waiting
{ "error": "the case kept changing while the draft was being accepted — reload and try again", "current": { "precondition": "A logged-in user with two items already in the cart." }}Rate-limited: either the per-route throttle or a tenant quota. Retry-After carries the seconds until the window rolls over.
object
Example generated
{ "error": "example"}Headers
Section titled “Headers ”Seconds until the window rolls over