Power Automate August 2, 2026 13 min read

Power Automate document extraction — invoices and statements into Microsoft 365

Connect FlowParse to Microsoft Power Automate and turn the PDFs arriving in a shared mailbox or a SharePoint library into structured rows, without leaving Microsoft 365. There is no published FlowParse connector in the Power Platform, so the flow uses the built-in HTTP action — which is a premium connector, and which times out at 120 seconds. This page is the worked setup, the two limits that actually decide whether it works, and the parts of the job Power Automate should keep.

FlowParse
flowparse.io

What this integration actually is

Power Automate is the automation layer most finance teams already have, because it comes with Microsoft 365 and it sits next to the two places finance documents land: a shared Outlook mailbox and a SharePoint library. What it cannot do on its own is read a PDF invoice or a bank statement and give you the numbers. That is the gap this page closes — a flow that takes each new file, sends it to the extraction API, and writes the result somewhere useful.

The whole integration is one action: an HTTP POST carrying the document as base64 and an API key in the header. Everything else in the flow is standard Power Automate — a trigger, an *Apply to each* over attachments, a *Parse JSON* to make the response usable, and whatever destination your team works in. No custom connector, no code, no Azure resources.

What comes back is structured: for an invoice, the header fields and line items; for a bank statement, every transaction row with dates, descriptions, amounts and balances. The same request handles both — the response says which document type it recognised, so one flow can cover a mailbox that receives a mix. The document extraction API is the endpoint reference; this page is the Power Automate-specific build.

FlowParse
flowparse.io

Two things to know before you build

There is no FlowParse connector in the Power Platform. You will not find us in the connector list, and there is no certified connector waiting for approval. The integration is the generic HTTP action, which is a first-class, fully supported way to call any REST API — but it is worth saying plainly rather than letting you search for a tile that does not exist.

The HTTP action is a premium connector. Connector licensing in Power Automate is evaluated per action, so a flow containing one HTTP call requires a licence that includes premium connectors — Power Automate Premium per user, or a per-flow/Process licence attached to that flow. If your organisation runs on the Power Automate capability included with Microsoft 365, this flow will not run until someone assigns the right licence. Check current Microsoft licensing before you promise anyone a delivery date.

Everything else is genuinely simple. If those two facts are acceptable, a working flow takes under an hour, and the rest of this page is the configuration — including the timeout that decides which documents can go through a flow at all and which should not.

Who this suits, and who should use something else

It suits teams whose documents already live in Microsoft 365: supplier invoices arriving at a shared AP mailbox, statements dropped into a SharePoint folder by the bookkeeper, expense receipts forwarded by staff. Power Automate keeps the whole path inside the tenant, which is usually the deciding factor for IT — no third-party automation platform holds a copy of anything on the way through.

It suits organisations where the destination is also Microsoft: an Excel Online table, a SharePoint list, a Dataverse table feeding a Power App, or a Teams message to whoever handles exceptions. If the data has to end up in one of those, a flow is fewer moving parts than any external tool.

It suits it less if you have no premium licence and no appetite to buy one, or if your documents are large multi-page statements. In both cases Make or n8n is the cheaper route, and for year-long statement files the browser batch converter is honestly the right tool — the reasons are in the timeout section below.

The shape of the flow

That is the entire build. Seven steps, of which exactly one is specific to us. The order matters more than it looks: filtering before the HTTP call is what stops you paying to extract email signatures, and branching after the parse is what stops an invoice flow from choking on a statement.

Keep the flow single-purpose. A flow that extracts and then also approves, posts and files becomes impossible to debug the first time a supplier sends a scan sideways. Extraction, then a clean handoff to whatever does the next thing, is the shape that survives contact with real mailboxes.

1

1. Trigger

When a new email arrives (V3) with Include Attachments on, or When a file is created in a SharePoint document library.

2

2. Filter

Only act on the attachments you want — PDFs, images, and (if you accept them) XLSX or CSV files. A signature image is not an invoice.

3

3. Encode

Outlook attachments arrive as base64 already. A SharePoint file needs Get file content, then base64() around it.

4

4. HTTP POST

One call to the extraction endpoint with the Authorization header and a JSON body containing the file and filename.

5

5. Parse JSON

Turn the response into usable dynamic content so the fields can be referenced downstream.

6

6. Branch

One path for an invoice, one for a bank statement, one for anything the API could not read.

7

7. Land it

Add a row to an Excel Online table, create a SharePoint list item, or write to Dataverse — then notify whoever needs to look.

Choosing the trigger

Most finance flows start from one of four triggers, and the choice quietly determines how much filtering work you do later. A shared mailbox catches everything a supplier sends, including the things you do not want. A SharePoint library gives you a controlled queue, at the cost of somebody having to put files in it.

A scheduled trigger is worth considering for volume: instead of firing once per email, run every hour, list the new files, and process them in a loop. That behaves better against rate limits and makes the run history far easier to read when something goes wrong.

TriggerGood forWatch out for
When a new email arrives (V3)A shared AP or receipts mailboxSignatures, logos and PDFs that are not invoices — filter by name, size and type
When a file is created (SharePoint)A controlled drop folderFires on every version and on files still syncing — add a delay or check the extension
When a file is created (OneDrive)One person's own workflowPersonal storage; it disappears when they leave
Recurrence + list filesVolume, and calmer run historiesYou handle the 'already processed' bookkeeping yourself
Manual / buttonTesting, and one-off catch-up runsNothing — start here while you are building

Getting the file in, without double-encoding it

The API takes the document as base64 in a JSON field, which in Power Automate means one of two expressions depending on where the file came from. An attachment from the Outlook trigger is already base64 — its `contentBytes` property is exactly what the API expects. A file read from SharePoint or OneDrive is binary, so it goes through the `base64()` function first.

Double-encoding is the single most common failure in this build. If you wrap `contentBytes` in `base64()`, the request is technically valid, the API receives something that decodes to a base64 string instead of a PDF, and you get a 400 back telling you the file is not readable. When a flow that worked last week suddenly fails after someone changed the trigger, this is almost always why.

Size matters too. The API accepts files up to 20 MB, which is generous for statements and invoices but not for a 300-page scanned archive. Power Automate has its own message-size ceilings around 100 MB per action, so in practice our limit is the one you will hit first — check the file size before the HTTP call and route anything oversized to a human.

The two expressions you actually need
// A file picked up from SharePoint or OneDrive is binary,
// so it has to be encoded before it goes in the JSON body:
base64(body('Get_file_content'))

// An attachment from the Outlook trigger is already base64 —
// use it as-is, encoding it twice is the classic mistake:
items('Apply_to_each')?['contentBytes']

The HTTP action, configured

One action, four fields. Method POST, URI the extract endpoint, one header for authentication and one for content type, and a JSON body with the file and its name. The filename is optional but worth sending — it is how the API infers the file type when the extension is not obvious, and it makes the run history readable when you are looking at fifty runs trying to find one bad document.

Put the API key in a secure input or an environment variable rather than typing it into the action. Power Automate will happily show the raw header in run history to anyone who can open the flow, and an API key that can spend your page budget deserves the same care as any other credential. Keys are issued in the API dashboard and can be rotated without touching the flow if you reference a variable.

Set the HTTP action's retry policy deliberately — the default is an exponential retry, and every retry that reaches us is a real extraction that consumes pages from your budget. The reasoning is in retries and billing; for a first build, turning retries off and handling failures explicitly is the safer default.

HTTP action — body
{
  "file": "@{items('Apply_to_each')?['contentBytes']}",
  "filename": "@{items('Apply_to_each')?['name']}"
}

Parse JSON so the fields become usable

Without a *Parse JSON* action the response is one opaque string and you end up writing `json(body('HTTP'))?['data']?['...']` expressions by hand in every downstream step. With it, the fields appear as dynamic content and the flow becomes editable by someone who is not you. Paste a real response into the *Generate from sample* box rather than writing the schema manually.

Keep the schema shallow. The top level is stable — `type`, `pages`, `billedPages` and `data` — while what sits inside `data` depends on the document. If you declare the entire nested structure and a supplier sends an invoice without a purchase-order number, a strict schema fails the whole run over a missing optional field. A shallow schema plus a second parse inside each branch is more robust.

Branch on `type` immediately after the parse. An invoice and a bank statement need genuinely different handling — one writes a row per document, the other writes a row per transaction — and mixing them in a single path produces flows nobody can follow six months later.

Parse JSON — a deliberately shallow schema
{
  "type": "object",
  "properties": {
    "type":        { "type": "string" },
    "pages":       { "type": "integer" },
    "billedPages": { "type": "integer" },
    "data":        { "type": "object" }
  }
}

The 120-second wall, and what to do about it

This is the constraint that decides which documents can go through a flow at all. A synchronous outbound HTTP request in Power Automate times out at 120 seconds. Our own extraction has an internal limit of 110 seconds and returns an error rather than hanging. Both numbers are real, both are hard, and neither is configurable from your side.

For ordinary documents this never comes up. A one-page invoice, a receipt photo, a two or three-page statement all finish comfortably inside the window. It bites on big files: a long multi-page statement or a scanned document that needs vision on every page can genuinely take longer than the flow will wait, and you will see a timeout rather than a result.

The fix is not a clever retry — it is not sending those documents through a flow. Split a year-long statement into months before it reaches the trigger, or send it through the batch converter in the browser where there is no 120-second ceiling, and keep the flow for the steady stream of ordinary documents it handles well.

DocumentTypical outcome in a flowWhat to do
1-page invoice or receiptComfortably inside the windowRun it in the flow
Digital statement, 2-6 pagesNormally fineRun it in the flow
Scanned statement, 10+ pagesAt risk of the 110s / 120s limitSplit by month, or use the browser batch flow
Year-long statement packWill not finish in a flowBatch converter, not Power Automate
Anything over 20 MBRejected before extraction startsSplit the file or compress the scan
FlowParse
flowparse.io

What failure looks like, and how to catch it

Three failures matter and each has a distinct status code. A 422 means the document was read but there was nothing extractable — a photo of a car park, a blank scan, a Word document exported to PDF with no financial content. That one costs nothing; the API deliberately does not bill a document it could not convert. A 429 means your page budget is exhausted. A 400 means the request was malformed, and in a flow that is almost always the double-encoding problem.

Handle them with *Configure run after* rather than letting the flow fail. Put the HTTP action and the parse inside a scope, add a second scope configured to run *has failed* or *has timed out*, and have that path post the filename and the error into a Teams channel or a SharePoint exception list. Silent failures in a finance flow are worse than loud ones — a missing invoice nobody was told about surfaces at month-end.

Keep the original file in the failure path. Whatever the flow does with successful documents, an exception item should carry a link back to the email or the library file so a person can open it. FlowParse deletes the original immediately after extraction and is not an archive, so your copy is the only copy.

Retries, billing and idempotency

The HTTP action retries by default with an exponential policy. That is sensible behaviour for an idempotent read and expensive behaviour for a billed extraction: every retry that reaches the API is a full extraction that consumes pages from your allowance, whether or not the flow ends up using the result. A transient network blip can quietly cost you four extractions of the same file.

Set the retry policy to none on the HTTP action, and handle retries where you can see them — an exception list a person reviews, or a second scheduled flow that reprocesses failures once. Manual reprocessing of a handful of documents is cheaper and far more predictable than an automatic policy nobody remembers configuring.

The API does not deduplicate for you. Sending the same statement twice produces two extractions and bills both, because it has no way to know whether you meant to. If your trigger can fire twice on the same file — SharePoint version events are the classic case — record what you have processed in a list or a column and check it before the call.

Where the data should land

An Excel Online table is the fastest destination and the right one for a first build: *Add a row into a table* maps parsed fields to columns and finance can open the file immediately. It is also the most fragile at volume — a workbook receiving hundreds of rows an hour from concurrent runs will eventually conflict, so keep it for tens of documents a day, not thousands.

A SharePoint list is the better default for anything ongoing. It handles concurrency properly, it gives you views, filters and per-item permissions, and it is where an exceptions queue naturally lives. For line items or transaction rows, use a second list with a lookup back to the document item rather than trying to flatten everything into one row.

Dataverse is worth it only when the data feeds a Power App or a model-driven process — it costs licensing and setup, and for a flow that produces a monthly transaction listing it is overkill. Whichever you choose, remember the extraction is a working dataset: the bank's PDF is still the evidence, and it belongs in a document library, not just in a list.

Invoices: one row per document, plus the line items

For a supplier invoice the response carries the header fields you would key by hand — supplier, invoice number, date, due date, currency, net, tax and total — plus the line items as a nested array. In a flow that maps naturally onto two destinations: one row in an invoice register, and one row per line in a details list, linked by the invoice number.

Line items are where the value is and where the temptation to skip is strongest. A register with totals only tells you what you spent; a register with lines tells you what you bought, which is what makes coding, cost analysis and any kind of spend review possible. If you are not going to use them, at least store them — extracting again later costs another page.

Do not treat extracted totals as verified. Numbers can be misread, particularly on poor scans, and the sensible defence is arithmetic: line total against unit price times quantity, sum of lines against the net, net plus tax against the gross. The invoice validation page covers the full rule set, and the checks are available over the API as well as in the workspace.

FlowParse
flowparse.io

Bank statements: rows, not fields

A bank statement is a different shape of problem. There is no single set of header fields to map — there is an account, a period, an opening and closing balance, and then anywhere from twenty to two thousand transaction rows. In a flow that means an *Apply to each* writing rows into a list, and it means thinking about volume before you turn it on.

Sending each transaction individually to a SharePoint list works and is slow; for a statement with hundreds of rows, prefer generating a file. The export endpoint can return the whole statement as an Excel workbook, and a flow that saves one workbook per statement into a library finishes in seconds instead of minutes and leaves finance with something they can actually work in.

Statements also carry a check that invoices do not: the running balance. Because opening plus the sum of transactions must equal closing, a complete extraction can be proven arithmetically. That is the difference between plausible data and provable data, and it is worth wiring into the flow rather than trusting the output.

FlowParse
flowparse.io

Proving nothing was dropped

The failure mode that matters in finance automation is not a misread character — it is a missing row. A dropped transaction leaves output that looks perfect: clean columns, plausible descriptions, no error anywhere. Nothing in a flow's run history will tell you it happened, which is why an automated pipeline needs a completeness check rather than a confidence score.

Every statement we extract is checked against its own arithmetic: opening balance plus the transactions must equal the closing balance, per account. When it reconciles you have a mathematical statement that no row is missing. When it does not, the result is flagged rather than quietly delivered — and in a flow that flag is what should route a document to a human instead of into the ledger.

Wire it in explicitly: branch on the validation result, send reconciled statements down the happy path, and send failures to an exception list with the file attached. That single branch is what turns this from an automation you have to spot-check into one you can trust. The mechanics are on bank statement validation.

FlowParse
flowparse.io

Approvals and Teams: the part that is not ours

Power Automate's approval actions are genuinely good, and they are the reason many teams build here rather than on an external platform. An extracted invoice becomes an adaptive card in Teams with supplier, amount and due date on it, the budget holder taps approve, and the flow continues. That is a real accounts-payable control built from parts you already own.

None of that is us, and we do not pretend otherwise. FlowParse has no approval workflow, no delegation rules, no purchase-order matching and no payment execution. It reads documents. Everything about who may approve what, and what happens after they do, belongs to your flow and your policy — which is exactly where it should live.

The practical division: extraction produces reliable data, the flow decides what happens to it. If you need the wider picture of how those halves fit together without buying a platform, the AP automation page and the running AP without a platform guide cover it.

The licensing reality, stated plainly

Power Automate licensing is evaluated per connector action, and the HTTP action is premium. A flow that contains it needs a licence covering premium connectors — Premium per user for the maker, or a per-flow licence attached to that specific flow so anyone in the organisation can trigger it without their own premium seat. Microsoft changes the names and the prices; check the current terms rather than trusting any blog, including this one, on numbers.

The per-flow route is usually the cheaper answer for finance. One shared flow processing an AP mailbox serves the whole team, and licensing the flow avoids buying premium seats for people who only ever look at the results. It is worth pricing both before you build, because discovering the constraint after the flow works is a bad conversation.

There are non-premium paths people try — a custom connector is also premium, and the Office Scripts route trades one limit for another. If the licence is genuinely unavailable, Make does the same job with no premium tier for HTTP, and n8n does it on your own server with no per-task meter at all.

Volume, throughput and a folder of 300 files

Per-document flows are fine at the pace a mailbox actually receives things. They are the wrong tool for a backlog. If somebody hands you a folder of 300 statements from the last three years, a flow will grind through them one at a time, hit concurrency limits, and produce a run history nobody wants to audit.

Do the backlog once, properly, somewhere else — the batch converter handles many files in one pass and merges them into a single workbook — and let the flow handle the steady state from that day forward. That is the pattern that keeps automation boring, which is what you want from finance automation.

If you do run volume through flows, set concurrency control deliberately rather than leaving *Apply to each* at its default parallelism. Sequential processing is slower and much easier to reason about when you need to explain why one document out of 200 is missing.

The SharePoint-first pattern most finance teams end up with

After a few iterations, most teams converge on the same design. A document library with folders per month is the drop point and the archive. A flow triggers on new files, extracts, and writes to two lists: one row per document, one row per line or transaction. A third list holds exceptions with the reason and a link back to the file.

The library is what makes this durable. Because we delete originals immediately after extraction, the copy in SharePoint is your record — the extracted rows are a working dataset, and the PDF the bank or supplier issued remains the evidence. Retention policies stay a Microsoft 365 matter, which is where your IT and compliance people can actually manage them.

From there everything else is reporting. A Power BI report over the lists, an Excel pivot, a monthly export to your accountant — all of it downstream of the same two lists, and none of it dependent on us being in the loop.

Power Automate versus the alternatives

All four platforms make the same HTTP call, so the choice is about cost, control and where your documents already live rather than about capability. The table is the short version; each of the other three has its own worked setup if you want the detail.

PlatformBest whenMain constraint
Power AutomateDocuments and destinations are in Microsoft 365HTTP is a premium connector; 120-second timeout
ZapierNon-technical maker, many other apps to connectWebhooks need a paid plan; per-task pricing
MakeVisual builder, tighter budgetHosted, so documents pass through Make
n8nSelf-hosted, high volume, strict data rulesYou run and update the server
Your own codeFull control of queueing and retriesYou build the error handling nobody else does

Where the documents actually go

In this design a document travels from your tenant to our API over TLS and back. Nothing sits on an intermediate automation platform, which is the main security argument for building here rather than on a hosted third-party tool. Processing happens in the EU; originals are deleted immediately after extraction, and extracted data is encrypted at rest.

We do not train models on customer documents. That is worth stating explicitly because it is the question every IT reviewer asks second, right after where the data is processed. The security page has the full detail, including sub-processors.

What we do not offer is on-premise or air-gapped deployment. If your policy is that financial documents may never leave your own network, no hosted API satisfies it — self-hosted n8n still sends the file to us, so the honest answer in that case is that we are not the right tool.

FlowParse
flowparse.io

The boundary, stated plainly

FlowParse is a document-extraction engine. It is not a connector in the Power Platform, not an accounts-payable platform, not an ERP and not an archive. It does not approve, post, pay or file anything, and it holds no ledger of its own.

It also does not push data anywhere. There is no callback and no outbound webhook from us — the API answers the request you make, and your flow decides where the answer goes. Anything described as event-driven in this stack is your flow reacting to your mailbox, not us calling you.

That boundary is deliberate. The extraction is the part that is genuinely hard and genuinely worth automating; approval routing, coding and posting belong in the systems your finance process already runs on, where they can be governed properly.

A worked example: 40 supplier invoices a week

A services business receives about forty supplier invoices a week at a shared AP mailbox. Before automation, someone opened each one, keyed six fields into a spreadsheet and filed the PDF — roughly four hours a week, and the spreadsheet was always a few days behind whoever chased it.

The flow they built: trigger on new mail with attachments, filter to PDFs over 20 KB, extract each attachment, parse, write one row into an invoice register list and one row per line into a details list, then save the PDF into a SharePoint library folder named by month. Anything the API could not read, and anything where the arithmetic did not check out, goes to an exceptions list with a Teams notification.

The result is not zero-touch and was never meant to be. Roughly one document a week lands in exceptions — a scanned credit note, a supplier statement sent instead of an invoice, one supplier whose PDF is genuinely a photograph. That is a five-minute job on Monday instead of four hours spread across the week, and the register is current rather than nearly current.

A checklist before you turn it on

Run the flow manually against ten real documents before you attach it to a live mailbox, and read every one of the ten outputs against the original. It takes twenty minutes and it is the only way to find out that your supplier writes dates the American way round or that one of them puts the total in the header.

1

Premium licence confirmed

The HTTP action will not run without one. Confirm it before building, not after.

2

Key stored securely

Environment variable or secure input, never typed into the action.

3

Retries set to none

Every automatic retry is a billed extraction. Handle failures where you can see them.

4

Size and type filter before the call

No signatures, no 30 MB scans, no Word documents.

5

Failure path exists

A scope configured to run after failure, writing to an exceptions list with a link to the file.

6

Originals archived by you

We delete after extraction. Your library is the record.

7

Validation branch wired

Statements that fail their balance check go to a human, not into the ledger.

8

Tested on your worst document

Not your cleanest one. The worst scan you have is the real test.

Where to go next

The endpoint reference, including the export and validation calls, is in the API docs, and keys come from the API dashboard. For per-document detail see the invoice parsing API, the receipt OCR API and the bank statement API; for spreadsheet output see the PDF to Excel API.

To compare platforms before committing, the worked setups for Zapier, Make and n8n follow the same structure as this page, and all integrations lists the cloud-storage routes as well.

If you would rather not automate at all, the browser flow does the same extraction by upload — bank statement to Excel for statements, invoice PDF to Excel for invoices, and batch for a folder at a time.

Build it in a flow this afternoon

One HTTP action, one Parse JSON, and every invoice in your AP mailbox becomes a row in a list you can actually work with.

Frequently asked questions

Related