Skip to main content

Review Batch

Apply one approve or reject decision to many review records with POST /v1/review/batch: per-item outcomes, partial-failure reporting, overwrite semantics.

POST /v1/review/batch applies one review decision (approve or reject) to many review items in a single API call. This is the fastest way to clear backlogs when you have high-confidence items that can be bulk-approved, or when rejecting a batch of items from a failed extraction run. The single action applies to every id — mixed verdicts take two calls with the corresponding id lists.

Validation is all-or-nothing, execution is per-item. The request is rejected as a whole with a 400 when ids is empty or contains anything that is not a well-formed UUID — no record is touched in that case. Once the shape is valid, each id is processed independently: records that exist are updated, and ids that match nothing produce an error entry without aborting the rest. processed and failed summarize the split, and results carries the per-id outcome in your input order.

An id fails with not_found in three indistinguishable cases: the record does not exist, it belongs to another workspace, or its source document is hidden from your API key's minting user by source-visibility rules. Hidden records are never mutated. Ids that resolve are actioned regardless of their current status — a batch approve overwrites an earlier rejection, and re-batching already-approved ids is a harmless no-op that still counts toward processed.

The batch write is narrower than the single-item action: it sets status and reviewed_at on each record but carries no reason, so review_comment is untouched and reviewed_by stays null. When individual audit comments matter — typically for rejections — loop over [POST /v1/review/:id/action](review-action) with a per-record reason instead. Items are processed sequentially on the server, so very large batches extend request latency roughly linearly; batches of 50–100 ids keep round-trips comfortable.

The batch endpoint processes items independently. If some items fail (e.g. not found), the remaining items are still processed — always check the results array for per-item outcomes rather than treating the HTTP 200 as all-approved.
POST/v1/review/batch

Body parameters

ids*string[]Non-empty array of review item UUIDs. Any malformed UUID fails the whole request with 400 before anything is processed.
action*stringAction to apply to every ID: `approve` or `reject`.

curl

curl -s -X POST https://api.talonic.com/v1/review/batch \
  -H "Authorization: Bearer tlnc_your_api_key" \
  -H "Content-Type: application/json" \
  -d '{
    "ids": [
      "a1b2c3d4-e5f6-7890-abcd-ef1234567890",
      "b2c3d4e5-f6a7-8901-bcde-f12345678901",
      "c3d4e5f6-a7b8-9012-cdef-123456789012"
    ],
    "action": "approve"
  }'

Response

Response fields

processedintegerNumber of records successfully actioned.
failedintegerNumber of records that could not be actioned.
resultsarrayPer-record outcome array, in the order the ids were sent.
results[].idstringReview record UUID.
results[].statusstringResulting status (approved, rejected) or "error" if the record could not be actioned.
results[].errorstringError code when status is "error" — not_found covers missing, foreign, and visibility-hidden records alike.

Response (partial failure)

{
  "processed": 2,
  "failed": 1,
  "results": [
    { "id": "a1b2c3d4-e5f6-7890-abcd-ef1234567890", "status": "approved" },
    { "id": "b2c3d4e5-f6a7-8901-bcde-f12345678901", "status": "approved" },
    { "id": "c3d4e5f6-a7b8-9012-cdef-123456789012", "status": "error", "error": "not_found" }
  ]
}

Errors

Error responses

400validation_errorEmpty ids array, a malformed UUID in ids, or an action other than approve/reject. Nothing is processed.
401unauthorizedMissing or invalid API key.
403insufficient_scopeThe key lacks the write scope.
429rate_limitedToo many requests. Retry after the period indicated in the Retry-After header.

A common pattern is to first call GET /v1/review?status=pending to collect IDs, filter client-side by overall_confidence above a safe threshold, then batch-approve those IDs here. Retries are safe: re-sending the same batch re-applies the same terminal statuses, so a timed-out call can be repeated without corrupting state — only reviewed_at moves forward.

Frequently asked questions

Is there a limit on how many items I can batch?+
There is no hard cap on array size, but items are processed sequentially on the server, so request latency grows with batch size. Batches of 50–100 items keep round-trips fast while still clearing backlogs quickly.
What happens if some items in the batch are already approved?+
Items that exist are actioned regardless of their current status, so a batch approve overwrites an earlier rejection and re-approving is a no-op that still counts as processed. Only IDs that cannot be found (or are hidden from your key) come back as error entries.
Can I mix approve and reject in one batch?+
No. A single `action` applies to every ID in the `ids` array. To approve some items and reject others, send two batch requests with the corresponding ID lists.
Can I attach a reason to batch decisions?+
No — the batch body carries only ids and action, so review_comment is left untouched on every record. When rejection reasons matter for audit, use POST /v1/review/:id/action per record, which accepts a reason.
Why is one id reported not_found when I can see it in the UI?+
The per-item not_found covers three cases identically: the id does not exist, it belongs to a different workspace, or the record's source document is hidden from the user who minted your API key. In the last case the record is real but not actionable with that key.
Does a 100-item batch count as 100 requests against my rate limit?+
No — rate limiting is per HTTP request, so one batch call consumes one unit of the platform namespace regardless of how many ids it carries. Batching is therefore also the rate-limit-friendly way to clear a large backlog compared to looping the single-item action.