QB
Accounting
Automate QuickBooks Invoice Entry — Parse PDFs Directly into QuickBooks Online
Every supplier invoice that arrives as a PDF can go directly into QuickBooks Online as a Bill — without anyone touching a keyboard.
Trusted by developers worldwide to automate document workflows.
✓ Free DocuParseAPI account✓ QuickBooks Online API✓ Python or Node
The guide
1
Get your credentials
You need three things: a DocuParseAPI key (from your dashboard), a QuickBooks Online OAuth 2.0 access token, and your QBO Company ID. Create a QBO app at developer.intuit.com to get OAuth credentials.
2
Extract the invoice
POST the PDF to DocuParseAPI. The response gives you every field QuickBooks needs:
merchant → VendorRef.name date → TxnDate due_date → DueDate invoice_id → DocNumber total → TotalAmt line_items → Line[] array
3
Find or create the vendor in QBO
Query QBO for a Vendor matching the extracted merchant name. If none exists, create one automatically:
def find_or_create_vendor(name, qbo_base, headers):
r = requests.get(f"{qbo_base}/query", headers=headers,
params={"query": f"SELECT * FROM Vendor WHERE DisplayName LIKE '%{name}%'",
"minorversion": "65"})
vendors = r.json().get("QueryResponse", {}).get("Vendor", [])
if vendors:
return vendors[0]["Id"]
r = requests.post(f"{qbo_base}/vendor", headers=headers,
params={"minorversion": "65"},
json={"DisplayName": name, "PrintOnCheckName": name})
return r.json()["Vendor"]["Id"]Need your API key first?
20 free documents/month — no credit card
4
Check for duplicate invoices
Before creating, query QBO for an existing Bill with the same DocNumber and VendorRef. If found, skip:
def is_duplicate(invoice_number, qbo_base, headers):
r = requests.get(f"{qbo_base}/query", headers=headers,
params={"query": f"SELECT * FROM Bill WHERE DocNumber = '{invoice_number}'",
"minorversion": "65"})
return len(r.json().get("QueryResponse", {}).get("Bill", [])) > 05
Create the Bill in QuickBooks
POST to the QBO /bill endpoint with the extracted fields mapped:
bill = {
"VendorRef": {"value": vendor_id},
"TxnDate": invoice["date"],
"DueDate": invoice["due_date"],
"DocNumber": invoice["invoice_id"],
"TotalAmt": float(invoice["total"]),
"Line": [{
"Amount": float(item["total"]),
"DetailType": "AccountBasedExpenseLineDetail",
"Description": item["description"],
"AccountBasedExpenseLineDetail": {
"AccountRef": {"value": "7"}
}
} for item in invoice["line_items"]]
}Full working example
python
import os, requests
QBO_BASE = f"https://quickbooks.api.intuit.com/v3/company/{os.environ['QBO_COMPANY_ID']}"
HEADERS = {"Authorization": f"Bearer {os.environ['QBO_ACCESS_TOKEN']}",
"Content-Type": "application/json", "Accept": "application/json"}
def extract_invoice(path):
with open(path, "rb") as f:
r = requests.post("https://docuparseapi.com/api/v1/extract",
headers={"Authorization": f"Bearer {os.environ['DOCUPARSE_API_KEY']}"},
files={"file": f}, timeout=30)
data = r.json()
if not data["success"]: raise RuntimeError(data["error"]["code"])
return data
def find_or_create_vendor(name):
r = requests.get(f"{QBO_BASE}/query", headers=HEADERS,
params={"query": f"SELECT * FROM Vendor WHERE DisplayName LIKE '%{name}%'",
"minorversion": "65"})
vendors = r.json().get("QueryResponse", {}).get("Vendor", [])
if vendors: return vendors[0]["Id"]
r = requests.post(f"{QBO_BASE}/vendor", headers=HEADERS, params={"minorversion":"65"},
json={"DisplayName": name})
return r.json()["Vendor"]["Id"]
def process(file_path):
inv = extract_invoice(file_path)
vendor_id = find_or_create_vendor(inv.get("merchant") or "Unknown")
r = requests.post(f"{QBO_BASE}/bill", headers=HEADERS, params={"minorversion":"65"},
json={"VendorRef":{"value":vendor_id}, "TxnDate":inv.get("date"),
"DocNumber":inv.get("invoice_id"), "TotalAmt":float(inv.get("total") or 0),
"Line":[{"Amount":float(i.get("total") or 0), "DetailType":"AccountBasedExpenseLineDetail",
"Description":i.get("description",""), "AccountBasedExpenseLineDetail":{"AccountRef":{"value":"7"}}}
for i in inv.get("line_items",[])]})
print(f"Bill created: {r.json()['Bill']['Id']}")
process("invoice.pdf")What gets extracted
Common errors and fixes
Ready to start?
20 documents free every month. No credit card. Set up in 5 minutes.
Get Your Free API Key