Skip to content

Change a manual mark

PATCH
/v1/results/{id}
curl --request PATCH \
--url https://beta-api.plune.ai/v1/results/example \
--header 'Authorization: Bearer <token>' \
--header 'Content-Type: application/json' \
--data '{ "status": "passed", "errorContext": null, "steps": [ { "index": 0, "status": "passed" }, { "index": 1, "status": "passed" }, { "index": 2, "status": "passed" } ] }'

The «To run» section of the run page (D34, api.ts → patchResult): a person who marked a case changes the mark — its status, its message, its steps — in place, while the run is open. Only a result with source: manual answers: a reporter’s result is evidence, and a run of 40 cases must not count 41 because one mark was corrected. Audited under the run. A patch never sets or changes failure; the message is sanitized like a submission’s.

id
required
string
Media type application/json

At least one key. Only a result with source: manual in an open run takes a patch — a reporter’s result is evidence and stands (404), and a closed run keeps its marks (409). outcome is recomputed from the new status.

object
status
string
Allowed values: passed failed broken blocked skipped
errorContext

null clears the message; redacted and truncated like a submission’s.

string
nullable
steps
Array<object>
nullable <= 200 items
object
index
required

The step’s position in the case’s steps, from 0.

integer
status
required
string
Allowed values: passed failed skipped
Example
{
"status": "passed",
"errorContext": null,
"steps": [
{
"index": 0,
"status": "passed"
},
{
"index": 1,
"status": "passed"
},
{
"index": 2,
"status": "passed"
}
]
}

The result as it is now

Media type application/json

One stored result, as every reader returns it — a run’s results, a test’s history, a corrected mark.

object
errorContext

Returned sanitized — no colour codes, no credentials — whether it was stored before the rules existed or after.

string
nullable
errorContextMeta

What the platform removed before storing — written whenever something was, even without text; null when nothing ever was.

object
redacted
required

Values replaced by a marker, in the text and in every string of failure, each once. The headline counts only when there is no text — otherwise it repeats a line of it.

integer
truncated
required

Whether the TEXT was cut to 256 KB. A shortened field of failure carries its own ….

boolean
failure

What the reporter said about the failed attempt, or null.

object
headline
string
<= 300 characters
steps
Array<string>
<= 20 items
stepsOmitted

How many steps between the outer and the inner ones were left out. Absent when none were.

integer
>= 1
location
object
file
required

From the repository root in posix form, the way a case’s specRef names it. A path of the machine is refused: absolute, with a drive or a scheme, from a home (~), or climbing out with ...

string
>= 1 characters /^(?![A-Za-z][A-Za-z0-9+.-]*:)(?![\\/~])(?!(?:.*[\\/])?\.\.(?:[\\/]|$)).+$/
line
required
integer
>= 1
column
integer
>= 1
file
string
<= 1000 characters
artifacts
Array
<= 50 items
object
name
required

As the runner named it — screenshot, trace, error-context.

string
>= 1 characters
contentType
string
>= 1 characters
name
string
<= 200 characters
contentType
string
<= 100 characters
artifactsOmitted

How many artifacts past the listed ones there are — all reachable through ciUrl.

integer
>= 1
ciUrl
string format: uri
/^[Hh][Tt][Tt][Pp][Ss]?:///
files

Files uploaded to this result — screenshots, and text (JSON, plain text, logs) — oldest first (ADR 0040) — present on a run’s results list, and only when there is one. The bytes are GET /v1/files/{id}.

Array<object>

A file of a result, everything but its bytes (ADR 0040).

object
id
required
string
name
required

The last segment of the name it was uploaded with, cleaned of credentials as a text is.

string
contentType
required

A log is text/plain.

string
Allowed values: image/png image/jpeg image/webp application/json text/plain
size
required

Bytes as kept: a picture at most 2 MiB; a text at most 512 KiB, and counted after its credentials are cleaned, so it can differ from what was sent.

integer
key
additional properties
any
Example
{
"id": "6f1c2b3a-0000-4000-8000-0000000000e1",
"runId": "6f1c2b3a-0000-4000-8000-0000000000d1",
"testCaseId": "6f1c2b3a-0000-4000-8000-0000000000c1",
"resultKey": "manual:6f1c2b3a-0000-4000-8000-0000000000c1",
"signature": "7f974c61f8f10065cd8ae6993cc069e4f85b1db1ed008b965885fb6f945a28c9",
"status": "passed",
"rawStatus": null,
"source": "manual",
"expectedStatus": "passed",
"outcome": "expected",
"execution": null,
"durationMs": null,
"caseVersion": 1,
"errorContext": null,
"errorContextMeta": null,
"assertions": [],
"steps": [
{
"index": 0,
"status": "passed"
},
{
"index": 1,
"status": "passed"
},
{
"index": 2,
"status": "passed"
}
],
"failure": null,
"executedBy": null,
"createdAt": "2026-09-16T09:12:04.151Z"
}

Invalid body, or nothing to change

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

No / invalid token or session

No such manual result in your projects — a reporter’s result reads as not found

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

The run is closed

Media type application/json
object
error
required
string
Example
{
"error": "the run is closed — its results stand"
}

Rate-limited: either the per-route throttle or a tenant quota. Retry-After carries the seconds until the window rolls over.

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

Seconds until the window rolls over