One page of the review queue, newest first
const url = 'https://beta-api.plune.ai/v1/review-items?state=pending&limit=50';const options = {method: 'GET', headers: {Authorization: 'Bearer <token>'}};
try { const response = await fetch(url, options); const data = await response.json(); console.log(data);} catch (error) { console.error(error);}curl --request GET \ --url 'https://beta-api.plune.ai/v1/review-items?state=pending&limit=50' \ --header 'Authorization: Bearer <token>'BREAKING as of R3: this read is always paged. A client that read items and never looked at nextCursor now sees only the first page. A limit outside the range is clamped; an invalid cursor is REFUSED rather than answered with the start of the queue — a silent restart reads as “nothing changed”, which is how the middle of a queue disappears unnoticed.
Authorizations
Section titled “Authorizations ”Parameters
Section titled “ Parameters ”Query Parameters
Section titled “Query Parameters ”Narrow to one state; omit for everything.
Page size. The maximum equals the ceiling on items per decision, so a list built from one visible page can never exceed what a single decision accepts.
nextCursor from the previous page. Omit for the first page.
Responses
Section titled “ Responses ”One page of your queue
object
The LIST form of a queue item, deliberately lighter than the single-item form. It names WHICH fields differ from the matched case, not what they contain, and carries a proposal’s title instead of the proposal. The full comparison is unbounded in the size of the proposal it describes, so a page of them could not hold a weight ceiling — read one item to get it. All THREE kinds of entry are reduced the same way: a disputed result keeps resultId, a proposal becomes proposedTitle, and a discovered test becomes discoveredTitle with discoveredSpecRef. Exactly one group is present.
object
Present on an entry disputing a RESULT.
The proposal’s title alone. Present exactly where proposedCase is on the single-item read — a one-field object would have promised a structure that is not there.
Which test was discovered. Present exactly where discoveredTest is on the single-item read (ADR 0029). Its keys are NOT here: they are bounded at 32 x 1024 characters, which is 32 KB on one row of a 256 KB page — read one item to get them.
Where that test lives, so a page can be scanned by location without opening anything. Accompanies discoveredTitle and never appears without it.
object
Source and technique ride a row because they DIFFER between rows — a reviewer can see a whole batch made by one method without opening anything. The rationale and the run cost are NOT here: the first would not fit the page budget, and a cost repeated down twenty rows reads as the cost of each proposal. Open an item for both.
The case an approved proposal became. Present only on an approved proposal: an entry that disputes a result never has one, and a pending or rejected proposal does not have one yet. This is the answer to “did the decision take” — the platform creates nothing silently, and this is where it says what it created.
Absent when no key matched — see CaseMatch for why the three cases are one answer.
object
An identifier another tool already uses for this test, so a report can find its case without anyone typing a Plune id. The order of kind is load-bearing: it is the ranking that decides which key wins when several match different cases.
object
Which fields differ. Empty means the proposal matches the case field for field; the VALUES live on the single-item read.
object
What happened to the test.
Whether it behaved as expected. Independent of statusChanged: a test can stay just as unsuccessful and still move from broken to failed, and that is exactly what changes what a reviewer does next. Both axes are reported always, changed or not, so that “the state moved and the behaviour did not” is never something to infer from a missing field.
Pass as cursor to read the next page; null on the last one. Keyset over the same pair the queue is ordered by — "<createdAt>|<id>", the spelling the audit feed already uses — so an item on a page boundary is neither skipped nor served twice.
Example
{ "items": [ { "schemaVersion": 1, "source": { "kind": "url" }, "state": "pending", "rejectionCategory": "duplicate", "match": { "matchedBy": { "kind": "playwright-id" }, "changedFields": [ "title" ] }, "previousRun": { "previousStatus": "passed", "previousOutcome": "expected" } } ]}Unknown state, or a position that is not a valid cursor
object
Example generated
{ "error": "example"}No / invalid token or session