Skip to content

Request a draft description and precondition from the project's AI provider

POST
/v1/test-cases/{id}/draft
curl --request POST \
--url https://beta-api.plune.ai/v1/test-cases/2489E9AD-2EE2-8E00-8EC9-32D5F69181C0/draft \
--header 'Authorization: Bearer <token>'

The call to the provider happens inside this request, up to 60 seconds (ADR-0001), so the answer already carries the outcome — drafted, the provider failed, or the call was aborted on timeout. Nothing about the case changes here (AC-01); a prior draft awaiting_decision for this case is replaced, whoever requested it (AC-19). One request per case at a time: while a call for this case is still running — anyone’s, for as long as the provider call can last — a new request is refused with 409 and nothing is paid for twice. The checks (that, and both rate-limit windows) and the start of the call are one atomic step, so requests that arrive together cannot all pass the same check. No request body: the code snapshot, provider, model and language all come from the case and the project’s AI settings, never from the client.

id
required
string format: uuid

The call’s outcome — awaiting_decision with the draft, or failed/aborted with no text (AC-09). A 200 either way: the request itself succeeded.

Media type application/json

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
id
required
string
state
required
string
Allowed values: in_progress awaiting_decision accepted rejected expired failed aborted
mine
required

Whether the caller is the member who requested this call.

boolean
requestedBy
required

userId of the member who asked — resolve through GET /v1/members like TestCaseMeta.createdBy.

string
requestedAt
required
string format: date-time
description

The drafted description, present while there is one to show (mine, and state carries text).

string
nullable
precondition
string
nullable
unseenNote

«Чого чернетка не бачила» — fixtures, hooks, helpers (AC-14). Never a field of the case.

string
nullable
codeChangedSinceRequest

Whether the case’s code snapshot changed, beyond whitespace, since this call was requested (AC-04b).

boolean
inputTokens
integer
nullable
outputTokens
integer
nullable
unitPriceUsd

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).

number
nullable
costUsd

null exactly when unitPriceUsd is null.

number
nullable
durationMs
integer
nullable
failureKind

Present exactly when state is failed.

string
Allowed values: key_rejected provider_rate_limited provider_unavailable invalid_response address_rejected
Examples

AC-01 — the provider answered in time

{
"id": "6f1c2b3a-0000-4000-8000-0000000000c1",
"state": "awaiting_decision",
"mine": true,
"requestedBy": "u-member1",
"requestedAt": "2026-09-16T09:12:04.151Z",
"description": "Opens the checkout page with an empty cart and asserts the empty-state message.",
"precondition": "A logged-in user with an empty cart.",
"unseenNote": "Does not see the `beforeEach` hook, which navigates to /checkout and logs the user in.",
"codeChangedSinceRequest": false,
"inputTokens": 812,
"outputTokens": 96,
"unitPriceUsd": 0.0000031,
"costUsd": 0.0028,
"durationMs": 4210
}

No / invalid token or session

A bearer token asked — requesting a draft is a human-session action only (AC-06)

Media type application/json
object
error
required
string
Example
{
"error": "requires a human session — a token cannot request or decide a draft"
}

Not found or not yours

Media type application/json
object
error
required
string
Example generated
{
"error": "example"
}

The action a client should not have been able to reach — the availability check (GET on this same path) already said no, and something changed the state in between.

Media type application/json
object
error
required
string
Examples

AC-07 — AI was turned off between the check and this request

{
"error": "AI is disabled for this project"
}

AC-10 — refused without calling the provider. Two independent windows: the member’s own (30 per 60 minutes) and the project’s (200 per 24 hours); both survive a restart (backed by ai_calls, ADR-0001) — unlike #/components/responses/RateLimited elsewhere in this document, this is not the in-memory per-instance limiter.

Media type application/json
object
error
required
string
Examples
{
"error": "rate limit exceeded — you can request another draft in 42 minutes"
}
Retry-After
integer

Seconds until enough calls have left the window for this request to pass — the time until the call that has to leave does, not the length of the window; the longer of the two when both are full. The message says the same in words

SAD §7/§11 — the server has no encryption key, so no project’s AI can work

Media type application/json
object
error
required
string
Example
{
"error": "AI platform not configured — contact your operator"
}