From quickbooks-online
Creates, sends, voids, and manages QuickBooks Online invoices for MSP clients including recurring, project-based, and time & materials billing.
How this skill is triggered — by the user, by Claude, or both
Slash command
/quickbooks-online:invoicesWhen to use
When creating, sending, voiding, and managing invoices for MSP clients. Use when: quickbooks invoice, qbo invoice, quickbooks billing, qbo billing, create invoice, send invoice, invoice management, managed services invoice, monthly billing, or recurring invoice.
The summary Claude sees in its skill listing — used to decide when to auto-load this skill
Invoices are the primary billing mechanism in QuickBooks Online. For MSPs, invoices typically represent monthly managed services fees, project work, hardware procurement, or ad-hoc support. QBO supports line items with service/product references, automatic tax calculation, email delivery, payment links, and integration with online payment processing. Invoices track due dates via payment terms a...
Invoices are the primary billing mechanism in QuickBooks Online. For MSPs, invoices typically represent monthly managed services fees, project work, hardware procurement, or ad-hoc support. QBO supports line items with service/product references, automatic tax calculation, email delivery, payment links, and integration with online payment processing. Invoices track due dates via payment terms and automatically contribute to the customer's outstanding balance.
| Status | Description | Balance Impact |
|---|---|---|
| Draft | Not yet sent | Adds to balance |
| Sent | Emailed to customer | Adds to balance |
| Partially Paid | Some payment applied | Reduced balance |
| Paid | Fully paid | Zero balance |
| Voided | Cancelled | Removed from balance |
| Overdue | Past due date | Adds to balance (flagged) |
Each invoice contains one or more line items. Line items reference Items (products/services) from the QBO Items list:
| Line Type | Description | MSP Example |
|---|---|---|
SalesItemLineDetail | Standard product/service line | Monthly IT services |
GroupLineDetail | Grouped bundle of items | Managed services bundle |
DescriptionOnlyLine | Text-only description line | Section headers |
DiscountLineDetail | Discount applied | Multi-year contract discount |
SubTotalLineDetail | Running subtotal | Subtotal before tax |
| Type | Frequency | Description |
|---|---|---|
| Recurring Monthly | Monthly | Managed services, monitoring, backup |
| Project-Based | One-time | Network upgrade, migration, deployment |
| Time & Materials | As incurred | Break-fix support, consulting hours |
| Hardware | One-time | Equipment procurement and markup |
| Field | Type | Required | Description |
|---|---|---|---|
Id | string | System | Auto-generated unique identifier |
DocNumber | string | No | Invoice number (auto-generated if blank) |
TxnDate | date | No | Invoice date (default: today) |
DueDate | date | No | Payment due date (calculated from terms) |
CustomerRef.value | string | Yes | Customer ID |
Line | array | Yes | Array of line items |
TotalAmt | decimal | Read-only | Total invoice amount |
Balance | decimal | Read-only | Remaining unpaid balance |
SyncToken | string | Required for updates | Optimistic locking token |
| Field | Type | Description |
|---|---|---|
SalesTermRef.value | string | Payment terms ID |
BillEmail.Address | string | Email to send invoice to |
BillAddr | object | Billing address |
ShipAddr | object | Shipping address |
CustomerMemo.value | string | Memo visible to customer |
PrivateNote | string | Internal note (not visible to customer) |
EmailStatus | string | "NotSet", "NeedToSend", "EmailSent" |
| Field | Type | Required | Description |
|---|---|---|---|
Line.Amount | decimal | Yes | Line total (Qty x Rate) |
Line.Description | string | No | Line item description |
Line.DetailType | string | Yes | "SalesItemLineDetail" |
Line.SalesItemLineDetail.ItemRef.value | string | Yes | Item ID |
Line.SalesItemLineDetail.Qty | decimal | No | Quantity |
Line.SalesItemLineDetail.UnitPrice | decimal | No | Unit price |
Line.SalesItemLineDetail.ServiceDate | date | No | Service date |
| Field | Type | Description |
|---|---|---|
TxnTaxDetail.TotalTax | decimal | Total tax amount |
TxnTaxDetail.TxnTaxCodeRef.value | string | Tax code ID |
GlobalTaxCalculation | string | "TaxExcluded", "TaxInclusive", "NotApplicable" |
| Field | Type | Description |
|---|---|---|
MetaData.CreateTime | datetime | Creation timestamp |
MetaData.LastUpdatedTime | datetime | Last update timestamp |
GET /v3/company/{realmId}/query?query=SELECT * FROM Invoice WHERE CustomerRef = '123' AND Balance > '0'&minorversion=73
Authorization: Bearer {access_token}
Accept: application/json
Common Queries:
-- Unpaid invoices for a customer
SELECT * FROM Invoice WHERE CustomerRef = '123' AND Balance > '0'
-- All invoices in a date range
SELECT * FROM Invoice WHERE TxnDate >= '2026-01-01' AND TxnDate <= '2026-01-31' ORDERBY TxnDate DESC
-- Overdue invoices (past due date with balance)
SELECT * FROM Invoice WHERE DueDate < '2026-02-23' AND Balance > '0' ORDERBY DueDate ASC
-- Recent invoices
SELECT * FROM Invoice ORDERBY TxnDate DESC MAXRESULTS 25
-- Invoices by doc number
SELECT * FROM Invoice WHERE DocNumber = 'INV-1042'
GET /v3/company/{realmId}/invoice/456?minorversion=73
Authorization: Bearer {access_token}
curl -s -H "Authorization: Bearer $QBO_ACCESS_TOKEN" \
-H "Accept: application/json" \
"https://quickbooks.api.intuit.com/v3/company/$QBO_REALM_ID/invoice/456?minorversion=73"
POST /v3/company/{realmId}/invoice?minorversion=73
Content-Type: application/json
Authorization: Bearer {access_token}
Monthly Managed Services Invoice:
{
"CustomerRef": {
"value": "123"
},
"TxnDate": "2026-02-01",
"SalesTermRef": {
"value": "3"
},
"BillEmail": {
"Address": "[email protected]"
},
"EmailStatus": "NeedToSend",
"Line": [
{
"Amount": 2500.00,
"Description": "Monthly Managed IT Services - February 2026\nIncludes: 24/7 monitoring, patch management, help desk support (unlimited)",
"DetailType": "SalesItemLineDetail",
"SalesItemLineDetail": {
"ItemRef": { "value": "1" },
"Qty": 1,
"UnitPrice": 2500.00,
"ServiceDate": "2026-02-01"
}
},
{
"Amount": 150.00,
"Description": "Cloud Backup Service - 500GB - February 2026",
"DetailType": "SalesItemLineDetail",
"SalesItemLineDetail": {
"ItemRef": { "value": "2" },
"Qty": 1,
"UnitPrice": 150.00,
"ServiceDate": "2026-02-01"
}
},
{
"Amount": 200.00,
"Description": "Email Security Filtering - 50 mailboxes - February 2026",
"DetailType": "SalesItemLineDetail",
"SalesItemLineDetail": {
"ItemRef": { "value": "3" },
"Qty": 50,
"UnitPrice": 4.00,
"ServiceDate": "2026-02-01"
}
}
],
"CustomerMemo": {
"value": "Thank you for choosing our managed IT services."
},
"PrivateNote": "Monthly recurring invoice - auto-generated"
}
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/invoice?minorversion=73" \
-d '{
"CustomerRef": { "value": "123" },
"Line": [{
"Amount": 2500.00,
"Description": "Monthly Managed IT Services - February 2026",
"DetailType": "SalesItemLineDetail",
"SalesItemLineDetail": {
"ItemRef": { "value": "1" },
"Qty": 1,
"UnitPrice": 2500.00
}
}]
}'
POST /v3/company/{realmId}/invoice/456/send?minorversion=73
Authorization: Bearer {access_token}
curl -s -X POST \
-H "Authorization: Bearer $QBO_ACCESS_TOKEN" \
-H "Content-Type: application/octet-stream" \
"https://quickbooks.api.intuit.com/v3/company/$QBO_REALM_ID/invoice/456/[email protected]&minorversion=73"
{
"Id": "456",
"SyncToken": "3",
"sparse": true,
"CustomerMemo": {
"value": "Payment is now overdue. Please remit immediately."
}
}
POST /v3/company/{realmId}/invoice?operation=void&minorversion=73
Content-Type: application/json
Authorization: Bearer {access_token}
{
"Id": "456",
"SyncToken": "3"
}
POST /v3/company/{realmId}/invoice?operation=delete&minorversion=73
Content-Type: application/json
Authorization: Bearer {access_token}
{
"Id": "456",
"SyncToken": "3"
}
GET /v3/company/{realmId}/invoice/456/pdf?minorversion=73
Authorization: Bearer {access_token}
Accept: application/pdf
async function generateMonthlyInvoices(billingMonth) {
// Fetch all active MSP clients
const customers = await qboQuery(
"SELECT * FROM Customer WHERE Active = true AND Balance >= '0'"
);
const clients = customers.QueryResponse.Customer || [];
const results = { created: [], errors: [] };
for (const client of clients) {
try {
// Build line items from client's service agreement
const lines = await buildServiceLines(client.Id, billingMonth);
if (lines.length === 0) continue;
const invoice = await createInvoice({
CustomerRef: { value: client.Id },
TxnDate: billingMonth + '-01',
BillEmail: { Address: client.PrimaryEmailAddr?.Address },
EmailStatus: 'NeedToSend',
Line: lines,
CustomerMemo: {
value: `Services for ${billingMonth}. Thank you for your business.`
}
});
results.created.push({
customer: client.DisplayName,
invoiceId: invoice.Id,
total: invoice.TotalAmt
});
} catch (error) {
results.errors.push({
customer: client.DisplayName,
error: error.message
});
}
}
return results;
}
async function createProjectInvoice(customerId, projectDetails) {
const lines = projectDetails.tasks.map(task => ({
Amount: task.hours * task.rate,
Description: `${task.description}\n${task.hours} hours @ $${task.rate}/hr`,
DetailType: 'SalesItemLineDetail',
SalesItemLineDetail: {
ItemRef: { value: task.itemId },
Qty: task.hours,
UnitPrice: task.rate,
ServiceDate: task.date
}
}));
return await createInvoice({
CustomerRef: { value: customerId },
Line: lines,
CustomerMemo: {
value: `Project: ${projectDetails.name}\nWork completed ${projectDetails.startDate} - ${projectDetails.endDate}`
},
PrivateNote: `PSA Ticket: ${projectDetails.ticketNumber}`
});
}
async function sendUnsentInvoices() {
const unsent = await qboQuery(
"SELECT * FROM Invoice WHERE EmailStatus = 'NeedToSend' AND Balance > '0'"
);
const invoices = unsent.QueryResponse.Invoice || [];
for (const invoice of invoices) {
const email = invoice.BillEmail?.Address;
if (email) {
await sendInvoice(invoice.Id, email);
}
}
return { sent: invoices.length };
}
async function getOverdueInvoices() {
const today = new Date().toISOString().split('T')[0];
const result = await qboQuery(
`SELECT * FROM Invoice WHERE DueDate < '${today}' AND Balance > '0' ORDERBY DueDate ASC`
);
const invoices = result.QueryResponse.Invoice || [];
return invoices.map(inv => ({
invoiceNumber: inv.DocNumber,
customer: inv.CustomerRef.name,
amount: inv.TotalAmt,
balance: inv.Balance,
dueDate: inv.DueDate,
daysOverdue: Math.floor((Date.now() - new Date(inv.DueDate)) / 86400000)
}));
}
| Code | Message | Resolution |
|---|---|---|
| 6000 | Business Validation | Check line item amounts and required fields |
| 6140 | Duplicate DocNumber | Use a different invoice number or let QBO auto-assign |
| 610 | Object Not Found | Verify CustomerRef, ItemRef, or Invoice ID |
| 5010 | Stale Object | Re-fetch SyncToken and retry |
| 2050 | Invalid Reference | Check CustomerRef, ItemRef, SalesTermRef values |
| Error | Cause | Fix |
|---|---|---|
| CustomerRef required | Missing customer | Add CustomerRef.value to request |
| Line required | No line items | Add at least one Line item |
| Invalid ItemRef | Bad item ID | Query Items for valid IDs |
| Amount mismatch | Qty x UnitPrice != Amount | Ensure Amount = Qty * UnitPrice |
async function safeCreateInvoice(data) {
try {
return await createInvoice(data);
} catch (error) {
const fault = error.Fault;
if (!fault) throw error;
const errorCode = fault.Error?.[0]?.code;
if (errorCode === '6140') {
// Duplicate DocNumber -- remove and let QBO auto-assign
delete data.DocNumber;
return await createInvoice(data);
}
if (errorCode === '610') {
// Invalid reference -- log details for debugging
console.log('Invalid reference. Verify CustomerRef and ItemRef values.');
console.log('Detail:', fault.Error[0].Detail);
}
throw error;
}
}
| Operation | Method | Endpoint |
|---|---|---|
| Create | POST | /v3/company/{realmId}/invoice |
| Read | GET | /v3/company/{realmId}/invoice/{id} |
| Update | POST | /v3/company/{realmId}/invoice |
| Delete | POST | /v3/company/{realmId}/invoice?operation=delete |
| Void | POST | /v3/company/{realmId}/invoice?operation=void |
| Send | POST | /v3/company/{realmId}/invoice/{id}/send |
| GET | /v3/company/{realmId}/invoice/{id}/pdf | |
| Query | GET | /v3/company/{realmId}/query?query=... |
npx claudepluginhub wyre-technology/msp-claude-plugins --plugin quickbooks-onlineCreates, searches, updates, voids, and manages Xero sales invoices (ACCREC) and supplier bills (ACCPAY). Covers invoice lifecycle, line items, tax handling, and recurring MSP billing workflows.
Creates, manages, and tracks Syncro MSP invoices, line items, and payments. Covers invoice fields, statuses, billing workflows, and API patterns for invoice operations.
Matches active Pax8 subscriptions against Xero or QuickBooks Online invoices to detect billing gaps, quantity mismatches, and margin discrepancies for MSPs.