Classify, then extract
Handle documents that arrive without a reliable label.
Goal. Take a document whose type you do not know, work out what it is, and route it to the right extraction schema.
Extraction is schema-driven — naming the wrong documentType produces thin or empty results rather than an error. When files arrive from a channel you do not control, classification is the step that makes extraction reliable.
Generated endpoint reference
Use Synchronous classification, asynchronous classification, and classification details for schemas. Use asynchronous extraction for the final submission.
Before you start
An API key, exported as
$DOCAI_API_KEY.A document of unknown type.
Step 1 — Classify
python -c "
import base64, json
content = base64.b64encode(open('unknown.pdf','rb').read()).decode()
json.dump({'content': content}, open('classify.json','w'))
"
curl -X POST "https://api-docai-uat.uptiq.ai/classify/sync" \
-H "X-Api-Key: $DOCAI_API_KEY" \
-H "Content-Type: application/json" \
--data-binary @classify.jsonClassification is much faster than extraction — 13 seconds in our testing, against 93 for a comparable extraction — so the synchronous endpoint is reasonable here in a way it is not for extraction.
result.type is the value you feed to extraction. result.summary is a genuinely useful by-product — a natural-language description you can log, show a reviewer, or use to explain a routing decision.
Step 2 — Gate on confidence
result.confidence runs 0 to 1. Do not route on the type alone.
Also check additionalClassifications. When it is non-empty the classifier saw more than one plausible answer, which is worth treating as a review signal even if the top confidence looks acceptable.
Pick a threshold from your own tolerance for a wrong extraction, not from the example above. A misrouted document does not error — it silently produces a poor result, which is harder to notice than a failure.
Asynchronous classification, if you prefer
POST /classify queues the job instead of waiting. Its response uses a different wrapper again — requestInfo, not data:
Retrieve it with GET /classifications/{id}, which wraps in classification:
That is four different wrapper keys across the API — data, extraction, requestInfo and classification — plus none at all on the synchronous endpoints. Conventions has the complete table. Unwrap in one place rather than inline at each call site.
Given classification takes ~13 seconds, the synchronous endpoint is usually the better choice unless you are processing a large backlog.
Step 3 — Extract with the classified type
Then poll as described in Extract asynchronously and poll.
A shortcut worth knowing
Extraction can classify internally. analysisDepth controls it:
standard (default)
Full analysis, including working out the document's structure
quick
Skips classification when documentType is provided
So if you already trust the type, analysisDepth: "quick" saves the platform repeating work you have done. Conversely, if you send a document without a confident type, leaving analysisDepth at standard lets extraction do its own analysis.
The explicit two-step in this recipe is still worth it when you need the classification decision as a first-class artifact — to log it, to gate on confidence, or to route to different downstream systems by document category.
Handling a ZIP of mixed documents
POST /classify/bulk takes a set, and a ZIP is classified per member document. Those results carry classificationGroupId, classificationGroupIndex and classificationGroupTotal so you can reassemble the set.
For a full worked example of a mixed packet, see Process a loan application packet.
When it goes wrong
Confidence consistently low
Poor scan quality
Check result.documentQuality; consider re-scanning
Type not in your routing table
The registry is larger than you assumed
Read it at build time — see Discovering document types
500 on classify
Missing or malformed body — not a server fault on this endpoint
Validate the JSON; see Errors
Extraction returns few fields despite a confident type
The type is right but the document is sparse
Check extractionMetrics.missingFields
Related pages
Classification API — every classification endpoint and parameter.
Document Classification — the same capability in the UI.
Document Types — the registry both steps draw on.
Process a loan application packet — this pattern at packet scale.
Last updated
Was this helpful?

