Skip to main content
Machine extraction is AwaitVerify’s machine-only tier. Where verify_document() puts a human reviewer on every document, POST /api/v1/extract runs the extraction entirely by machine and returns per-field confidence scores — with an optional toggle to escalate low-confidence fields to AwaitVerify’s human reviewers before the response returns. Use it when you have document volume that doesn’t justify a human on every page, but you still want honest signals about which fields to trust.
Call it from the Python SDK (pip install awaithumans) with extract_document() / awaitExtract, or hit the HTTP endpoint directly — both are shown below.

The endpoint

Get your API key from app.awaithumans.dev/keys — the same key you use for verify_document(). One request carries one document page image, base64-encoded. image/png or image/jpeg, max 10 MB. Multi-page documents: rasterize each page and send one request per page.

Request

Send exactly one of doc_type or response_schema — both or neither is a 422.

Response

Abbreviated passport example:

Confidence scores are provisional — read this before thresholding

The calibration object tells you how to interpret the scores, and right now it says "calibrated": false. Here is what that means, honestly: While calibrated is false, confidence and agreement are provisional rank-orderings, not probabilities. They come from two signals:
  1. K-sample cross-model agreement — we run the extraction multiple times (usage.samples) across models and measure how often the samples agree on each field.
  2. Deterministic validators — where the document format allows it, we verify fields mechanically. For passports, that’s the ICAO 9303 MRZ check digits: if a check digit fails, the field’s confidence is capped near zero regardless of agreement.
A provisional confidence of 0.9 does not mean “90% chance the value is correct.” It means the field ranks higher than a field scored 0.7. Use provisional scores to rank fields for review and to drive the human_review toggle — do not hard-threshold them in your own pipeline (e.g. “auto-accept everything above 0.85”) as if they were error rates. calibrated: true turns on automatically once our labeled dev set is in place. At that point scores become calibrated probabilities and we publish threshold→error tables, so “reject below 0.85” becomes a statement with a known error rate. Until then, every field carries the PROVISIONAL_CALIBRATION flag as a machine-readable reminder.

Field flags

The human_review toggle

With human_review set to "low_confidence" or "all", the request blocks until human review completes — set your HTTP client timeout accordingly. With "off", responses are machine-fast.

Custom schemas

When none of the built-in document types fit, define your own fields:
Field type selects the engine’s comparison semantics: "string" (case-insensitive), "code" (exact, uppercase — identifiers, reference numbers), "date" (must be YYYY-MM-DD; anything else is flagged FORMAT_INVALID). Up to 40 fields; names are snake_case. Every field is nullable — the engine abstains rather than guesses, same as the built-in schemas. Custom schemas have no deterministic validators, so their ceiling reflects the unvalidated discount until calibration takes over.

Envelopes: one applicant, several documents

POST /api/v1/extract/envelope extracts 2–10 documents belonging to the same applicant in one call and cross-checks them against each other — the passport number quoted on a travel declaration, the passenger name on a ticket against the passport surname, nationalities across documents.
The response carries a full extraction result per document (same shape as the single-document response), plus envelope_confidence and a cross_checks list describing every detected inconsistency. When two documents disagree, both fields are capped and flagged CROSS_DOC_MISMATCH — the system knows they can’t both be right, not which one is misread. Pages bill together at the machine rate. Envelopes are machine-only: run documents individually if you want the human_review toggle.

Examples

Python SDK

extract_document_sync(...) is the blocking variant. Reads the AWAITHUMANS_API_KEY and AWAITHUMANS_MANAGED_URL environment variables, or pass api_key= / managed_url= explicitly. With human_review on, the call blocks until review completes — the SDK sizes its timeout accordingly. For several documents from one applicant, extract_envelope(documents=[...]) maps to the envelope endpoint.

curl

Python (httpx)

Errors

Every error response carries a stable error_code you can pattern-match on.

Pricing

Human-escalated pages (via human_review) additionally bill at the human verification rate — $0.80/page standard. usage.cost_cents on each response tells you exactly what the request cost, and usage.balance_after_cents what’s left. Billing draws from the same balance as verify_document(); top up at app.awaithumans.dev/billing.

Privacy and retention

Processing is ephemeral. Page images are deleted at response time — once you have the response, we no longer have the image. We retain only extraction metadata (timestamps, doc type, confidence statistics, usage); never field values, never images. One exception, bounded and controllable: quality-assurance sampling. A small percentage of extractions is reviewed by AwaitVerify’s human reviewers to calibrate the confidence scores, under a bounded 30-day retention window. You can disable QA sampling from your dashboard settings or by contract — when disabled, nothing is retained.

Where to go next

The three flows

When you need a human on every document: verify_document() with Flows A, B, and C.

Security model

Fragmentation, AES-256-GCM, and what we retain vs. what we never see.