Docs/Python
Language Guides

Python

Parse receipts and invoices in Python using the requests library. No SDK needed.

Installation

Only requests is required:

pip install requests

Authentication

Get your API key from your dashboard. Pass it in the Authorization header as a Bearer token. Store it in an environment variable — never hardcode it.

import os
API_KEY = os.environ["RECEIPTCONVERTER_API_KEY"]
BASE_URL = "https://receiptconverter.com/api/v1"

Uploading a file

Send a multipart/form-data POST request with the receipt file:

import requests, os

API_KEY = os.environ["RECEIPTCONVERTER_API_KEY"]

def parse_receipt(file_path: str) -> dict:
    with open(file_path, "rb") as f:
        response = requests.post(
            "https://receiptconverter.com/api/v1/convert",
            headers={"Authorization": f"Bearer {API_KEY}"},
            files={"file": f},
        )
    response.raise_for_status()
    return response.json()

receipt = parse_receipt("receipt.jpg")
print(receipt["data"]["vendor"])   # e.g. "Starbucks"
print(receipt["data"]["total"])    # e.g. 12.50

Parsing from a URL

If the receipt is already hosted online, pass a URL as JSON:

import requests, os

API_KEY = os.environ["RECEIPTCONVERTER_API_KEY"]

def parse_receipt_url(url: str, file_name: str | None = None) -> dict:
    payload = {"url": url}
    if file_name:
        payload["file_name"] = file_name

    response = requests.post(
        "https://receiptconverter.com/api/v1/convert",
        headers={
            "Authorization": f"Bearer {API_KEY}",
            "Content-Type": "application/json",
        },
        json=payload,
    )
    response.raise_for_status()
    return response.json()

receipt = parse_receipt_url(
    "https://example.com/receipts/lunch.pdf",
    file_name="lunch_march.pdf"
)

Error handling

Handle common errors gracefully:

import requests, os

API_KEY = os.environ["RECEIPTCONVERTER_API_KEY"]

def parse_receipt_safe(file_path: str) -> dict | None:
    try:
        with open(file_path, "rb") as f:
            response = requests.post(
                "https://receiptconverter.com/api/v1/convert",
                headers={"Authorization": f"Bearer {API_KEY}"},
                files={"file": f},
                timeout=30,
            )

        if response.status_code == 429:
            data = response.json()
            print(f"Rate limit hit. Upgrade at {data.get('upgrade_url')}")
            return None

        if response.status_code == 401:
            print("Invalid API key.")
            return None

        response.raise_for_status()
        return response.json()

    except requests.exceptions.Timeout:
        print("Request timed out.")
        return None
    except requests.exceptions.RequestException as e:
        print(f"Request failed: {e}")
        return None

Batch processing

Use concurrent.futures to process multiple receipts in parallel. Stay within your plan's rate limits — Pro allows 30 req/min, Pro Plus 120 req/min.

import requests, os, time
from concurrent.futures import ThreadPoolExecutor, as_completed
from pathlib import Path

API_KEY = os.environ["RECEIPTCONVERTER_API_KEY"]

def parse_one(path: Path) -> tuple[str, dict | None]:
    try:
        with open(path, "rb") as f:
            r = requests.post(
                "https://receiptconverter.com/api/v1/convert",
                headers={"Authorization": f"Bearer {API_KEY}"},
                files={"file": (path.name, f)},
                timeout=30,
            )
        if r.status_code == 429:
            time.sleep(2)
            return str(path), None
        r.raise_for_status()
        return str(path), r.json()
    except Exception as e:
        return str(path), None

receipts = list(Path("./receipts").glob("*.jpg"))

with ThreadPoolExecutor(max_workers=5) as pool:
    futures = {pool.submit(parse_one, p): p for p in receipts}
    for future in as_completed(futures):
        path, result = future.result()
        if result:
            vendor = result["data"]["vendor"]
            total  = result["data"]["total"]
            print(path + ": " + str(vendor) + " - " + str(total))
        else:
            print(path + ": failed")

Working with the response

receipt = parse_receipt("receipt.jpg")
data = receipt["data"]

# Basic fields
print(data["vendor"])          # "Starbucks"
print(data["date"])            # "2024-03-15"
print(data["total"])           # 12.50
print(data["currency"])        # "USD"
print(data["payment_method"])  # "Visa ****4242"
print(data["category"])        # "Food & Drink"

# Line items
for item in data.get("items", []):
    name  = item["name"]
    qty   = item["quantity"]
    price = item["unit_price"]
    print("  " + name + ": " + str(qty) + " x $" + str(price))

# Taxes
for tax in data.get("taxes", []):
    label  = tax["label"]
    amount = tax["amount"]
    print("  " + label + ": $" + str(amount))

# Tip
if data.get("tip"):
    tip = data["tip"]
    print("  Tip: $" + str(tip))
Need help? Read the full API reference, check the batch processing guide, or contact us.