Verifying documents at volume: what to design for before you integrate anything
Manual document review does not fail loudly. It degrades. The first thirty applications of the month get read properly; by the two hundredth, the check has quietly become a glance at the net figure and a decision that was mostly made before the file was opened. Nobody decides to stop checking — the checking just thins out under load, and there is no event anywhere in your system that records it happening.
That is the real argument for automating a document check, and it is not the one usually made. It is not that software catches more forgeries than a careful human. It is that software applies the same check to the two hundredth file as to the first, and leaves a record either way.
These are notes on designing that in — written from our own contract, but most of it applies whatever you integrate.
Put the check at intake, not at decision
The instinct is to verify at the point of decision, next to the underwriting or approval step. That is too late for two reasons.
- By then the applicant has moved on and asking for a replacement document costs you a re-engagement rather than a follow-up question in an open conversation.
- You lose the cheapest possible outcome: catching a file that is unreadable, encrypted, a photograph of a screen, or the wrong document entirely — before a person has spent any time on it.
Run it when the file lands. Store the result against the application. Let the decision step read a result it did not have to wait for.
What a response has to give you
Three things, and a response missing any of them will force you to build around it. Ours splits them into verdict, signals and processing:
A verdict you can branch on. A small closed set of statuses, not a number you have to invent thresholds for. Ours is authentic, suspicious, tampered, inconclusive and unsupported, with a confidence value alongside. The point of a closed set is that your routing logic is readable a year later: a score of 0.71 means nothing to the person maintaining your intake flow in eighteen months.
Signals a human can be shown. Not the verdict's reasoning as prose, but the individual findings, each with an id, a severity and a piece of evidence — invariant_balance, module M8, medium, "Closing balance: expected 4310.50, found 6310.50". This is what someone reviewing a flagged application actually needs, and it is the difference between a tool that makes a decision and a tool that supports one. Over fifty signals can fire; the ones that did are the ones you show.
Timings you can budget. How long the call took, which engine version produced it and which rules revision it ran under. The last two matter more than they look: when a customer disputes a result from four months ago, "which version said that" is the first question, and it is unanswerable unless you stored the answer.
Design for inconclusive first
This is the part most integrations get wrong, and it is worth more than everything else on this page.
Every document-forensics system returns a large share of results that are neither clean nor damning — because that is the honest answer for a large share of real documents. A statement re-rendered by a bank portal, a file re-encoded by an applicant's phone, a PDF stripped of its metadata by an email gateway: none of those are fraud, and none of them look untouched either. Ours returns inconclusive often, and any vendor whose demo does not show you that path is showing you a demo.
So the integration question is not "what do we do when it says tampered". Tampered is easy — a human looks at it. The question is what happens to the much larger pile in the middle, and there are only three honest answers: pass it through with the finding attached, ask for a specific different artefact, or route it to a person. Pick one deliberately per flow, and make sure the one you picked is not "treat it as clean because the queue was long".
The useful move is to attach a concrete next action rather than a shrug: ask the issuer for the original as their system produced it — not a scan, not a re-save — and check that one. That request costs the honest applicant nothing and is the single hardest thing for a fabricated document to survive. We added exactly that to our own report for exactly this reason.
Never auto-reject on a single signal
A modification timestamp later than creation is the most common finding in document forensics and one of the weakest. It appears whenever anyone adds a comment, prints to PDF, or re-saves a file unchanged — which bank portals, mail gateways and phones all do routinely.
Wire a rule that refuses an application on that alone and you have built a machine that rejects honest people at scale, quietly, with an audit trail that makes it look deliberate. Automate the routing, not the refusal: a flagged file should reach a person faster, not skip them.
Practical constraints worth knowing up front
- Synchronous is simpler than it sounds. Our median verdict comes back under a second, with a slow tail in low single-digit seconds — well inside a normal request cycle, which means no queue, no callback endpoint and no partial state to reconcile. Give it a timeout and a fallback anyway.
- Issuer-agnostic beats an institution list. There is no per-bank onboarding to wait for and no template library that has to catch up with a new issuer. Our endpoint accepts an issuer_hint field and discards it — the analysis reads the file, not a claimed layout.
- Decide what you store before the first call, not after. The verdict and the signal list are small and worth keeping against the application. The document itself is a different question with a different answer in every jurisdiction; ours is deleted on a fixed schedule regardless of plan.
- Version everything you keep. Engine version and rules revision on every stored result, so a dispute months later is a lookup rather than an argument.
Where this stands today
One thing to be straight about: our verification API is not open self-serve. The endpoint shape above is real and it is what the service returns — the API page documents the request and response against the live contract rather than an aspiration — but access is arranged rather than signed up for. Tell us the volume and the flow and we will send credentials and the endpoint documentation.
If you want to see the analysis before talking to anyone: upload a file on the homepage for a full forensic report — the first check is free — or run the metadata checker, which parses the PDF in your own browser and uploads nothing at all. And if you are still deciding whether this belongs in your flow, what metadata can and cannot prove is the honest version of what a check like this is worth.