Skip to content

IDP Activities

Version: 1.20.4  ·  ID: zoan-packages-idp  ·  Author: Zoan Software

The IDP (Intelligent Document Processing) package reads documents whose layout changes from one issuer to another: invoices, purchase orders, records, forms. The idea is to describe what each value means rather than where it is, so the same configuration works for every layout of the same document type.

  • No session: each activity takes the document path (or the document already read) and works on it.
  • The route picks itself: IDP — Load Document checks whether the PDF has a text layer. If it does, it reads it (free and exact); if not, it scans it with Azure Document Intelligence. Both routes return the same structure, so what comes after does not change.
  • Coordinates are unified: every word comes out in pixels at the dpi you ask for, with a top-left origin, wherever the document came from.
  • AI and reading included in your plan (since 1.20.0): with no credentials in the activity or the project, the model and the scan reading go through Zoan Cloud, with no keys to set up; the usage (tokens and pages) shows up in AI Usage. With your own credentials, calls go straight to your providers.
  • Personal data is hidden before it leaves: IDP — Classify and IDP — Extract mask IDs, tax IDs, emails, phones, accounts, addresses and names in the text before sending it to the model (maskPii, on by default) and restore the real values in the result.

Each word comes with its box (x, y, width, height). That is what lets you go back to the document from an extracted value: highlight where an invoice number came from, show it to a person to validate, or audit an extraction months later.

If you use the same dpi in PDF To Images, the boxes land exactly on top of the rendered page, with no conversion at all. It is the base any visual review is drawn on.

The first two are the normal path. The ones below are still there for anyone who needs to get in between.

ActivityTypeOutputWhat it does
IDP — Classifyidp-classifyobjectReads a document, tells which type it is and splits it into segments. Returns the document already read
IDP — Extractidp-extractobjectExtracts an extraction project’s fields, routes to the layout profile, locates each value and stores the result
IDP — Load Documentidp-load-documentobjectLoads a document and returns its text and its positioned words
IDP — Build Classifieridp-build-classifierobjectBuilds the schema that identifies which type the document is
IDP — Build Schemaidp-build-schemaList<object>Splits a taxonomy into the schemas that fit in one call
IDP — Groundidp-groundobjectLocates each extracted value and flags what needs review

Two nodes:

IDP — Classify → is it the right type? → IDP — Extract

IDP — Classify returns the document already read together with the verdict, and IDP — Extract reuses it: the file is read only once. With a scan that is not a minor optimisation — re-reading means paying Azure twice.

They are separate on purpose. What to do with a document that doesn’t belong is your decision, not an activity’s: one that decides on its own not to do its job hides the control flow, and it also prevents the one thing you really need when the queue brings everything — classify once and route to the right project.

The two guarantees, which are not the same

Section titled “The two guarantees, which are not the same”

It is worth keeping them apart in your head because they protect against different things:

  • Classifying answers “is this document the type I think it is?”. Without that step, a purchase order processed as an invoice can slip in wrong data with high confidence.
  • Grounding answers “is this value written in the document?”. It catches that the model made it up, not that the document is the wrong one.

Neither covers the other. See IDP — Build Classifier for the specific case that slips through.

The scan route uses Azure Document Intelligence (the prebuilt-layout model), which reads handwriting — important because in many documents the part nobody ever digitised (a signature, a margin note, a form filled in by hand) is handwritten. It needs no training or labelling: it works with any document from day one.

With the reading included in your plan, each reading accepts up to 50 MB and 2000 pages, and counts toward the monthly page quota. A document that does not fit in what is left is rejected before it is read, with the figures, and you never get a partial reading presented as complete (see IDP — Load Document).

Enqueue (once per batch):

List Files path = env("INVOICES_DIR") pattern = "*.pdf" recursive → files
Foreach items = files itemVariable = path
Queue Add Item queueName = "invoices" reference = path
specificContent = { "path": path }

reference = the path. It is the queue’s idempotency key and the one the document will carry in Zoan Cloud, so re-running it duplicates nothing and you can get from the item to the document.

Process:

Queue Process queueName = "invoices" itemVariable = item onError = continue
Set Variable name = content value = item.SpecificContent
IDP — Classify path = content["path"]
projects = ["supplier-invoice"]
dpi = 200
→ doc
If condition = doc["recognized"] == false
Queue Set Transaction Status item = item status = "successful"
output = { "discarded": true, "type": doc["documentType"] }
Continue
IDP — Extract document = doc ← already read: not re-read
path = content["path"]
reference = item.Reference
project = "supplier-invoice"
→ res
Queue Set Transaction Status item = item status = "successful"
output = { "documentId": res["documentId"],
"needsReview": res["needsReview"],
"values": res["values"] }

IDP — Extract stores the document and its extraction in Zoan Cloud, where Zoan Cloud shows the pages in the validation station; there is no need to upload it separately with Documents — Upload.

Queue Process closes each item on its own —successful if the body finishes, failed if it throws— but it closes it with an empty output: it throws the result away. With auto-close, your telemetry is “processed 400, 12 failed” and nothing more.

That is why the example calls Queue Set Transaction Status by hand: if the body already set the status, auto-close steps aside. That way each document leaves a queryable trail — what was extracted, with what confidence, why it went to review, and why it was discarded if it was.

With that you get:

WhereWhat it gives you
GET /queues/:id/metricsTotal, counts per status, success rate, hourly throughput, mean and p95 times.
GET /queues/:id/itemsEach document with its reference, status and the output you gave it.
validacion-* queueHow many and which ones need a person.