Skip to main content
Explicit review decisions require the review-state migration and a compatible backend deployment. Documentation publication does not enable the feature. Check review capabilities before integrating. For managed documents, missing or unknown review_status stops automatic processing. Projects explicitly opt in after customer integrations support terminal decisions. False or absent review_decision_managed keeps existing legacy behavior; it never enrolls a document implicitly.

Select the contract first

Read review_decision_managed from the existing extraction response. False or absent preserves your existing legacy processing, polling, editing, and PUT integration. Do not switch that document because its project later opts in. Only new requests explicitly sending review_contract="decisions_v1" can become managed, subject to project activation and trusted access. Omitted requests remain legacy, even when other robots in that project adopt the feature. True uses the managed helper below. The helper returns legacy_policy if the server says the document is unmanaged; it does not infer a managed approval.

Poll each known document

Read GET /api/v1/review/{document_id} for authoritative state and decision evidence. For approval, retrieve the exact extraction ID from the audit event. For a document without a decision, query extraction history by document ID and require one matching record. Keep the work item identity in your integration. A document disappearing from the pending list does not prove approval.

Python example

This function returns a named outcome. The caller must handle cancellation, legacy policy, and timeout separately. It never returns extraction data for a rejected, expired, or unknown state.

Polling limits and failures

Use a bounded interval, such as 10?15 seconds, and back off on temporary failures. Respect Retry-After when supplied. Stop automatic processing on access errors or unknown state. For multiple documents, apply the same state dispatch to each known document; paginate history if querying a list. Do not poll only the pending queue to detect approval. A local timeout stops waiting in your process. It does not approve, reject, or expire the document. Caller-triggered expiry is a separate API-key request and requires pending age strictly greater than ten days. There is no scheduler or webhook in this contract. For 409 on a decision request, refresh state and capabilities. Do not automatically submit a different decision. After an uncertain network failure, retry the exact decision payload with its original idempotency UUID and caller identity.

Node.js state dispatch

Apply this dispatch after reading authoritative state and its stored extraction. cancelWorkItem, processDocument, and applyLegacyPolicy are functions owned by your integration.

Batch and concurrent polling

Keep a set of document IDs that belong to your workflow. Poll each ID with the same dispatcher and remove it only after recording a named terminal outcome. Cancel rejected/expired work items separately from successful outputs. Bounded concurrency prevents a large batch from exhausting API limits. An empty page or an item absent from a pending queue is not a terminal outcome. Configure polling interval, local timeout, and maximum backoff per workflow. These settings control your process, not server expiry. Track approved, rejected, expired, legacy-policy, local-timeout, and technical-failure counts separately. Do not log API keys or document contents.