BlogReceipt to JSON API: Convert Any Receipt to Structured Data

Receipt to JSON API: Convert Any Receipt to Structured Data

2026-06-01 · 7 min read

1
API call
4
languages covered
~3s
response time
Free
20 receipts/month

A receipt is unstructured visual data — pixels arranged to look like text. A JSON object with named fields is structured data your application can store, query, display, and process. Converting between those two representations is what a receipt-to-JSON API does.

Here's the complete picture: the request format, the response structure, what every field means, and working code in four languages.

Quick Start

The Request

bash
curl -X POST https://docuparseapi.com/api/v1/extract \
  -H "Authorization: Bearer YOUR_API_KEY" \
  -F "file=@receipt.jpg"

That's the entire integration surface. One endpoint, one file parameter, one authorization header.

Accepted file types: JPG, PNG, PDF Maximum file size: 10MB Accepted sources: Scanned documents, photos, digital PDFs — the API handles OCR automatically when needed

Get a free API key at docuparseapi.com/signup — 20 documents/month, no credit card.

API Response

The Response

json
{
  "success": true,
  "document_id": "doc_clx7abc123",
  "document_type": "receipt",
  "merchant": "Target",
  "date": "2026-05-14",
  "currency": "USD",
  "subtotal": "43.97",
  "tax": "3.52",
  "total": "47.49",
  "tax_rate": "8.00%",
  "receipt_id": "4821-0594",
  "payment_method": "Mastercard",
  "line_items": [
    {
      "description": "Cotton T-Shirt",
      "quantity": 2,
      "unit_price": "9.99",
      "amount": "19.98"
    },
    {
      "description": "Notebook - 5 pack",
      "quantity": 1,
      "unit_price": "7.99",
      "amount": "7.99"
    },
    {
      "description": "USB-C Cable",
      "quantity": 1,
      "unit_price": "15.99",
      "amount": "15.99"
    }
  ],
  "processing_time_ms": 2980
}
All Fields

Field Reference

FieldTypeAlwaysDescription
merchantstring | null✓ YesStore or vendor name
datestring | null✓ YesISO 8601 transaction date
totalstring | null✓ YesFinal charged amount
subtotalstring | nullIf presentPre-tax amount
taxstring | null✓ YesTax amount charged
tax_ratestring | nullIf presentTax percentage
currencystring | null✓ YesISO 4217 currency code
receipt_idstring | nullIf presentReceipt or transaction number
payment_methodstring | nullIf presentCard, cash, etc.
line_itemsarray✓ YesItems: description, quantity, amount
document_idstring✓ YesUnique extraction ID for dedup
✓ Missing fields return null, never omitted. Check null before using.
Field Type Description
success boolean Whether extraction succeeded
document_id string Unique ID for this extraction — use for deduplication
document_type string "receipt" or "invoice"
merchant string | null Store or vendor name
date string | null Transaction date in ISO 8601 (YYYY-MM-DD)
currency string | null ISO 4217 code: USD, EUR, GBP, etc.
subtotal string | null Pre-tax amount
tax string | null Tax amount
tax_rate string | null Tax percentage
total string | null Final charged amount
receipt_id string | null The receipt's own identifier
payment_method string | null Card type, cash, etc.
line_items array Individual items — see below
processing_time_ms number Extraction time in milliseconds

Why monetary values are strings: Floating-point arithmetic introduces rounding errors in financial calculations. 42.10 stored as a float can become 42.09999999 in some languages. Strings preserve the exact decimal representation from the original document. Convert to Decimal or BigDecimal (not float) for arithmetic.

Missing fields return null, not omitted: If a receipt has no receipt ID, the response contains "receipt_id": null — not a missing key. This means you can safely access any field without checking for key existence first.

Try it in Python, Node.js, PHP, or Ruby — no account needed
Upload a receipt. See the same structured JSON your chosen language would receive.
Open Live Demo →
Free tier · 20 documents/month — free forever · No credit card · No account needed for the demo
Python · Node · PHP · Ruby

Code in Four Languages

Python · Node.js · PHP · Ruby
import os
import requests
from decimal import Decimal

def receipt_to_json(file_path: str) -> dict:
    """Convert a receipt image or PDF to structured JSON."""
    with open(file_path, "rb") as f:
        response = requests.post(
            "https://docuparseapi.com/api/v1/extract",
            headers={"Authorization": f"Bearer {os.environ['DOCUPARSE_API_KEY']}"},
            files={"file": f},
            timeout=30,
        )
    
    response.raise_for_status()
    data = response.json()
    
    if not data["success"]:
        raise RuntimeError(f"[{data['error']['code']}] {data['error']['message']}")
    
    return data


# Usage
receipt = receipt_to_json("receipt.jpg")

merchant = receipt.get("merchant") or "Unknown"
total = Decimal(receipt["total"]) if receipt.get("total") else Decimal("0")
currency = receipt.get("currency") or "USD"

print(f"{merchant}: {currency} {total}")

for item in receipt.get("line_items", []):
    qty = item.get("quantity", 1)
    desc = item.get("description", "")
    amount = item.get("amount", "?")
    print(f"  {qty}× {desc} = {amount}")
The code above works the moment you have a key.
20 documents/month — free forever. No credit card. Works in any language.
Storage

Working With the Structured Data

Store in a database

python
import sqlite3
import json
from decimal import Decimal

def store_receipt(conn: sqlite3.Connection, receipt: dict) -> int:
    conn.execute("""
        CREATE TABLE IF NOT EXISTS receipts (
            id INTEGER PRIMARY KEY AUTOINCREMENT,
            document_id TEXT UNIQUE,
            merchant TEXT,
            date TEXT,
            currency TEXT,
            total REAL,
            tax REAL,
            payment_method TEXT,
            line_items TEXT,
            created_at TEXT DEFAULT CURRENT_TIMESTAMP
        )
    """)
    
    cursor = conn.execute("""
        INSERT OR IGNORE INTO receipts
        (document_id, merchant, date, currency, total, tax, payment_method, line_items)
        VALUES (?, ?, ?, ?, ?, ?, ?, ?)
    """, (
        receipt.get("document_id"),
        receipt.get("merchant"),
        receipt.get("date"),
        receipt.get("currency"),
        float(receipt.get("total") or 0),
        float(receipt.get("tax") or 0),
        receipt.get("payment_method"),
        json.dumps(receipt.get("line_items", [])),
    ))
    
    conn.commit()
    return cursor.lastrowid

Prevent duplicate submissions

Use document_id — it's unique per extraction:

python
existing = db.receipts.find_one({"document_id": receipt["document_id"]})
if existing:
    return {"status": "duplicate", "existing_id": existing["id"]}

Aggregate spending by merchant

python
receipts = [receipt_to_json(f) for f in receipt_files]
by_merchant = {}
for r in receipts:
    m = r.get("merchant") or "Unknown"
    by_merchant[m] = by_merchant.get(m, 0) + float(r.get("total") or 0)

for merchant, total in sorted(by_merchant.items(), key=lambda x: -x[1]):
    print(f"{merchant}: ${total:.2f}")
Errors

Error Response Format

When success is false:

json
{
  "success": false,
  "error": {
    "code": "EXTRACTION_FAILED",
    "message": "Document extraction failed for this file."
  }
}

Error codes:

Code Meaning What to do
MISSING_API_KEY No authorization header Add Authorization: Bearer YOUR_KEY
INVALID_API_KEY Key not found Check the key, regenerate if needed
LIMIT_EXCEEDED Monthly document limit reached Upgrade plan or wait for reset
UNSUPPORTED_FILE_TYPE Not PDF, JPG, or PNG Convert file format before sending
FILE_TOO_LARGE Over 10MB Compress the file
EXTRACTION_FAILED Document couldn't be parsed Try a cleaner scan or a different file

Get Started

Next Steps

Python · Node.js · PHP · Ruby

Your receipt data is one API call away.

Any language. Any receipt format. Named JSON fields. 20 documents/month — free forever.

More from the blog