The line-matching problem, not the single-statement problem
Extracting one settlement statement well is a prerequisite; the harder, more valuable problem a marketplace or payments platform actually has is turning hundreds or thousands of those statements — across many merchants and processors — into individually typed, referenced line items a matching engine can actually use. A gross payout figure at the bottom of a statement tells you almost nothing; the forty or four hundred lines that produced it, each traceable to an order, a fee category or a chargeback case, are what a reconciliation process is actually built on.
This feature is about that line-level structure specifically — not a single number extracted correctly, but every deduction on a statement classified, tagged and validated, consistently, across whatever mix of processors and merchants a platform's real settlement volume actually looks like.
What settlement line matching means here
There is no separate "matching mode" or dedicated batch endpoint — settlement line matching, in the sense this page covers, is the natural result of calling POST /extractmany times concurrently across a platform's statements, exactly the way the payout reconciliation API is used for a single merchant. What makes it "matching" is entirely on your side — how your pipeline tags each call and correlates the typed line items with your own order ledger afterward.
This design choice is deliberate rather than a missing feature. A platform's order data — which order maps to which transaction, which merchant owns which listing — is exactly the kind of business logic that shouldn't live inside a document-extraction API. Keeping the API agnostic to that structure means your platform's own data model stays the single source of truth for matching, while the API stays focused on the one thing it does well: turning a statement into correct, validated, typed data.
The shape of a settlement batch
A typical settlement-close run pulls every merchant's pending statements — each already tagged with a merchant ID, processor and expected currency on your side — and issues one /extract call per statement, correlating each response back to the merchant it belongs to.
const queue = await getPendingStatements()
// [{ merchantId, processor, expectedCurrency, fileUrl }, ...]
async function processOne(stmt) {
const result = await extract(stmt.fileUrl)
await saveResult(stmt.merchantId, stmt.processor, result)
}
// Concurrency-limited settlement close across the whole merchant roster
await runWithConcurrency(queue, processOne, { concurrency: 25 })How line categories are typed
Each line on a statement is classified against the same fixed vocabulary regardless of processor — gross sale, processing fee, refund, chargeback, adjustment, reserve hold, and net payout — based on the statement's own labeling and context, the way an experienced ops analyst would read it. A processor that labels a category slightly differently on its own statement doesn't require a separate mapping table on your side; classification happens once, during extraction, into a consistent shape.
Tagging results back to an order, merchant and processor
The API has no concept of merchant, processor or order ledger — it receives a statement and returns a result, nothing more. Correlating that result with the right merchant is your pipeline's responsibility, the same discipline it already applies to keeping any other financial data organized by merchant today. Every line item that carries an order or transaction reference on the original statement keeps that reference in the structured output, so your own matching logic has something concrete to join against.
Per-statement balance checks before matching begins
Every statement in a settlement batch is checked against its own net payout independently of every other statement — a merchant in one region reconciling correctly has no bearing on whether a merchant in another does. This per-statement validation is what lets a platform trust a full settlement-close run at face value, rather than spot-checking arithmetic across hundreds of merchants and processors by hand after the fact.
This independence matters specifically at batch scale, where it's tempting to treat one flagged statement as a signal to distrust the whole close. It isn't — a flagged statement is a property of that one merchant's statement, not a reason to re-check the other 199 merchants in the same batch. Treating each flag in isolation is what keeps a reconciliation team's review time proportional to genuine exceptions rather than to batch size.
Where extraction ends and matching begins
This feature deliberately stops at the line-item level — a validated, typed, referenced line per deduction, per statement. Actually matching a settlement line against a specific order in your own order-management system, in whatever data model and matching rules your platform already uses, is your platform's job, not the extraction API's.
That boundary is worth being explicit about, because it's the single most common point of confusion for a team integrating this for the first time: the API gives you clean, comparable, referenced inputs to a matching step your platform already has or is building — it doesn't replace that matching logic, and shouldn't need to, since only your platform actually knows which order a given reference number corresponds to.
Retry strategy for a settlement-close run
Because every call is independent, a failed request in the middle of a 200-merchant close is a single retry, not a reason to restart the run. Most production integrations wrap each call in a small exponential-backoff retry before routing a still-failing statement to manual handling — the same pattern any team already uses for any external API call, unchanged by how many merchants or processors a given close spans.
What building this yourself involves
None of the batch mechanics here are exotic — a worker pool, a merchant-tagging layer and a retry wrapper are standard patterns most engineering teams already know how to build. What a platform is not building, by using the extraction API underneath this pipeline, is the document-understanding model itself: reliably classifying and typing lines across a genuinely diverse range of processor layouts, plus the arithmetic validation, is months of work and a labeled dataset most platforms don't have sitting around.
| Component | Effort if built in-house |
|---|---|
| Worker pool + queue + retry logic | A few days, standard engineering patterns |
| Merchant/processor tagging and correlation layer | A few days — reuses your existing data model |
| Document classification + line-item typing across processors | Months, plus a representative labeled dataset |
| Arithmetic/balance validation logic | Weeks, with ongoing tuning as unfamiliar layouts surface |
Steps to run your first settlement batch
Get an API key
A free plan account gets full accuracy against a smaller monthly allowance — enough to test a real settlement batch.
Build a small queue and worker pool
Most teams start with a concurrency of 10–25 and adjust based on how quickly a settlement close needs to clear.
Tag each statement with merchant, processor and expected currency
This is the correlation key your pipeline uses to file the result correctly afterward.
Run a real pilot batch across a handful of merchants
A batch of statements from three to five merchants on different processors is enough to validate the whole pipeline end to end.
Add retry handling and route flagged results to review
Standard exponential-backoff retry on failures, with low-confidence or unreconciled results routed separately.
A worked example: a 200-merchant weekly close
A platform with 200 active merchants across four processors needs its weekly settlement close refreshed — 200 statements in total, averaging 4 pages each. At a concurrency of 25 in-flight requests and roughly 4 seconds per document including network round-trip, the full close completes in:
| Concurrency | Approx. total time, 200 statements |
|---|---|
| 1 (sequential) | ~13 minutes |
| 10 | ~1.5 minutes |
| 25 | Under a minute |
At 800 pages total, the extraction cost for this close is €28 — well inside the noise for a platform whose reconciliation team previously spent multiple full days a week on the same statements by hand.
Confidence scoring across mixed-quality statements
A real settlement-close batch is never uniform quality — a clean PDF export from a major processor next to a slightly rough CSV or scan from a smaller regional one. Each statement gets its own independent confidence signal, so a low-confidence statement from one merchant doesn't drag down or get averaged with a high-confidence one from another merchant in the same batch.
Handling statements that don't reconcile
A statement whose line items don't sum to its net payout is flagged in its own response rather than silently folded into a merchant's ledger — your pipeline can route these specifically to an ops analyst, separate from the low-confidence-but-valid statements that just need a quick visual check.
Throughput at settlement-close scale
Most integrations settle on a concurrency between 10 and 50 in-flight requests, which comfortably clears even a large platform's weekly settlement close inside a few minutes. Platforms serving a growing merchant roster typically raise concurrency gradually as overall volume grows, monitoring error rates rather than jumping straight to a very high setting.
Where FlowParse's own matching feature fits in
Building matching logic against your own order ledger is real engineering work, and not every team wants to own it. FlowParse's own fee and payout matching feature runs the same underlying line-item extraction but checks each settlement report against its own printed totals directly in the product — useful when a finance team wants a matched, confidence- scored view of a single settlement report without building a matching engine against an external order ledger at all. The two are complementary: the API on this page is for a platform that wants the typed line items to match against its own data; the in-app feature is for a team that wants a finished, matched report from a single upload.
Testing a settlement batch before it touches production
Before a settlement-close run writes into a merchant-facing ledger, it's worth running it once against a small, representative slice of the merchant roster rather than the whole book at once — three or four merchants spanning different processors and at least one unfamiliar layout is usually enough to surface a tagging bug, a currency mismatch, or a statement structure the pipeline handles differently than expected, before it happens across hundreds of merchants simultaneously.
A useful discipline here is picking merchants you can independently verify — a statement whose correct net payout an ops analyst already knows offhand, or one with a recent manual entry to compare against. Confirming the API's output matches a number you can already trust is a far more convincing test than checking that the pipeline runs without throwing an error, since a pipeline can run cleanly end to end and still write a subtly wrong category or a misattributed reference if the correlation logic has a bug.
Once a small representative batch has been checked this way, scaling the same pipeline to the full merchant roster is mechanical — nothing about extraction quality or line typing changes with scale, only the number of statements queued. Teams that skip this small-batch check and go straight to a full settlement close tend to find their first real bug in front of a merchant's finance team rather than in a controlled test, which is the specific outcome this step is meant to avoid.
Edge cases a line-matching pipeline needs to expect
| Case | How to handle it |
|---|---|
| A line item has no printed order reference | Route it to your own unmatched-line review queue — the API returns it typed with an empty reference rather than guessing one |
| A merchant settles through more than one processor | Tag each statement independently — nothing requires a one-merchant-to-one-processor assumption |
| A single call times out or errors | Retry with backoff — the rest of the settlement close is unaffected |
| A very large multi-page settlement report | Processed the same as any document — pages billed at the same flat per-page rate |
Who this is built for
Marketplace platforms with many sellers
Where dozens or hundreds of merchants, each on their own processor, is the normal case.
Payment platforms and PSPs
Needing consistent, comparable line-item data before their own matching logic runs.
Engineering teams building an internal reconciliation pipeline
Assembling their own queue and worker pool around a reliable extraction API.
Platforms migrating off manual settlement-report reconciliation
Where an ops analyst currently reads statements and keys deductions into a spreadsheet by hand.
Keeping an audit trail across a settlement close
Because every response is returned directly to your call rather than retained centrally, the audit trail for a settlement-close run lives entirely in your own system — each result written alongside its source statement reference and a timestamp the moment it comes back, giving a finance team a complete, reviewable record of exactly what was extracted from which merchant's statement, without depending on FlowParse to retain anything after the call completes.
Where this fits in an existing reconciliation workflow
Settlement line matching typically sits right after statement collection and right before your own matching logic — statements land in an intake queue from wherever a platform already gathers them, a scheduled or manually-triggered close processes everything pending, and the extracted, validated, typed line items feed straight into whatever matching and ledger-write logic already exists. Nothing about adopting this changes the surrounding workflow; it replaces the typing step, not the matching decision.
For a platform building this fresh, that placement — after collection, before matching — is worth designing in deliberately rather than discovering later, since it determines how cleanly extraction can be added without disturbing whatever manual or partially-automated process already runs. The cleanest integrations treat the extraction API as the one step that turns a document into data, distinguished from the matching step by a clean handoff of typed, referenced line items, rather than blending the two into one undifferentiated pipeline.
What this feature does not do
It does not decide which order a settlement line belongs to, does not apply your platform's own matching rules, and does not replace an ops analyst's judgment about an unusual adjustment — it turns a statement into structured, validated, typed and referenced data, which is the mechanical step immediately before matching, not a replacement for the matching logic or the judgment that follows it.
Security and data handling
Uploads are encrypted with TLS from end to end.
Processing runs on infrastructure with SOC 2-aligned controls.
Original statements are deleted shortly after processing.
Nothing uploaded is ever used to train AI models.
Full details are on the security page.
Get your API key
Build a small worker pool, tag a handful of real merchant statements, and run your first concurrent settlement batch. A free plan account processes real documents at full accuracy against a smaller monthly allowance.
