import time
import requests
def poll_for_review(document_id, api_key, project_id=None, timeout=600):
base = "https://api.documind.cloud/api/v1"
headers = {"X-API-Key": api_key}
if project_id:
headers["X-Project-ID"] = project_id
deadline = time.monotonic() + timeout
interval = 10
while time.monotonic() < deadline:
try:
response = requests.get(
f"{base}/review/{document_id}", headers=headers, timeout=30
)
if response.status_code == 429 or response.status_code >= 500:
time.sleep(interval)
interval = min(interval * 2, 60)
continue
response.raise_for_status()
except (requests.Timeout, requests.ConnectionError):
time.sleep(interval)
interval = min(interval * 2, 60)
continue
review = response.json()
if review.get("review_decision_managed") is not True:
return {"outcome": "legacy_policy"}
state = review.get("review_status")
if state in ("rejected", "expired"):
return {"outcome": "cancel", "review_status": state}
if state == "legacy_reviewed":
return {"outcome": "legacy_policy", "review_status": state}
if state == "approved":
extraction_id = (review.get("decision") or {}).get("extraction_id")
if not extraction_id:
raise RuntimeError("Approval evidence unavailable; stop processing")
response = requests.get(
f"{base}/data/extractions/{extraction_id}", headers=headers, timeout=30
)
response.raise_for_status()
extraction = response.json()
if extraction.get("document_id") != document_id or extraction.get("status") != "completed":
raise RuntimeError("Approved extraction not completed; stop processing")
results = extraction.get("reviewed_results")
if results is None:
results = extraction.get("results")
if not isinstance(results, dict):
raise RuntimeError("Approved results unavailable; stop processing")
return {"outcome": "continue", "results": results}
if state == "not_required":
response = requests.get(
f"{base}/data/extractions", headers=headers,
params={"document_id": document_id, "limit": 2}, timeout=30
)
response.raise_for_status()
items = response.json().get("items", [])
if len(items) != 1:
raise RuntimeError("Document missing or ambiguous; stop processing")
extraction = items[0]
if extraction.get("review_status") != "not_required":
raise RuntimeError("Review state changed; poll again before processing")
if extraction.get("status") == "completed":
return {"outcome": "continue", "results": extraction["results"]}
if extraction.get("status") == "failed":
raise RuntimeError("Extraction failed; stop processing")
elif state != "pending":
raise RuntimeError("Review state unavailable; check compatibility")
time.sleep(interval)
return {"outcome": "local_timeout"}
# The API key comes from your application's secret configuration.
# Dispatch explicitly. Do not use result truthiness as proof of approval.
outcome = poll_for_review(document_id, api_key, project_id)
if outcome["outcome"] == "continue":
process_document(outcome["results"])
elif outcome["outcome"] == "cancel":
cancel_downstream_work_item(document_id)
elif outcome["outcome"] == "legacy_policy":
apply_existing_legacy_policy(document_id)
else:
alert_review_team(document_id)