Classify + Extract in One Call
Classify a document and extract its data in a single API call. Instead of calling
Classify Document to get a label, picking a template
yourself, and then running a separate extract, you create a Classifier whose labels are mapped to
extraction templates, then submit the document once with a classifier_id. DocumentPro classifies the
document, automatically selects the mapped template, and extracts — all in one request, with no
pre-OCR or pre-classify step.
When to use it
Use this flow when you receive mixed document types — invoices, purchase orders, remittances, etc. — and want each one automatically routed to the right extraction template without deciding up front which template applies.
If you only need a label (no extraction), use Classify Document or Run Classification instead.
Prerequisites
- An extraction template (Workflow) for each document type you expect. See Create Workflow.
- A saved Classifier whose
classesmap each label to atemplate_id.
Step 1 — Create a Classifier with template mappings
Each item in classes can include a template_id — the extraction template to run when a document is
classified with that label. You can also set default_template_id and min_confidence as fallbacks
(see Fallbacks below).
curl -X POST "https://api.documentpro.ai/v1/classifiers" \
-H "x-api-key: $API_KEY" -H "Content-Type: application/json" \
-d '{
"name": "Inbound Doc Router",
"classes": [
{ "label": "invoice", "description": "A commercial invoice or bill", "template_id": "tmpl_invoice" },
{ "label": "purchase_order", "description": "A purchase order", "template_id": "tmpl_po" }
],
"default_template_id": "tmpl_generic",
"min_confidence": 0.6
}'
# -> { "classifier_id": "clf_9a1…", "name": "Inbound Doc Router", "configs": { … } }
See Create Classifier for the full field reference — the
request body is flat (not nested under configs); the response nests the saved settings under configs.
Step 2 — Submit a document with classifier_id
There are two equivalent ways to submit — pick whichever fits your integration. Both call the same underlying classify-and-route logic and both are fully supported in production.
Modern: POST /v1/extract
Pass classifier_id instead of template_id. Accepts it as a JSON body field, a multipart form field,
or a query param:
# JSON body with a previously uploaded document
curl -X POST "https://api.documentpro.ai/v1/extract" \
-H "x-api-key: $API_KEY" -H "Content-Type: application/json" \
-d '{ "document_id": "3f2c…", "classifier_id": "clf_9a1…" }'
# JSON body with a public/presigned URL
curl -X POST "https://api.documentpro.ai/v1/extract" \
-H "x-api-key: $API_KEY" -H "Content-Type: application/json" \
-d '{ "url": "https://…/invoice.pdf", "classifier_id": "clf_9a1…" }'
# multipart file upload
curl -X POST "https://api.documentpro.ai/v1/extract?classifier_id=clf_9a1…" \
-H "x-api-key: $API_KEY" -F "file=@invoice.pdf"
Response (async): { "request_id": "req_…" }.
Classic: run_parser
If you're already using Run Extract, pass classifier_id
as a query param instead of template_id:
curl --location "https://api.documentpro.ai/v1/documents/{document_id}/run_parser?classifier_id=clf_9a1…" \
--header 'x-api-key: YOUR_API_KEY'
Both paths require the document to already be uploaded (or provided via url/file) — no pre-OCR or
pre-classify step is required, unlike the standalone POST /v1/classify endpoint. If both template_id
and classifier_id are supplied, classifier_id takes precedence. Only saved classifiers are
supported here — the inline classification_schema used by standalone Classify Document is not accepted
in the combined call.
Step 3 — Poll for the result
Poll with GET /files?request_id=… (the same endpoint used by Poll Extract)
or GET /v1/extract?request_id=… — both return the same result object.
The envelope follows how the request was submitted, not which poll endpoint you call:
// Submitted via POST /v1/extract -> extracted data at results.data
{
"request_id": "req_…",
"request_status": "completed",
"classification": "invoice",
"confidence_scores": { "invoice": 0.95, "purchase_order": 0.05 },
"classify_credits": 1,
"credits_used": 3,
"total_credits": 4,
"results": {
"num_pages": 1,
"data": { /* extracted fields */ }
}
}
// Submitted via classic run_parser -> extracted data at response_body.result_json_data
{
"request_id": "req_…",
"request_status": "completed",
"classification": "invoice",
"confidence_scores": { "invoice": 0.95, "purchase_order": 0.05 },
"classify_credits": 1,
"credits_used": 3,
"total_credits": 4,
"response_body": {
"template_id": "tmpl_invoice", // auto-selected by the classifier
"result_json_data": { /* extracted fields */ }
// semantic-chunking results use response_body.chunks instead
}
}
classification, confidence_scores, classify_credits, and total_credits are always top-level,
regardless of submission method. A request created via POST /v1/extract always returns the
results.data shape (even if you poll GET /files); a request created via run_parser always returns
the response_body.result_json_data shape.
Fallbacks
default_template_id: used when the winning label has notemplate_idmapped, or its confidence is belowmin_confidence.min_confidence(0.0–1.0): if the winning label's confidence is below this threshold, routing falls back todefault_template_idinstead of that label's mapped template.
If neither applies — the winning label has no template_id and no default_template_id is set — the
request fails. See Failure modes below.
Failure modes
If a document classifies to a label with no template_id mapped, and the classifier has no
default_template_id, the request ends with request_status: "failed" and a message like:
"Document classified as '<label>' but no extraction template is mapped to that category. Configure a
template_idfor this label (or adefault_template_idon the classifier)."
The classify credit is refunded when this happens. To avoid it, either map every label to a
template_id or set a default_template_id on the classifier.
Standard extract errors (invalid file, insufficient credits, etc.) apply as usual.
Pricing
The combined call charges a flat 1 credit per document for classification, plus normal extraction credits for the auto-selected template. The result itemizes both:
classify_credits— flat 1 credit/documentcredits_used— extraction credits (unchanged pricing)total_credits—classify_credits + credits_used
Standalone Classify Document and Run Classification are also a flat 1 credit/document. Extraction pricing is unchanged.
Backward compatibility
POST /v1/extract/run_parsercalls with atemplate_idand noclassifier_idbehave exactly as before.- The classification-related result fields are additive —
null/0for ordinary extract requests, so existing integrations are unaffected. - Standalone
POST /v1/classifystill requires an OCR'd document and still returns400if the document hasn't been processed yet — that caveat applies only to the standalone endpoint, not to this combined flow.
Full end-to-end example
# 1) Create a Classifier that maps each label to an extraction template
curl -X POST "https://api.documentpro.ai/v1/classifiers" \
-H "x-api-key: $API_KEY" -H "Content-Type: application/json" \
-d '{
"name": "Inbound Doc Router",
"classes": [
{ "label": "invoice", "description": "A commercial invoice", "template_id": "tmpl_invoice" },
{ "label": "purchase_order", "description": "A purchase order", "template_id": "tmpl_po" }
],
"default_template_id": "tmpl_generic",
"min_confidence": 0.6
}'
# -> { "classifier_id": "clf_9a1…", "name": "Inbound Doc Router", "configs": { … } }
# 2) Submit a document for combined classify + extract
curl -X POST "https://api.documentpro.ai/v1/extract" \
-H "x-api-key: $API_KEY" -H "Content-Type: application/json" \
-d '{ "url": "https://…/some-document.pdf", "classifier_id": "clf_9a1…" }'
# -> { "request_id": "req_…" }
# 3) Poll for the result
curl "https://api.documentpro.ai/files?request_id=req_…" -H "x-api-key: $API_KEY"
# -> classification + auto-selected template + extracted data + itemized credits
Next Steps
- Create Classifier for the full classifier field reference.
- Run Extract for the classic
run_parserendpoint and its other parameters. - Poll Extract for the full result schema.