Xero Invoices Management
Overview
Invoices are the core transaction entity in Xero for billing and accounts payable. For MSPs, invoices represent two primary flows: sales invoices (ACCREC) for billing managed services clients, and supplier bills (ACCPAY) for vendor costs like software licenses, hardware purchases, and ISP charges.
Core Concepts
Invoice Types
| Type | Code | Description | MSP Use Case |
|---|
| Sales Invoice | ACCREC | Accounts Receivable - you bill a customer | Monthly managed services, project work |
| Supplier Bill | ACCPAY | Accounts Payable - a vendor bills you | Software licenses, hardware, ISP bills |
Invoice Status Lifecycle
DRAFT --> SUBMITTED --> AUTHORISED --> PAID
\--> VOIDED
\--> DELETED (draft only)
| Status | Description | Editable | Can Pay |
|---|
DRAFT | Created but not submitted | Yes | No |
SUBMITTED | Submitted for approval | Limited | No |
AUTHORISED | Approved and sent to client | No | Yes |
PAID | Fully paid | No | N/A |
VOIDED | Cancelled/voided | No | No |
DELETED | Removed (draft only) | N/A | N/A |
Invoice Numbering
Xero auto-generates sequential invoice numbers (e.g., INV-0001, INV-0002) or you can set custom numbers using the InvoiceNumber field. MSPs often use prefixes like MS- for managed services or PJ- for project invoices.
Field Reference
Core Fields
| Field | Type | Required | Description |
|---|
InvoiceID | string (UUID) | System | Auto-generated unique identifier |
InvoiceNumber | string | No | Invoice number (auto-generated if blank) |
Type | string | Yes | ACCREC (sales) or ACCPAY (bill) |
Contact | object | Yes | Contact object with ContactID |
Date | string | No | Invoice date (YYYY-MM-DDT00:00:00) |
DueDate | string | No | Payment due date |
Status | string | No | DRAFT, SUBMITTED, AUTHORISED, PAID, VOIDED |
LineAmountTypes | string | No | Exclusive, Inclusive, or NoTax |
Reference | string | No | Reference text (e.g., PO number) |
Url | string | No | URL link for the invoice |
CurrencyCode | string | No | Currency code (e.g., USD, AUD) |
BrandingThemeID | string | No | Invoice template/theme ID |
Line Item Fields
| Field | Type | Required | Description |
|---|
Description | string | Yes | Line item description |
Quantity | decimal | No | Quantity (default 1) |
UnitAmount | decimal | Yes* | Price per unit |
AccountCode | string | Yes* | GL account code |
TaxType | string | No | Tax type code |
ItemCode | string | No | Inventory item code |
LineAmount | decimal | No | Total line amount (calculated) |
DiscountRate | decimal | No | Discount percentage |
Tracking | array | No | Tracking category assignments |
*Required for AUTHORISED status.
Financial Summary Fields (Read-Only)
| Field | Type | Description |
|---|
SubTotal | decimal | Sum of line items before tax |
TotalTax | decimal | Total tax amount |
Total | decimal | Total including tax |
AmountDue | decimal | Remaining unpaid amount |
AmountPaid | decimal | Amount already paid |
AmountCredited | decimal | Amount from credit notes |
HasAttachments | boolean | Whether attachments exist |
Payments | array | Associated payment records |
API Patterns
List Invoices
curl -s -X GET "https://api.xero.com/api.xro/2.0/Invoices" \
-H "Authorization: Bearer ${ACCESS_TOKEN}" \
-H "xero-tenant-id: ${XERO_TENANT_ID}" \
-H "Accept: application/json"
With Filters:
# Sales invoices only
curl -s -X GET "https://api.xero.com/api.xro/2.0/Invoices?where=Type==%22ACCREC%22" \
-H "Authorization: Bearer ${ACCESS_TOKEN}" \
-H "xero-tenant-id: ${XERO_TENANT_ID}" \
-H "Accept: application/json"
# Outstanding invoices
curl -s -X GET "https://api.xero.com/api.xro/2.0/Invoices?where=Type==%22ACCREC%22&&AmountDue>0" \
-H "Authorization: Bearer ${ACCESS_TOKEN}" \
-H "xero-tenant-id: ${XERO_TENANT_ID}" \
-H "Accept: application/json"
# Invoices for a specific contact
curl -s -X GET "https://api.xero.com/api.xro/2.0/Invoices?where=Contact.ContactID==guid(%22${CONTACT_ID}%22)" \
-H "Authorization: Bearer ${ACCESS_TOKEN}" \
-H "xero-tenant-id: ${XERO_TENANT_ID}" \
-H "Accept: application/json"
# Invoices by date range
curl -s -X GET "https://api.xero.com/api.xro/2.0/Invoices?where=Date>=DateTime(2026,3,1)&&Date<=DateTime(2026,3,31)" \
-H "Authorization: Bearer ${ACCESS_TOKEN}" \
-H "xero-tenant-id: ${XERO_TENANT_ID}" \
-H "Accept: application/json"
# Overdue invoices
curl -s -X GET "https://api.xero.com/api.xro/2.0/Invoices?where=Type==%22ACCREC%22&&Status==%22AUTHORISED%22&&DueDate<DateTime(2026,2,23)" \
-H "Authorization: Bearer ${ACCESS_TOKEN}" \
-H "xero-tenant-id: ${XERO_TENANT_ID}" \
-H "Accept: application/json"
Get Single Invoice
curl -s -X GET "https://api.xero.com/api.xro/2.0/Invoices/${INVOICE_ID}" \
-H "Authorization: Bearer ${ACCESS_TOKEN}" \
-H "xero-tenant-id: ${XERO_TENANT_ID}" \
-H "Accept: application/json"
Create Sales Invoice (ACCREC)
curl -s -X POST "https://api.xero.com/api.xro/2.0/Invoices" \
-H "Authorization: Bearer ${ACCESS_TOKEN}" \
-H "xero-tenant-id: ${XERO_TENANT_ID}" \
-H "Content-Type: application/json" \
-d '{
"Type": "ACCREC",
"Contact": {
"ContactID": "'${CONTACT_ID}'"
},
"Date": "2026-03-01T00:00:00",
"DueDate": "2026-03-31T00:00:00",
"LineAmountTypes": "Exclusive",
"Reference": "March 2026 Managed Services",
"LineItems": [
{
"Description": "Monthly Managed Services - Acme Corp (25 endpoints)",
"Quantity": 1,
"UnitAmount": 2500.00,
"AccountCode": "200",
"TaxType": "OUTPUT"
},
{
"Description": "Microsoft 365 Business Premium Licenses (25 users)",
"Quantity": 25,
"UnitAmount": 22.00,
"AccountCode": "200",
"TaxType": "OUTPUT"
},
{
"Description": "Backup & Disaster Recovery - 500GB",
"Quantity": 1,
"UnitAmount": 350.00,
"AccountCode": "200",
"TaxType": "OUTPUT"
}
],
"Status": "DRAFT"
}'
Create Supplier Bill (ACCPAY)
curl -s -X POST "https://api.xero.com/api.xro/2.0/Invoices" \
-H "Authorization: Bearer ${ACCESS_TOKEN}" \
-H "xero-tenant-id: ${XERO_TENANT_ID}" \
-H "Content-Type: application/json" \
-d '{
"Type": "ACCPAY",
"Contact": {
"ContactID": "'${VENDOR_CONTACT_ID}'"
},
"Date": "2026-03-01T00:00:00",
"DueDate": "2026-03-31T00:00:00",
"InvoiceNumber": "VENDOR-INV-2026-03",
"Reference": "Monthly software licenses",
"LineAmountTypes": "Exclusive",
"LineItems": [
{
"Description": "RMM Platform - 150 endpoints",
"Quantity": 150,
"UnitAmount": 3.50,
"AccountCode": "400",
"TaxType": "INPUT"
}
],
"Status": "DRAFT"
}'
Update Invoice
curl -s -X POST "https://api.xero.com/api.xro/2.0/Invoices/${INVOICE_ID}" \
-H "Authorization: Bearer ${ACCESS_TOKEN}" \
-H "xero-tenant-id: ${XERO_TENANT_ID}" \
-H "Content-Type: application/json" \
-d '{
"InvoiceID": "'${INVOICE_ID}'",
"Reference": "Updated reference",
"Status": "AUTHORISED"
}'
Void Invoice
curl -s -X POST "https://api.xero.com/api.xro/2.0/Invoices/${INVOICE_ID}" \
-H "Authorization: Bearer ${ACCESS_TOKEN}" \
-H "xero-tenant-id: ${XERO_TENANT_ID}" \
-H "Content-Type: application/json" \
-d '{
"InvoiceID": "'${INVOICE_ID}'",
"Status": "VOIDED"
}'
Batch Create Invoices
curl -s -X POST "https://api.xero.com/api.xro/