Developer API August 1, 2026 13 min read

Receipt OCR API — Photos and Scans to Structured Data

The FlowParse receipt OCR API reads receipts — phone photos, crumpled thermal paper, scanned expense claims — and returns merchant, date, total, tax, payment method and every line item as typed JSON. `POST /api/v1/extract` runs OCR and field extraction in one call, so your expense app, accounting tool or reimbursement flow receives data instead of an image. No templates per merchant, no OCR engine to host.

FlowParse
flowparse.io

What a receipt OCR API does

A receipt OCR API takes an image of a receipt and returns the information printed on it as structured data. OCR is only the first half of that job: recognising the characters on a crumpled till roll is hard, but knowing which of the recognised numbers is the total, which is the tax and which is the change given is the part that decides whether the output is useful. An API that returns raw text has done the easy half and left you the difficult one.

FlowParse returns fields, not text. `POST /api/v1/extract` accepts a photo, a scan or a PDF, recognises the content, works out what each value means, and returns merchant, date, total, tax, payment method and a line-item array in a stable snake_case schema. Receipts are classified automatically, so the same endpoint that handles invoices and bank statements handles receipts too — the response `type` tells you which it found.

This matters most in expense workflows, where the input is genuinely bad: a photo taken in a restaurant at an angle, in poor light, of paper that has been in a pocket all day. That is the realistic case, not a flat 300 DPI scan, and it is what the engine is built to survive.

FlowParse
flowparse.io

Read a receipt in one call

Base64-encode the image and POST it. Classification is automatic, so you do not need a separate receipt endpoint or a type hint. Create a key at get an API key; the full reference is in the API docs.

POST /api/v1/extract
curl -X POST https://flowparse.io/api/v1/extract \
  -H "Authorization: Bearer pf_live_xxx" \
  -H "Content-Type: application/json" \
  -d '{ "file": "iVBORw0KGgoAAAANS...", "filename": "lunch.jpg" }'

What comes back from a receipt

Receipts carry fewer fields than invoices but the ones they carry are the ones expense systems need. Amounts are typed as numbers and dates as ISO-8601, so a receipt printed as 02/10/24 in a country that writes day-first is not silently read as February.

FieldTypeWhat it holds
merchantstringTrading name as printed at the top of the receipt
datestring (ISO-8601)Transaction date, normalised from any local format
totalnumberAmount actually paid
taxnumberVAT / GST / sales tax where the receipt breaks it out
currencystringISO currency code detected from the receipt
payment_methodstringCard, cash or the method printed on the slip
line_items[]arrayPer-item description, quantity, unit_price and amount
FlowParse
flowparse.io

A receipt, structured

Receipts share the invoice data shape, because a receipt is economically the same object — a merchant, a date, a total, a tax figure and a set of lines. Reusing one schema means your storage layer and your export mapping do not fork, and the validate, export and merge endpoints accept it without translation.

200 OK — receipt
{
  "type": "receipt",
  "pages": 1,
  "billedPages": 1,
  "data": {
    "type": "invoice",
    "data": {
      "supplier_name": "Corner Cafe",
      "invoice_date": "2026-07-22",
      "currency": "EUR",
      "tax_amount": 1.42,
      "total": 18.40,
      "line_items": [
        { "description": "Flat white", "quantity": 2, "unit_price": 3.50, "amount": 7.00 },
        { "description": "Club sandwich", "quantity": 1, "unit_price": 11.40, "amount": 11.40 }
      ]
    }
  }
}

Thermal paper, folds and bad light

Receipts are the worst input in document processing and it is worth being honest about why. Thermal paper fades, especially after a few weeks in a wallet or a hot car. Till rolls are narrow, so long item names wrap onto a second line. Photos are taken at an angle, under a table lamp, with a shadow across the middle. Some receipts are printed in a font designed for speed rather than legibility, and a faded 8 becomes a plausible 3.

Three things make the difference in practice. Recognition works on the image geometry rather than a naive left-to-right text dump, so a wrapped item stays attached to its price. Field assignment is semantic — the total is identified by its role on the receipt, not by being the last number — so a change-given line is not mistaken for the amount paid. And genuinely illegible values are returned as null with lower confidence rather than guessed, because in expense processing a missing field prompts a question while a wrong field becomes a wrong reimbursement.

What you can do on your side is mostly about capture. A photo taken flat, in even light, with the whole receipt in frame and nothing else, is worth more than any post-processing. If you control the mobile app, guiding the user to that photo is the single highest-return improvement available to you.

FlowParse
flowparse.io

Knowing which receipts to trust

Because receipt input quality varies so much, a confidence gate matters more here than anywhere else. `POST /api/v1/validate` scores an extracted receipt on internal consistency — do the line amounts sum toward the total, is the tax plausible for the currency, is the date real and not in the future, are required fields present — and returns a 0–100 score with a grade.

In an expense flow that maps naturally onto policy. High grades post straight through to reimbursement. Middling grades go to a reviewer with the questionable field highlighted. Low grades bounce back to the employee with a request for a better photo, which is far cheaper than an accountant discovering the problem at month end. The point is not to eliminate human review but to spend it only where it changes an outcome.

POST /api/v1/validate
curl -X POST https://flowparse.io/api/v1/validate \
  -H "Authorization: Bearer pf_live_xxx" \
  -d '{ "type": "invoice", "data": { ... } }'
# → { "validations": [ { "score": { "value": 88, "grade": "B" }, "checks": [ ... ] } ] }

Photo to reimbursement

1

Capture

The employee photographs the receipt in your app or forwards it to a mailbox.

2

Extract

POST the base64 image to /api/v1/extract and read the typed receipt data.

3

Validate

Score it with /api/v1/validate and route by grade — auto-approve, review, or ask for a re-shoot.

4

Categorise

Apply your own expense categories to the merchant and line items.

5

Export

Push the approved claim into your ledger with /api/v1/export.

FlowParse
flowparse.io

What you can send

Expense capture is mostly images, and the API takes them directly. PDFs still turn up — hotel folios, online order confirmations, receipts emailed as attachments — and are handled on the same endpoint, using the text layer when there is one, which is more accurate than photographing a screen.

InputTypical sourcePath
JPG / PNG photoPhone camera in an expense appOCR, then semantic field assignment
PDF (digital)Emailed receipt or order confirmationText layer read exactly
PDF (scanned)Batch-scanned expense claimsOCR, then field assignment
Multi-page PDFA folio or a stapled set of receiptsEvery page read; results returned together
FlowParse
flowparse.io

Why templates do not work for receipts

Template-based capture is at its weakest on receipts. There are millions of merchants and no two till systems agree on layout, so nobody can pre-configure the long tail. Even a single merchant changes their receipt format when they change point-of-sale providers. A rules library that must be authored per layout is structurally the wrong tool for a document type whose defining feature is unbounded variety.

Semantic extraction does not need to have seen the merchant before. It identifies the total by its role and position relative to the other figures, recognises tax lines by their labels in several languages, and understands that a two-line item is one item. That is why a receipt from a café in a town nobody configured returns clean data on the first request — and why the accuracy question shifts from 'is this merchant supported' to 'is this photo legible', which is a question you can actually act on.

FlowParse
flowparse.io

Building an expense flow on top

Most teams using a receipt OCR API are building the same thing: employees capture receipts, the system extracts and categorises them, a manager approves, and finance reimburses and posts to the ledger. The API covers capture and extraction; the categorisation and policy rules are yours, because they encode decisions only your finance team can make — what counts as client entertainment, which cost centre a purchase belongs to, what threshold needs a second approval.

A pattern that works well is to store the raw extraction alongside your enriched record rather than overwriting it. When a category is later corrected, you still have exactly what the receipt said, which keeps the audit trail honest and gives you the data to improve your own categorisation rules. If you want the same job done without building anything, receipt to Excel and expense reports from receipts cover the browser route.

FlowParse
flowparse.io

Calling it from your application

The API is JSON over HTTPS with no SDK requirement, so it drops into whatever you already use — a Node backend, a Python worker, a Rails job, a mobile backend for your expense app. Base64-encode the image, POST it, read `type` and `data`. Because every FlowParse endpoint shares the schema, a small internal module of extract, validate and export functions is usually the whole integration surface.

For a mobile expense app specifically, do the upload from your backend rather than the device. It keeps your API key off client devices where it cannot be rotated, lets you compress and re-orient the photo consistently before sending, and gives you one place to implement retry and queueing when a user is on a poor connection in a restaurant basement.

Month-end batches of receipts

Expense receipts arrive in a burst at month end — an entire team submitting a month of accumulated photos in the same afternoon. Extract each receipt individually and in parallel across a worker pool rather than in one large request, so a single unreadable image does not fail the batch and each document is independently retryable.

When the output should be one spreadsheet rather than one record per receipt, `POST /api/v1/merge` consolidates up to 100 documents into a single Excel workbook — useful for handing a client's month of receipts to a bookkeeper in one file. Preview requests are free, so you can build that path before spending anything. Batch processing does the same in the browser.

Status codes and what they mean here

One code deserves special attention on receipts: `422`. It means the document was unreadable or had nothing extractable, and it is not billed — which is exactly right for expense capture, because unreadable photos are common and you should not pay for them. Treat 422 as a prompt to ask the employee for a better photo rather than as a system error.

CodeMeaningWhat to do
200Receipt read successfullyValidate, categorise, then post
400Malformed request or bad base64Fix the encoding before retrying
401Invalid or missing keyCheck the Authorization header
422Unreadable image (not billed)Ask for a re-shoot in better light
429Page budget exhaustedTop up, then resume the queue
503Temporarily unavailableRetry with exponential backoff

Cost, and what you never pay for

Extraction bills per page from your page balance, and a receipt is almost always one page — so a receipt is one billed page. Validation and export previews are free, and unreadable documents are not billed at all. That combination keeps expense capture cheap even when a proportion of submissions are poor photos. Plans and allowances are on the pricing page.

CapabilityEndpointBilling
Read a receipt → JSONPOST /api/v1/extractPer page
Validate / confidence scorePOST /api/v1/validateFree
Unreadable documentPOST /api/v1/extract → 422Not billed
Export to file or ledger formatPOST /api/v1/exportPer page (preview free)
Merge a month of receiptsPOST /api/v1/mergePer page (preview free)
FlowParse
flowparse.io

What gets built with it

Expense management apps

Employees snap a receipt; your app receives merchant, date, total and tax without typing.

Accounting practices

Digitise a client's shoebox of receipts into a categorised, reviewable ledger feed.

Corporate cards

Match card transactions to submitted receipts automatically and chase only the missing ones.

Field service & trades

Capture fuel, parts and materials receipts on site and cost them to the right job.

Matching receipts to card transactions

The most valuable thing you can do with a structured receipt is match it to the card transaction it belongs to. Once merchant, date and total are typed fields, matching becomes a solvable problem rather than a manual reconciliation: compare amount within a tolerance, date within a day or two to allow for settlement lag, and merchant name with fuzzy matching to survive the difference between a trading name and the descriptor a bank prints.

That is the same engine behind `POST /api/v1/reconcile` and the reconciliation engine, and it changes what finance chases. Instead of asking everyone for all their receipts, you ask only the people whose transactions have none — which is a much shorter and much better-received list. Extract the card statement with the bank statement API and you have both sides of the match from one key.

FlowParse
flowparse.io

Being realistic about receipt accuracy

Anyone quoting a single accuracy number for receipt OCR is quoting it against their own test set, and receipts vary far too much for that number to predict your results. A clean digital PDF receipt is read essentially exactly. A flat, well-lit photo of fresh thermal paper is read very well. A creased, faded receipt photographed at an angle in a dim room is genuinely hard, and no vendor is immune to that — the honest difference between tools is what they do when the input is bad.

Our answer is to make uncertainty visible rather than hide it. Ambiguous values come back as null with lower confidence instead of a plausible guess, and the validator scores internal consistency so you have a per-document signal rather than a vendor average. You can then set your own threshold: strict for anything above a spend limit, relaxed for a €4 coffee where review costs more than the error. That is a policy decision, and the API gives you the numbers to make it rather than making it for you.

FlowParse
flowparse.io

Tax on receipts, and why it is fiddly

Receipts handle tax inconsistently, and any system that assumes otherwise will produce wrong numbers. Some print a clear tax line. Some print a rate only. Some print a summary of several rates for a basket containing both standard-rated and zero-rated items. Small merchants below a registration threshold print none at all, and their receipt is not a valid tax document no matter how well it is read.

The API returns what the receipt actually states rather than deriving tax from an assumed rate, and returns null when nothing is stated. That is deliberate: an inferred tax figure that finds its way onto a VAT return is a real liability. Where a fuller check is needed on supplier documents, the AI VAT auditor applies the rules, and the VAT number validator confirms a registration is genuine.

Handling employee receipts responsibly

Receipts are more personal than most business documents. They show where an employee was, at what time, and often what they ate or bought — including for trips that turn out not to be reimbursable. Treating that data casually is a privacy problem before it is a security one.

Requests travel over HTTPS, keys are stored hashed and can be rotated per environment, and uploaded files are processed to produce the response rather than retained as downloadable documents; nothing is used to train models. On your side, keep images and extracted JSON out of logs, store only the fields your expense process needs, and set a retention period on receipt images that matches your actual obligation rather than keeping everything indefinitely. The security page covers the platform side.

Wiring it up without an engineering team

Plenty of receipt workflows never need custom code. Automation platforms can call the API directly: Zapier with Webhooks by Zapier, Make with its HTTP module, and n8n with the HTTP Request node. A typical build watches a shared mailbox or a cloud folder, base64-encodes each new attachment, posts it to the extraction endpoint and appends the fields to a spreadsheet.

That is often enough for a small finance team, and it has the advantage of being visible and editable by the people who own the process rather than the people who own the codebase. When the volume or the rules outgrow it, the same API calls move into your application unchanged.

Tracking quality as your inputs change

Receipt pipelines degrade quietly. A new cohort of employees photographs receipts worse than the last, a mobile app update changes image compression, a client starts forwarding screenshots instead of photos — and your review queue grows without anyone deciding it should. Logging the validation grade with every receipt turns that into a chart you can watch instead of a feeling.

Track the 422 rate too, since it is the clearest signal of capture quality: a rising share of unreadable submissions is a user-experience problem, not an OCR problem, and the fix is in your capture flow. On the cost side, per-key usage and page totals are visible in the dashboard, so you can attribute spend to the integration that caused it.

FlowParse
flowparse.io

What we would do in your position

Capture beats correction, so invest in the photo before you invest in the pipeline. Guide users to shoot flat, in even light, with only the receipt in frame, and reject obviously bad images at capture time while the receipt is still in the person's hand — an hour later they have thrown it away and the data is gone for good.

After that, the rules are the same as any extraction pipeline. Validate everything and route by grade. Store the raw extraction next to your enriched record. Make jobs idempotent so a retry cannot double-post an expense. Handle 429 by pausing and 503 by backing off. And set your review threshold by value rather than uniformly, because scrutinising a €4 coffee to the same standard as a €4,000 flight is a poor use of the only expensive resource in the process — a person's attention.

Where to go next

For supplier invoices rather than receipts, see the invoice parsing API. For statements and card feeds, the bank statement API and the bank statement OCR API cover both digital and scanned. For the cross-type view of every document, see the document extraction API, and for spreadsheet output rather than JSON, the PDF to Excel API. A complete worked integration, including batching and error handling, is in the API guide.

FlowParse
flowparse.io

Turn receipt photos into data

One call reads the merchant, date, total, tax and line items — with a confidence score so you review only what needs a human.

Frequently asked questions

Related