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

FieldTypeRequiredNotes
document_base64stringYesOne page image, base64. Max 10 MB decoded.
media_typestringYes"image/png" or "image/jpeg".
doc_typestringYesOne of "passport", "travel_ticket", "airport_stamp", "proof_of_profile", "travel_declaration".
human_reviewstringNo"off", "low_confidence" (default), or "all". Details below.

Response

Abbreviated passport example:
KeyWhat it is
dataThe extracted fields, typed per doc_type. Every field is nullable. When the system can’t read a field, it abstains with null rather than guessing.
fieldsMap of field path → {confidence, agreement, flags}. confidence and agreement are 0..1. flags is a list of strings (table below).
document_confidenceAggregate confidence across the document’s fields, 0..1.
doc_typeEcho of the requested doc type.
pagesPages processed in this request (currently always 1).
calibration{version, calibrated}. Read the next section before using the scores.
usage{pages, samples, cost_cents, balance_after_cents} — what this request processed and what it cost. samples is the number of extraction samples run for cross-model agreement.

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

FlagWhat it means
LOW_AGREEMENTThe extraction samples disagreed on this field’s value.
CHECKSUM_FAILEDA deterministic validator failed — e.g. an ICAO 9303 MRZ check digit on a passport. Confidence is capped near zero.
NOT_FOUNDThe system abstained: the field is null in data because it couldn’t be read reliably.
FORMAT_INVALIDThe value doesn’t match the expected format — e.g. a date that isn’t ISO 8601.
PROVISIONAL_CALIBRATIONScores on this field are uncalibrated (see the section above). Present on every field while calibration.calibrated is false.
CROSS_DOC_MISMATCHThe value failed a cross-check against another document in the same envelope.
LOW_IMAGE_QUALITYThe page image was too degraded (blur, glare, resolution) to read this field confidently.
HUMAN_VERIFIEDThe field was verified by a human reviewer via the human_review toggle.

The human_review toggle

ValueBehaviorBilling
"off"Machine only. No human ever sees the page.Machine rate only.
"low_confidence" (default)Fields below the escalation threshold are verified by AwaitVerify human reviewers before the response returns. Verified fields carry the HUMAN_VERIFIED flag.Machine rate + human rate on escalated pages.
"all"Every field is human-verified.Machine rate + human rate.
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.

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.
Statuserror_codeWhat happenedWhyFix
401API_KEY_INVALIDRequest rejected before processing.The Authorization: Bearer key is missing, malformed, or revoked.Check the header; get a fresh key at app.awaithumans.dev/keys.
402INSUFFICIENT_BALANCERequest rejected before processing.Your balance can’t cover this request.Top up at app.awaithumans.dev/billing, then retry.
400EXTRACTION_INVALID_PAYLOADRequest body rejected.A required field is missing or malformed — bad base64, unknown media_type, invalid human_review value.The error message names the field; fix the payload.
413EXTRACTION_PAYLOAD_TOO_LARGERequest body rejected.The decoded image exceeds 10 MB.Downscale or re-encode the page image under 10 MB.
422EXTRACTION_DOC_TYPE_UNSUPPORTEDRequest rejected.doc_type isn’t one of the five supported types.Use passport, travel_ticket, airport_stamp, proof_of_profile, or travel_declaration.
502EXTRACTION_PROVIDER_ERRORExtraction failed mid-flight.An upstream model provider errored or timed out.Transient — retry with backoff. You’re not billed for failed requests.
503EXTRACTION_DISABLEDEndpoint unavailable.Machine extraction is disabled for your account or temporarily offline.Check status.awaithumans.dev; if account-level, contact support.

Pricing

VolumePer page
Pay-as-you-go$0.25
5,000+ pages/month$0.15
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.