QuickBooks Online Expense Management
Overview
Expenses in QuickBooks Online are tracked through two primary entities: Purchase (for direct expenses like checks, credit card charges, and cash payments) and Bill (for accounts payable -- vendor invoices you owe). For MSPs, expense tracking is critical for per-client profitability analysis: tracking software licenses, hardware costs, subcontractor fees, and third-party service costs against the revenue each client generates.
Key Concepts
Expense Types (Purchase Entity)
The Purchase entity covers direct expenses paid immediately or via credit card:
| PaymentType | Description | MSP Example |
|---|
Cash | Cash/bank payment | Petty cash for supplies |
Check | Check payment | Vendor payment by check |
CreditCard | Credit card charge | Software subscription charge |
Bills vs Purchases
| Entity | When to Use | Payment Timing |
|---|
| Purchase | Expense already paid | Immediate (check, cash, credit card) |
| Bill | Vendor invoice received | Deferred (pay later via BillPayment) |
MSP Expense Categories
| Category | Description | Examples |
|---|
| Software Licenses | Per-seat or per-client licenses | Microsoft 365, antivirus, RMM seats |
| Hardware | Equipment for clients | Servers, firewalls, workstations |
| Subcontractors | Outsourced labor | Cabling, specialized consulting |
| Cloud Services | Hosted services | Azure, AWS, backup storage |
| Telecom | Communication services | Internet, VoIP, SIP trunks |
| Training | Staff certifications | Vendor certs, training courses |
Per-Client Cost Tracking
QBO supports assigning expenses to customers, enabling per-client profitability analysis. Use the CustomerRef field on line items to allocate costs to specific MSP clients.
Field Reference
Purchase Core Fields
| Field | Type | Required | Description |
|---|
Id | string | System | Auto-generated unique identifier |
PaymentType | string | Yes | "Cash", "Check", or "CreditCard" |
AccountRef.value | string | Yes | Bank or credit card account ID |
EntityRef.value | string | No | Vendor ID |
TxnDate | date | No | Transaction date (default: today) |
TotalAmt | decimal | Read-only | Total expense amount |
DocNumber | string | No | Reference number |
PrivateNote | string | No | Internal memo |
Line | array | Yes | Array of expense line items |
SyncToken | string | Required for updates | Optimistic locking token |
Purchase Line Item Fields
| Field | Type | Required | Description |
|---|
Line.Amount | decimal | Yes | Line amount |
Line.Description | string | No | Line description |
Line.DetailType | string | Yes | "AccountBasedExpenseLineDetail" or "ItemBasedExpenseLineDetail" |
Line.AccountBasedExpenseLineDetail.AccountRef.value | string | Yes (account-based) | Expense account ID |
Line.AccountBasedExpenseLineDetail.CustomerRef.value | string | No | Customer to allocate cost to |
Line.AccountBasedExpenseLineDetail.BillableStatus | string | No | "Billable", "NotBillable", "HasBeenBilled" |
Line.ItemBasedExpenseLineDetail.ItemRef.value | string | Yes (item-based) | Item ID |
Line.ItemBasedExpenseLineDetail.Qty | decimal | No | Quantity |
Line.ItemBasedExpenseLineDetail.UnitPrice | decimal | No | Unit price |
Bill Core Fields
| Field | Type | Required | Description |
|---|
Id | string | System | Auto-generated unique identifier |
VendorRef.value | string | Yes | Vendor ID |
APAccountRef.value | string | No | Accounts payable account ID |
TxnDate | date | No | Bill date |
DueDate | date | No | Payment due date |
TotalAmt | decimal | Read-only | Total bill amount |
Balance | decimal | Read-only | Remaining unpaid balance |
Line | array | Yes | Array of line items |
SyncToken | string | Required for updates | Optimistic locking token |
Vendor Core Fields
| Field | Type | Required | Description |
|---|
Id | string | System | Auto-generated unique identifier |
DisplayName | string | Yes | Vendor name |
CompanyName | string | No | Legal company name |
PrimaryPhone.FreeFormNumber | string | No | Phone number |
PrimaryEmailAddr.Address | string | No | Email address |
Balance | decimal | Read-only | Outstanding balance owed |
Active | boolean | No | Whether vendor is active |
API Patterns
Query Purchases (Expenses)
GET /v3/company/{realmId}/query?query=SELECT * FROM Purchase WHERE PaymentType = 'CreditCard' AND TxnDate >= '2026-01-01'&minorversion=73
Authorization: Bearer {access_token}
Accept: application/json
Common Queries:
-- All credit card expenses in a date range
SELECT * FROM Purchase WHERE PaymentType = 'CreditCard' AND TxnDate >= '2026-01-01' AND TxnDate <= '2026-01-31'
-- Expenses for a specific vendor
SELECT * FROM Purchase WHERE EntityRef = '42'
-- All expenses in a month
SELECT * FROM Purchase WHERE TxnDate >= '2026-02-01' AND TxnDate <= '2026-02-28' ORDERBY TxnDate DESC
-- All bills (accounts payable)
SELECT * FROM Bill WHERE Balance > '0' ORDERBY DueDate ASC
-- Bills for a specific vendor
SELECT * FROM Bill WHERE VendorRef = '42' AND Balance > '0'
-- All vendors
SELECT * FROM Vendor WHERE Active = true ORDERBY DisplayName
Create Purchase (Credit Card Expense)
POST /v3/company/{realmId}/purchase?minorversion=73
Content-Type: application/json
Authorization: Bearer {access_token}
Software license expense allocated to a client:
{
"PaymentType": "CreditCard",
"AccountRef": {
"value": "41"
},
"EntityRef": {
"value": "42",
"type": "Vendor"
},
"TxnDate": "2026-02-15",
"Line": [
{
"Amount": 450.00,
"Description": "Microsoft 365 Business Premium - 30 seats - Acme Corp - February 2026",
"DetailType": "AccountBasedExpenseLineDetail",
"AccountBasedExpenseLineDetail": {
"AccountRef": { "value": "60" },
"CustomerRef": { "value": "123" },
"BillableStatus": "Billable"
}
},
{
"Amount": 120.00,
"Description": "SentinelOne Endpoint Protection - 30 seats - Acme Corp - February 2026",
"DetailType": "AccountBasedExpenseLineDetail",
"AccountBasedExpenseLineDetail": {
"AccountRef": { "value": "60" },
"CustomerRef": { "value": "123" },
"BillableStatus": "Billable"
}
}
],
"PrivateNote": "Monthly software licenses for Acme Corp"
}
curl -s -X POST \
-H "Authorization: Bearer $QBO_ACCESS_TOKEN" \
-H "Content-Type: application/json" \
-H "Accept: application/json" \
"https://quickbooks.api.intuit.com/v3/company/$QBO_REALM_ID/purchase?minorversion=73" \
-d '{
"PaymentType": "CreditCard",
"AccountRef": { "value": "41" },
"EntityRef": { "value": "42", "type": "Vendor" },
"Line": [{
"Amount": 450.00,
"Description": "Microsoft 365 - Acme Corp - Feb 2026",
"DetailType": "AccountBasedExpenseLineDetail",
"AccountBasedExpenseLineDetail": {
"AccountRef": { "value": "60" },
"CustomerRef": { "value": "123" },
"BillableStatus": "Billable"
}
}]
}'
Create Bill (Vendor Invoice)
{
"VendorRef": {
"value": "42"
},
"TxnDate": "2026-02-10",
"DueDate": "2026-03-12",
"Line": [
{
"Amount": 2400.00,
"Description": "Cabling project - Acme Corp new office build-out",
"DetailType": "AccountBasedExpenseLineDetail",
"AccountBasedExpenseLineDetail": {
"AccountRef": { "value": "62" },
"CustomerRef": { "value": "123" },
"BillableStatus": "Billable"
}
}
],
"PrivateNote": "Subcontractor cabl