For the complete documentation index, see llms.txt. This page is also available as Markdown.
Classification

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.json

Classification 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.

Asynchronous classification, if you prefer

POST /classify queues the job instead of waiting. Its response uses a different wrapper againrequestInfo, not data:

Retrieve it with GET /classifications/{id}, which wraps in classification:

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:

Value
Behaviour

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.

Those group fields appear only for ZIP uploads. A standard PDF or Excel classification does not carry them, so do not write a handler that requires them.

For a full worked example of a mixed packet, see Process a loan application packet.

When it goes wrong

Symptom
Cause
Fix

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

Last updated